summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile52
-rw-r--r--lib/Makefile.inc3
-rw-r--r--lib/compat/Makefile16
-rw-r--r--lib/compat/Makefile.inc3
-rw-r--r--lib/compat/compat1x/Makefile27
-rw-r--r--lib/compat/compat1x/libc.so.1.1.gz.uu3921
-rw-r--r--lib/compat/compat1x/libcurses.so.1.1.gz.uu428
-rw-r--r--lib/compat/compat1x/libf2c.so.1.1.gz.uu787
-rw-r--r--lib/compat/compat1x/libg++.so.1.1.gz.uu3530
-rw-r--r--lib/compat/compat1x/libgcc.so.1.1.gz.uu133
-rw-r--r--lib/compat/compat1x/libgnumalloc.so.1.1.gz.uu142
-rw-r--r--lib/compat/compat1x/libgnuregex.so.1.1.gz.uu270
-rw-r--r--lib/compat/compat1x/libln.so.1.1.gz.uu13
-rw-r--r--lib/compat/compat1x/libm.so.1.1.gz.uu538
-rw-r--r--lib/compat/compat1x/libmalloc.so.1.1.gz.uu183
-rw-r--r--lib/compat/compat1x/libreadline.so.1.1.gz.uu1117
-rw-r--r--lib/compat/compat1x/libresolv.so.1.1.gz.uu153
-rw-r--r--lib/compat/compat1x/librpcsvc.so.1.1.gz.uu165
-rw-r--r--lib/compat/compat1x/libskey.so.1.1.gz.uu247
-rw-r--r--lib/compat/compat1x/libtelnet.so.1.1.gz.uu63
-rw-r--r--lib/compat/compat1x/libtermcap.so.1.1.gz.uu75
-rw-r--r--lib/compat/compat1x/libutil.so.1.1.gz.uu208
-rw-r--r--lib/compat/compat1x/liby.so.1.1.gz.uu18
-rw-r--r--lib/compat/compat20/Makefile23
-rw-r--r--lib/compat/compat20/libdialog.so.2.0.gz.uu486
-rw-r--r--lib/compat/compat20/libforms.so.2.0.gz.uu78
-rw-r--r--lib/compat/compat20/libg++.so.2.0.gz.uu4306
-rw-r--r--lib/compat/compat20/libgcc.so.261.0.gz.uu174
-rw-r--r--lib/compat/compat20/libncurses.so.2.0.gz.uu562
-rw-r--r--lib/compat/compat20/libreadline.so.2.0.gz.uu1199
-rw-r--r--lib/compat/compat21/Makefile22
-rw-r--r--lib/compat/compat21/libc.so.2.2.gz.uu4566
-rw-r--r--lib/compat/compat21/libg++.so.3.0.gz.uu4253
-rw-r--r--lib/compat/compat21/libgmp.so.2.0.gz.uu426
-rw-r--r--lib/csu/i386/Makefile63
-rw-r--r--lib/csu/i386/c++rt0.c107
-rw-r--r--lib/csu/i386/crt0.c441
-rw-r--r--lib/csu/i386/dlfcn.h53
-rw-r--r--lib/csu/i386/dlopen.3213
-rw-r--r--lib/libF77/F77_aloc.c32
-rw-r--r--lib/libF77/Notice23
-rw-r--r--lib/libF77/README108
-rw-r--r--lib/libF77/Version.c49
-rw-r--r--lib/libF77/abort_.c18
-rw-r--r--lib/libF77/c_abs.c14
-rw-r--r--lib/libF77/c_cos.c17
-rw-r--r--lib/libF77/c_div.c37
-rw-r--r--lib/libF77/c_exp.c19
-rw-r--r--lib/libF77/c_log.c17
-rw-r--r--lib/libF77/c_sin.c17
-rw-r--r--lib/libF77/c_sqrt.c35
-rw-r--r--lib/libF77/cabs.c27
-rw-r--r--lib/libF77/d_abs.c12
-rw-r--r--lib/libF77/d_acos.c13
-rw-r--r--lib/libF77/d_asin.c13
-rw-r--r--lib/libF77/d_atan.c13
-rw-r--r--lib/libF77/d_atn2.c13
-rw-r--r--lib/libF77/d_cnjg.c12
-rw-r--r--lib/libF77/d_cos.c13
-rw-r--r--lib/libF77/d_cosh.c13
-rw-r--r--lib/libF77/d_dim.c10
-rw-r--r--lib/libF77/d_exp.c13
-rw-r--r--lib/libF77/d_imag.c10
-rw-r--r--lib/libF77/d_int.c13
-rw-r--r--lib/libF77/d_lg10.c13
-rw-r--r--lib/libF77/d_log.c13
-rw-r--r--lib/libF77/d_mod.c40
-rw-r--r--lib/libF77/d_nint.c14
-rw-r--r--lib/libF77/d_prod.c10
-rw-r--r--lib/libF77/d_sign.c12
-rw-r--r--lib/libF77/d_sin.c13
-rw-r--r--lib/libF77/d_sinh.c13
-rw-r--r--lib/libF77/d_sqrt.c13
-rw-r--r--lib/libF77/d_tan.c13
-rw-r--r--lib/libF77/d_tanh.c13
-rw-r--r--lib/libF77/derf_.c12
-rw-r--r--lib/libF77/derfc_.c14
-rw-r--r--lib/libF77/ef1asc_.c21
-rw-r--r--lib/libF77/ef1cmc_.c14
-rw-r--r--lib/libF77/erf_.c12
-rw-r--r--lib/libF77/erfc_.c12
-rw-r--r--lib/libF77/f2ch.add162
-rw-r--r--lib/libF77/getarg_.c28
-rw-r--r--lib/libF77/getenv_.c51
-rw-r--r--lib/libF77/h_abs.c12
-rw-r--r--lib/libF77/h_dim.c10
-rw-r--r--lib/libF77/h_dnnt.c14
-rw-r--r--lib/libF77/h_indx.c26
-rw-r--r--lib/libF77/h_len.c10
-rw-r--r--lib/libF77/h_mod.c10
-rw-r--r--lib/libF77/h_nint.c14
-rw-r--r--lib/libF77/h_sign.c12
-rw-r--r--lib/libF77/hl_ge.c12
-rw-r--r--lib/libF77/hl_gt.c12
-rw-r--r--lib/libF77/hl_le.c12
-rw-r--r--lib/libF77/hl_lt.c12
-rw-r--r--lib/libF77/i_abs.c12
-rw-r--r--lib/libF77/i_dim.c10
-rw-r--r--lib/libF77/i_dnnt.c14
-rw-r--r--lib/libF77/i_indx.c26
-rw-r--r--lib/libF77/i_len.c10
-rw-r--r--lib/libF77/i_mod.c10
-rw-r--r--lib/libF77/i_nint.c14
-rw-r--r--lib/libF77/i_sign.c12
-rw-r--r--lib/libF77/iargc_.c11
-rw-r--r--lib/libF77/l_ge.c12
-rw-r--r--lib/libF77/l_gt.c12
-rw-r--r--lib/libF77/l_le.c12
-rw-r--r--lib/libF77/l_lt.c12
-rw-r--r--lib/libF77/lbitbits.c62
-rw-r--r--lib/libF77/lbitshft.c11
-rw-r--r--lib/libF77/main.c135
-rw-r--r--lib/libF77/pow_ci.c20
-rw-r--r--lib/libF77/pow_dd.c13
-rw-r--r--lib/libF77/pow_di.c35
-rw-r--r--lib/libF77/pow_hh.c33
-rw-r--r--lib/libF77/pow_ii.c33
-rw-r--r--lib/libF77/pow_qq.c33
-rw-r--r--lib/libF77/pow_ri.c35
-rw-r--r--lib/libF77/pow_zi.c54
-rw-r--r--lib/libF77/pow_zz.c23
-rw-r--r--lib/libF77/r_abs.c12
-rw-r--r--lib/libF77/r_acos.c13
-rw-r--r--lib/libF77/r_asin.c13
-rw-r--r--lib/libF77/r_atan.c13
-rw-r--r--lib/libF77/r_atn2.c13
-rw-r--r--lib/libF77/r_cnjg.c11
-rw-r--r--lib/libF77/r_cos.c13
-rw-r--r--lib/libF77/r_cosh.c13
-rw-r--r--lib/libF77/r_dim.c10
-rw-r--r--lib/libF77/r_exp.c13
-rw-r--r--lib/libF77/r_imag.c10
-rw-r--r--lib/libF77/r_int.c13
-rw-r--r--lib/libF77/r_lg10.c13
-rw-r--r--lib/libF77/r_log.c13
-rw-r--r--lib/libF77/r_mod.c40
-rw-r--r--lib/libF77/r_nint.c14
-rw-r--r--lib/libF77/r_sign.c12
-rw-r--r--lib/libF77/r_sin.c13
-rw-r--r--lib/libF77/r_sinh.c13
-rw-r--r--lib/libF77/r_sqrt.c13
-rw-r--r--lib/libF77/r_tan.c13
-rw-r--r--lib/libF77/r_tanh.c13
-rw-r--r--lib/libF77/s_cat.c75
-rw-r--r--lib/libF77/s_cmp.c44
-rw-r--r--lib/libF77/s_copy.c51
-rw-r--r--lib/libF77/s_paus.c88
-rw-r--r--lib/libF77/s_rnge.c26
-rw-r--r--lib/libF77/s_stop.c37
-rw-r--r--lib/libF77/sig_die.c45
-rw-r--r--lib/libF77/signal1.h25
-rw-r--r--lib/libF77/signal_.c19
-rw-r--r--lib/libF77/system_.c36
-rw-r--r--lib/libF77/z_abs.c12
-rw-r--r--lib/libF77/z_cos.c15
-rw-r--r--lib/libF77/z_div.c36
-rw-r--r--lib/libF77/z_exp.c17
-rw-r--r--lib/libF77/z_log.c16
-rw-r--r--lib/libF77/z_sin.c15
-rw-r--r--lib/libF77/z_sqrt.c29
-rw-r--r--lib/libI77/Notice23
-rw-r--r--lib/libI77/README225
-rw-r--r--lib/libI77/Version.c244
-rw-r--r--lib/libI77/backspace.c98
-rw-r--r--lib/libI77/close.c95
-rw-r--r--lib/libI77/dfe.c152
-rw-r--r--lib/libI77/dolio.c20
-rw-r--r--lib/libI77/due.c70
-rw-r--r--lib/libI77/endfile.c195
-rw-r--r--lib/libI77/err.c278
-rw-r--r--lib/libI77/f2ch.add162
-rw-r--r--lib/libI77/fio.h102
-rw-r--r--lib/libI77/fmt.c488
-rw-r--r--lib/libI77/fmt.h99
-rw-r--r--lib/libI77/fmtlib.c45
-rw-r--r--lib/libI77/fp.h28
-rw-r--r--lib/libI77/iio.c142
-rw-r--r--lib/libI77/ilnw.c77
-rw-r--r--lib/libI77/inquire.c106
-rw-r--r--lib/libI77/lio.h74
-rw-r--r--lib/libI77/lread.c659
-rw-r--r--lib/libI77/lwrite.c310
-rw-r--r--lib/libI77/open.c239
-rw-r--r--lib/libI77/rawio.h43
-rw-r--r--lib/libI77/rdfmt.c475
-rw-r--r--lib/libI77/rewind.c24
-rw-r--r--lib/libI77/rsfe.c79
-rw-r--r--lib/libI77/rsli.c103
-rw-r--r--lib/libI77/rsne.c609
-rw-r--r--lib/libI77/sfe.c42
-rw-r--r--lib/libI77/sue.c83
-rw-r--r--lib/libI77/typesize.c12
-rw-r--r--lib/libI77/uio.c68
-rw-r--r--lib/libI77/util.c51
-rw-r--r--lib/libI77/wref.c275
-rw-r--r--lib/libI77/wrtfmt.c387
-rw-r--r--lib/libI77/wsfe.c84
-rw-r--r--lib/libI77/wsle.c40
-rw-r--r--lib/libI77/wsne.c26
-rw-r--r--lib/libI77/xwsne.c72
-rw-r--r--lib/libalias/Makefile11
-rw-r--r--lib/libalias/alias.c1142
-rw-r--r--lib/libalias/alias.h102
-rw-r--r--lib/libalias/alias_db.c1972
-rw-r--r--lib/libalias/alias_ftp.c220
-rw-r--r--lib/libalias/alias_irc.c311
-rw-r--r--lib/libalias/alias_local.h91
-rw-r--r--lib/libalias/alias_util.c135
-rw-r--r--lib/libc/Makefile42
-rw-r--r--lib/libc/Makefile.inc25
-rw-r--r--lib/libc/amd64/SYS.h86
-rw-r--r--lib/libc/amd64/gen/Makefile.inc5
-rw-r--r--lib/libc/amd64/gen/_setjmp.S92
-rw-r--r--lib/libc/amd64/gen/frexp.c67
-rw-r--r--lib/libc/amd64/gen/infinity.c9
-rw-r--r--lib/libc/amd64/gen/isinf.c68
-rw-r--r--lib/libc/amd64/gen/ldexp.c74
-rw-r--r--lib/libc/amd64/gen/setjmp.S113
-rw-r--r--lib/libc/amd64/gen/sigsetjmp.S125
-rw-r--r--lib/libc/amd64/net/Makefile.inc4
-rw-r--r--lib/libc/amd64/net/htonl.S53
-rw-r--r--lib/libc/amd64/net/htons.S51
-rw-r--r--lib/libc/amd64/net/ntohl.S53
-rw-r--r--lib/libc/amd64/net/ntohs.S51
-rw-r--r--lib/libc/amd64/sys/Makefile.inc13
-rw-r--r--lib/libc/amd64/sys/brk.S91
-rw-r--r--lib/libc/amd64/sys/cerror.S87
-rw-r--r--lib/libc/amd64/sys/exect.S56
-rw-r--r--lib/libc/amd64/sys/pipe.S51
-rw-r--r--lib/libc/amd64/sys/ptrace.S62
-rw-r--r--lib/libc/amd64/sys/reboot.S47
-rw-r--r--lib/libc/amd64/sys/sbrk.S95
-rw-r--r--lib/libc/amd64/sys/setlogin.S59
-rw-r--r--lib/libc/amd64/sys/sigreturn.S52
-rw-r--r--lib/libc/amd64/sys/vfork.S101
-rw-r--r--lib/libc/compat-43/Makefile.inc19
-rw-r--r--lib/libc/compat-43/creat.27
-rw-r--r--lib/libc/compat-43/creat.c1
-rw-r--r--lib/libc/compat-43/gethostid.36
-rw-r--r--lib/libc/compat-43/getwd.c2
-rw-r--r--lib/libc/compat-43/killpg.25
-rw-r--r--lib/libc/compat-43/killpg.c1
-rw-r--r--lib/libc/compat-43/setpgrp.c1
-rw-r--r--lib/libc/compat-43/setruid.312
-rw-r--r--lib/libc/compat-43/sigblock.24
-rw-r--r--lib/libc/compat-43/sigcompat.c4
-rw-r--r--lib/libc/compat-43/sigpause.26
-rw-r--r--lib/libc/compat-43/sigsetmask.26
-rw-r--r--lib/libc/compat-43/sigvec.211
-rw-r--r--lib/libc/db/Makefile.inc15
-rw-r--r--lib/libc/db/README40
-rw-r--r--lib/libc/db/btree/Makefile.inc5
-rw-r--r--lib/libc/db/btree/bt_open.c8
-rw-r--r--lib/libc/db/changelog (renamed from lib/libc/db/VERSION)80
-rw-r--r--lib/libc/db/db/Makefile.inc5
-rw-r--r--lib/libc/db/doc/hash.usenix.ps12209
-rw-r--r--lib/libc/db/doc/libtp.usenix.ps12340
-rw-r--r--lib/libc/db/hash/Makefile.inc5
-rw-r--r--lib/libc/db/hash/hash.c23
-rw-r--r--lib/libc/db/hash/hash.h6
-rw-r--r--lib/libc/db/hash/hash_bigkey.c2
-rw-r--r--lib/libc/db/hash/hash_page.c2
-rw-r--r--lib/libc/db/hash/hsearch.c2
-rw-r--r--lib/libc/db/hash/ndbm.c61
-rw-r--r--lib/libc/db/man/Makefile.inc11
-rw-r--r--lib/libc/db/man/hash.38
-rw-r--r--lib/libc/db/man/mpool.33
-rw-r--r--lib/libc/db/man/recno.34
-rw-r--r--lib/libc/db/mpool/Makefile.inc5
-rw-r--r--lib/libc/db/mpool/mpool.libtp2
-rw-r--r--lib/libc/db/recno/Makefile.inc5
-rw-r--r--lib/libc/db/recno/rec_close.c2
-rw-r--r--lib/libc/db/recno/rec_open.c2
-rw-r--r--lib/libc/db/test/btree.tests/main.c2
-rw-r--r--lib/libc/db/test/hash.tests/driver2.c2
-rw-r--r--lib/libc/db/test/hash.tests/tcreat3.c2
-rw-r--r--lib/libc/db/test/hash.tests/tdel.c4
-rw-r--r--lib/libc/db/test/hash.tests/thash4.c10
-rw-r--r--lib/libc/db/test/hash.tests/tseq.c2
-rw-r--r--lib/libc/gen/Makefile.inc110
-rw-r--r--lib/libc/gen/__xuname.c125
-rw-r--r--lib/libc/gen/_rand48.c46
-rw-r--r--lib/libc/gen/alarm.343
-rw-r--r--lib/libc/gen/arc4random.383
-rw-r--r--lib/libc/gen/arc4random.c172
-rw-r--r--lib/libc/gen/assert.c1
-rw-r--r--lib/libc/gen/clock.38
-rw-r--r--lib/libc/gen/clock.c5
-rw-r--r--lib/libc/gen/closedir.c7
-rw-r--r--lib/libc/gen/config.c187
-rw-r--r--lib/libc/gen/config_open.373
-rw-r--r--lib/libc/gen/confstr.312
-rw-r--r--lib/libc/gen/confstr.c1
-rw-r--r--lib/libc/gen/crypt.339
-rw-r--r--lib/libc/gen/crypt.c21
-rw-r--r--lib/libc/gen/ctermid.32
-rw-r--r--lib/libc/gen/daemon.312
-rw-r--r--lib/libc/gen/devname.32
-rw-r--r--lib/libc/gen/directory.36
-rw-r--r--lib/libc/gen/disklabel.c20
-rw-r--r--lib/libc/gen/drand48.c22
-rw-r--r--lib/libc/gen/erand48.c23
-rw-r--r--lib/libc/gen/err.341
-rw-r--r--lib/libc/gen/err.c66
-rw-r--r--lib/libc/gen/exec.317
-rw-r--r--lib/libc/gen/exec.c47
-rw-r--r--lib/libc/gen/fnmatch.318
-rw-r--r--lib/libc/gen/fnmatch.c96
-rw-r--r--lib/libc/gen/frexp.34
-rw-r--r--lib/libc/gen/fstab.c71
-rw-r--r--lib/libc/gen/ftok.385
-rw-r--r--lib/libc/gen/ftok.c47
-rw-r--r--lib/libc/gen/fts-compat.c995
-rw-r--r--lib/libc/gen/fts-compat.h128
-rw-r--r--lib/libc/gen/fts.37
-rw-r--r--lib/libc/gen/fts.c995
-rw-r--r--lib/libc/gen/getbootfile.370
-rw-r--r--lib/libc/gen/getbootfile.c55
-rw-r--r--lib/libc/gen/getbsize.38
-rw-r--r--lib/libc/gen/getcap.3147
-rw-r--r--lib/libc/gen/getcap.c63
-rw-r--r--lib/libc/gen/getcwd.35
-rw-r--r--lib/libc/gen/getcwd.c166
-rw-r--r--lib/libc/gen/getdomainname.399
-rw-r--r--lib/libc/gen/getdomainname.c61
-rw-r--r--lib/libc/gen/getfsent.314
-rw-r--r--lib/libc/gen/getgrent.343
-rw-r--r--lib/libc/gen/getgrent.c418
-rw-r--r--lib/libc/gen/getgrouplist.33
-rw-r--r--lib/libc/gen/getgrouplist.c8
-rw-r--r--lib/libc/gen/gethostname.36
-rw-r--r--lib/libc/gen/gethostname.c2
-rw-r--r--lib/libc/gen/getloadavg.35
-rw-r--r--lib/libc/gen/getlogin.c4
-rw-r--r--lib/libc/gen/getmntinfo.39
-rw-r--r--lib/libc/gen/getnetgrent.38
-rw-r--r--lib/libc/gen/getnetgrent.c304
-rw-r--r--lib/libc/gen/getosreldate.c63
-rw-r--r--lib/libc/gen/getpagesize.39
-rw-r--r--lib/libc/gen/getpagesize.c20
-rw-r--r--lib/libc/gen/getpass.324
-rw-r--r--lib/libc/gen/getpass.c73
-rw-r--r--lib/libc/gen/getpwent.365
-rw-r--r--lib/libc/gen/getpwent.c658
-rw-r--r--lib/libc/gen/getttyent.350
-rw-r--r--lib/libc/gen/getttyent.c101
-rw-r--r--lib/libc/gen/getusershell.31
-rw-r--r--lib/libc/gen/getusershell.c2
-rw-r--r--lib/libc/gen/getvfsbyname.39
-rw-r--r--lib/libc/gen/getvfsbyname.c7
-rw-r--r--lib/libc/gen/getvfsent.3228
-rw-r--r--lib/libc/gen/getvfsent.c248
-rw-r--r--lib/libc/gen/glob.312
-rw-r--r--lib/libc/gen/glob.c77
-rw-r--r--lib/libc/gen/initgroups.34
-rw-r--r--lib/libc/gen/initgroups.c2
-rw-r--r--lib/libc/gen/isatty.c17
-rw-r--r--lib/libc/gen/jrand48.c21
-rw-r--r--lib/libc/gen/lcong48.c30
-rw-r--r--lib/libc/gen/ldexp.36
-rw-r--r--lib/libc/gen/lrand48.c23
-rw-r--r--lib/libc/gen/mrand48.c23
-rw-r--r--lib/libc/gen/msgctl.3207
-rw-r--r--lib/libc/gen/msgctl.c15
-rw-r--r--lib/libc/gen/msgget.3134
-rw-r--r--lib/libc/gen/msgget.c14
-rw-r--r--lib/libc/gen/msgrcv.3207
-rw-r--r--lib/libc/gen/msgrcv.c17
-rw-r--r--lib/libc/gen/msgsnd.3159
-rw-r--r--lib/libc/gen/msgsnd.c16
-rw-r--r--lib/libc/gen/nice.33
-rw-r--r--lib/libc/gen/nlist.34
-rw-r--r--lib/libc/gen/nlist.c87
-rw-r--r--lib/libc/gen/nrand48.c21
-rw-r--r--lib/libc/gen/ntp_gettime.c59
-rw-r--r--lib/libc/gen/opendir.c63
-rw-r--r--lib/libc/gen/pause.38
-rw-r--r--lib/libc/gen/popen.320
-rw-r--r--lib/libc/gen/popen.c41
-rw-r--r--lib/libc/gen/psignal.36
-rw-r--r--lib/libc/gen/psignal.c2
-rw-r--r--lib/libc/gen/pw_scan.c141
-rw-r--r--lib/libc/gen/pw_scan.h36
-rw-r--r--lib/libc/gen/pwcache.314
-rw-r--r--lib/libc/gen/pwcache.c41
-rw-r--r--lib/libc/gen/raise.c1
-rw-r--r--lib/libc/gen/rand48.3160
-rw-r--r--lib/libc/gen/rand48.h30
-rw-r--r--lib/libc/gen/rewinddir.c2
-rw-r--r--lib/libc/gen/scandir.c5
-rw-r--r--lib/libc/gen/seed48.c36
-rw-r--r--lib/libc/gen/seekdir.c2
-rw-r--r--lib/libc/gen/semconfig.c13
-rw-r--r--lib/libc/gen/semctl.c15
-rw-r--r--lib/libc/gen/semget.c15
-rw-r--r--lib/libc/gen/semop.c15
-rw-r--r--lib/libc/gen/setdomainname.c (renamed from lib/libc/net/getnetbyaddr.c)33
-rw-r--r--lib/libc/gen/setflags.c163
-rw-r--r--lib/libc/gen/setflagsbyname.c163
-rw-r--r--lib/libc/gen/sethostname.c4
-rw-r--r--lib/libc/gen/setjmp.37
-rw-r--r--lib/libc/gen/setmode.34
-rw-r--r--lib/libc/gen/setmode.c12
-rw-r--r--lib/libc/gen/setproctitle.3113
-rw-r--r--lib/libc/gen/setproctitle.c125
-rw-r--r--lib/libc/gen/shmat.c19
-rw-r--r--lib/libc/gen/shmctl.c19
-rw-r--r--lib/libc/gen/shmdt.c17
-rw-r--r--lib/libc/gen/shmget.c19
-rw-r--r--lib/libc/gen/siginterrupt.36
-rw-r--r--lib/libc/gen/siginterrupt.c1
-rw-r--r--lib/libc/gen/signal.324
-rw-r--r--lib/libc/gen/sigsetops.37
-rw-r--r--lib/libc/gen/sigsetops.c5
-rw-r--r--lib/libc/gen/sleep.323
-rw-r--r--lib/libc/gen/sleep.c118
-rw-r--r--lib/libc/gen/srand48.c30
-rw-r--r--lib/libc/gen/stringlist.3120
-rw-r--r--lib/libc/gen/stringlist.c120
-rw-r--r--lib/libc/gen/strtofflags.c163
-rw-r--r--lib/libc/gen/sysconf.316
-rw-r--r--lib/libc/gen/sysconf.c6
-rw-r--r--lib/libc/gen/sysctl.3120
-rw-r--r--lib/libc/gen/sysctl.c1
-rw-r--r--lib/libc/gen/sysctlbyname.c33
-rw-r--r--lib/libc/gen/syslog.314
-rw-r--r--lib/libc/gen/syslog.c212
-rw-r--r--lib/libc/gen/tcgetpgrp.312
-rw-r--r--lib/libc/gen/tcsendbreak.320
-rw-r--r--lib/libc/gen/tcsetattr.3100
-rw-r--r--lib/libc/gen/tcsetpgrp.34
-rw-r--r--lib/libc/gen/telldir.c31
-rw-r--r--lib/libc/gen/termios.c21
-rw-r--r--lib/libc/gen/time.32
-rw-r--r--lib/libc/gen/times.33
-rw-r--r--lib/libc/gen/timezone.32
-rw-r--r--lib/libc/gen/timezone.c32
-rw-r--r--lib/libc/gen/ttyname.c122
-rw-r--r--lib/libc/gen/ttyslot.c8
-rw-r--r--lib/libc/gen/tzset.37
-rw-r--r--lib/libc/gen/ualarm.37
-rw-r--r--lib/libc/gen/ualarm.c2
-rw-r--r--lib/libc/gen/uname.39
-rw-r--r--lib/libc/gen/uname.c71
-rw-r--r--lib/libc/gen/unvis.39
-rw-r--r--lib/libc/gen/unvis.c35
-rw-r--r--lib/libc/gen/usleep.36
-rw-r--r--lib/libc/gen/usleep.c122
-rw-r--r--lib/libc/gen/utime.36
-rw-r--r--lib/libc/gen/valloc.34
-rw-r--r--lib/libc/gen/vis.334
-rw-r--r--lib/libc/gen/vis.c11
-rw-r--r--lib/libc/gmon/Makefile.inc12
-rw-r--r--lib/libc/gmon/gmon.c8
-rw-r--r--lib/libc/gmon/mcount.c169
-rw-r--r--lib/libc/gmon/moncontrol.36
-rw-r--r--lib/libc/i386/DEFS.h18
-rw-r--r--lib/libc/i386/SYS.h61
-rw-r--r--lib/libc/i386/gen/Makefile.inc6
-rw-r--r--lib/libc/i386/gen/_setjmp.S34
-rw-r--r--lib/libc/i386/gen/alloca.S13
-rw-r--r--lib/libc/i386/gen/fabs.S13
-rw-r--r--lib/libc/i386/gen/frexp.c8
-rw-r--r--lib/libc/i386/gen/infinity.c9
-rw-r--r--lib/libc/i386/gen/isinf.c10
-rw-r--r--lib/libc/i386/gen/ldexp.c18
-rw-r--r--lib/libc/i386/gen/modf.S20
-rw-r--r--lib/libc/i386/gen/setjmp.S51
-rw-r--r--lib/libc/i386/gen/sigsetjmp.S125
-rw-r--r--lib/libc/i386/net/Makefile.inc3
-rw-r--r--lib/libc/i386/net/htonl.S53
-rw-r--r--lib/libc/i386/net/htons.S51
-rw-r--r--lib/libc/i386/net/ntohl.S53
-rw-r--r--lib/libc/i386/net/ntohs.S51
-rw-r--r--lib/libc/i386/stdlib/Makefile.inc3
-rw-r--r--lib/libc/i386/stdlib/abs.S17
-rw-r--r--lib/libc/i386/stdlib/div.S47
-rw-r--r--lib/libc/i386/stdlib/labs.S51
-rw-r--r--lib/libc/i386/stdlib/ldiv.S47
-rw-r--r--lib/libc/i386/string/Makefile.inc9
-rw-r--r--lib/libc/i386/string/bcmp.S70
-rw-r--r--lib/libc/i386/string/bcopy.S103
-rw-r--r--lib/libc/i386/string/bzero.S98
-rw-r--r--lib/libc/i386/string/ffs.S59
-rw-r--r--lib/libc/i386/string/index.S69
-rw-r--r--lib/libc/i386/string/memchr.S64
-rw-r--r--lib/libc/i386/string/memcmp.S81
-rw-r--r--lib/libc/i386/string/memcpy.S2
-rw-r--r--lib/libc/i386/string/memmove.S2
-rw-r--r--lib/libc/i386/string/memset.S95
-rw-r--r--lib/libc/i386/string/rindex.S70
-rw-r--r--lib/libc/i386/string/strcat.S106
-rw-r--r--lib/libc/i386/string/strchr.S69
-rw-r--r--lib/libc/i386/string/strcmp.S125
-rw-r--r--lib/libc/i386/string/strcpy.S95
-rw-r--r--lib/libc/i386/string/strlen.S59
-rw-r--r--lib/libc/i386/string/strncmp.S172
-rw-r--r--lib/libc/i386/string/strrchr.S70
-rw-r--r--lib/libc/i386/string/swab.S105
-rw-r--r--lib/libc/i386/sys/Makefile.inc13
-rw-r--r--lib/libc/i386/sys/Ovfork.S55
-rw-r--r--lib/libc/i386/sys/brk.S58
-rw-r--r--lib/libc/i386/sys/cerror.S56
-rw-r--r--lib/libc/i386/sys/exect.S18
-rw-r--r--lib/libc/i386/sys/fork.S15
-rw-r--r--lib/libc/i386/sys/i386_get_ldt.298
-rw-r--r--lib/libc/i386/sys/i386_get_ldt.c55
-rw-r--r--lib/libc/i386/sys/i386_set_ldt.c55
-rw-r--r--lib/libc/i386/sys/mount.S13
-rw-r--r--lib/libc/i386/sys/pipe.S15
-rw-r--r--lib/libc/i386/sys/ptrace.S27
-rw-r--r--lib/libc/i386/sys/reboot.S13
-rw-r--r--lib/libc/i386/sys/rfork.S51
-rw-r--r--lib/libc/i386/sys/sbrk.S66
-rw-r--r--lib/libc/i386/sys/setlogin.S26
-rw-r--r--lib/libc/i386/sys/sigpending.S15
-rw-r--r--lib/libc/i386/sys/sigprocmask.S24
-rw-r--r--lib/libc/i386/sys/sigreturn.S24
-rw-r--r--lib/libc/i386/sys/sigsuspend.S24
-rw-r--r--lib/libc/i386/sys/syscall.S20
-rw-r--r--lib/libc/locale/Makefile.inc29
-rw-r--r--lib/libc/locale/ansi.c7
-rw-r--r--lib/libc/locale/collate.c197
-rw-r--r--lib/libc/locale/collate.h66
-rw-r--r--lib/libc/locale/collcmp.c93
-rw-r--r--lib/libc/locale/ctype.317
-rw-r--r--lib/libc/locale/euc.438
-rw-r--r--lib/libc/locale/euc.5241
-rw-r--r--lib/libc/locale/euc.c2
-rw-r--r--lib/libc/locale/isalnum.34
-rw-r--r--lib/libc/locale/isalpha.34
-rw-r--r--lib/libc/locale/isascii.32
-rw-r--r--lib/libc/locale/isblank.32
-rw-r--r--lib/libc/locale/iscntrl.34
-rw-r--r--lib/libc/locale/isctype.c11
-rw-r--r--lib/libc/locale/isdigit.34
-rw-r--r--lib/libc/locale/isgraph.34
-rw-r--r--lib/libc/locale/islower.34
-rw-r--r--lib/libc/locale/isprint.34
-rw-r--r--lib/libc/locale/ispunct.34
-rw-r--r--lib/libc/locale/isspace.34
-rw-r--r--lib/libc/locale/isupper.36
-rw-r--r--lib/libc/locale/isxdigit.34
-rw-r--r--lib/libc/locale/mbrune.34
-rw-r--r--lib/libc/locale/multibyte.36
-rw-r--r--lib/libc/locale/nomacros.c9
-rw-r--r--lib/libc/locale/none.c2
-rw-r--r--lib/libc/locale/rune.315
-rw-r--r--lib/libc/locale/rune.c171
-rw-r--r--lib/libc/locale/runetype.c64
-rw-r--r--lib/libc/locale/setinvalidrune.c44
-rw-r--r--lib/libc/locale/setlocale.326
-rw-r--r--lib/libc/locale/setlocale.c226
-rw-r--r--lib/libc/locale/setlocale.h34
-rw-r--r--lib/libc/locale/setrunelocale.c130
-rw-r--r--lib/libc/locale/table.c6
-rw-r--r--lib/libc/locale/toascii.34
-rw-r--r--lib/libc/locale/tolower.34
-rw-r--r--lib/libc/locale/tolower.c60
-rw-r--r--lib/libc/locale/toupper.38
-rw-r--r--lib/libc/locale/toupper.c60
-rw-r--r--lib/libc/locale/utf2.411
-rw-r--r--lib/libc/locale/utf2.5 (renamed from lib/libc/gen/realpath.3)132
-rw-r--r--lib/libc/locale/utf2.c2
-rw-r--r--lib/libc/net/Makefile.inc46
-rw-r--r--lib/libc/net/addr2ascii.3215
-rw-r--r--lib/libc/net/addr2ascii.c92
-rw-r--r--lib/libc/net/ascii2addr.c72
-rw-r--r--lib/libc/net/base64.c321
-rw-r--r--lib/libc/net/ether_addr.c226
-rw-r--r--lib/libc/net/ethers.3193
-rw-r--r--lib/libc/net/gethostbydns.c736
-rw-r--r--lib/libc/net/gethostbyht.c202
-rw-r--r--lib/libc/net/gethostbyname.377
-rw-r--r--lib/libc/net/gethostbynis.c142
-rw-r--r--lib/libc/net/gethostnamadr.c542
-rw-r--r--lib/libc/net/getnetbydns.c310
-rw-r--r--lib/libc/net/getnetbyht.c173
-rw-r--r--lib/libc/net/getnetbynis.c177
-rw-r--r--lib/libc/net/getnetent.317
-rw-r--r--lib/libc/net/getnetnamadr.c190
-rw-r--r--lib/libc/net/getproto.c2
-rw-r--r--lib/libc/net/getprotoent.38
-rw-r--r--lib/libc/net/getprotoname.c2
-rw-r--r--lib/libc/net/getservbyname.c16
-rw-r--r--lib/libc/net/getservbyport.c16
-rw-r--r--lib/libc/net/getservent.313
-rw-r--r--lib/libc/net/getservent.c157
-rw-r--r--lib/libc/net/herror.c23
-rw-r--r--lib/libc/net/inet.329
-rw-r--r--lib/libc/net/inet_addr.c76
-rw-r--r--lib/libc/net/inet_net_ntop.c140
-rw-r--r--lib/libc/net/inet_net_pton.c208
-rw-r--r--lib/libc/net/inet_neta.c83
-rw-r--r--lib/libc/net/inet_network.c6
-rw-r--r--lib/libc/net/inet_ntop.c190
-rw-r--r--lib/libc/net/inet_pton.c214
-rw-r--r--lib/libc/net/iso_addr.c38
-rw-r--r--lib/libc/net/linkaddr.315
-rw-r--r--lib/libc/net/linkaddr.c4
-rw-r--r--lib/libc/net/map_v4v6.c128
-rw-r--r--lib/libc/net/ns.33
-rw-r--r--lib/libc/net/ns_addr.c6
-rw-r--r--lib/libc/net/nsap_addr.c103
-rw-r--r--lib/libc/net/rcmd.310
-rw-r--r--lib/libc/net/rcmd.c150
-rw-r--r--lib/libc/net/res_comp.c496
-rw-r--r--lib/libc/net/res_config.h8
-rw-r--r--lib/libc/net/res_data.c111
-rw-r--r--lib/libc/net/res_debug.c1520
-rw-r--r--lib/libc/net/res_init.c459
-rw-r--r--lib/libc/net/res_mkquery.c186
-rw-r--r--lib/libc/net/res_query.c401
-rw-r--r--lib/libc/net/res_send.c767
-rw-r--r--lib/libc/net/res_stubs.c64
-rw-r--r--lib/libc/net/resolver.354
-rw-r--r--lib/libc/nls/Makefile.inc11
-rw-r--r--lib/libc/nls/catclose.354
-rw-r--r--lib/libc/nls/catclose.c25
-rw-r--r--lib/libc/nls/catgets.366
-rw-r--r--lib/libc/nls/catgets.c28
-rw-r--r--lib/libc/nls/catopen.382
-rw-r--r--lib/libc/nls/catopen.c26
-rw-r--r--lib/libc/nls/msgcat.c428
-rw-r--r--lib/libc/nls/msgcat.h170
-rw-r--r--lib/libc/quad/Makefile.inc16
-rw-r--r--lib/libc/quad/muldi3.c2
-rw-r--r--lib/libc/quad/qdivrem.c2
-rw-r--r--lib/libc/quad/quad.h7
-rw-r--r--lib/libc/regex/Makefile.inc12
-rw-r--r--lib/libc/regex/cclass.h44
-rw-r--r--lib/libc/regex/cname.h192
-rw-r--r--lib/libc/regex/engine.c9
-rw-r--r--lib/libc/regex/regcomp.c163
-rw-r--r--lib/libc/regex/regerror.c38
-rw-r--r--lib/libc/regex/regex.34
-rw-r--r--lib/libc/regex/regex2.h8
-rw-r--r--lib/libc/rpc/DISCLAIMER28
-rw-r--r--lib/libc/rpc/Makefile.inc120
-rw-r--r--lib/libc/rpc/PSD.doc/nfs.rfc.ms1372
-rw-r--r--lib/libc/rpc/PSD.doc/rpc.prog.ms2684
-rw-r--r--lib/libc/rpc/PSD.doc/rpc.rfc.ms1302
-rw-r--r--lib/libc/rpc/PSD.doc/rpcgen.ms1299
-rw-r--r--lib/libc/rpc/PSD.doc/xdr.nts.ms1966
-rw-r--r--lib/libc/rpc/PSD.doc/xdr.rfc.ms1058
-rw-r--r--lib/libc/rpc/README233
-rw-r--r--lib/libc/rpc/auth_des.c554
-rw-r--r--lib/libc/rpc/auth_none.c136
-rw-r--r--lib/libc/rpc/auth_time.c501
-rw-r--r--lib/libc/rpc/auth_unix.c349
-rw-r--r--lib/libc/rpc/authdes_prot.c82
-rw-r--r--lib/libc/rpc/authunix_prot.c68
-rw-r--r--lib/libc/rpc/bindresvport.330
-rw-r--r--lib/libc/rpc/bindresvport.c107
-rw-r--r--lib/libc/rpc/clnt_generic.c137
-rw-r--r--lib/libc/rpc/clnt_perror.c254
-rw-r--r--lib/libc/rpc/clnt_raw.c242
-rw-r--r--lib/libc/rpc/clnt_simple.c122
-rw-r--r--lib/libc/rpc/clnt_tcp.c580
-rw-r--r--lib/libc/rpc/clnt_udp.c553
-rw-r--r--lib/libc/rpc/clnt_unix.c635
-rw-r--r--lib/libc/rpc/crypt_client.c89
-rw-r--r--lib/libc/rpc/des_crypt.3126
-rw-r--r--lib/libc/rpc/des_crypt.c153
-rw-r--r--lib/libc/rpc/des_soft.c67
-rw-r--r--lib/libc/rpc/get_myaddress.c109
-rw-r--r--lib/libc/rpc/getrpcent.396
-rw-r--r--lib/libc/rpc/getrpcent.c303
-rw-r--r--lib/libc/rpc/getrpcport.329
-rw-r--r--lib/libc/rpc/getrpcport.c63
-rw-r--r--lib/libc/rpc/key_call.c425
-rw-r--r--lib/libc/rpc/key_prot_xdr.c166
-rw-r--r--lib/libc/rpc/netname.c136
-rw-r--r--lib/libc/rpc/netnamer.c327
-rw-r--r--lib/libc/rpc/pmap_clnt.c149
-rw-r--r--lib/libc/rpc/pmap_getmaps.c86
-rw-r--r--lib/libc/rpc/pmap_getport.c91
-rw-r--r--lib/libc/rpc/pmap_prot.c59
-rw-r--r--lib/libc/rpc/pmap_prot2.c118
-rw-r--r--lib/libc/rpc/pmap_rmt.c415
-rw-r--r--lib/libc/rpc/publickey.344
-rw-r--r--lib/libc/rpc/publickey.537
-rw-r--r--lib/libc/rpc/rpc.31737
-rw-r--r--lib/libc/rpc/rpc.534
-rw-r--r--lib/libc/rpc/rpc_callmsg.c193
-rw-r--r--lib/libc/rpc/rpc_commondata.c43
-rw-r--r--lib/libc/rpc/rpc_dtablesize.c61
-rw-r--r--lib/libc/rpc/rpc_prot.c297
-rw-r--r--lib/libc/rpc/rpc_secure.3330
-rw-r--r--lib/libc/rpc/rpcdname.c77
-rw-r--r--lib/libc/rpc/rstat.157
-rw-r--r--lib/libc/rpc/rstat_svc.821
-rw-r--r--lib/libc/rpc/rtime.343
-rw-r--r--lib/libc/rpc/rtime.c157
-rw-r--r--lib/libc/rpc/svc.c494
-rw-r--r--lib/libc/rpc/svc_auth.c211
-rw-r--r--lib/libc/rpc/svc_auth_des.c531
-rw-r--r--lib/libc/rpc/svc_auth_unix.c148
-rw-r--r--lib/libc/rpc/svc_raw.c168
-rw-r--r--lib/libc/rpc/svc_run.c87
-rw-r--r--lib/libc/rpc/svc_simple.c150
-rw-r--r--lib/libc/rpc/svc_tcp.c448
-rw-r--r--lib/libc/rpc/svc_udp.c480
-rw-r--r--lib/libc/rpc/svc_unix.c511
-rw-r--r--lib/libc/stdio/Makefile.inc26
-rw-r--r--lib/libc/stdio/asprintf.c59
-rw-r--r--lib/libc/stdio/clrerr.c14
-rw-r--r--lib/libc/stdio/fclose.c16
-rw-r--r--lib/libc/stdio/feof.c5
-rw-r--r--lib/libc/stdio/ferror.c5
-rw-r--r--lib/libc/stdio/fflush.32
-rw-r--r--lib/libc/stdio/fflush.c23
-rw-r--r--lib/libc/stdio/fgetc.c19
-rw-r--r--lib/libc/stdio/fgetln.33
-rw-r--r--lib/libc/stdio/fgetln.c9
-rw-r--r--lib/libc/stdio/fgetpos.c19
-rw-r--r--lib/libc/stdio/fgets.321
-rw-r--r--lib/libc/stdio/fgets.c28
-rw-r--r--lib/libc/stdio/fileno.c5
-rw-r--r--lib/libc/stdio/findfp.c10
-rw-r--r--lib/libc/stdio/flags.c8
-rw-r--r--lib/libc/stdio/fopen.310
-rw-r--r--lib/libc/stdio/fprintf.c5
-rw-r--r--lib/libc/stdio/fpurge.c32
-rw-r--r--lib/libc/stdio/fputc.c19
-rw-r--r--lib/libc/stdio/fputs.32
-rw-r--r--lib/libc/stdio/fputs.c19
-rw-r--r--lib/libc/stdio/fread.36
-rw-r--r--lib/libc/stdio/fread.c15
-rw-r--r--lib/libc/stdio/freopen.c4
-rw-r--r--lib/libc/stdio/fscanf.c16
-rw-r--r--lib/libc/stdio/fseek.32
-rw-r--r--lib/libc/stdio/fseek.c33
-rw-r--r--lib/libc/stdio/fsetpos.c5
-rw-r--r--lib/libc/stdio/ftell.c20
-rw-r--r--lib/libc/stdio/funopen.37
-rw-r--r--lib/libc/stdio/fvwrite.c5
-rw-r--r--lib/libc/stdio/fwalk.c7
-rw-r--r--lib/libc/stdio/fwrite.c20
-rw-r--r--lib/libc/stdio/getc.310
-rw-r--r--lib/libc/stdio/getc.c19
-rw-r--r--lib/libc/stdio/getchar.c19
-rw-r--r--lib/libc/stdio/gets.c9
-rw-r--r--lib/libc/stdio/getw.c5
-rw-r--r--lib/libc/stdio/mktemp.322
-rw-r--r--lib/libc/stdio/mktemp.c15
-rw-r--r--lib/libc/stdio/perror.c2
-rw-r--r--lib/libc/stdio/printf.3102
-rw-r--r--lib/libc/stdio/printf.c5
-rw-r--r--lib/libc/stdio/putc.c19
-rw-r--r--lib/libc/stdio/putchar.c19
-rw-r--r--lib/libc/stdio/puts.c19
-rw-r--r--lib/libc/stdio/putw.c19
-rw-r--r--lib/libc/stdio/refill.c11
-rw-r--r--lib/libc/stdio/remove.c5
-rw-r--r--lib/libc/stdio/rewind.c14
-rw-r--r--lib/libc/stdio/rget.c10
-rw-r--r--lib/libc/stdio/scanf.321
-rw-r--r--lib/libc/stdio/scanf.c16
-rw-r--r--lib/libc/stdio/setbuf.38
-rw-r--r--lib/libc/stdio/setbuffer.c6
-rw-r--r--lib/libc/stdio/setvbuf.c18
-rw-r--r--lib/libc/stdio/snprintf.c7
-rw-r--r--lib/libc/stdio/sprintf.c6
-rw-r--r--lib/libc/stdio/sscanf.c9
-rw-r--r--lib/libc/stdio/stdio.338
-rw-r--r--lib/libc/stdio/stdio.c17
-rw-r--r--lib/libc/stdio/tempnam.c17
-rw-r--r--lib/libc/stdio/tmpnam.32
-rw-r--r--lib/libc/stdio/ungetc.32
-rw-r--r--lib/libc/stdio/ungetc.c45
-rw-r--r--lib/libc/stdio/vasprintf.c119
-rw-r--r--lib/libc/stdio/vfprintf.c509
-rw-r--r--lib/libc/stdio/vfscanf.c92
-rw-r--r--lib/libc/stdio/vprintf.c5
-rw-r--r--lib/libc/stdio/vscanf.c19
-rw-r--r--lib/libc/stdio/vsnprintf.c6
-rw-r--r--lib/libc/stdio/vsprintf.c6
-rw-r--r--lib/libc/stdio/vsscanf.c10
-rw-r--r--lib/libc/stdio/wbuf.c5
-rw-r--r--lib/libc/stdio/wsetup.c5
-rw-r--r--lib/libc/stdlib/Makefile.inc32
-rw-r--r--lib/libc/stdlib/abort.38
-rw-r--r--lib/libc/stdlib/abort.c23
-rw-r--r--lib/libc/stdlib/abs.37
-rw-r--r--lib/libc/stdlib/alloca.34
-rw-r--r--lib/libc/stdlib/atexit.c3
-rw-r--r--lib/libc/stdlib/atoi.c1
-rw-r--r--lib/libc/stdlib/bsearch.32
-rw-r--r--lib/libc/stdlib/calloc.c2
-rw-r--r--lib/libc/stdlib/exit.36
-rw-r--r--lib/libc/stdlib/getenv.c44
-rw-r--r--lib/libc/stdlib/getopt.316
-rw-r--r--lib/libc/stdlib/getsubopt.33
-rw-r--r--lib/libc/stdlib/getsubopt.c3
-rw-r--r--lib/libc/stdlib/heapsort.c3
-rw-r--r--lib/libc/stdlib/labs.32
-rw-r--r--lib/libc/stdlib/ldiv.32
-rw-r--r--lib/libc/stdlib/malloc.3393
-rw-r--r--lib/libc/stdlib/malloc.c1410
-rw-r--r--lib/libc/stdlib/memory.35
-rw-r--r--lib/libc/stdlib/merge.c4
-rw-r--r--lib/libc/stdlib/qsort.c34
-rw-r--r--lib/libc/stdlib/radixsort.37
-rw-r--r--lib/libc/stdlib/radixsort.c10
-rw-r--r--lib/libc/stdlib/random.353
-rw-r--r--lib/libc/stdlib/random.c106
-rw-r--r--lib/libc/stdlib/realpath.32
-rw-r--r--lib/libc/stdlib/realpath.c2
-rw-r--r--lib/libc/stdlib/setenv.c7
-rw-r--r--lib/libc/stdlib/strhash.c436
-rw-r--r--lib/libc/stdlib/strtod.c72
-rw-r--r--lib/libc/stdlib/strtol.34
-rw-r--r--lib/libc/stdlib/strtol.c6
-rw-r--r--lib/libc/stdlib/strtoll.c138
-rw-r--r--lib/libc/stdlib/strtoq.c6
-rw-r--r--lib/libc/stdlib/strtoul.c6
-rw-r--r--lib/libc/stdlib/strtoull.c116
-rw-r--r--lib/libc/stdlib/strtouq.c8
-rw-r--r--lib/libc/stdlib/system.35
-rw-r--r--lib/libc/stdlib/system.c52
-rw-r--r--lib/libc/stdtime/Makefile.inc16
-rw-r--r--lib/libc/stdtime/asctime.c61
-rw-r--r--lib/libc/stdtime/ctime.3257
-rw-r--r--lib/libc/stdtime/difftime.c77
-rw-r--r--lib/libc/stdtime/localtime.c1754
-rw-r--r--lib/libc/stdtime/private.h218
-rw-r--r--lib/libc/stdtime/strftime.3212
-rw-r--r--lib/libc/stdtime/strftime.c574
-rw-r--r--lib/libc/stdtime/time2posix.3114
-rw-r--r--lib/libc/stdtime/tzfile.5122
-rw-r--r--lib/libc/stdtime/tzfile.h187
-rw-r--r--lib/libc/string/Makefile.inc61
-rw-r--r--lib/libc/string/memccpy.33
-rw-r--r--lib/libc/string/memccpy.c5
-rw-r--r--lib/libc/string/memcmp.33
-rw-r--r--lib/libc/string/memset.c2
-rw-r--r--lib/libc/string/strcasecmp.33
-rw-r--r--lib/libc/string/strcasecmp.c53
-rw-r--r--lib/libc/string/strcat.35
-rw-r--r--lib/libc/string/strcmp.c2
-rw-r--r--lib/libc/string/strcoll.36
-rw-r--r--lib/libc/string/strcoll.c77
-rw-r--r--lib/libc/string/strdup.36
-rw-r--r--lib/libc/string/strdup.c6
-rw-r--r--lib/libc/string/strerror.318
-rw-r--r--lib/libc/string/strerror.c14
-rw-r--r--lib/libc/string/string.313
-rw-r--r--lib/libc/string/strmode.33
-rw-r--r--lib/libc/string/strncmp.c3
-rw-r--r--lib/libc/string/strsep.35
-rw-r--r--lib/libc/string/strsep.c2
-rw-r--r--lib/libc/string/strspn.32
-rw-r--r--lib/libc/string/strxfrm.327
-rw-r--r--lib/libc/string/strxfrm.c99
-rw-r--r--lib/libc/sys/Makefile.inc184
-rw-r--r--lib/libc/sys/_exit.214
-rw-r--r--lib/libc/sys/accept.228
-rw-r--r--lib/libc/sys/access.215
-rw-r--r--lib/libc/sys/acct.27
-rw-r--r--lib/libc/sys/adjtime.26
-rw-r--r--lib/libc/sys/bind.232
-rw-r--r--lib/libc/sys/brk.232
-rw-r--r--lib/libc/sys/chdir.214
-rw-r--r--lib/libc/sys/chflags.219
-rw-r--r--lib/libc/sys/chmod.229
-rw-r--r--lib/libc/sys/chown.247
-rw-r--r--lib/libc/sys/chroot.26
-rw-r--r--lib/libc/sys/clock_gettime.2124
-rw-r--r--lib/libc/sys/close.243
-rw-r--r--lib/libc/sys/connect.239
-rw-r--r--lib/libc/sys/dup.292
-rw-r--r--lib/libc/sys/execve.243
-rw-r--r--lib/libc/sys/fcntl.281
-rw-r--r--lib/libc/sys/flock.240
-rw-r--r--lib/libc/sys/fork.227
-rw-r--r--lib/libc/sys/fsync.228
-rw-r--r--lib/libc/sys/ftruncate.c16
-rw-r--r--lib/libc/sys/getdirentries.250
-rw-r--r--lib/libc/sys/getfh.212
-rw-r--r--lib/libc/sys/getfsstat.246
-rw-r--r--lib/libc/sys/getgid.213
-rw-r--r--lib/libc/sys/getgroups.22
-rw-r--r--lib/libc/sys/getitimer.27
-rw-r--r--lib/libc/sys/getlogin.259
-rw-r--r--lib/libc/sys/getpeername.232
-rw-r--r--lib/libc/sys/getpgrp.219
-rw-r--r--lib/libc/sys/getpid.215
-rw-r--r--lib/libc/sys/getpriority.22
-rw-r--r--lib/libc/sys/getrlimit.222
-rw-r--r--lib/libc/sys/getrusage.223
-rw-r--r--lib/libc/sys/getsockname.229
-rw-r--r--lib/libc/sys/getsockopt.268
-rw-r--r--lib/libc/sys/gettimeofday.211
-rw-r--r--lib/libc/sys/getuid.220
-rw-r--r--lib/libc/sys/intro.290
-rw-r--r--lib/libc/sys/ioctl.231
-rw-r--r--lib/libc/sys/issetugid.294
-rw-r--r--lib/libc/sys/kill.214
-rw-r--r--lib/libc/sys/ktrace.213
-rw-r--r--lib/libc/sys/link.226
-rw-r--r--lib/libc/sys/listen.257
-rw-r--r--lib/libc/sys/lseek.216
-rw-r--r--lib/libc/sys/lseek.c17
-rw-r--r--lib/libc/sys/madvise.289
-rw-r--r--lib/libc/sys/mincore.237
-rw-r--r--lib/libc/sys/minherit.294
-rw-r--r--lib/libc/sys/mkdir.212
-rw-r--r--lib/libc/sys/mkfifo.29
-rw-r--r--lib/libc/sys/mknod.228
-rw-r--r--lib/libc/sys/mlock.225
-rw-r--r--lib/libc/sys/mmap.275
-rw-r--r--lib/libc/sys/mount.249
-rw-r--r--lib/libc/sys/mprotect.239
-rw-r--r--lib/libc/sys/msync.243
-rw-r--r--lib/libc/sys/munmap.216
-rw-r--r--lib/libc/sys/nanosleep.2119
-rw-r--r--lib/libc/sys/nfssvc.242
-rw-r--r--lib/libc/sys/open.240
-rw-r--r--lib/libc/sys/pathconf.219
-rw-r--r--lib/libc/sys/pipe.228
-rw-r--r--lib/libc/sys/profil.217
-rw-r--r--lib/libc/sys/ptrace.2293
-rw-r--r--lib/libc/sys/quotactl.27
-rw-r--r--lib/libc/sys/read.265
-rw-r--r--lib/libc/sys/readlink.216
-rw-r--r--lib/libc/sys/reboot.210
-rw-r--r--lib/libc/sys/recv.232
-rw-r--r--lib/libc/sys/rename.212
-rw-r--r--lib/libc/sys/revoke.29
-rw-r--r--lib/libc/sys/rfork.2137
-rw-r--r--lib/libc/sys/rmdir.24
-rw-r--r--lib/libc/sys/rtprio.2108
-rw-r--r--lib/libc/sys/select.244
-rw-r--r--lib/libc/sys/semctl.2173
-rw-r--r--lib/libc/sys/semget.2137
-rw-r--r--lib/libc/sys/semop.2192
-rw-r--r--lib/libc/sys/send.238
-rw-r--r--lib/libc/sys/setgroups.22
-rw-r--r--lib/libc/sys/setpgid.27
-rw-r--r--lib/libc/sys/setregid.292
-rw-r--r--lib/libc/sys/setreuid.290
-rw-r--r--lib/libc/sys/setsid.225
-rw-r--r--lib/libc/sys/setuid.245
-rw-r--r--lib/libc/sys/shmat.2110
-rw-r--r--lib/libc/sys/shmctl.2136
-rw-r--r--lib/libc/sys/shmget.2138
-rw-r--r--lib/libc/sys/shutdown.25
-rw-r--r--lib/libc/sys/sigaction.260
-rw-r--r--lib/libc/sys/sigaltstack.217
-rw-r--r--lib/libc/sys/sigpending.210
-rw-r--r--lib/libc/sys/sigprocmask.28
-rw-r--r--lib/libc/sys/sigreturn.232
-rw-r--r--lib/libc/sys/sigstack.22
-rw-r--r--lib/libc/sys/sigsuspend.210
-rw-r--r--lib/libc/sys/socket.242
-rw-r--r--lib/libc/sys/socketpair.28
-rw-r--r--lib/libc/sys/stat.267
-rw-r--r--lib/libc/sys/statfs.249
-rw-r--r--lib/libc/sys/swapon.28
-rw-r--r--lib/libc/sys/symlink.215
-rw-r--r--lib/libc/sys/sync.211
-rw-r--r--lib/libc/sys/syscall.210
-rw-r--r--lib/libc/sys/truncate.217
-rw-r--r--lib/libc/sys/truncate.c4
-rw-r--r--lib/libc/sys/umask.210
-rw-r--r--lib/libc/sys/unlink.221
-rw-r--r--lib/libc/sys/utimes.26
-rw-r--r--lib/libc/sys/vfork.237
-rw-r--r--lib/libc/sys/wait.214
-rw-r--r--lib/libc/sys/write.267
-rw-r--r--lib/libc/xdr/Makefile.inc44
-rw-r--r--lib/libc/xdr/xdr.3825
-rw-r--r--lib/libc/xdr/xdr.c719
-rw-r--r--lib/libc/xdr/xdr_array.c155
-rw-r--r--lib/libc/xdr/xdr_float.c314
-rw-r--r--lib/libc/xdr/xdr_mem.c242
-rw-r--r--lib/libc/xdr/xdr_rec.c586
-rw-r--r--lib/libc/xdr/xdr_reference.c136
-rw-r--r--lib/libc/xdr/xdr_sizeof.c163
-rw-r--r--lib/libc/xdr/xdr_stdio.c189
-rw-r--r--lib/libc/yp/Makefile.inc17
-rw-r--r--lib/libc/yp/xdryp.c119
-rw-r--r--lib/libc/yp/yplib.c1033
-rw-r--r--lib/libc_r/Makefile21
-rw-r--r--lib/libc_r/man/Makefile.inc17
-rw-r--r--lib/libc_r/man/pthread_create.3109
-rw-r--r--lib/libc_r/man/pthread_detach.379
-rw-r--r--lib/libc_r/man/pthread_equal.366
-rw-r--r--lib/libc_r/man/pthread_exit.399
-rw-r--r--lib/libc_r/man/pthread_getspecific.382
-rw-r--r--lib/libc_r/man/pthread_join.3100
-rw-r--r--lib/libc_r/man/pthread_key_create.398
-rw-r--r--lib/libc_r/man/pthread_key_delete.392
-rw-r--r--lib/libc_r/man/pthread_once.3100
-rw-r--r--lib/libc_r/man/pthread_self.359
-rw-r--r--lib/libc_r/man/pthread_setspecific.391
-rw-r--r--lib/libc_r/sys/Makefile.inc5
-rw-r--r--lib/libc_r/sys/__error.c50
-rw-r--r--lib/libc_r/uthread/Makefile.inc93
-rw-r--r--lib/libc_r/uthread/pthread_private.h783
-rw-r--r--lib/libc_r/uthread/uthread_accept.c97
-rw-r--r--lib/libc_r/uthread/uthread_attr_destroy.c60
-rw-r--r--lib/libc_r/uthread/uthread_attr_getdetachstate.c57
-rw-r--r--lib/libc_r/uthread/uthread_attr_getstackaddr.c52
-rw-r--r--lib/libc_r/uthread/uthread_attr_getstacksize.c52
-rw-r--r--lib/libc_r/uthread/uthread_attr_init.c59
-rw-r--r--lib/libc_r/uthread/uthread_attr_setcreatesuspend.c0
-rw-r--r--lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c51
-rw-r--r--lib/libc_r/uthread/uthread_attr_setdetachstate.c59
-rw-r--r--lib/libc_r/uthread/uthread_attr_setprio.c50
-rw-r--r--lib/libc_r/uthread/uthread_attr_setstackaddr.c52
-rw-r--r--lib/libc_r/uthread/uthread_attr_setstacksize.c52
-rw-r--r--lib/libc_r/uthread/uthread_autoinit.cc88
-rw-r--r--lib/libc_r/uthread/uthread_bind.c50
-rw-r--r--lib/libc_r/uthread/uthread_clean.c68
-rw-r--r--lib/libc_r/uthread/uthread_close.c96
-rw-r--r--lib/libc_r/uthread/uthread_cond.c347
-rw-r--r--lib/libc_r/uthread/uthread_condattr_destroy.c52
-rw-r--r--lib/libc_r/uthread/uthread_condattr_init.c58
-rw-r--r--lib/libc_r/uthread/uthread_connect.c76
-rw-r--r--lib/libc_r/uthread/uthread_create.c280
-rw-r--r--lib/libc_r/uthread/uthread_detach.c83
-rw-r--r--lib/libc_r/uthread/uthread_dup.c37
-rw-r--r--lib/libc_r/uthread/uthread_dup2.c74
-rw-r--r--lib/libc_r/uthread/uthread_equal.c43
-rw-r--r--lib/libc_r/uthread/uthread_execve.c112
-rw-r--r--lib/libc_r/uthread/uthread_exit.c205
-rw-r--r--lib/libc_r/uthread/uthread_fchmod.c50
-rw-r--r--lib/libc_r/uthread/uthread_fchown.c51
-rw-r--r--lib/libc_r/uthread/uthread_fcntl.c116
-rw-r--r--lib/libc_r/uthread/uthread_fd.c405
-rw-r--r--lib/libc_r/uthread/uthread_file.c125
-rw-r--r--lib/libc_r/uthread/uthread_flock.c49
-rw-r--r--lib/libc_r/uthread/uthread_fork.c92
-rw-r--r--lib/libc_r/uthread/uthread_fstat.c57
-rw-r--r--lib/libc_r/uthread/uthread_fstatfs.c57
-rw-r--r--lib/libc_r/uthread/uthread_fsync.c49
-rw-r--r--lib/libc_r/uthread/uthread_getdirentries.c50
-rw-r--r--lib/libc_r/uthread/uthread_getpeername.c50
-rw-r--r--lib/libc_r/uthread/uthread_getprio.c73
-rw-r--r--lib/libc_r/uthread/uthread_getsockname.c50
-rw-r--r--lib/libc_r/uthread/uthread_getsockopt.c50
-rw-r--r--lib/libc_r/uthread/uthread_info.c182
-rw-r--r--lib/libc_r/uthread/uthread_init.c228
-rw-r--r--lib/libc_r/uthread/uthread_ioctl.c53
-rw-r--r--lib/libc_r/uthread/uthread_join.c116
-rw-r--r--lib/libc_r/uthread/uthread_kern.c1739
-rw-r--r--lib/libc_r/uthread/uthread_kill.c78
-rw-r--r--lib/libc_r/uthread/uthread_listen.c50
-rw-r--r--lib/libc_r/uthread/uthread_longjmp.c45
-rw-r--r--lib/libc_r/uthread/uthread_mattr_init.c58
-rw-r--r--lib/libc_r/uthread/uthread_mattr_kind_np.c64
-rw-r--r--lib/libc_r/uthread/uthread_multi_np.c44
-rw-r--r--lib/libc_r/uthread/uthread_mutex.c393
-rw-r--r--lib/libc_r/uthread/uthread_mutexattr_destroy.c52
-rw-r--r--lib/libc_r/uthread/uthread_nanosleep.c118
-rw-r--r--lib/libc_r/uthread/uthread_once.c50
-rw-r--r--lib/libc_r/uthread/uthread_open.c80
-rw-r--r--lib/libc_r/uthread/uthread_pipe.c53
-rw-r--r--lib/libc_r/uthread/uthread_queue.c124
-rw-r--r--lib/libc_r/uthread/uthread_read.c83
-rw-r--r--lib/libc_r/uthread/uthread_readv.c83
-rw-r--r--lib/libc_r/uthread/uthread_recvfrom.c70
-rw-r--r--lib/libc_r/uthread/uthread_resume.c0
-rw-r--r--lib/libc_r/uthread/uthread_resume_np.c70
-rw-r--r--lib/libc_r/uthread/uthread_select.c172
-rw-r--r--lib/libc_r/uthread/uthread_self.c43
-rw-r--r--lib/libc_r/uthread/uthread_sendto.c63
-rw-r--r--lib/libc_r/uthread/uthread_seterrno.c61
-rw-r--r--lib/libc_r/uthread/uthread_setjmp.c44
-rw-r--r--lib/libc_r/uthread/uthread_setprio.c80
-rw-r--r--lib/libc_r/uthread/uthread_setsockopt.c50
-rw-r--r--lib/libc_r/uthread/uthread_shutdown.c71
-rw-r--r--lib/libc_r/uthread/uthread_sig.c167
-rw-r--r--lib/libc_r/uthread/uthread_sigaction.c82
-rw-r--r--lib/libc_r/uthread/uthread_sigblock.c48
-rw-r--r--lib/libc_r/uthread/uthread_sigmask.c92
-rw-r--r--lib/libc_r/uthread/uthread_signal.c57
-rw-r--r--lib/libc_r/uthread/uthread_sigprocmask.c92
-rw-r--r--lib/libc_r/uthread/uthread_sigsetmask.c48
-rw-r--r--lib/libc_r/uthread/uthread_sigsuspend.c66
-rw-r--r--lib/libc_r/uthread/uthread_sigwait.c73
-rw-r--r--lib/libc_r/uthread/uthread_single_np.c44
-rw-r--r--lib/libc_r/uthread/uthread_socket.c57
-rw-r--r--lib/libc_r/uthread/uthread_socketpair.c55
-rw-r--r--lib/libc_r/uthread/uthread_spec.c237
-rw-r--r--lib/libc_r/uthread/uthread_suspend.c0
-rw-r--r--lib/libc_r/uthread/uthread_suspend_np.c67
-rw-r--r--lib/libc_r/uthread/uthread_wait4.c61
-rw-r--r--lib/libc_r/uthread/uthread_write.c83
-rw-r--r--lib/libc_r/uthread/uthread_writev.c83
-rw-r--r--lib/libc_r/uthread/uthread_yield.c49
-rw-r--r--lib/libcom_err/Makefile14
-rw-r--r--lib/libcom_err/com_err.396
-rw-r--r--lib/libcom_err/com_err.c111
-rw-r--r--lib/libcom_err/com_err.h36
-rw-r--r--lib/libcom_err/doc/Makefile7
-rw-r--r--lib/libcom_err/doc/com_err.texinfo616
-rw-r--r--lib/libcom_err/error_message.c72
-rw-r--r--lib/libcom_err/error_table.h30
-rw-r--r--lib/libcom_err/et_name.c43
-rw-r--r--lib/libcom_err/init_et.c55
-rw-r--r--lib/libcom_err/internal.h18
-rw-r--r--lib/libcom_err/mit-sipb-copyright.h19
-rw-r--r--lib/libcom_err/test/test.c47
-rw-r--r--lib/libcom_err/test/test1.et69
-rw-r--r--lib/libcom_err/test/test2.et9
-rw-r--r--lib/libcompat/4.1/ascftime.c52
-rw-r--r--lib/libcompat/4.1/cftime.399
-rw-r--r--lib/libcompat/4.1/cftime.c53
-rw-r--r--lib/libcompat/4.1/ftime.36
-rw-r--r--lib/libcompat/4.1/ftime.c54
-rw-r--r--lib/libcompat/4.1/getpw.312
-rw-r--r--lib/libcompat/4.1/getpw.c58
-rw-r--r--lib/libcompat/4.1/gtty.c52
-rw-r--r--lib/libcompat/4.1/stty.32
-rw-r--r--lib/libcompat/4.1/stty.c52
-rw-r--r--lib/libcompat/4.1/vlimit.34
-rw-r--r--lib/libcompat/4.1/vtimes.36
-rw-r--r--lib/libcompat/4.3/cfree.349
-rw-r--r--lib/libcompat/4.3/cfree.c2
-rw-r--r--lib/libcompat/4.3/insque.312
-rw-r--r--lib/libcompat/4.3/insque.c1
-rw-r--r--lib/libcompat/4.3/lsearch.31
-rw-r--r--lib/libcompat/4.3/lsearch.c1
-rw-r--r--lib/libcompat/4.3/re_comp.33
-rw-r--r--lib/libcompat/4.3/regex.c (renamed from lib/libc/db/btree/bt_stack.c)98
-rw-r--r--lib/libcompat/4.3/remque.c1
-rw-r--r--lib/libcompat/4.3/rexec.311
-rw-r--r--lib/libcompat/4.3/rexec.c249
-rw-r--r--lib/libcompat/4.4/cuserid.382
-rw-r--r--lib/libcompat/Makefile38
-rw-r--r--lib/libcompat/SysV/ftok.385
-rw-r--r--lib/libcompat/SysV/ftok.c47
-rw-r--r--lib/libcompat/regexp/regexp.34
-rw-r--r--lib/libcompat/regexp/regexp.c39
-rw-r--r--lib/libcrypt/Makefile41
-rw-r--r--lib/libcrypt/crypt.c157
-rw-r--r--lib/libcurses/EXAMPLES/ex1.c10
-rw-r--r--lib/libcurses/Makefile16
-rw-r--r--lib/libcurses/PSD.doc/appenA77
-rw-r--r--lib/libcurses/PSD.doc/ex1.c10
-rw-r--r--lib/libcurses/PSD.doc/ex2.c4
-rw-r--r--lib/libcurses/PSD.doc/life.c2
-rw-r--r--lib/libcurses/_putchar.c47
-rw-r--r--lib/libcurses/addbytes.c6
-rw-r--r--lib/libcurses/clrtoeol.c2
-rw-r--r--lib/libcurses/cr_put.c33
-rw-r--r--lib/libcurses/cur_hash.c6
-rw-r--r--lib/libcurses/curses.326
-rw-r--r--lib/libcurses/curses.c14
-rw-r--r--lib/libcurses/curses.h94
-rw-r--r--lib/libcurses/deleteln.c4
-rw-r--r--lib/libcurses/erase.c2
-rw-r--r--lib/libcurses/getch.c12
-rw-r--r--lib/libcurses/getstr.c14
-rw-r--r--lib/libcurses/id_subwins.c2
-rw-r--r--lib/libcurses/initscr.c2
-rw-r--r--lib/libcurses/insch.c2
-rw-r--r--lib/libcurses/insertln.c6
-rw-r--r--lib/libcurses/newwin.c23
-rw-r--r--lib/libcurses/overlay.c2
-rw-r--r--lib/libcurses/overwrite.c2
-rw-r--r--lib/libcurses/refresh.c349
-rw-r--r--lib/libcurses/scanw.c2
-rw-r--r--lib/libcurses/setterm.c35
-rw-r--r--lib/libcurses/standout.c23
-rw-r--r--lib/libcurses/tscroll.c5
-rw-r--r--lib/libcurses/tstp.c12
-rw-r--r--lib/libcurses/tty.c83
-rw-r--r--lib/libcurses/unctrl.c2
-rw-r--r--lib/libdisk/Makefile60
-rw-r--r--lib/libdisk/blocks.c41
-rw-r--r--lib/libdisk/change.c82
-rw-r--r--lib/libdisk/chunk.c434
-rw-r--r--lib/libdisk/create_chunk.c358
-rw-r--r--lib/libdisk/disk.c386
-rw-r--r--lib/libdisk/disklabel.c33
-rw-r--r--lib/libdisk/libdisk.3339
-rw-r--r--lib/libdisk/libdisk.h326
-rw-r--r--lib/libdisk/rules.c316
-rw-r--r--lib/libdisk/tst01.c296
-rw-r--r--lib/libdisk/write_disk.c233
-rw-r--r--lib/libedit/Makefile40
-rw-r--r--lib/libedit/TEST/test.c72
-rw-r--r--lib/libedit/chared.c78
-rw-r--r--lib/libedit/chared.h6
-rw-r--r--lib/libedit/common.c156
-rw-r--r--lib/libedit/editline.3532
-rw-r--r--lib/libedit/editrc.5292
-rw-r--r--lib/libedit/el.c25
-rw-r--r--lib/libedit/emacs.c64
-rw-r--r--lib/libedit/hist.c2
-rw-r--r--lib/libedit/hist.h2
-rw-r--r--lib/libedit/history.c179
-rw-r--r--lib/libedit/key.c54
-rw-r--r--lib/libedit/key.h4
-rw-r--r--lib/libedit/map.c52
-rw-r--r--lib/libedit/map.h2
-rw-r--r--lib/libedit/parse.c23
-rw-r--r--lib/libedit/parse.h2
-rw-r--r--lib/libedit/prompt.c6
-rw-r--r--lib/libedit/read.c25
-rw-r--r--lib/libedit/refresh.c84
-rw-r--r--lib/libedit/search.c119
-rw-r--r--lib/libedit/search.h4
-rw-r--r--lib/libedit/sig.c10
-rw-r--r--lib/libedit/sys.h4
-rw-r--r--lib/libedit/term.c191
-rw-r--r--lib/libedit/term.h4
-rw-r--r--lib/libedit/tokenizer.c10
-rw-r--r--lib/libedit/tokenizer.h2
-rw-r--r--lib/libedit/tty.c84
-rw-r--r--lib/libedit/tty.h15
-rw-r--r--lib/libedit/vi.c130
-rw-r--r--lib/libf2c/Makefile38
-rw-r--r--lib/libftpio/Makefile28
-rw-r--r--lib/libftpio/ftp.errors44
-rw-r--r--lib/libftpio/ftpio.3198
-rw-r--r--lib/libftpio/ftpio.c865
-rw-r--r--lib/libftpio/ftpio.h68
-rw-r--r--lib/libgnumalloc/Makefile30
-rw-r--r--lib/libgnumalloc/cfree.c5
-rw-r--r--lib/libipx/Makefile9
-rw-r--r--lib/libipx/ipx.3125
-rw-r--r--lib/libipx/ipx_addr.c227
-rw-r--r--lib/libipx/ipx_ntoa.c98
-rw-r--r--lib/libkse/Makefile21
-rw-r--r--lib/libkse/sys/Makefile.inc5
-rw-r--r--lib/libkse/thread/Makefile.inc93
-rw-r--r--lib/libkse/thread/thr_attr_destroy.c60
-rw-r--r--lib/libkse/thread/thr_attr_getdetachstate.c57
-rw-r--r--lib/libkse/thread/thr_attr_getstackaddr.c52
-rw-r--r--lib/libkse/thread/thr_attr_getstacksize.c52
-rw-r--r--lib/libkse/thread/thr_attr_init.c59
-rw-r--r--lib/libkse/thread/thr_attr_setcreatesuspend_np.c51
-rw-r--r--lib/libkse/thread/thr_attr_setdetachstate.c59
-rw-r--r--lib/libkse/thread/thr_attr_setstackaddr.c52
-rw-r--r--lib/libkse/thread/thr_attr_setstacksize.c52
-rw-r--r--lib/libkse/thread/thr_clean.c68
-rw-r--r--lib/libkse/thread/thr_close.c96
-rw-r--r--lib/libkse/thread/thr_cond.c347
-rw-r--r--lib/libkse/thread/thr_condattr_destroy.c52
-rw-r--r--lib/libkse/thread/thr_condattr_init.c58
-rw-r--r--lib/libkse/thread/thr_create.c280
-rw-r--r--lib/libkse/thread/thr_detach.c83
-rw-r--r--lib/libkse/thread/thr_equal.c43
-rw-r--r--lib/libkse/thread/thr_exit.c205
-rw-r--r--lib/libkse/thread/thr_fcntl.c116
-rw-r--r--lib/libkse/thread/thr_fork.c92
-rw-r--r--lib/libkse/thread/thr_fsync.c49
-rw-r--r--lib/libkse/thread/thr_getprio.c73
-rw-r--r--lib/libkse/thread/thr_info.c182
-rw-r--r--lib/libkse/thread/thr_init.c228
-rw-r--r--lib/libkse/thread/thr_join.c116
-rw-r--r--lib/libkse/thread/thr_kern.c1739
-rw-r--r--lib/libkse/thread/thr_kill.c78
-rw-r--r--lib/libkse/thread/thr_mattr_init.c58
-rw-r--r--lib/libkse/thread/thr_mattr_kind_np.c64
-rw-r--r--lib/libkse/thread/thr_multi_np.c44
-rw-r--r--lib/libkse/thread/thr_mutex.c393
-rw-r--r--lib/libkse/thread/thr_mutexattr_destroy.c52
-rw-r--r--lib/libkse/thread/thr_nanosleep.c118
-rw-r--r--lib/libkse/thread/thr_once.c50
-rw-r--r--lib/libkse/thread/thr_open.c80
-rw-r--r--lib/libkse/thread/thr_private.h783
-rw-r--r--lib/libkse/thread/thr_read.c83
-rw-r--r--lib/libkse/thread/thr_readv.c83
-rw-r--r--lib/libkse/thread/thr_resume_np.c70
-rw-r--r--lib/libkse/thread/thr_select.c172
-rw-r--r--lib/libkse/thread/thr_self.c43
-rw-r--r--lib/libkse/thread/thr_seterrno.c61
-rw-r--r--lib/libkse/thread/thr_setprio.c80
-rw-r--r--lib/libkse/thread/thr_sig.c167
-rw-r--r--lib/libkse/thread/thr_sigaction.c82
-rw-r--r--lib/libkse/thread/thr_sigmask.c92
-rw-r--r--lib/libkse/thread/thr_sigprocmask.c92
-rw-r--r--lib/libkse/thread/thr_sigsuspend.c66
-rw-r--r--lib/libkse/thread/thr_sigwait.c73
-rw-r--r--lib/libkse/thread/thr_single_np.c44
-rw-r--r--lib/libkse/thread/thr_spec.c237
-rw-r--r--lib/libkse/thread/thr_suspend_np.c67
-rw-r--r--lib/libkse/thread/thr_wait4.c61
-rw-r--r--lib/libkse/thread/thr_write.c83
-rw-r--r--lib/libkse/thread/thr_writev.c83
-rw-r--r--lib/libkse/thread/thr_yield.c49
-rw-r--r--lib/libkvm/Makefile6
-rw-r--r--lib/libkvm/kvm.34
-rw-r--r--lib/libkvm/kvm.c37
-rw-r--r--lib/libkvm/kvm.h73
-rw-r--r--lib/libkvm/kvm_amd64.c181
-rw-r--r--lib/libkvm/kvm_file.c15
-rw-r--r--lib/libkvm/kvm_getfiles.39
-rw-r--r--lib/libkvm/kvm_getloadavg.38
-rw-r--r--lib/libkvm/kvm_getloadavg.c1
-rw-r--r--lib/libkvm/kvm_getprocs.319
-rw-r--r--lib/libkvm/kvm_hp300.c12
-rw-r--r--lib/libkvm/kvm_i386.c181
-rw-r--r--lib/libkvm/kvm_mips.c4
-rw-r--r--lib/libkvm/kvm_nlist.34
-rw-r--r--lib/libkvm/kvm_open.39
-rw-r--r--lib/libkvm/kvm_private.h3
-rw-r--r--lib/libkvm/kvm_proc.c373
-rw-r--r--lib/libkvm/kvm_read.31
-rw-r--r--lib/libkvm/kvm_sparc.c14
-rw-r--r--lib/libm/Makefile20
-rw-r--r--lib/libm/common/atan2.c60
-rw-r--r--lib/libm/common/sincos.c4
-rw-r--r--lib/libm/common/tan.c2
-rw-r--r--lib/libm/common/trig.h42
-rw-r--r--lib/libm/common_source/acos.310
-rw-r--r--lib/libm/common_source/acosh.34
-rw-r--r--lib/libm/common_source/acosh.c10
-rw-r--r--lib/libm/common_source/asin.34
-rw-r--r--lib/libm/common_source/asincos.c38
-rw-r--r--lib/libm/common_source/asinh.34
-rw-r--r--lib/libm/common_source/asinh.c12
-rw-r--r--lib/libm/common_source/atan.34
-rw-r--r--lib/libm/common_source/atan.c18
-rw-r--r--lib/libm/common_source/atan2.35
-rw-r--r--lib/libm/common_source/atanh.34
-rw-r--r--lib/libm/common_source/atanh.c4
-rw-r--r--lib/libm/common_source/ceil.38
-rw-r--r--lib/libm/common_source/cos.310
-rw-r--r--lib/libm/common_source/cosh.34
-rw-r--r--lib/libm/common_source/cosh.c26
-rw-r--r--lib/libm/common_source/erf.c16
-rw-r--r--lib/libm/common_source/exp.34
-rw-r--r--lib/libm/common_source/exp.c20
-rw-r--r--lib/libm/common_source/exp__E.c10
-rw-r--r--lib/libm/common_source/expm1.c32
-rw-r--r--lib/libm/common_source/fabs.34
-rw-r--r--lib/libm/common_source/floor.310
-rw-r--r--lib/libm/common_source/ieee.34
-rw-r--r--lib/libm/common_source/infnan.32
-rw-r--r--lib/libm/common_source/j0.34
-rw-r--r--lib/libm/common_source/j0.c28
-rw-r--r--lib/libm/common_source/j1.c32
-rw-r--r--lib/libm/common_source/jn.c44
-rw-r--r--lib/libm/common_source/lgamma.34
-rw-r--r--lib/libm/common_source/log.c2
-rw-r--r--lib/libm/common_source/log10.c10
-rw-r--r--lib/libm/common_source/log1p.c30
-rw-r--r--lib/libm/common_source/log__L.c12
-rw-r--r--lib/libm/common_source/pow.c23
-rw-r--r--lib/libm/common_source/rint.32
-rw-r--r--lib/libm/common_source/sin.34
-rw-r--r--lib/libm/common_source/sinh.34
-rw-r--r--lib/libm/common_source/sinh.c8
-rw-r--r--lib/libm/common_source/sqrt.34
-rw-r--r--lib/libm/common_source/tan.34
-rw-r--r--lib/libm/common_source/tanh.34
-rw-r--r--lib/libm/common_source/tanh.c4
-rw-r--r--lib/libm/ieee/cabs.c26
-rw-r--r--lib/libm/ieee/cbrt.c12
-rw-r--r--lib/libm/ieee/support.c106
-rw-r--r--lib/libmd/Makefile91
-rw-r--r--lib/libmd/md2.copyright17
-rw-r--r--lib/libmd/md2.h40
-rw-r--r--lib/libmd/md2c.c199
-rw-r--r--lib/libmd/md4.copyright20
-rw-r--r--lib/libmd/md4.h42
-rw-r--r--lib/libmd/md4c.c279
-rw-r--r--lib/libmd/md5.copyright21
-rw-r--r--lib/libmd/md5.h4
-rw-r--r--lib/libmd/md5c.c331
-rw-r--r--lib/libmd/mdX.3137
-rw-r--r--lib/libmd/mdXhl.c71
-rw-r--r--lib/libmd/mddriver.c67
-rw-r--r--lib/libmytinfo/EXAMPLES/terminfo.src104
-rw-r--r--lib/libmytinfo/INSTALL211
-rw-r--r--lib/libmytinfo/Makefile58
-rw-r--r--lib/libmytinfo/README75
-rw-r--r--lib/libmytinfo/README.doc125
-rw-r--r--lib/libmytinfo/TESTS/Makefile42
-rw-r--r--lib/libmytinfo/TESTS/caps.c173
-rw-r--r--lib/libmytinfo/TESTS/clear.c156
-rw-r--r--lib/libmytinfo/TESTS/quit.c72
-rw-r--r--lib/libmytinfo/TESTS/tput.c196
-rw-r--r--lib/libmytinfo/TESTS/tset.c919
-rw-r--r--lib/libmytinfo/TESTS/ttest.c297
-rw-r--r--lib/libmytinfo/addstr.c88
-rw-r--r--lib/libmytinfo/bin_order48
-rw-r--r--lib/libmytinfo/bsearch.c97
-rw-r--r--lib/libmytinfo/buildpath.c203
-rw-r--r--lib/libmytinfo/cap_list529
-rw-r--r--lib/libmytinfo/compar.c40
-rw-r--r--lib/libmytinfo/config.h89
-rw-r--r--lib/libmytinfo/defs.h195
-rw-r--r--lib/libmytinfo/fillterm.c81
-rw-r--r--lib/libmytinfo/findcap.c149
-rw-r--r--lib/libmytinfo/findterm.c286
-rw-r--r--lib/libmytinfo/getother.c49
-rw-r--r--lib/libmytinfo/gettbin.c127
-rw-r--r--lib/libmytinfo/gettcap.c276
-rw-r--r--lib/libmytinfo/gettinfo.c303
-rw-r--r--lib/libmytinfo/mkbinorder.c116
-rw-r--r--lib/libmytinfo/mkcaplist.c166
-rw-r--r--lib/libmytinfo/mkcapsort.c134
-rw-r--r--lib/libmytinfo/mktermhead.c160
-rw-r--r--lib/libmytinfo/mkversion.c35
-rw-r--r--lib/libmytinfo/readcaps.c151
-rw-r--r--lib/libmytinfo/tcapconv.c194
-rw-r--r--lib/libmytinfo/tcapvars.c36
-rw-r--r--lib/libmytinfo/term.h664
-rw-r--r--lib/libmytinfo/term.head527
-rw-r--r--lib/libmytinfo/term.tail137
-rw-r--r--lib/libmytinfo/termcap.c165
-rw-r--r--lib/libmytinfo/terminfo.c132
-rw-r--r--lib/libmytinfo/tgoto.c148
-rw-r--r--lib/libmytinfo/tiget.c51
-rw-r--r--lib/libmytinfo/tmatch.c37
-rw-r--r--lib/libmytinfo/tparm.c807
-rw-r--r--lib/libmytinfo/tputs.c266
-rw-r--r--lib/libmytinfo/tty.c446
-rw-r--r--lib/libmytinfo/version.h10
-rw-r--r--lib/libncurses/COPYRIGHT.NEW19
-rw-r--r--lib/libncurses/COPYRIGHT.OLD5
-rw-r--r--lib/libncurses/MKkeyname.awk30
-rw-r--r--lib/libncurses/MKkeys.awk1
-rw-r--r--lib/libncurses/Makefile209
-rw-r--r--lib/libncurses/README42
-rw-r--r--lib/libncurses/TESTS/Makefile35
-rw-r--r--lib/libncurses/TESTS/README21
-rw-r--r--lib/libncurses/TESTS/battle.c705
-rw-r--r--lib/libncurses/TESTS/copy.c39
-rw-r--r--lib/libncurses/TESTS/corner.c16
-rw-r--r--lib/libncurses/TESTS/ensor.c52
-rw-r--r--lib/libncurses/TESTS/firework.c113
-rw-r--r--lib/libncurses/TESTS/getch.c29
-rw-r--r--lib/libncurses/TESTS/hanoi.c275
-rw-r--r--lib/libncurses/TESTS/knight.c320
-rw-r--r--lib/libncurses/TESTS/ncurses.c1121
-rw-r--r--lib/libncurses/TESTS/newdemo.c350
-rw-r--r--lib/libncurses/TESTS/over.c120
-rw-r--r--lib/libncurses/TESTS/rain.c96
-rw-r--r--lib/libncurses/TESTS/scroll.c30
-rw-r--r--lib/libncurses/TESTS/scroll2.c91
-rw-r--r--lib/libncurses/TESTS/scroll3.c51
-rw-r--r--lib/libncurses/TESTS/test.c27
-rw-r--r--lib/libncurses/TESTS/testcurs.c532
-rw-r--r--lib/libncurses/TESTS/worm.c268
-rw-r--r--lib/libncurses/TESTS/xmas.c1192
-rw-r--r--lib/libncurses/copyright.c19
-rw-r--r--lib/libncurses/curs_addch.3115
-rw-r--r--lib/libncurses/curs_addchst.349
-rw-r--r--lib/libncurses/curs_addstr.344
-rw-r--r--lib/libncurses/curs_attr.384
-rw-r--r--lib/libncurses/curs_beep.329
-rw-r--r--lib/libncurses/curs_bkgd.350
-rw-r--r--lib/libncurses/curs_border.367
-rw-r--r--lib/libncurses/curs_clear.353
-rw-r--r--lib/libncurses/curs_color.3138
-rw-r--r--lib/libncurses/curs_delch.334
-rw-r--r--lib/libncurses/curs_delln.350
-rw-r--r--lib/libncurses/curs_getch.3188
-rw-r--r--lib/libncurses/curs_getstr.353
-rw-r--r--lib/libncurses/curs_getyx.341
-rw-r--r--lib/libncurses/curs_inch.340
-rw-r--r--lib/libncurses/curs_inchstr.345
-rw-r--r--lib/libncurses/curs_initscr.384
-rw-r--r--lib/libncurses/curs_inopts.3170
-rw-r--r--lib/libncurses/curs_insch.336
-rw-r--r--lib/libncurses/curs_insstr.359
-rw-r--r--lib/libncurses/curs_instr.344
-rw-r--r--lib/libncurses/curs_kernel.3115
-rw-r--r--lib/libncurses/curs_move.328
-rw-r--r--lib/libncurses/curs_outopts.3115
-rw-r--r--lib/libncurses/curs_overlay.341
-rw-r--r--lib/libncurses/curs_pad.374
-rw-r--r--lib/libncurses/curs_printw.341
-rw-r--r--lib/libncurses/curs_refresh.369
-rw-r--r--lib/libncurses/curs_scanw.343
-rw-r--r--lib/libncurses/curs_scr_dmp.358
-rw-r--r--lib/libncurses/curs_scroll.337
-rw-r--r--lib/libncurses/curs_slk.385
-rw-r--r--lib/libncurses/curs_termatt.374
-rw-r--r--lib/libncurses/curs_termin.3191
-rw-r--r--lib/libncurses/curs_touch.357
-rw-r--r--lib/libncurses/curs_util.381
-rw-r--r--lib/libncurses/curs_window.3123
-rw-r--r--lib/libncurses/curses.h530
-rw-r--r--lib/libncurses/curses.priv.h122
-rw-r--r--lib/libncurses/doc/color.doc71
-rw-r--r--lib/libncurses/doc/manual.doc1361
-rw-r--r--lib/libncurses/keys.list149
-rw-r--r--lib/libncurses/lib_acs.c98
-rw-r--r--lib/libncurses/lib_addch.c107
-rw-r--r--lib/libncurses/lib_addstr.c56
-rw-r--r--lib/libncurses/lib_beep.c56
-rw-r--r--lib/libncurses/lib_bkgd.c37
-rw-r--r--lib/libncurses/lib_box.c131
-rw-r--r--lib/libncurses/lib_clear.c24
-rw-r--r--lib/libncurses/lib_clrbot.c53
-rw-r--r--lib/libncurses/lib_clreol.c48
-rw-r--r--lib/libncurses/lib_color.c107
-rw-r--r--lib/libncurses/lib_delch.c38
-rw-r--r--lib/libncurses/lib_delwin.c36
-rw-r--r--lib/libncurses/lib_doupdate.c595
-rw-r--r--lib/libncurses/lib_endwin.c50
-rw-r--r--lib/libncurses/lib_erase.c50
-rw-r--r--lib/libncurses/lib_getch.c224
-rw-r--r--lib/libncurses/lib_getstr.c113
-rw-r--r--lib/libncurses/lib_inchstr.c29
-rw-r--r--lib/libncurses/lib_initscr.c31
-rw-r--r--lib/libncurses/lib_insch.c36
-rw-r--r--lib/libncurses/lib_insdel.c49
-rw-r--r--lib/libncurses/lib_insstr.c21
-rw-r--r--lib/libncurses/lib_kernel.c312
-rw-r--r--lib/libncurses/lib_longname.c35
-rw-r--r--lib/libncurses/lib_move.c30
-rw-r--r--lib/libncurses/lib_mvcur.c700
-rw-r--r--lib/libncurses/lib_mvwin.c29
-rw-r--r--lib/libncurses/lib_newterm.c176
-rw-r--r--lib/libncurses/lib_newwin.c185
-rw-r--r--lib/libncurses/lib_options.c252
-rw-r--r--lib/libncurses/lib_overlay.c110
-rw-r--r--lib/libncurses/lib_pad.c143
-rw-r--r--lib/libncurses/lib_printw.c75
-rw-r--r--lib/libncurses/lib_raw.c201
-rw-r--r--lib/libncurses/lib_refresh.c74
-rw-r--r--lib/libncurses/lib_scanw.c66
-rw-r--r--lib/libncurses/lib_screen.c58
-rw-r--r--lib/libncurses/lib_scroll.c201
-rw-r--r--lib/libncurses/lib_scrreg.c32
-rw-r--r--lib/libncurses/lib_set_term.c33
-rw-r--r--lib/libncurses/lib_slk.c251
-rw-r--r--lib/libncurses/lib_touch.c48
-rw-r--r--lib/libncurses/lib_trace.c179
-rw-r--r--lib/libncurses/lib_tstp.c50
-rw-r--r--lib/libncurses/lib_twait.c75
-rw-r--r--lib/libncurses/lib_unctrl.c32
-rw-r--r--lib/libncurses/lib_vidattr.c181
-rw-r--r--lib/libncurses/lib_window.c85
-rw-r--r--lib/libncurses/ncurses.3427
-rw-r--r--lib/libncurses/term.5153
-rw-r--r--lib/libncurses/terminfo.51656
-rw-r--r--lib/libncurses/terminfo.h2
-rw-r--r--lib/libncurses/unctrl.h19
-rw-r--r--lib/libncurses/version.h3
-rw-r--r--lib/libopie/Makefile31
-rw-r--r--lib/libopie/config.h322
-rw-r--r--lib/libpam/modules/pam_kerberosIV/klogin.c204
-rw-r--r--lib/libpam/modules/pam_login_access/login.access.550
-rw-r--r--lib/libpam/modules/pam_login_access/login_access.c239
-rw-r--r--lib/libpcap/Makefile40
-rw-r--r--lib/libpthread/Makefile21
-rw-r--r--lib/libpthread/man/Makefile.inc17
-rw-r--r--lib/libpthread/man/pthread_create.3109
-rw-r--r--lib/libpthread/man/pthread_detach.379
-rw-r--r--lib/libpthread/man/pthread_equal.366
-rw-r--r--lib/libpthread/man/pthread_exit.399
-rw-r--r--lib/libpthread/man/pthread_getspecific.382
-rw-r--r--lib/libpthread/man/pthread_join.3100
-rw-r--r--lib/libpthread/man/pthread_key_create.398
-rw-r--r--lib/libpthread/man/pthread_key_delete.392
-rw-r--r--lib/libpthread/man/pthread_once.3100
-rw-r--r--lib/libpthread/man/pthread_self.359
-rw-r--r--lib/libpthread/man/pthread_setspecific.391
-rw-r--r--lib/libpthread/sys/Makefile.inc5
-rw-r--r--lib/libpthread/thread/Makefile.inc93
-rw-r--r--lib/libpthread/thread/thr_attr_destroy.c60
-rw-r--r--lib/libpthread/thread/thr_attr_getdetachstate.c57
-rw-r--r--lib/libpthread/thread/thr_attr_getstackaddr.c52
-rw-r--r--lib/libpthread/thread/thr_attr_getstacksize.c52
-rw-r--r--lib/libpthread/thread/thr_attr_init.c59
-rw-r--r--lib/libpthread/thread/thr_attr_setcreatesuspend_np.c51
-rw-r--r--lib/libpthread/thread/thr_attr_setdetachstate.c59
-rw-r--r--lib/libpthread/thread/thr_attr_setstackaddr.c52
-rw-r--r--lib/libpthread/thread/thr_attr_setstacksize.c52
-rw-r--r--lib/libpthread/thread/thr_clean.c68
-rw-r--r--lib/libpthread/thread/thr_close.c96
-rw-r--r--lib/libpthread/thread/thr_cond.c347
-rw-r--r--lib/libpthread/thread/thr_condattr_destroy.c52
-rw-r--r--lib/libpthread/thread/thr_condattr_init.c58
-rw-r--r--lib/libpthread/thread/thr_create.c280
-rw-r--r--lib/libpthread/thread/thr_detach.c83
-rw-r--r--lib/libpthread/thread/thr_equal.c43
-rw-r--r--lib/libpthread/thread/thr_exit.c205
-rw-r--r--lib/libpthread/thread/thr_fcntl.c116
-rw-r--r--lib/libpthread/thread/thr_fork.c92
-rw-r--r--lib/libpthread/thread/thr_fsync.c49
-rw-r--r--lib/libpthread/thread/thr_getprio.c73
-rw-r--r--lib/libpthread/thread/thr_info.c182
-rw-r--r--lib/libpthread/thread/thr_init.c228
-rw-r--r--lib/libpthread/thread/thr_join.c116
-rw-r--r--lib/libpthread/thread/thr_kern.c1739
-rw-r--r--lib/libpthread/thread/thr_kill.c78
-rw-r--r--lib/libpthread/thread/thr_mattr_init.c58
-rw-r--r--lib/libpthread/thread/thr_mattr_kind_np.c64
-rw-r--r--lib/libpthread/thread/thr_multi_np.c44
-rw-r--r--lib/libpthread/thread/thr_mutex.c393
-rw-r--r--lib/libpthread/thread/thr_mutexattr_destroy.c52
-rw-r--r--lib/libpthread/thread/thr_nanosleep.c118
-rw-r--r--lib/libpthread/thread/thr_once.c50
-rw-r--r--lib/libpthread/thread/thr_open.c80
-rw-r--r--lib/libpthread/thread/thr_private.h783
-rw-r--r--lib/libpthread/thread/thr_read.c83
-rw-r--r--lib/libpthread/thread/thr_readv.c83
-rw-r--r--lib/libpthread/thread/thr_resume_np.c70
-rw-r--r--lib/libpthread/thread/thr_select.c172
-rw-r--r--lib/libpthread/thread/thr_self.c43
-rw-r--r--lib/libpthread/thread/thr_seterrno.c61
-rw-r--r--lib/libpthread/thread/thr_setprio.c80
-rw-r--r--lib/libpthread/thread/thr_sig.c167
-rw-r--r--lib/libpthread/thread/thr_sigaction.c82
-rw-r--r--lib/libpthread/thread/thr_sigmask.c92
-rw-r--r--lib/libpthread/thread/thr_sigprocmask.c92
-rw-r--r--lib/libpthread/thread/thr_sigsuspend.c66
-rw-r--r--lib/libpthread/thread/thr_sigwait.c73
-rw-r--r--lib/libpthread/thread/thr_single_np.c44
-rw-r--r--lib/libpthread/thread/thr_spec.c237
-rw-r--r--lib/libpthread/thread/thr_suspend_np.c67
-rw-r--r--lib/libpthread/thread/thr_wait4.c61
-rw-r--r--lib/libpthread/thread/thr_write.c83
-rw-r--r--lib/libpthread/thread/thr_writev.c83
-rw-r--r--lib/libpthread/thread/thr_yield.c49
-rw-r--r--lib/libresolv/Makefile30
-rw-r--r--lib/libresolv/fakelib.c1
-rw-r--r--lib/librpc/rpc/Makefile29
-rw-r--r--lib/librpcsvc/Makefile36
-rw-r--r--lib/librpcsvc/publickey.c172
-rw-r--r--lib/librpcsvc/rnusers.c68
-rw-r--r--lib/librpcsvc/rstat.c67
-rw-r--r--lib/librpcsvc/rwall.c52
-rw-r--r--lib/librpcsvc/secretkey.c85
-rw-r--r--lib/librpcsvc/xcrypt.c192
-rw-r--r--lib/librpcsvc/yp_passwd.c90
-rw-r--r--lib/librpcsvc/yp_update.c204
-rw-r--r--lib/libscsi/Makefile21
-rw-r--r--lib/libscsi/scsi.3350
-rw-r--r--lib/libscsi/scsi.c1192
-rw-r--r--lib/libscsi/scsi.h86
-rw-r--r--lib/libskey/Makefile18
-rw-r--r--lib/libskey/mdx.h19
-rw-r--r--lib/libskey/pathnames.h6
-rw-r--r--lib/libskey/put.c2292
-rw-r--r--lib/libskey/skey.159
-rw-r--r--lib/libskey/skey.3157
-rw-r--r--lib/libskey/skey.access.5125
-rw-r--r--lib/libskey/skey.h60
-rw-r--r--lib/libskey/skey_crypt.c38
-rw-r--r--lib/libskey/skey_getpass.c37
-rw-r--r--lib/libskey/skeyaccess.c485
-rw-r--r--lib/libskey/skeylogin.c342
-rw-r--r--lib/libskey/skeysubr.c130
-rw-r--r--lib/libss/Makefile38
-rw-r--r--lib/libss/copyright.h19
-rw-r--r--lib/libss/data.c16
-rw-r--r--lib/libss/error.c101
-rw-r--r--lib/libss/execute_cmd.c221
-rw-r--r--lib/libss/help.c148
-rw-r--r--lib/libss/invocation.c84
-rw-r--r--lib/libss/list_rqs.c94
-rw-r--r--lib/libss/listen.c164
-rw-r--r--lib/libss/pager.c91
-rw-r--r--lib/libss/parse.c138
-rw-r--r--lib/libss/prompt.c32
-rw-r--r--lib/libss/request_tbl.c66
-rw-r--r--lib/libss/requests.c52
-rw-r--r--lib/libss/ss.h69
-rw-r--r--lib/libss/ss_err.et39
-rw-r--r--lib/libss/ss_internal.h115
-rw-r--r--lib/libss/std_rqs.ct46
-rw-r--r--lib/libtcl/Makefile295
-rw-r--r--lib/libtcl/tclConfig.sh99
-rw-r--r--lib/libtelnet/Makefile33
-rw-r--r--lib/libtelnet/genget.c1
-rw-r--r--lib/libtelnet/getent.c3
-rw-r--r--lib/libtelnet/misc.c5
-rw-r--r--lib/libterm/Makefile13
-rw-r--r--lib/libtermcap/Makefile25
-rw-r--r--lib/libtermcap/pathnames.h1
-rw-r--r--lib/libtermcap/termcap.358
-rw-r--r--lib/libtermcap/termcap.c100
-rw-r--r--lib/libtermcap/termcap.h53
-rw-r--r--lib/libtermcap/tgoto.c34
-rw-r--r--lib/libtermcap/tospeed.c72
-rw-r--r--lib/libtermcap/tparm.c753
-rw-r--r--lib/libtermcap/tputs.c18
-rw-r--r--lib/libutil/Makefile34
-rw-r--r--lib/libutil/_secure_path.370
-rw-r--r--lib/libutil/_secure_path.c72
-rw-r--r--lib/libutil/libutil.h57
-rw-r--r--lib/libutil/login.369
-rw-r--r--lib/libutil/login.c1
-rw-r--r--lib/libutil/login.conf.5364
-rw-r--r--lib/libutil/login_auth.371
-rw-r--r--lib/libutil/login_auth.c670
-rw-r--r--lib/libutil/login_cap.3392
-rw-r--r--lib/libutil/login_cap.c780
-rw-r--r--lib/libutil/login_cap.h156
-rw-r--r--lib/libutil/login_class.3187
-rw-r--r--lib/libutil/login_class.c387
-rw-r--r--lib/libutil/login_ok.3138
-rw-r--r--lib/libutil/login_ok.c251
-rw-r--r--lib/libutil/login_times.3155
-rw-r--r--lib/libutil/login_times.c162
-rw-r--r--lib/libutil/login_tty.366
-rw-r--r--lib/libutil/login_tty.c5
-rw-r--r--lib/libutil/logout.371
-rw-r--r--lib/libutil/logout.c1
-rw-r--r--lib/libutil/logwtmp.373
-rw-r--r--lib/libutil/logwtmp.c22
-rw-r--r--lib/libutil/pty.3144
-rw-r--r--lib/libutil/pty.c13
-rw-r--r--lib/libutil/pw_util.c233
-rw-r--r--lib/libutil/setproctitle.3113
-rw-r--r--lib/libutil/setproctitle.c125
-rw-r--r--lib/libutil/stat_flags.c163
-rw-r--r--lib/libutil/uucplock.3170
-rw-r--r--lib/libutil/uucplock.c182
-rw-r--r--lib/libxpg4/Makefile9
-rw-r--r--lib/liby/Makefile25
-rw-r--r--lib/liby/main.c3
-rw-r--r--lib/liby/yyerror.c1
-rw-r--r--lib/libz/ChangeLog239
-rw-r--r--lib/libz/Makefile36
-rw-r--r--lib/libz/README99
-rw-r--r--lib/libz/adler32.c48
-rw-r--r--lib/libz/algorithm.doc105
-rw-r--r--lib/libz/compress.c57
-rw-r--r--lib/libz/crc32.c162
-rw-r--r--lib/libz/deflate.c1207
-rw-r--r--lib/libz/deflate.h275
-rw-r--r--lib/libz/example.c503
-rw-r--r--lib/libz/gzio.c523
-rw-r--r--lib/libz/infblock.c402
-rw-r--r--lib/libz/infblock.h37
-rw-r--r--lib/libz/infcodes.c247
-rw-r--r--lib/libz/infcodes.h27
-rw-r--r--lib/libz/inffast.c168
-rw-r--r--lib/libz/inffast.h17
-rw-r--r--lib/libz/inflate.c345
-rw-r--r--lib/libz/inftrees.c470
-rw-r--r--lib/libz/inftrees.h59
-rw-r--r--lib/libz/infutil.c87
-rw-r--r--lib/libz/infutil.h99
-rw-r--r--lib/libz/minigzip.c246
-rw-r--r--lib/libz/trees.c1141
-rw-r--r--lib/libz/uncompr.c58
-rw-r--r--lib/libz/zconf.h184
-rw-r--r--lib/libz/zlib.h780
-rw-r--r--lib/libz/zutil.c211
-rw-r--r--lib/libz/zutil.h203
-rw-r--r--lib/msun/Makefile154
-rw-r--r--lib/msun/bsdsrc/b_exp.c203
-rw-r--r--lib/msun/bsdsrc/b_log.c486
-rw-r--r--lib/msun/bsdsrc/b_tgamma.c336
-rw-r--r--lib/msun/bsdsrc/mathimpl.h98
-rw-r--r--lib/msun/i387/e_acos.S56
-rw-r--r--lib/msun/i387/e_asin.S55
-rw-r--r--lib/msun/i387/e_atan2.S44
-rw-r--r--lib/msun/i387/e_exp.S96
-rw-r--r--lib/msun/i387/e_fmod.S48
-rw-r--r--lib/msun/i387/e_log.S44
-rw-r--r--lib/msun/i387/e_log10.S44
-rw-r--r--lib/msun/i387/e_remainder.S48
-rw-r--r--lib/msun/i387/e_scalb.S45
-rw-r--r--lib/msun/i387/e_sqrt.S43
-rw-r--r--lib/msun/i387/s_atan.S44
-rw-r--r--lib/msun/i387/s_ceil.S58
-rw-r--r--lib/msun/i387/s_copysign.S48
-rw-r--r--lib/msun/i387/s_cos.S56
-rw-r--r--lib/msun/i387/s_finite.S46
-rw-r--r--lib/msun/i387/s_floor.S58
-rw-r--r--lib/msun/i387/s_ilogb.S53
-rw-r--r--lib/msun/i387/s_log1p.S55
-rw-r--r--lib/msun/i387/s_logb.S44
-rw-r--r--lib/msun/i387/s_rint.S43
-rw-r--r--lib/msun/i387/s_scalbn.S45
-rw-r--r--lib/msun/i387/s_significand.S44
-rw-r--r--lib/msun/i387/s_sin.S56
-rw-r--r--lib/msun/i387/s_tan.S58
-rw-r--r--lib/msun/man/acos.396
-rw-r--r--lib/msun/man/acosh.388
-rw-r--r--lib/msun/man/asin.398
-rw-r--r--lib/msun/man/asinh.376
-rw-r--r--lib/msun/man/atan.382
-rw-r--r--lib/msun/man/atan2.3196
-rw-r--r--lib/msun/man/atanh.390
-rw-r--r--lib/msun/man/ceil.368
-rw-r--r--lib/msun/man/cos.3 (renamed from lib/libc/stdlib/calloc.3)67
-rw-r--r--lib/msun/man/cosh.382
-rw-r--r--lib/msun/man/erf.393
-rw-r--r--lib/msun/man/exp.3320
-rw-r--r--lib/msun/man/fabs.374
-rw-r--r--lib/msun/man/floor.368
-rw-r--r--lib/msun/man/fmod.385
-rw-r--r--lib/msun/man/hypot.3134
-rw-r--r--lib/msun/man/ieee.3182
-rw-r--r--lib/msun/man/ieee_test.3107
-rw-r--r--lib/msun/man/j0.3155
-rw-r--r--lib/msun/man/lgamma.3139
-rw-r--r--lib/msun/man/math.3635
-rw-r--r--lib/msun/man/rint.368
-rw-r--r--lib/msun/man/sin.380
-rw-r--r--lib/msun/man/sinh.382
-rw-r--r--lib/msun/man/sqrt.3134
-rw-r--r--lib/msun/man/tan.379
-rw-r--r--lib/msun/man/tanh.378
-rw-r--r--lib/msun/src/e_acos.c111
-rw-r--r--lib/msun/src/e_acosf.c89
-rw-r--r--lib/msun/src/e_acosh.c69
-rw-r--r--lib/msun/src/e_acoshf.c57
-rw-r--r--lib/msun/src/e_asin.c120
-rw-r--r--lib/msun/src/e_asinf.c92
-rw-r--r--lib/msun/src/e_atan2.c130
-rw-r--r--lib/msun/src/e_atan2f.c105
-rw-r--r--lib/msun/src/e_atanh.c74
-rw-r--r--lib/msun/src/e_atanhf.c58
-rw-r--r--lib/msun/src/e_cosh.c93
-rw-r--r--lib/msun/src/e_coshf.c71
-rw-r--r--lib/msun/src/e_exp.c167
-rw-r--r--lib/msun/src/e_expf.c103
-rw-r--r--lib/msun/src/e_fmod.c140
-rw-r--r--lib/msun/src/e_fmodf.c113
-rw-r--r--lib/msun/src/e_gamma.c37
-rw-r--r--lib/msun/src/e_gamma_r.c35
-rw-r--r--lib/msun/src/e_gammaf.c39
-rw-r--r--lib/msun/src/e_gammaf_r.c38
-rw-r--r--lib/msun/src/e_hypot.c128
-rw-r--r--lib/msun/src/e_hypotf.c87
-rw-r--r--lib/msun/src/e_j0.c487
-rw-r--r--lib/msun/src/e_j0f.c444
-rw-r--r--lib/msun/src/e_j1.c486
-rw-r--r--lib/msun/src/e_j1f.c444
-rw-r--r--lib/msun/src/e_jn.c281
-rw-r--r--lib/msun/src/e_jnf.c212
-rw-r--r--lib/msun/src/e_lgamma.c36
-rw-r--r--lib/msun/src/e_lgamma_r.c312
-rw-r--r--lib/msun/src/e_lgammaf.c39
-rw-r--r--lib/msun/src/e_lgammaf_r.c248
-rw-r--r--lib/msun/src/e_log.c146
-rw-r--r--lib/msun/src/e_log10.c98
-rw-r--r--lib/msun/src/e_log10f.c67
-rw-r--r--lib/msun/src/e_logf.c97
-rw-r--r--lib/msun/src/e_pow.c312
-rw-r--r--lib/msun/src/e_powf.c253
-rw-r--r--lib/msun/src/e_rem_pio2.c183
-rw-r--r--lib/msun/src/e_rem_pio2f.c196
-rw-r--r--lib/msun/src/e_remainder.c80
-rw-r--r--lib/msun/src/e_remainderf.c73
-rw-r--r--lib/msun/src/e_scalb.c55
-rw-r--r--lib/msun/src/e_scalbf.c52
-rw-r--r--lib/msun/src/e_sinh.c86
-rw-r--r--lib/msun/src/e_sinhf.c68
-rw-r--r--lib/msun/src/e_sqrt.c453
-rw-r--r--lib/msun/src/e_sqrtf.c97
-rw-r--r--lib/msun/src/get_hw_float.c50
-rw-r--r--lib/msun/src/k_cos.c96
-rw-r--r--lib/msun/src/k_cosf.c64
-rw-r--r--lib/msun/src/k_rem_pio2.c320
-rw-r--r--lib/msun/src/k_rem_pio2f.c213
-rw-r--r--lib/msun/src/k_sin.c79
-rw-r--r--lib/msun/src/k_sinf.c54
-rw-r--r--lib/msun/src/k_standard.c782
-rw-r--r--lib/msun/src/k_tan.c131
-rw-r--r--lib/msun/src/k_tanf.c101
-rw-r--r--lib/msun/src/math.h273
-rw-r--r--lib/msun/src/math_private.h223
-rw-r--r--lib/msun/src/s_asinh.c65
-rw-r--r--lib/msun/src/s_asinhf.c57
-rw-r--r--lib/msun/src/s_atan.c139
-rw-r--r--lib/msun/src/s_atanf.c119
-rw-r--r--lib/msun/src/s_cbrt.c93
-rw-r--r--lib/msun/src/s_cbrtf.c83
-rw-r--r--lib/msun/src/s_ceil.c80
-rw-r--r--lib/msun/src/s_ceilf.c61
-rw-r--r--lib/msun/src/s_copysign.c38
-rw-r--r--lib/msun/src/s_copysignf.c41
-rw-r--r--lib/msun/src/s_cos.c82
-rw-r--r--lib/msun/src/s_cosf.c59
-rw-r--r--lib/msun/src/s_erf.c314
-rw-r--r--lib/msun/src/s_erff.c223
-rw-r--r--lib/msun/src/s_expm1.c228
-rw-r--r--lib/msun/src/s_expm1f.c133
-rw-r--r--lib/msun/src/s_fabs.c35
-rw-r--r--lib/msun/src/s_fabsf.c38
-rw-r--r--lib/msun/src/s_finite.c35
-rw-r--r--lib/msun/src/s_finitef.c38
-rw-r--r--lib/msun/src/s_floor.c81
-rw-r--r--lib/msun/src/s_floorf.c70
-rw-r--r--lib/msun/src/s_frexp.c59
-rw-r--r--lib/msun/src/s_frexpf.c52
-rw-r--r--lib/msun/src/s_ilogb.c50
-rw-r--r--lib/msun/src/s_ilogbf.c43
-rw-r--r--lib/msun/src/s_isnan.c38
-rw-r--r--lib/msun/src/s_isnanf.c40
-rw-r--r--lib/msun/src/s_ldexp.c32
-rw-r--r--lib/msun/src/s_ldexpf.c35
-rw-r--r--lib/msun/src/s_lib_version.c39
-rw-r--r--lib/msun/src/s_log1p.c173
-rw-r--r--lib/msun/src/s_log1pf.c112
-rw-r--r--lib/msun/src/s_logb.c42
-rw-r--r--lib/msun/src/s_logbf.c39
-rw-r--r--lib/msun/src/s_matherr.c30
-rw-r--r--lib/msun/src/s_modf.c83
-rw-r--r--lib/msun/src/s_modff.c64
-rw-r--r--lib/msun/src/s_nextafter.c79
-rw-r--r--lib/msun/src/s_nextafterf.c70
-rw-r--r--lib/msun/src/s_rint.c93
-rw-r--r--lib/msun/src/s_rintf.c77
-rw-r--r--lib/msun/src/s_scalbn.c66
-rw-r--r--lib/msun/src/s_scalbnf.c62
-rw-r--r--lib/msun/src/s_signgam.c3
-rw-r--r--lib/msun/src/s_significand.c34
-rw-r--r--lib/msun/src/s_significandf.c31
-rw-r--r--lib/msun/src/s_sin.c82
-rw-r--r--lib/msun/src/s_sinf.c53
-rw-r--r--lib/msun/src/s_tan.c76
-rw-r--r--lib/msun/src/s_tanf.c48
-rw-r--r--lib/msun/src/s_tanh.c86
-rw-r--r--lib/msun/src/s_tanhf.c64
-rw-r--r--lib/msun/src/w_acos.c43
-rw-r--r--lib/msun/src/w_acosf.c47
-rw-r--r--lib/msun/src/w_acosh.c42
-rw-r--r--lib/msun/src/w_acoshf.c47
-rw-r--r--lib/msun/src/w_asin.c44
-rw-r--r--lib/msun/src/w_asinf.c48
-rw-r--r--lib/msun/src/w_atan2.c43
-rw-r--r--lib/msun/src/w_atan2f.c47
-rw-r--r--lib/msun/src/w_atanh.c47
-rw-r--r--lib/msun/src/w_atanhf.c52
-rw-r--r--lib/msun/src/w_cabs.c27
-rw-r--r--lib/msun/src/w_cabsf.c21
-rw-r--r--lib/msun/src/w_cosh.c42
-rw-r--r--lib/msun/src/w_coshf.c46
-rw-r--r--lib/msun/src/w_drem.c15
-rw-r--r--lib/msun/src/w_dremf.c16
-rw-r--r--lib/msun/src/w_exp.c53
-rw-r--r--lib/msun/src/w_expf.c58
-rw-r--r--lib/msun/src/w_fmod.c43
-rw-r--r--lib/msun/src/w_fmodf.c47
-rw-r--r--lib/msun/src/w_gamma.c49
-rw-r--r--lib/msun/src/w_gamma_r.c46
-rw-r--r--lib/msun/src/w_gammaf.c48
-rw-r--r--lib/msun/src/w_gammaf_r.c51
-rw-r--r--lib/msun/src/w_hypot.c43
-rw-r--r--lib/msun/src/w_hypotf.c47
-rw-r--r--lib/msun/src/w_j0.c41
-rw-r--r--lib/msun/src/w_j0f.c45
-rw-r--r--lib/msun/src/w_j1.c42
-rw-r--r--lib/msun/src/w_j1f.c46
-rw-r--r--lib/msun/src/w_jn.c42
-rw-r--r--lib/msun/src/w_jnf.c42
-rw-r--r--lib/msun/src/w_lgamma.c49
-rw-r--r--lib/msun/src/w_lgamma_r.c46
-rw-r--r--lib/msun/src/w_lgammaf.c48
-rw-r--r--lib/msun/src/w_lgammaf_r.c51
-rw-r--r--lib/msun/src/w_log.c43
-rw-r--r--lib/msun/src/w_log10.c46
-rw-r--r--lib/msun/src/w_log10f.c51
-rw-r--r--lib/msun/src/w_logf.c48
-rw-r--r--lib/msun/src/w_pow.c61
-rw-r--r--lib/msun/src/w_powf.c72
-rw-r--r--lib/msun/src/w_remainder.c42
-rw-r--r--lib/msun/src/w_remainderf.c46
-rw-r--r--lib/msun/src/w_scalb.c60
-rw-r--r--lib/msun/src/w_scalbf.c65
-rw-r--r--lib/msun/src/w_sinh.c42
-rw-r--r--lib/msun/src/w_sinhf.c46
-rw-r--r--lib/msun/src/w_sqrt.c42
-rw-r--r--lib/msun/src/w_sqrtf.c46
-rw-r--r--lib/msun/src/w_y0.c50
-rw-r--r--lib/msun/src/w_y0f.c54
-rw-r--r--lib/msun/src/w_y1.c50
-rw-r--r--lib/msun/src/w_y1f.c54
-rw-r--r--lib/msun/src/w_yn.c50
-rw-r--r--lib/msun/src/w_ynf.c50
-rw-r--r--lib/ncurses/ncurses/Makefile209
1972 files changed, 222485 insertions, 31279 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 64afb1b..9b64d7d 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,14 +1,54 @@
# @(#)Makefile 8.1 (Berkeley) 6/4/93
-SUBDIR= libc libcurses libcompat libedit libkvm libm libmp \
- libplot libresolv librpc/rpc libtelnet libterm libutil liby
-
.if ${MACHINE} == "tahoe"
-SUBDIR+=csu/tahoe.pcc
+SUBDIR=csu/tahoe.pcc
.elif ${MACHINE} == "vax"
-SUBDIR+=csu/vax.pcc
+SUBDIR=csu/vax.pcc
.else
-SUBDIR+=csu/${MACHINE}
+SUBDIR=csu/${MACHINE}
+.endif
+
+# XXX MISSING: libplot
+SUBDIR+=libalias libc libcompat libcom_err libcurses libdisk libedit \
+ libf2c libftpio libgnumalloc libipx libkvm libmd libmytinfo \
+ libncurses libopie libpcap libresolv librpcsvc \
+ libscsi libskey libss libtermcap libutil libxpg4 liby libz
+
+.if !defined(NOLIBC_R)
+SUBDIR+= libc_r
+.endif
+
+.if !defined(NOTCL) && exists (${.CURDIR}/../contrib/tcl) && \
+ exists(${.CURDIR}/../usr.bin/tclsh) && exists (${.CURDIR}/libtcl)
+SUBDIR+=libtcl
+.endif
+
+.if !exists(${.CURDIR}/../secure) || defined(NOSECURE) || defined(NOCRYPT)
+SUBDIR+= libcrypt
+.else
+SUBDIR+= ../secure/lib/libcrypt
+.if defined(RELEASEDIR)
+# releases do need both libraries
+SUBDIR+= libcrypt
+.endif
.endif
+.if !exists(${.CURDIR}/../eBones) || defined(NOSECURE) || !defined(MAKE_EBONES)
+SUBDIR+= libtelnet
+.else
+.if defined(RELEASEDIR)
+# releases do need both libraries
+SUBDIR+= libtelnet
+.endif
+SUBDIR+= ../eBones/lib/libtelnet
+.endif
+
+.if defined(WANT_CSRG_LIBM)
+SUBDIR+= libm
+.else
+SUBDIR+= msun
+.endif
+
+SUBDIR+= compat
+
.include <bsd.subdir.mk>
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
new file mode 100644
index 0000000..62677fd
--- /dev/null
+++ b/lib/Makefile.inc
@@ -0,0 +1,3 @@
+# Default version for system libs (override in <lib>/Makefile if necessary)
+SHLIB_MAJOR?= 2
+SHLIB_MINOR?= 0
diff --git a/lib/compat/Makefile b/lib/compat/Makefile
new file mode 100644
index 0000000..4de6109
--- /dev/null
+++ b/lib/compat/Makefile
@@ -0,0 +1,16 @@
+# $Id$
+
+SUBDIR=
+
+# Note that compat21 is *not* for the 2.1.x branch!
+.if defined(COMPAT1X) || defined(RELEASEDIR)
+SUBDIR+= compat1x
+.endif
+.if defined(COMPAT20) || defined(RELEASEDIR)
+SUBDIR+= compat20
+.endif
+.if defined(COMPAT21) || defined(RELEASEDIR)
+SUBDIR+= compat21
+.endif
+
+.include <bsd.subdir.mk>
diff --git a/lib/compat/Makefile.inc b/lib/compat/Makefile.inc
new file mode 100644
index 0000000..5201d4a
--- /dev/null
+++ b/lib/compat/Makefile.inc
@@ -0,0 +1,3 @@
+# $Id$
+
+LIBCOMPATDIR?= ${LIBDIR}/compat
diff --git a/lib/compat/compat1x/Makefile b/lib/compat/compat1x/Makefile
new file mode 100644
index 0000000..51e6807
--- /dev/null
+++ b/lib/compat/compat1x/Makefile
@@ -0,0 +1,27 @@
+# $Id$
+
+DISTRIBUTION= compat1x
+
+LIBS= libc.so.1.1 libcurses.so.1.1 libf2c.so.1.1 libg++.so.1.1 \
+ libgcc.so.1.1 libgnumalloc.so.1.1 libgnuregex.so.1.1 libln.so.1.1 \
+ libm.so.1.1 libmalloc.so.1.1 libreadline.so.1.1 libresolv.so.1.1 \
+ librpcsvc.so.1.1 libskey.so.1.1 libtelnet.so.1.1 libtermcap.so.1.1 \
+ libutil.so.1.1 liby.so.1.1
+
+CLEANFILES+= ${LIBS}
+LINKS= ${LIBCOMPATDIR}/libtermcap.so.1.1 ${LIBCOMPATDIR}/libtermlib.so.1.1
+
+all: ${LIBS}
+
+.for lib in ${LIBS}
+${lib}: ${lib}.gz.uu
+ uudecode -p ${.CURDIR}/${lib}.gz.uu | gunzip > ${lib}
+.endfor
+
+beforeinstall:
+ ${INSTALL} ${COPY} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} ${LIBS} \
+ ${DESTDIR}${LIBCOMPATDIR}
+
+# Get all the fruit, even though we don't set PROG.
+# XXX bsd.lib.mk has fruitflies, e.g., it fails if LIBS is empty.
+.include <bsd.prog.mk>
diff --git a/lib/compat/compat1x/libc.so.1.1.gz.uu b/lib/compat/compat1x/libc.so.1.1.gz.uu
new file mode 100644
index 0000000..f2e0046
--- /dev/null
+++ b/lib/compat/compat1x/libc.so.1.1.gz.uu
@@ -0,0 +1,3921 @@
+begin 444 libc.so.1.1.gz
+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
+.!&D%@O\';ULWR:(F!@"^
+`
+end
diff --git a/lib/compat/compat1x/libcurses.so.1.1.gz.uu b/lib/compat/compat1x/libcurses.so.1.1.gz.uu
new file mode 100644
index 0000000..db25272
--- /dev/null
+++ b/lib/compat/compat1x/libcurses.so.1.1.gz.uu
@@ -0,0 +1,428 @@
+begin 444 libcurses.so.1.1.gz
+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
+*_PV+62([R<4``,+_
+`
+end
diff --git a/lib/compat/compat1x/libf2c.so.1.1.gz.uu b/lib/compat/compat1x/libf2c.so.1.1.gz.uu
new file mode 100644
index 0000000..eaea7ba
--- /dev/null
+++ b/lib/compat/compat1x/libf2c.so.1.1.gz.uu
@@ -0,0 +1,787 @@
+begin 444 libf2c.so.1.1.gz
+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
+:ZD-;/8/G!4>S[:>_ZZ'R./,_"Z[B"V9S`0`G
+`
+end
diff --git a/lib/compat/compat1x/libg++.so.1.1.gz.uu b/lib/compat/compat1x/libg++.so.1.1.gz.uu
new file mode 100644
index 0000000..f32ca72
--- /dev/null
+++ b/lib/compat/compat1x/libg++.so.1.1.gz.uu
@@ -0,0 +1,3530 @@
+begin 444 libg++.so.1.1.gz
+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
+FZE-(8[Y^>F3">O&X8B^-'M)/+!_$)-J]Q\>O3/7_*2>&+A5C!@#$
+`
+end
diff --git a/lib/compat/compat1x/libgcc.so.1.1.gz.uu b/lib/compat/compat1x/libgcc.so.1.1.gz.uu
new file mode 100644
index 0000000..3a20167
--- /dev/null
+++ b/lib/compat/compat1x/libgcc.so.1.1.gz.uu
@@ -0,0 +1,133 @@
+begin 444 libgcc.so.1.1.gz
+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
+==O9EC;/+^OWIYVU88>%O"O\*(/0#Q4I#3Q9A``!H
+`
+end
diff --git a/lib/compat/compat1x/libgnumalloc.so.1.1.gz.uu b/lib/compat/compat1x/libgnumalloc.so.1.1.gz.uu
new file mode 100644
index 0000000..bc63c8e
--- /dev/null
+++ b/lib/compat/compat1x/libgnumalloc.so.1.1.gz.uu
@@ -0,0 +1,142 @@
+begin 444 libgnumalloc.so.1.1.gz
+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
+H-E^KGN,HRH9&/BISL*ECY3HT4VX]"!%2)'@[\8V7X3?0Z7W,^$P``(`?
+`
+end
diff --git a/lib/compat/compat1x/libgnuregex.so.1.1.gz.uu b/lib/compat/compat1x/libgnuregex.so.1.1.gz.uu
new file mode 100644
index 0000000..14b5a9e
--- /dev/null
+++ b/lib/compat/compat1x/libgnuregex.so.1.1.gz.uu
@@ -0,0 +1,270 @@
+begin 444 libgnuregex.so.1.1.gz
+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
+*_PM)1.Y1!H8``+D)
+`
+end
diff --git a/lib/compat/compat1x/libln.so.1.1.gz.uu b/lib/compat/compat1x/libln.so.1.1.gz.uu
new file mode 100644
index 0000000..14a62ce
--- /dev/null
+++ b/lib/compat/compat1x/libln.so.1.1.gz.uu
@@ -0,0 +1,13 @@
+begin 444 libln.so.1.1.gz
+M'XL("#\3%RX``VQI8FQN+G-O+C$N,0#MF3U+`T$0AB?Q(VHA*=.IA9`B1`B(
+M"*)>-)'`:81$4$36>'>$R.4B&"4!"VT$L4GIO[%()?@3;(5H(UB*H+.7/3>(
+M0@K!YGU@;CYV=NZN'-Y[NCRG*)%OC,LV29JMJ\="1P:[%^TY[NDLR4>*']=[
+M[W=M\C@*$R5.V4?8#W#K$%N(;9#\,Y\/)I@YK,XBJC>HC:A:@!^K[QI3^;[*
+MI]0[`N)JEJV*,S(/ZW^95??/U/T%MM&>W/@V3XC5G0UC/;?"T9J93QNFR&>S
+MA4Q1%(VTF1$DFDW7:9!PZDZC3J):JGB<V*5ZB9UG\[5N[>'VA0``````````
+M@']&[MQ1WH'CT?[OR!W<9EOF>)/M1M7E3A_C)=J4"9_'E&\]O?G;?ZOSJOPS
+M^]"/LP$``````````/#WR)U=:N]R3Q\GK;%/D];3$Z2U]!1I'7V>M(:^R'Z"
+MNCTY-5?&VSWQ(?6CJ_\FJ+N5`UE+'M>H;%DI8=6J1Q77L9-2:B][)U\%8=$G
+(L6!$I=8@``#Q
+`
+end
diff --git a/lib/compat/compat1x/libm.so.1.1.gz.uu b/lib/compat/compat1x/libm.so.1.1.gz.uu
new file mode 100644
index 0000000..07ba894
--- /dev/null
+++ b/lib/compat/compat1x/libm.so.1.1.gz.uu
@@ -0,0 +1,538 @@
+begin 444 libm.so.1.1.gz
+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
+@OFR18Y*M8+AP_D8Z.K17HWCU1](!*_PW"GMBI1G=``#O
+`
+end
diff --git a/lib/compat/compat1x/libmalloc.so.1.1.gz.uu b/lib/compat/compat1x/libmalloc.so.1.1.gz.uu
new file mode 100644
index 0000000..468d9f8
--- /dev/null
+++ b/lib/compat/compat1x/libmalloc.so.1.1.gz.uu
@@ -0,0 +1,183 @@
+begin 444 libmalloc.so.1.1.gz
+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
+('3(EEH]B``!S
+`
+end
diff --git a/lib/compat/compat1x/libreadline.so.1.1.gz.uu b/lib/compat/compat1x/libreadline.so.1.1.gz.uu
new file mode 100644
index 0000000..680c543
--- /dev/null
+++ b/lib/compat/compat1x/libreadline.so.1.1.gz.uu
@@ -0,0 +1,1117 @@
+begin 444 libreadline.so.1.1.gz
+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
+1,)'P20W=E.>?"MZ>E&CO`0"^
+`
+end
diff --git a/lib/compat/compat1x/libresolv.so.1.1.gz.uu b/lib/compat/compat1x/libresolv.so.1.1.gz.uu
new file mode 100644
index 0000000..2ff9c90
--- /dev/null
+++ b/lib/compat/compat1x/libresolv.so.1.1.gz.uu
@@ -0,0 +1,153 @@
+begin 444 libresolv.so.1.1.gz
+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
+H:471X]9OYO3K.E9UG>J%KS0]O)"Z'#SM\_.O!E+L_Q<9C<FN?D@``*^@
+`
+end
diff --git a/lib/compat/compat1x/librpcsvc.so.1.1.gz.uu b/lib/compat/compat1x/librpcsvc.so.1.1.gz.uu
new file mode 100644
index 0000000..b9c2570
--- /dev/null
+++ b/lib/compat/compat1x/librpcsvc.so.1.1.gz.uu
@@ -0,0 +1,165 @@
+begin 444 librpcsvc.so.1.1.gz
+M'XL(")0.%RX``VQI8G)P8W-V8RYS;RXQ+C$`[%P+=)1%EJZ0$`)&004))($`
+M>9($$D(("0$2()T$\B2!\`I-2#HDT$F'3C<DBB,<4&0P8\9=9Q9QSH`KZXJS
+M(^JXPJBSJ*,.KG,$'S."Z\KH<#8,NN(;@9BM^NM6U>V_.YV*Q#UGS^8_]JG<
+M^U?=NO75K>?_R>ODKNUD'2%D%#&>AA&$1!'U+-MSKJ*+_;%ZQTL9-%^/.[3'
+M'=)U._WSSN.NX4<#Z*L+09V=J<?W5E\]\1++7[5<EAA*L^V]/62O.[2!!!&R
+MO*HKFVIV_CZ4EBWLL`25575-,10A5#&[PQ)*%2.D(J[#,HHJ/K,*Q2T=EM%4
+M<=9J5!["*P^D=7?8OER]UDJK-]5_IU743ZL^*.UD\:H/2$5"AR6$*G9+11CW
+M90NO:02O:6AGI[DN65.X56)SXKN>'@ULSJ]%OMU/R_":;]XY+\`]ACLXO8=9
+M<@]+/7XAA-9M&%35F^SMP_:>7BM:$LM-/2P58WA;*[B7P[B70WK',!?;K5Z+
+M^H+9#>5F>NL+:>5*M<3G='<O^)CC[55:9F,4E`I?:W2%\M<7IO=7(U^/50M?
+M*:9$8+J_3TREM7QJP(A;<&%[M3GNI`^RS,VL3`^198HTRGRPAF9_*I0*&T.A
+M6$RUUO@ZM`:UU]TC8@CZ/$4JH,]W]_CK<VFUU/`GA/D3`O[<OT;+GS'8GW,R
+MIB%6_J%'+U;>6,WJ#\)XC-&K__[5J/[4[TQXA/4##Y_SWVHU_ZWNW1^9?YC*
+M7ZR3_\^K4+PGKM:(]T.K4'M/K#*-S:.K=.?):FPG4\`T<M?7;'`8MNS"^,A=
+M?S&4#+\JI7S=4+(Y<X%2/F,HV1R>K)0/&4HVCX<I98>A#*/*0-F*;1V6"*KX
+M?*50;.JP1%'%7Z1B58<EFBI.2@5=4^*IXM]6HC4EB2I>D:%`UY295/$TCLUL
+M-C_ZG\<05JDK$5;+L"\,IT78%X91VDK3^C9YI6E]2\"^,`C"-.?41U9XSC5G
+M5_0]U[2N\)S3?M5[&=3FN2M0F\]?16N5G%<?Z^['6O5)%;+W[574?M;!]VCW
+MQ2%LYPFSG9/:=JJQG48O.U=U[8S!=EZXX@NGG?U9TU]>CNQM]FEOXG?]L.?&
+M]G9(>UF\G7<O1_LA-K"V+D?[(3:PZI?WL1]"=0W'=77(NB8TL/UEAV5168>E
+M@)I<LMPTS_5F[]@R9,]VV1<6M_4'VT9LSRWM+>58;%LFFI[+L=@D%2D<BU52
+M,1&:E$2;E$+?M"W3G7?/52(?)G6CN&-5[KJB&W>_P'9.7S79^8-V_"[#=FJ^
+M-8V#[=IVKL=V"J^B=9CY8[^"UF$&Y?[+6ON29RKH^A@$$]=UE1KKXYT5R(^?
+M7D)^L/8<P/L!YMCN"LU83,9VRRM$("S@8;A"!E,J7P,R9$51/4^Q@];&47PM
+MF%>A/YZ.+15U"ANT[NZEK.Y1:LU_;JEN[#4N16T8\\TUCZ=QV-[<I0*3Q=Q4
+MDE1D<DS"I2(>SGU2,9:OB]^6>^V9>HW_<AQO7_MJ2ZG_MOC:[^67RV6RP]L7
+MG_M?[$=JN0F#E'(3!G'E"`/6Y.!RA`';(GU5IHW!OC)4=WJ/K_-D'QC@MB\I
+MDVT_KW>>'8?K+RY#>]$0&&MZ<7FJ%-D9:K83HFUGC[0C[AZ.EXJ[AY4<CT=*
+MA?4"'H,_DXH,CO_M4A'+]V9U4C&&;T\K2C7GC&]+4+N22]&^D;4KJ!3M&YDK
+M7Y2@?2.+C0D]:`_+EIE3)0@;MJD]6:([]INP+P>EG2SN2UL)V@<P7S:4H'T`
+M\^4^'A):\U8`KBN]!.')Z@HM07BRNC)T[R4>+49VWR\VQ<G%;KT]=&VQC'-F
+ML,\S6IK*W^XG/VY_L3D.9Q>;[L`F%J.^9B#<(!5Q/`X+>TQGA`;M<;"C"-\+
+M%9GP+S.O@;<5:<9S`K9;;;;[F\O(+FM2FJ[=4TLD7@$<KY`B@9?8\_JU)2WM
+M7N)YUCF^1.>L4[Y$K;.CV3H;M+%G.:_W\27,D3!V8#U`Q"'XQ^JXO)>(0["Z
+MB[F5CY@ZJ6A49EG?\NY<)BRSM8)-*U<7H[6";58N+$9K!>NH,XO16L%V42<6
+M:Z\538M1W^U;C,:.<6^@?6Z*P78*I9VI&X.XI?K%HN?&<K!B]'T\48AL?U(H
+M;(_?&,QMCUBLOW>Z'=LZ6*C\!%N_*T1^LOYC!33]G(1M%Q>:L,PNU)V33Q?X
+MO`_.X@Z=E8H$'C'A,J#@;/9:@3\\T/X&U6DK4'-3@#'6'BP02.0:*MZ*NZ0V
+M$;2L,UL*T+AD3I86:([Q3_+Q>1O/;6RLD`*_F*G[#V8ECP[3"&,[O+&N;.?Q
+MH#(VTH-]8.$]EV\0Y<-8^=&H_"OY?LKC^,\WS^UK\DUSU9Q\34Q.6_"^)]]T
+M7\9,G;68[LM8)[PEE.R^C'7"BU*QB</YA%2LXHO)`:DHY+%TKP6M/VSV^9$%
+MK3]L]FFRH+AFL\\:BUX?!5KD]%MHT5HO3^7A.QT9&_%[@W=>&N**NV/XSDL!
+MKM`+89V=.R\%NL9>&-G)T?DUOP@)IIO;87[W]SC^<5U[\DQCMRU/=^Q&YJDU
+M(XI/[D'4XF[#XFC68;,#V)VV>,<[ID&]'F<,*H9T8)[LY"!#R=#^[T52^:G1
+M\VS`GU;*,X3?/U1U_5XI7S:4;*?XN%(>,91LM_B04NXWE+.ILD,I[S*4[&ZT
+M32A=[@Y+#ML/2D4=N\BIZBJ1B@K9R$!^O[-S$322Q58E5=R*[V+74$4COO^L
+M8WO\1;JX'UKH$_>1BR2PT3YPO[A0OAXJ<=^[4+;\(A&X;U'*]R3N-4KYBL2]
+M2"F?D+AG*.6#$O>I2KE;XCY&*%U;..9!4F'CF'^Q0"@J.>9GI&)ASU/1'IB/
+M%`UD>P6&>;"\6AK+,3^T0'M]RUW@$^/'%D@0WR7>&-^C7A\C`N.X!;+I#TN,
+M;U+*>R7&W;FB<3_B^'XL%4T<V_>D8@W']4VI6,(Q?4$JLCBF1Z0B@6/Z2ZD(
+MXYC^)+>O-13/;7&YGOO+=;DZ^\O/<LQK1GRN6#,R^<0S3/H5SR?YKW/07H]-
+M\N=RM/MOAU=]1W-,:]1JO]\%D:WT'+Q'D7/S>':?Q5:6+3FZW\LOS)>PC?-N
+MB_=:_:S*'^`G/S[_S_>YCL#<_O!\W3DF=[X9O[;Y`K\$;JQJOHPCA@3K,;L?
+M^_CQK.N=>?B[R#S3>M0U3]?G#FSG";.=NS6_P^;/,_9'#1V3"9%;H_WS?-Z[
+M^F[/4.D'/4-5=<V?)X!SL<./<2\H534<N.NDMV4\U"_/%8KYK!";7+Z9*PHE
+M\4-45==?I6H<4[%=S:FYVF.D>JZ'GS^7QL*XE[$]_NX[3/VIOO_.5=]_O7WQ
+M%;/O9)MC+52Z`G<%7V2;[@K.2`5\3WPA&_4WP^9(MF[<+,M&<;,Y&\V?K.J6
+M;#1_&M]_L]'\R7RQ9&N/_SG]Y<L<FS.P?)E&;._..>C^@IER245_^3(W8KO)
+M<TQC3Y<O\^]9_>?+_#P+\0<N9&E\'[%EX?UOEO#U>_)EQF9YKH=E67U_C_XH
+MT_,;=H1&F<<SO?@R7V5JC2]WY@_!EYF8Z<67L>GY<V[V0/!E?CG;BR_##&O4
+M;\/U#SA?9MAL-?_Y\4?Q7S)D_DB=_(]DH'B_DJ$1[^X,?.^585X7,W3GR61L
+MQR=?)EL8QWR9.*54?)F;E%+Q9;IGF<[_;![O4DK%EWE+*`5?YD6I`+[,$U(!
+M?)D#4@%\F7MGH35EH/DR`;,05C'8%X;3:.P+PRAPEFE]^SS=M+Y];[[,UG3/
+MN>9(>M]SS<)TSSEM6^]E\/?O]('ERSP_<V#X,FYLYQKX,LG8SC7P9<ZE#2Q?
+MYGYL;P#X,GG8GA=?9D4:V@^Q@96?AO9#;&#-2M._HSX]0XLO$YZF>9^X!]L;
+M`+Y,)K;GQ9<IFB&:#GR9.5(!?)FI4F'FRQ3,T)UWGTX=&+Y,$[9S#7R9&&SG
+M&O@R[Z?\$'R9W2F(+_->BL;ZN`S[T3=?ILILL[?V=4_'_98B`J'??)D;4O3'
+MTQY9)^++_'$ZJQOQ9>Z9KAM[F;@-`\"7.3\-V;M^NL`$N")7IZ'O?PR3"U(!
+M?)DS4@%\F1/3]+__X;H'C"\S=II<)JN]??&Y_TU&?@1,,V%`S!A\DXPP8$W^
+M4S+"@&V17D[6QJ`1UWW-?)GPY/[R9<XGH?HCD]%>M']\F8/8SCM))COZ?)F5
+MTHZX>^A,$G</P)?9*JT#7Z9>*H`O4RP5P)>9*17`EYF2I#EGG$A$[>I.1/M&
+MUJZW$]&^D;GR4B+:-_KDRQQ,1-BP3>V!1-VQ/Q?[LEG:`;Y,02+:!Q@<ED2T
+M#^@O7^;45/P=,!'AR>KZCZD(SW[Q9=JQW7^9:HH37;Y,VE3%?YFJ<48+5/D+
+M_>3'[4\PQV'(5-,=V*<)IC/"?TK%M?-ERA,03G<FF/#WXLLL2=#E?\7C>R&S
+M72^^3*"NW8/2KN#+O!MONM__-%Z++U,5[WG6Z8S7.>M,BE?KK(DO<X?AR`_!
+MEXD1E@5?YO4XM%:PS<JS<6BM8!UU.`ZM%6P7M2].>ZV8&X?/.W%H[/2/+_-5
+M++(S3MJ1?)E9<:+G@"_#"FCZN`_;?CY6V)9\F3.Q^GNG8FQK<ZSR$VS])!;Y
+MR?JO6-_/SV+PNA=KPC(T5G=.?A3;^1Y\F0=B^L^728]1<Q/GR]AC!!*8+[-<
+M:C%?)B<&C4OFY,08S3'^?+0_OLS):#TNQM;HWO@R?XK6X<MDB/)>?)F?^2N/
+MXW^*>6Y/BC;-5==%:V+RZ!2\[YEBNB]CIHXHI>++_*-0"K[,?5(!?)D=4@%\
+MF1:I`+Z,=0I:?]CL4S(%K3]L]ID[!<4UFWV2INCUT5N3U7?1*5KKY<')_WM\
+MF71<U\K)IK%;,%EW['XRR2>GH&JR)`WXXLO,5J\57^:M2;*3%5_F=TJI^#*/
+M*J7BR_R]4BJ^S!U*J?@R3J54?)EJI51\F0*A%'R9#*D`OLP$J?#BRU1,@D;J
+M\V7>C=+%W1WE$_</HB2POO@RQ]5KQ9=9'25;KO@R%J54?)E4I51\F0BE5'R9
+M84JI^#*7)TJEXLN<$TK!EWE;*H`O\Y)4`%_FL%1X\64^F"@P[XTOXYZHO;[=
+M.-$GQK=-E"#ZXLNL4:\57^:;";+IBB_SH5(JOLP?A5+P99Z3"N#+/"85P)=Y
+M2"J`+_-3J0"^S':I`+Z,0RJ`+[-V0G_X,M]$>NXO4R;H["]?B#2O&9<BQ9H!
+M?)D_1Z*]'IOD7Y$*V)\\':G=?^5>]=TMZ^LO7V9H)-ZC>/-E+)&ZW\N?C5#W
+M"Q$:YZZ]*O\I/_GQ^3_"'U_&%:$[Q]P88<:O($+@!WR9N`@91X(OD^W'/GY,
+M_+]PY/.)</.^/%S[_W_'=G:8[>CR9<:&^^#+;`KO!U_FG?$>/)21X0(XR9>Y
+M.EZH@"_SWGCA+?!E7I,*R9=Y51:2?)G?2)7DRQP<KSU&DCW]W""-]9LO<]\Z
+M0NAV,ND!FMY(TX=H6D+3PS2ET9/T)$W3:?I;FHZAZ8LTG4[3.II:"8EHH"G=
+M)T78:;J`IJ_1=`E]WT)3&Y7?I.DX*I^A*44SZ4.:AM#41=,-]'T;3>E9,F(;
+M38?1]&\TI<?-I.W<CXA=W*^("NIK+?T-)49]+"]AVVCVU9\.8I;7>$;0'YW6
+M2!(Q_&-U&,]-]#<7WF40HVV$V60`3:6_F^DOC?YNH#]Z*B`CZ6\1,7PF=<3P
+M@7TT(4/HCRX5A(88*::_8/JC1R9"`6=?-@V?$NAO+/WE$@,+X[F%_C83_L_\
+MS*:_0+#!;&;2WW#P^3KZHSL0PM@5.?1W/?W-(@8F9"DQ^H#00RKK,U).#&P)
+M6TQI!+#K6@.+>/!Q+=@B@%DZY$V$-A+P/1EL3H>R<Z`-J8!-"I2IA+PSH*Z9
+M4*8%\LR',OF09QY@F@5Y%X`/RZ%-1=`7V8#)0L""0)DR\*4`\JR&/B1@VP)U
+MY@%6]8#Y8JBK$&PN([PO&R`O@;*B;TK`YVJHJQ3*5H$M`KZN(+S/">19"3X2
+MZ(M&PONH";`B4/<&:/,JL+D&;*T#&^OA'8$V.B"/#7QB#^O+&L)CV@EE">B:
+MP<9&PL?()L)CU@XV"&!#``,"OA(H0Z`,@3($VD#`-@&?V-,"Z6:B'C86A4-L
+M_`VE@V342"Z/`_GMF[F<!')V`)=9/P<@6Q9X?W8XERM!/A#*Y5J0+XY5?N+R
+M;?"^;B*7=X)_Z\"_!^#]/;=P^9]`3AK-Y:,@;P/[)T#N!'_.@&R/XO)_@5PV
+ME,N?F_SIAO<I4-_P`"YWC0%\`CSSQYCDZ9!_5""7LT$^$L'E(E/^Y2:Y!O*+
+M.'68WK?#^X^OY_(>D-?<R.7](%="_QT6]0\#O$!>!/Z]"/*[T-XWA/^3N?P^
+MR#E!7/X8Y)/0O]T@SP[G<N@0B)<;N!P)\A]@8DL&N2&,RW-`WC:.R_D@;X?\
+M*T&^.)[+=I`?A/:W@]QR'>`!\G,`VOXAGOC],[S_>`27GP%Y%\33JR!7WL3E
+MTR!W`;X70(X&?*^8[`\+Y.\OA7!Y+,B=0[@<#?(:D&>#G`/CKP#DT=#^2O$>
+MXGF]>`_E72"W07_N!/DHX'\?R,^!_8>%?]"_3X+\.OQ[=L=!/@+VW@#Y5X#'
+M1R`?A_H_`_E!P/,[82^*RR.#8/P!2)-`/@+]/PWD!R%_!LBAX$]>D">^Y?`^
+M!>*E#N1HB&^'*7\;O(\"^SM`#H/^N1?D,L#C%R`70'S_&N1=$'\O"'M@_R3(
+M1=#^#T#^$O#Z)(CO@5)6</E+>$_`_I"A,%Z@O2-!W@[S4SC(1\#?J2#?#>,Q
+M`^2W8?Y<"'(E^%L!\G'(7POR+JC/!7(0S&\[00Z!_/>"/'H"EQ\`.0K\>P3D
+M>!B/3X(\$^;CET`^">/K39`O0O]_)-H']BZ"G`+MZ0;Y$KP/">;KPTE8($<&
+M\[V8D$<'P_P">$T!^23T5QK(?X5XR0'Y*,P?5NNBE26YQ84+B;6MSFEMMC=9
+M6UTUKE8D-M0X;37.#:#:!#D@@\WE6+^1_TUSU:E\S?6MM0['ID8;%]VNIA;^
+M5XW36=/._VQJMS;641?RBTH7Y!992RV6BKQ*:V7N@J(\*\_AJJ6UFYUQVEI%
+MC6U6EZN]R5%G4R[8&YLWR1RMV-EZ5WN+<,?:V`S:U@W4Q'IED)9UV^'=%ENM
+MR^'D?]N:W4W\K[I&9TN-JP&*,[1:MU)'N;S>X;##7^TN&P+-[JC=Q"6[HWF#
+M\I=:D^XV0SX$HV@T-*'1;FNN:0))_67'0+6V4(0IS%S:X'2X6YH](*)5JAJ,
+M!K@:A24FUK<Z$(3,6JV[R6U7/=E89Q?F-KL=KAJ4DUG:4@-YG<R:U4-%Z[8W
+MM@*^M=0;ERFX/-O?XJ`=98.F;'4VXMP,FV:'J[&^7<D4<I=GCMJ:YEJEJ6]M
+ML-;4UMI:9>N=C:(WJ&N.%M3R^H::9ME0YIJ[V;MS&ASV.N$?:ZV[%1ESX@#P
+M=*W)X6YV*20X[!Z!P/([6^S0N/:6EAH:9W6>@8)LK7?4(1S,KM8W8.=8$)C'
+MB-7+654YZW,94!Y.JM'E:*G9[`:P-MA<1EQ849C5N%Q@0`Z])D<SS`GTG;+4
+M9L5-;6UO8D-:69+&G:UBG&[RG+98\W`_TC[G<X3-96N#(IXV65-4N^I;*5ZH
+M&U4^6UN+P^F27=ALS%^&4YL]NY]G5,-.=BB>NU@\N-`HQ2-2NJ)PL36[G.T>
+M,U]KXZUR6+?A4!:#5'8:-83&>!.:.NIYQ]CJ:M@XMC77H?[R')DXU*D]-0<Z
+MC3G)R#SX##Z#S^`S^`P^@\___8<=*T>MH^?==?IEV%WFW?2WW4++Y=.S.%Q2
+MLRO!L^6$E+&/$NO@KE?3;N?YR\87C,ZNSR']&TT#:/HA38?0]`Q-`VGZ)DV#
+M:/H:38?2]$6:!M/TMS0=0=,G:1I*T\,TO9ZF#]'T!IH^0-.;2'1A7584V^RT
+M.!VN:6U)6Z)2IZ5&I69FIDU/R9R>.C,J-2-KY@SZ7]1&5VU47EM+5+2'GT9Y
+M8S_NIW!:+X5%>;8![:/^F?[J;^[;_W1_Y>EFTD_16;@HS]_L;K4Y6W7+>-=G
+M[.?]%,_L%3!>GNV1H7@:+YZ:.CTM)6I&2E9::M;,U"BZH?:#MW-KC=W>>_7I
+M*7WT%]U/&Z=4/R92_>%M')S]%.XMV$1Y<3;T8\)O?P_&^V"\_S^)]\%G\!E\
+M!I_!9_`9?`:?P<?_PSZ+L^,Z.Z<SBH7@3D42Q9M*(8HS-8\H?E014=RHU43Q
+MHFQ$<:`87TOPGW83Q7WZ.Z)X3X>(XCS]*U%\IU>)XCJ]313/Z0.B.$T7B.(S
+M71'^!Q(2@GA*88B#%(OX1K,0UZ@`\8RJ$,?(AOA%#L0MVH9X13]&G*)]B$]T
+M&'&)C@4H'M%K`8I#="9`\8>Z`A1WZ,L`Q1L*1IRA<8@O%(NX0O_3KMF$1!5%
+M<?PRWQ\D%4)(+B8D"2$IB>C#P.R#;)$&45#8F&.((8TD%5*!!9$EJ-A*VVA!
+M&"Z2PJ@VE8L*"HO*110T"&&+D"*K19O.\9[;^;>Q>!*!S$;_/,YOSGOWG7=G
+MX/U6@R>T#9R@/>`#U8,+Y#PC]H#:P0&ZY%/?9]"GKL]MGWH^3WWJ^+SUJ=_S
+MP1VG>_?-'6?W`IR>1>#S%(++LP8\GJW@\.P"?R<%[LYQ\';.@K/3#;[.%;^Z
+M.L/N<VB=1UP]U3SQJY_SVJ\NSD>_>CC?_>#<@&^3`ZY-/G@VR\&Q*0._IA+<
+MFOW@U32"4],,/HUS>]BEZ0BH1]/KG",ZAVL!]6=N!=2=&0FH-_,BH,[,N#LW
+M^LPO`75E?.#)Y(`CDP=^3"&X,2O!BRD')V8G^#"UX,*DP8,Y"0[,N:#Z+QU!
+M=5\N!M5[N>P^WZB/P[[+O:"Z+L^"UCGF=7X7M/L:YTG(O-&%:!8^T5X4#EEE
+MB;W@G)!E><X7AVP]YR+(I<*N.&#,)F'9-=XN+*_/7JGGW`#YA+!-Q)Z!ON>%
+MY?VV1^HY#T"^*^P0L0^`?2PLK_E+J><\#GG*72^Q/X1E7]H7MBSOU0O"MIYS
+M`G))V+*)6F/6ABW++G69L/R,[)!ZSM60T\+6$'M,6/:Q3[F^-),77"_*/9`'
+MA>TC]D98U_F.ZTM_'KI>E,<@3PB;(782V*_`!B-:GPNY,"+7FZ+G-Z+KO"IB
+M6=Z'-TH]YRK(M<+6$-L0T;Y-PO+^T"KUG#LA]PO;1^P`]+WNV`*:<U=/>11R
+M1M@,L1/`3@I[?RG==ZGG'(MJSH_*]=894Q#5<RZ*2M]EQJR3>LX5D/<)6T-L
+M;53[-@A;1C>[1>HYMT'N%;:/V'Y@!X1E$?^FU',>@?Q*V`RQ;Z(ZS^/")M8;
+M\UGJ.;,,[O+"F&7GTX^3O)C.<R)FV9I28XJEGO,&R)7"5A&[.Z;S7"UL@GX4
+M'7*]*+=`;A>VB]CNF*YSC^M;;LQ5UXOR,.1'PCXG=A38,6#?0_T4Y%!<KI?V
+MTGEQ7>?<N&6'-ANS)&[K.:^`7"YL%;$5<>U;)6SK%NHA]9S3D$\+VT5L&_3M
+MC,_:1?Q+__#_28<SF88S.H6_ZX-9:?!/TN`_\`2S;N!LW,"9?<"L!CCG-$#W
+M1I&/%S>G37TJ59),I>EL&@_6%=/NFZP_?/37@63*)(^DFGD1[;_IH?7(NI>)
+M7O'9G3G?$8^D?:GHE;;/@D=X^AGWR/*[1(^L>X_H%>>O#H^LVS(]XMGYSL[W
+,7)[OGZ.=52GWA0``
+`
+end
diff --git a/lib/compat/compat1x/libskey.so.1.1.gz.uu b/lib/compat/compat1x/libskey.so.1.1.gz.uu
new file mode 100644
index 0000000..91d8512
--- /dev/null
+++ b/lib/compat/compat1x/libskey.so.1.1.gz.uu
@@ -0,0 +1,247 @@
+begin 444 libskey.so.1.1.gz
+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
+L;!T*WIZ>;?ZTN3.N_865A?$EU/]NWYW/5R)UM+1AY!<6^O\`!^*N:-QF``"P
+`
+end
diff --git a/lib/compat/compat1x/libtelnet.so.1.1.gz.uu b/lib/compat/compat1x/libtelnet.so.1.1.gz.uu
new file mode 100644
index 0000000..0cc9cb9
--- /dev/null
+++ b/lib/compat/compat1x/libtelnet.so.1.1.gz.uu
@@ -0,0 +1,63 @@
+begin 444 libtelnet.so.1.1.gz
+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
+LLP8QW!Z^"[!:F%^&I_N\`<1TLAY_)PN<NGEYM9-UKP[F\'\#[[3E%#\D```-
+`
+end
diff --git a/lib/compat/compat1x/libtermcap.so.1.1.gz.uu b/lib/compat/compat1x/libtermcap.so.1.1.gz.uu
new file mode 100644
index 0000000..54a3cc1
--- /dev/null
+++ b/lib/compat/compat1x/libtermcap.so.1.1.gz.uu
@@ -0,0 +1,75 @@
+begin 444 libtermcap.so.1.1.gz
+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
+!`'3Y
+`
+end
diff --git a/lib/compat/compat1x/libutil.so.1.1.gz.uu b/lib/compat/compat1x/libutil.so.1.1.gz.uu
new file mode 100644
index 0000000..53f55b6
--- /dev/null
+++ b/lib/compat/compat1x/libutil.so.1.1.gz.uu
@@ -0,0 +1,208 @@
+begin 444 libutil.so.1.1.gz
+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
+J&"^%6PO%*3H-=4_)+8;L[R9?17SG"_4)+8+R5'8NK^Z_`=`L!/1I80``
+`
+end
diff --git a/lib/compat/compat1x/liby.so.1.1.gz.uu b/lib/compat/compat1x/liby.so.1.1.gz.uu
new file mode 100644
index 0000000..7f8c710
--- /dev/null
+++ b/lib/compat/compat1x/liby.so.1.1.gz.uu
@@ -0,0 +1,18 @@
+begin 444 liby.so.1.1.gz
+M'XL("-,.%RX``VQI8GDN<V\N,2XQ`.V9SVL341#')ZT_TE8DX$D0C$HA%4FR
+MC4&"($W:IA2C*;0>Q!_/97=;%],D[*:0>*H6!`U"S_X%'CQZ\!CH1<$_0#R)
+M($0OBD<1UIGM;#9=+Q5/RGQ@]COS=N:]Q]YFYRT\VH0$@&_(.[0DA%Q[_&FY
+M3\Z-!SL7,*=_F1Z7\+'4S^)STAW?DW,,U[R-^-.M#U\];ZF[=0"7#SX'2C^.
+MK[1>]];/-SOA_@XN'@8X=Q]U!/4AZ@3J$]115!,5]SCA[X,6`S^F=U1'-0/&
+M..<06YQS@/UQS@'V)]@"_-Q$^)[B.QR?XK,#SD;B7"0NT%WP<G,<E_ANY_G"
+MBY'\*N<G@^_.YW_C\V_RW8-8C]0K-7?]:O'*XBQZ"Y5JJ5A1U7)Y>7Y%K11+
+ME7D%JM-IZHYK@5IM.G:]M8J)RBW3NN4X#0>4U;+:+92VC<]UW:ZC;^HM':5N
+M4K:_)@B"(`B"(`B"(/R34%^<P)XRE=A_#?7$=]$VT:?6/LZ-*/7EK]&O44![
+MLA+;GW]XGH?:_\[Z!36&^A%U!/4]ZBC,I,Y,49^9-L;RZ5PR5;*<>U;-ZDPE
+MM8R6RQ2TR%THGSM8OV1ZN"2?T?*90O9OOH\@"((@"((@"((@_`]0STZS<NK3
+MCT(X\YZ$<'Z=AG!VG8=P3GT1PADUS;>#^?0"ZDG8S:GR&>3?'O*;=&X,8!OS
+MV^@?03L-N_\4J'8&K<OYY#\;\E]P;0]K7PZMO^)]Z.X]V-],?._L^[>IM_\K
+MPFW`FF%,*Z.QWK1KEIFF8?A:?6.PH`Q0KF&XMCG0X)_$G]169K,#_Q?(]\^5
+$F"$``&%,
+`
+end
diff --git a/lib/compat/compat20/Makefile b/lib/compat/compat20/Makefile
new file mode 100644
index 0000000..a9849be
--- /dev/null
+++ b/lib/compat/compat20/Makefile
@@ -0,0 +1,23 @@
+# $Id$
+
+DISTRIBUTION= compat20
+
+LIBS= libdialog.so.2.0 libforms.so.2.0 libg++.so.2.0 libgcc.so.261.0 \
+ libncurses.so.2.0 libreadline.so.2.0
+
+CLEANFILES+= ${LIBS}
+
+all: ${LIBS}
+
+.for lib in ${LIBS}
+${lib}: ${lib}.gz.uu
+ uudecode -p ${.CURDIR}/${lib}.gz.uu | gunzip > ${lib}
+.endfor
+
+beforeinstall:
+ ${INSTALL} ${COPY} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} ${LIBS} \
+ ${DESTDIR}${LIBCOMPATDIR}
+
+# Get all the fruit, even though we don't set PROG.
+# XXX bsd.lib.mk has fruitflies, e.g., it fails if LIBS is empty.
+.include <bsd.prog.mk>
diff --git a/lib/compat/compat20/libdialog.so.2.0.gz.uu b/lib/compat/compat20/libdialog.so.2.0.gz.uu
new file mode 100644
index 0000000..f3231e5
--- /dev/null
+++ b/lib/compat/compat20/libdialog.so.2.0.gz.uu
@@ -0,0 +1,486 @@
+begin 444 libdialog.so.2.0.gz
+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
+<?`)I/GQ"%0FS(AFNL$JYK+SS_G_RJ@X[1N<``"X1
+`
+end
diff --git a/lib/compat/compat20/libforms.so.2.0.gz.uu b/lib/compat/compat20/libforms.so.2.0.gz.uu
new file mode 100644
index 0000000..0baf3b4
--- /dev/null
+++ b/lib/compat/compat20/libforms.so.2.0.gz.uu
@@ -0,0 +1,78 @@
+begin 444 libforms.so.2.0.gz
+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
+-!#EZ_2^C!929\C,``#[\
+`
+end
diff --git a/lib/compat/compat20/libg++.so.2.0.gz.uu b/lib/compat/compat20/libg++.so.2.0.gz.uu
new file mode 100644
index 0000000..d835d3b
--- /dev/null
+++ b/lib/compat/compat20/libg++.so.2.0.gz.uu
@@ -0,0 +1,4306 @@
+begin 444 libg++.so.2.0.gz
+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
+FS'-?I3.Q='RITTB?!Q,G04Z`/`V9V-KEA>J6Z/\#C*%HA.C7!P`Q
+`
+end
diff --git a/lib/compat/compat20/libgcc.so.261.0.gz.uu b/lib/compat/compat20/libgcc.so.261.0.gz.uu
new file mode 100644
index 0000000..65766d6
--- /dev/null
+++ b/lib/compat/compat20/libgcc.so.261.0.gz.uu
@@ -0,0 +1,174 @@
+begin 444 libgcc.so.261.0.gz
+M'XL("-%0XS$``VQI8F=C8RYS;RXR-C$N,`#,6@]T4]=YO[:%$4:)!!@P8+!"
+M3,'@4)22%J4DL1V>0Q@*AB!#0D#8E@QRY#^1](`RE#A]<;*7=]1HHVG/LIZ-
+M=EO:]:2K3T@3%I;6)AP;,B<(XV/DV`8U]1(9:YGCXR&E1['VW?N^IW^8A&P[
+MV][AZ;[?_?Y_WWWWSS,]Y/E6LHX0HB/LVCF7$#U)7F;Q7R5.K?TUISG_KH)-
+M&D,O=$8^@RZ9#EU_&?F<<J311;\L=(,^F9^297[HNA1BO(C-ZDL?B1?%<]/*
+MR_S16^4?YM1#O`XIB$WI>""H""*=R^"WI6`AK*,BGJEZR3S5^H&F7C3'!AIC
+MPWO'A[GQP;W1@<8IB8NF\JL'*'],,L?>U(AF8(@*8=5@8?%N$,OP&/@'.76R
+M<QH,LM3^WM@`ERG-Z`,9_`.<)I#HDNEI\0(.V#2I=$W`E,X?X#5I^1CF=!^.
+M7@VVCFQJG2S3OMRQ(@XDI1Y?3=<-[553*M<:R]+^,(6JT-^.PZ4P3?6TQLI<
+MV89>'"]`-_0J1'X&XTV,-)3/@D=DF<&C:&K\G.;F_MT"/;!7PZQG."_3F4-)
+MIAOL&WI3-$`&TD*@\M3Y%);,^&'\[:J6>)WDR:=OV<<B%X41"$-.Y,8E+B9R
+MDY()WM@+VE_SFJS/<DPQT30I`<D\Z;6%]EG2APS35[JK^M$017N>?7='*2'=
+M7(PBB5>+_*3$:T0^"O9$OD_B\T4^('BBQ+,*F*C;H#;RH6@.2Z9H9*"MUYWU
+ML&@:E_@PDQP'2<$3()[B"'AH[J.<(Y(ID.`,2?P(TQL"O0TDS@?B?%^<C\;Y
+MR=#H&D)$KD\T@\$8<=^!\D.I\D&)'V+R09"7N#[)'/#:SNU)1LGB6Y\2GW,-
+MC6\R$5^8Q3?.XNMA\?D%SSB+;U*.+XQ>CV=X'69>CPL>/_&`<SWHG#_#N1[F
+MG-]KCNZ(\_XXWQ/GQ^-\.)0'C@B>2>)>(9FC$E3)'PG0<-^+?-C6X<[:`G%+
+M?!]+?4#D:7UA_O#:.O:DE1#B2X3VX]6$-!#)G"^9=#NV2V8-C(,=VT,_A6YI
+M;RPQ?\-\E!"Q`HUZ=H.0@PHQD]+>R71[,/C,=`9G#G<E_;TLCHM_]-JBF?X)
+M80V(P*1OU@@>'7%O_JT>"&MHPF-MUY^9W\U%*6?DBOB9V'_I4Q@X8T4^L1]2
+M<NEC8*%/.MH=%<]<NC;;'!/-,)PG(6E>6SAS.$]GK_(&>ZSZXF>1@4M!>'G`
+MFL\G=E%[GU)[7=0>6)Z\]!&S%KVYM?\7]C+S*5[L_+Q(A-=13N@43>BRS'Q.
+MW7H^=U4;XMI_-JMQGJH0^_EY@#5)[,X1NO3353_I;V+$3:RDPSZ?'*N1N/PU
+M'"S=NLYK125^(Z=Q+8CS^7%>%^<UU;M"E''T.S`7^B13_L51-HGE=P:+V'*O
+M*SFSQ#0)08+S(+1C.PAT@L"SW6"E=910,44.)A[-Q6LTKR9-Y^^+)$YW,91U
+MCDZ3YIC1K'&5[:B"&0<4M*ZD8UXG!+.\ZUM`^'IGEO:YWX!"XY3K"3%:,F[D
+M\EUUXG@)O!;YWO550O?4Z(_H/&**&4U1UT%X7\I*.FGFJ5,QF,.H6ZM!:^2R
+MMS)+XF,E74G]YOSK9[+<CQFGG#-+IL:VTS$AFW!JF0D^/ZMKVYB1]E-H`HN;
+MP>+82A_D(1(P<CKG[;]C,Q2OR^'SQ[2^WTVQ^8J^R=[U\"JKQ;M%*&HH;<;(
+MRL[.@4N%UXR,*_<KKIG_S4O]?WPIZP$,(='<!UD536')HX9%H.T\WV2<.+1`
+MC(H3$9AXN1'Q<C<7I#D;*_4)GC[":]G2+/H-O8RA3QS'IZ#8+T85(<%30+3/
+M[056T3.N+#7F`EA`Q#P)!NT6U6@9&Y]&/GSHSFYNA#*@)5GV#EEV5,W8?-IW
+MS.'6B2)8$-IZ^4=`RCG#Z.D[K`-1ZL\:3]\2/CRF]DVGJI\P570U-A7`+D#,
+M@G==+%>-OD.8[K?9W&$.T*6+@T4\0*>H'EA)Q8N70K"HS3K#UO;`)1M$*YF&
+M+H5$+D0Q3"4]8I3US.JB'9\`W1R*P,H/2>B/`#_7(YK]QHG#N?PB8_30_+@)
+M%E&_Q/6LX?J6F,*BR0\<*<ZZ[UKCZ5G"^V4[0:KSWT6/?Q;=U[!E0>(*)/.X
+MJ(,MAUBEDDPC\*I)D'LNL3B>G7[^@H5>\M!9`^IMO'`L]YGYQG[7#$/'V%R?
+ML?^P^A3-XEBN[U0VM!E3V#3RSMS#MRXO7^-E\KX]91Z\MIQM0$`O[K;:XIZ\
+MR!7A,HE<C<,N;D+\7'P/)G+#^>T[KI86"V?57H$,Q^/#9.C\E?/B1++_2B?;
+M'V4/!+VV\3W3K!D)^^H4^PTI]J,WV(\^"U-)$3DT+](5GTF(>[8XT?J!&ESJ
+M%R],ZUKK35V+,M?DXPJL,-,Z&"S'MC-C?W+V#D+@/.$]KK\"^K,#`\D=L;/P
+M9D>JL1*?SWM\%9.XTGDSKAETI4C?W,C7-K@O9/BQ\0ZV)?<>;P>M`U_+CS>8
+MQ'_!#UHWS`MI?:`,U])U*35\52]GY_2ZJW!<6I@X4,P=#IRB+&_3G]$A^/%Y
+M3VX`GN'<P.?4#R[VA@9V(LP/]=6-Q8\_!HZ(_8:X&#%<A\VJZ.G;52V7<-`3
+M;B!T9P[;<O^@)Q"J!:.#C0$AFN71>4^6@=;!M8.-X2N=P`DM*!PN+-YG$6&+
+M[`D-<R-71KTGF7\+$OY]`\;#S;PPG"\Q^Q>9^L:6^[Z$)\OLGV/JDS@_'`K@
+MM4\.JM3]\`M%+#T#GV*YW+?+SH5^#H2Q^;Z!(.(?`XX$A%X2^3"Q49[V^HIZ
+M+"B21\GICN!7U^-<\'^F'KW+4NOA#]Y*/9A__^OUB"QEZ4FKAVH`\E^T+%$/
+MAK7+;EJ/5'T_7THC3]>G&=Q8'+J\-*&/X>ZEMUA?N;9%9<GG1)U7I=1YK6S8
+M>_K$1Y#M;Z)Y?EY:F=^G988ZOT9YUMY2G0.B9^B&.@_!H7C0$PQ=*Z1&@UCG
+M4Q]EU)F6]81L"MU9]155#2PR#8T5PQ[@2^L:F&."G4%`,@]Y;3W3KRXT3UHE
+M3ZEK7&[AUU_C@G^`&%9]W36N=5E*S99UW'#./;9$KMCQ_2.@?O77F;\=3.)6
+MYV]YO\`VE+#5AX/Q(I_O1>U#+RZHW'#1G:=]LU/[9F^)?VS&9G[4T#'-7B%U
+M?'<O)B0T;PG;IZ704^9_8$@<F>*0Z),J(#S;U0Z_U:'1Q?1WD"KY8#%5<H-\
+M_6)6G[;K_-S?LCW,;)\DJ.%!(G%_=:@=R,)9%00Q"I[NV8??IQ+B*YEY=<BW
+M./F!(94^D_:;U9+$5&;!YC57.JZ!9W$.8Z^V.]U\C4/?:&ML=GY/;SM29[-9
+M;5:]O4F_O\EV>&5>AKZW%A'2L-PK%'X<CU<U9(=6@?Z&>&@1#6ZZ_+VPB)[G
+MU.!_;E4H)\7)F^1[UR(YGN"BM'BJ)1,MIZ&W[;QGEC"ET[[<H7W3+YYKZW5G
+M1P+B11\<`JZ7MW7P$?$<G/'.OUM#:FO7-O-N4E'CLM?I:QW-=4_J6YS-]7:'
+MO>F`OM[>9'<=A#B;F_0K7'FDTNZPP4.I?H7#JJ]-BKCT>7ED8U-SD^U^HH>K
+M@NFY<\5JZ[V0*UL=[P8=*U:#D-O>:%OE*M'76*U.F\MUGW[=D15K5SN.$'T]
+MWU3GMC<WW:=?<==J%]&#`[;[F!#0P"X\NT@>R<O#7`CAS2GO;V4![&>%29IN
+M[\GKT%2')@OH1[DHO)(0\.W5H2'`HQ/9;(QZ^5AUZ-T".NI^`[]57N$+*@J'
+MZ]!>P-)QJE<XF]_6JWWN%]F)SW#"T8*5A^8^>[0@E$.(]J_E+ZIP/._FQAF9
+M?B/3"D?U1/D0"^>!;BZ<2BM.H86E+1K1%$H_#'5S0W(3D)L^VC3D;1?-':%%
+M<&P6.7^<A_-.1]RI\@IW?H)NO[J0$,-UX2R<.SJ,?$C[@U_0D;Q%+9K.^NCW
+MA1&).VM4/SU#`KLCTE$X>0\9-6\=RI4VO@53.?V.Z)XC'=7#(<6H>NMIN3O(
+MG%XI511*&]O;XGRN]W09V%O7$?LG>IJ?^,?(1?'"-CC@>7)@V1<\8<9<_.7,
+M`<H<$+BSJDKJYTLU0&R`66&(!KCA"QK@N8:\.#\26L-`#P7!T#(*NEF$HU<)
+M^V92D1]?WQ[GSTD5:O;0XZW,@ESXO<)#F!6JTKN`5E(/:6'1K*?1J-I%[A2,
+MBEE>B?HHFD[%>?C7YQ6>3I%\E$GJF"2DITBJT(.=75[A!RE,:U.8('X#C3^I
+M7F#J.:K>*[R2(A:93\7@H-;A%?XNI?\JZU=78A5?6@C92>=X9SY]]:.A7R4T
+M2#MT,$[;=G]!65]5!L3+R/?^?'K2>TU>B=+FU+GSV9PJW$_X$N$TZ^5GQT_2
+M/Z^%7@):=RZ=:26!4L1*G7B2/B2F5ZHK<[^3U/UF/I4LI`(M*N&(BK@U4J[0
+MI8K[J;E)14N:S/>93`&UJ1/^&.<7&GJ9I%;H4,$8AM\*80.!N:N_[;I;ZT-6
+M57O<_P@_$3^93_V^G)]P,6W^AV[A]#$:#Z_M%N@#?0X=HY^AIED/(O/D]4`X
+M`6PP*R\&^\8JU>'9QBHUO#-T^?%)91JH,:R-J."&[X>OSY,GZ;^E?S+I,L3!
+M:RM,T*+TDRSVAPOJ@?!T?MR]Y6VZU$B:!:(I:F14YVIIZP*5:)J4H6M)6]R=
+M[U4]TQG,-F[-53EG2\"IR3V<(WEBPAD-[%"$8PO4<?XTO'@SX;1_&YWC&+NT
+M*5>=_+"6&N,\YAY=C$,7Y^$RDE:/B;EL?#3H0MN!+G:*!JE2(Y:K)!@+Y6IO
+M=8'P=$'<O53*-I:K#N500H7*6*ZFCVIP2K@WSO]!SJ!8KA$E^I`</82T\$Z;
+M_E!B874?;+;JZVH<#ILU+\W/)\&-AB5>H>7?Y+5T:"Y;2]^?F[*6TNO%=83`
+MH:?T+Z"]#]I7H'T<VI]!^UUH?PEM";2O0VN`]NUU;!"4GH%V/[3O0?L`M%9H
+M'R*DL!?:!P$?A!9V-H4?0@O;@]*/H(5==>DU:,N@=4`[!^@3T.X#_$=HC=!F
+M&]@!O;0%\#U`SP-L`SP7VMW0+H9V.[3+H;T?VM70UD#K!GYX<0J/0`MG^<)C
+MT,(IH_!NH"\'^@8#LZ<)&-B?PC6P%%%^,AON'7#33SO`3TKA?A3N%7#?!3>=
+MA0G2(`]D%M+H,(3X".23?(>P&,EZN.EN\5ZXU\!=#S==>,$?<AMA\1/8I=!\
+M$PYN.]S?AGLSD?\\OQ+N7"+_?9Z.[2+454%8;=CU35I>PF*B>2=T0W@GW#/A
+M+H;[=J1ID1=B)JO@GH>QT?>=_G<`F*G(6KAA(J;Y)+`0DF_`36>'N^%>A#'0
+M&$V8J]48PW?1MTKTU8`QWH>^/(*^?`MU;L38OHV^;,)<<JCS'LPU09\VH(\/
+MHVXC^O00ZGP"<UV+LF58@YTH6X4R]Z.OC>C#@]BW'W.WA20OJL.!M=F+.?\3
+ME"'H\^,8\U;TQ4+DVE6CK[M1YS:4/8B\!'.X#W/S&/(0]'47UH!>="R:B3P&
+M"<9$L(^@K3J4J4&;3Z).@C[2:P^V3V!+8[*A#U;TG6`N".JB%\UI`]HX@+P$
+M9>E5C^T!;`]B:\>V`5OJ4Q.1<TJO1I*\Z%AE!2;R^Y&50J/C=0:\C.NPLU#!
+M.3)>@7@\6\9K$>N0?X."D;\<L1___\M617Z^C/<@#J;$23%[L>!J1G_WH[_/
+M(WW3$AG_"+$/[?T-XG;$_X"X%?6_0?6!KR&#;*(+Z2<6R/1A11_&]['B+\J/
+M*_J1_CGB,J3G9,E8C_3;$.L0+T1<-E/&RQ&?*)1Q)>(J]'];ENSO!O1WG\*/
+M\3^5E5Z_(XC5B%]0_$'\YPI&H;_*X/]EAK[7D;\%_3F-.+Q4QO^"F$U@</T>
+M<0?*AQ'WH;]Q)3[,-\T+Q1OGR'@9XA/HQ!K$!/-W#V(?TBL0MZ,]DX)Q?.U&
+M7*"5<;TBC_2CB(OGR?C/%'FLSW'$@7P9_Q2Q'^VW(]84R+@#\7Y,Z`7%WNTR
+M'D9\\#897U/T83YBB$-(GY4CX]?0_X6(MZ(_Q3GI]5J7@3=DX/(,O!GUC>?)
+MN!JQ%>O;F,'/Y\CC,8#C\7GD;T&Z#W$5YO<G&?(_0WH0W^_7%'ZDOZ7X,T/&
+M9Q!O0G_Z$2M*@SGRFN];*^-/D-Z.]/_(L/\%TM?ERGBF*IU^FTJ.;[=!GC,6
+MJ+"><V7Z'8@[T+]2Q.NP?@\@'D>E#R-6-GT[,^SM4?1C9SWBH$;&+8I^Y/]3
+MQ'H<7VV*?GR_?IBA_Q6DMZ/_?Y]!_U4&?@/YJ_!]>T<ES[_JNV5\5B7OP11\
+M/D/^HN(_=@XJ_J.^$07C?!=6XL'Q'D'LQ_IDS\#QA?*S$?L1YR/>C_P6RZ;'
+M'BDW/?P@L=34-CO=T&&IMQ^QUKOL]/&`VU5_-WVP/84/-5:KM?Y;]*G)AEV,
+MW\KX:WF[PVUO`MIA"JWV0\A,G^STZ:&MVRK*MUJV558^RNVT["ROV,I9F&2M
+MQ=YD=UOH%R**'8KV1MXA2UH<KH-.%WNT'0%.*]_8^#V+U5;G8`9L]36\PTTM
+M6P[6-%D=-B<+P&9-JI%=<;BQ"WR2U;$GF0AL^%3C.J@8KK<W6>''Z7);Z$?!
+M%OH%R^*NJ778+(TU[KJ#LB'T-\,!:[/E@*.YML9AL;J;G2YTGE(V[=RVP[+U
+MX4=W6BR*9=F<BZ]%5Q],97&YG76-+7($:(N>KBQXNDI-_R%;'23$87/;E$B4
+M0!/>U,G>N&PWI`S*R3>Y7%C1>D=SC=ME=]6C9Y@=[+;6HP$LC,76XK0WN>M3
+M];C21H:KYI#-:3O@2G(<04M42R+A,D$6M1UQVYJLX)`<-(P45G]EI/!0/<MA
+MBPN:I*PR@)F?5O13\2&9&B2[ZE,EK:F21X!$55N><C8U68FEQ>9T-D.>_K.=
+MLX^MJKSC^.T+!4I;2[G*RY@CL@TW">E09,#<=-4JIG$.'7^L<^6VO;>]RVUO
+MN2_%,66""1HWA-'-J4'6U8P-$V$L)&,O3$7^8IM5V3)EQ*C$#&:JRY8($N;V
+M^][G>^[Y=EO"<QO&7_<DU]^GO_L]SSWG.<]Y7L[W8"(XT769I"L+Q]&7[NY.
+M7H._[!R3V5P\$[88.^4^6_FFN\8WX$R\\..V)ZNPIZNKHY-7.MO*[U@Q^5"6
+M#[.YWDQZ74?NZP/2'OOC/87ZLA.]N]#<<AFK+ZL6)&.YH!%"EK0,'MD6?K#7
+MVC4K(V@"^>+-.ZZ!\1ZW$M@:4T$[ZPI**Q3B+H2=4.&'7'$\AT0BRV17*A[+
+M='3%NGIMQT0F'NSN&D<BD<IG[;02Z8%XO_M1=W+=L5S,`BY,HBN5SL;91;&5
+MQM<&=W\L6=@O'QY&*KR_>X(>(17T%BFVQ?)VD3<,TXTV>%_9?%YI<<-:YS[[
+MS+O<YJVVT-]VA<MCB!^PA?L\S#WL^X(9>IYRMYTZ6WB"LNWDWQG_:K'"XIL6
+M*RT>LUAE\66+U1:/6)QD\9#%&HMX"7&RQ9]9G&+Q*8NU%D<LUEE\W&*]Q>T6
+M&RP^9+'1XB:+TRVNM]AD,6,Q:O%K%B^UV&GQ,HM?MCC3XBJ+LRS>:G'N>>L(
+MTXM@F5BHXXA;XUP?X5KO(@C*6WDK;^6MO)6W\E;>REMY*V_EK;R5MV##XK'P
+M:+K9O1L0>*NS`ZYR[PL$GNI5D=!/71)PE?/-`Q]U9:"_U/G/@7_:&0F]4_B^
+M@6]Z?R3T3(<BH5^Z(Q)ZI;LBH4^Z+Q)ZI,]'0G_T6+"O?4X$QV!Q+"C'/N]%
+MQ`\5+[16?-"H>*`?$?^S1;S/-O$]V\7S[!>_\E[Q-HL^9X7S.`/-L/B7N\6[
+M_(7XEJ/B61X3OW),O,H/*D*?LDX\RMGB3\X7;[)9?,D5XDFVBA]YIWB1O>)#
+M#HH'N5'\QZWB/>X4WW&/>(X'Q6_\K7B-KXC/&'B.\!A/5X;^XB3Q%IO$%YPG
+MGN!2\?]N$>]OE?A^7Q6/KU?\O:QX>QO$U]LNGMX.\?.>%"]OG_AVOZH*/;K#
+M5:$_-UH5>G/'`KV=[UCPN[;/Z:K0CZL4[ZU>?+>9XKE=(7[;0O':5HBOUBJ>
+MV1?$+ULM7EF[^&)Q\<3ZQ0\;%"]LH_A@WZX./;#O!7G[[`R.WS2[J]T[0;@7
+MX.%5DY\7_B,U.*\WF`?_31A^&S2X?^LGN3QXKO`B:G!-ES,/7BG<3@W:1H)Y
+M<%[X`6K0YPPQ#QX1WD\-KM>SS(-'A=^@!O?:&//@<\(--4Z#>WQ.C<N#/R&\
+M@AKTI:W,@[\DW$,-^KT,\^"-PD/4H#WO9![\M/`SU*"?/\(\^%7AMZE!G_8>
+M\^!)DT.>.9G7U'@^\^#%PC=2@W9^._/@#N&UU*#O^B;SX(>%AZE!O[>'>?!!
+MX5%J<,^^QCQX3/A?U*`?NV2*RX,O%VZ>PFMAO()Y\*W"7Z$&]W4/\^!!X0>I
+M0?\\Q#QX1'@_-1B;GF$>_(+PZ]1@+'N;>?!9X;JIO!;&ETUE_1M_3'@I->@K
+M;F`>?+MP)S6XWU/,@[\AO(4:C,7?9QZ\2_@`-1B7#S$/?DGX!#7H3\:8!Y\3
+M;JAE/6/<JF7=&B\07D8-YBHMS(-7"7=3@SE//_/@>X6W4H,YP&/,@W\B_$MJ
+M,*8?9AY\5/@M:C#/>9=Y\`?"C=-8/\8?FL8Z,?ZD\&>H0>)FYO&?U<*]U&"\
+MRS(/WB3\76K0APTS#]XK_!PU&!]_SSSXN/`[U&`<?)]Y\)2ZD.?4\7XW_CCS
+MX"7"-U.#\>4.YL&=PCEJ,$^[CWGP5N$?4H.YRM/,@W\M_`(U&$-?91Y\4OAL
+M<,S&M?4\3N/9PE?5LWZL;2YG'KQ2N!U<X3A1[][C17^[EOMB?+^'>O"WA)^@
+M!N/O;N;!!X2/4+,&<ZK@V"S^1?A]X7\&OVMQ6@-_RWB.\$+AY@:.B18_QSSX
+M-N$UPMWD!RWV<M]&F\NM8QZ\6?A1X1WDJ/$P]]UFO)=Y\&^$7Q3^`_E1XU?(
+MP\;'60[6*2>9!Y\6GGH)ZWFZFP=7DQ<(+Q.^CGRE\0WD9N.;6`[F?E]D'KQ&
+M.$,-YFD;F`=O$?X!-7A)>P_SX(/"H\)'R77&?R+/,OXSR[G>YL^GF`>?$:YM
+M#+FAD7V"\8>9!R\4_JSPY\F_,V[EOIAOKV(>'!/.BF:3Y+\C_*1H]DG^6>&7
+M1?.ZY-\5KIC.]F-</YWMQ'BN\")JL`Y:SCQXI7`[-5C;)I@'YX4?H`9S^R'F
+MP2/"^ZG!VNTP\^"CPF^1[S$^13W61Z>9!]<TA3RKB>W$UHP?91Y\M?!-U,PS
+M;F,>W"[<9XQ_I72+K5\&D:]T^4W4W&F\F;S:^"'R7<8/D^\WWDX>-GZ$_&/C
+MQ\FO&>\DOV,\0CYKO(M<;>O'I\@UQGN;7)^)OP_P7+#>.40-^"7A$Z+YA^0K
+M9X0<G<%YH_%\YL&+A6\4S6V2OTLX/</5VW&KMPTSPN/<PGW7V!KJ$>K!/Q+^
+MN6B>D_R+PF^*YI3DSPC71MTQG+%CF$L^9[R`C'\H<5W475/H[XB&QQD7'A#>
+M'&7;L[7PUBC;F_%.X9\*[X^.>\^Q_(+C__D%QY+?;"R_T7BQWVCT>EO1^RW%
+M"_Y^8OA>X@5Z(W'"KR+*2XC_\ZW#"_JV(>^41=ETQ*IW<4=7NF\@::I%A=WZ
+M\\5$AS43'KN?N!0MKZ&?N!0MNS=OL7]=Q$HI.59*R:Z#]ZR+0@_LIW7-W_.`
+M"R.2G];UL'Y:#H/>XJR_..A+2Y)G/>5A3^&GE][6N\*S)5Q([P-Q@XUW8_+6
+MNM'=LS+6>E=#H;OSDQ;Z-$^I?ZDI_U)3_J469GJ^->`M+4PD?6O`6YKR+S7E
+M7ZJ;<?IW@"4,!M[:?"D%YTLIV4T=_(<D[X(YAON/,J6(_0_#S53\:YDS2?\=
+MW+303X_ITOH.SM"*Z.8]GK]8BK@X^?62M[4T1\()<0F[%"?<WONTM7PJ(NN#
+MB>R':7I)^[6U+(X$:U/O09P+H0G]D/>.P:2YE*/RUH\_JF!-4^K5O7LB5RE7
+MXCF5H'?GD?.<`A677W[RP5@FENG)>HZ/;L'K)TX/8-7EK1WT%LL2WO_2VB^X
+ME;#_`9G>3]S9Z:OKZ(W';&G8G^^ST;,GF<N.:[)M+5?;YQK[++'/M?99:I]/
+MVV<9-,U20F'IZ_>KLFCUG43'^@;2^/^O>;8X+&K]I'C,E8REDNOM^VO_ZT\\
+M5/`\)SS0\6RSO;Y+`3S>X*.M@72VF!DH?AD^^DHEL[F(>S;V'U]-J"`\VO)N
++RO\&%(^I,PAG``!+
+`
+end
diff --git a/lib/compat/compat20/libncurses.so.2.0.gz.uu b/lib/compat/compat20/libncurses.so.2.0.gz.uu
new file mode 100644
index 0000000..645c357
--- /dev/null
+++ b/lib/compat/compat20/libncurses.so.2.0.gz.uu
@@ -0,0 +1,562 @@
+begin 444 libncurses.so.2.0.gz
+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
+L<NE1P-E4TN=8IY.CDN'FH[ZSP=)GWXK8)CY<\Z+B.\2R-7P'BQ7]M@4'`0`I
+`
+end
diff --git a/lib/compat/compat20/libreadline.so.2.0.gz.uu b/lib/compat/compat20/libreadline.so.2.0.gz.uu
new file mode 100644
index 0000000..6e030c5
--- /dev/null
+++ b/lib/compat/compat20/libreadline.so.2.0.gz.uu
@@ -0,0 +1,1199 @@
+begin 444 libreadline.so.2.0.gz
+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
+A0UZ[*LNNP,X$:]$R&=Q/&&+96N.7;>9_`8NWL`*8'`(`
+`
+end
diff --git a/lib/compat/compat21/Makefile b/lib/compat/compat21/Makefile
new file mode 100644
index 0000000..0fcb691
--- /dev/null
+++ b/lib/compat/compat21/Makefile
@@ -0,0 +1,22 @@
+# $Id: Makefile,v 1.8 1997/02/22 14:57:39 peter Exp $
+
+DISTRIBUTION= compat21
+
+LIBS= libc.so.2.2 libg++.so.3.0 libgmp.so.2.0
+
+CLEANFILES+= ${LIBS}
+
+all: ${LIBS}
+
+.for lib in ${LIBS}
+${lib}: ${lib}.gz.uu
+ uudecode -p ${.CURDIR}/${lib}.gz.uu | gunzip > ${lib}
+.endfor
+
+beforeinstall:
+ ${INSTALL} ${COPY} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} ${LIBS} \
+ ${DESTDIR}${LIBCOMPATDIR}
+
+# Get all the fruit, even though we don't set PROG.
+# XXX bsd.lib.mk has fruitflies, e.g., it fails if LIBS is empty.
+.include <bsd.prog.mk>
diff --git a/lib/compat/compat21/libc.so.2.2.gz.uu b/lib/compat/compat21/libc.so.2.2.gz.uu
new file mode 100644
index 0000000..2c1f1d9
--- /dev/null
+++ b/lib/compat/compat21/libc.so.2.2.gz.uu
@@ -0,0 +1,4566 @@
+begin 444 libc.so.2.2.gz
+M'XL("#L'OC(``VQI8F,N<V\N,BXR`.S]#7P4598PC%=W*DDG-'0##02)TBHH
+MR%>"*#2B)I%.@*$A1+K#J*@1$D($@DE5`@Y-@I7&5,H:>P;=<69\=MV=CW5V
+MW-4=!?$#3)!-P'$U,(SB#,YDE-&*G9F)F"$M]E#_<\ZMZH\DJ+O/L^_O?7__
+M!^U4U?TX]]Q[SSGWW'O//?=-;F\[5YK.<04<UW*8XYYJYC@WE_@W;?G&Q>[-
+MUR^Z\9[Z2N&>+1N%N1MF-[CSYU[OSO=X;IB7=\.\Z_/<>3<L7I"W^/I%[KI-
+M=9NW5M:[O3NVNZ=Q?OF/4I_]=@WAW+GG]>CJ=$[QVA2_7?$Y9>^`[(_*OICJ
+M'2BML6BGUT#D^O[CKW.I_Q+E;_K*\A=^>?D[+ET^IZV[1/D`(PY@(0+PVQ2?
+M7?$Z9:LJ/3F&X^0B7EYA[RIR8:*N(B<^E/4Q!)2<]XM55+B^W:Y-H*(@!<0'
+MX@E^PQ(HHAW2U%AJ^(!V%OI%BEK$\4K&WIZ.8\Z]/7+&00LDCZ2%\]O5RNB=
+M=Q.^5$\^#BF\*E[/<7O/=;SAW'M.]L=4?\P`7*9)!N!L!BT]'`9XROHH0$O&
+MN605JZ_7&6H7+M/K('>I+MJUE2R[D)G?'K%!7H(R0ITS+Y&?_YKYNWSQ-CN^
+M.M%F\?A_9O$UG$Z-ICT)B0:[.[2I"5CY[4-Z-#G_)E^\/ZV(SZ2Z+"EJ%7(C
+M5X7#2A&_IDPIX/7NR$3VSL'KJ'"B_5DAU/:V\D0_CD.@0:BT79DD7;`(Q74V
+MZ8)5:(P$PW)GES=&]%'.J\5\:3D`UKNEHS9HGDE*"1\HIP)#[8['VZ?KD$[V
+MQA1O+.*%-L*\T92\5C/K1):52\T95;S1%'S5RKX[[[YG*('7-VP0-FR_9^X&
+M]QRWN'&[N[YVP_V5@GM#766%L+EVFWM[7>U]6RJWIJ3;4+%M6ZW@!H;$U-LJ
+MME:Z:^O<6S;7"Y7;S(0$H'*QNU84W+55[JV56VOK=F8;M.I*:J\/OI'.Y>M=
+MWC[D'"EHT\4Y-1E`IE;M7X%\9*]-.FH/M0?'J])3SU_02[5:".T=`[4*AU_#
+MNM4X5;$_H#DAN-/[J36@BS;M?OB0CB+53:CJ\I[C@$#Z*&(%1=A5;U\I?<]G
+MWZ%V<6R-%0,F4P"VZC6J=(P*O.C#(#ZD.UJ^QR$HF_8\!/6V<8A#C4W[-7S)
+M791$N!>(27:@?%G-URS07L:H3HPZ+WB[BO.PSO+NV<H^._:D52YV`PG(Q=.4
+M(IM</$.53J%`*;95*=YS>WNJY&)>\=GD,0'M#H33'\D-AU7I4\1*D6P`(?TY
+M^%.JK818[-\>HW^3:5Q:D0XH.Y%#`/'K3$:#7KH'NFFQ>VO%_955&^_9L;U.
+M&-99`">IHSP`":KT\<IXE<0K5.E[^X=B<Q@2]'X;&Z?Z.>@@[<#*>/.(TT?*
+MH$*"@%8.?_//1]8!K7=E6B%"E58>A*2JU/(B/`*L$FJ)K51;"TD3C2EUN>7=
+MT[J*L4DATZM&$W85\QQRMSPQH$U!%/K5R@'60,-H\.[EP+.B3=D]VZ!#)!#5
+MVU^JWZB]^PV#1';EZ8V\OK!4^^-%79<[%6^_7.Q48!@I=@&KR<4YP*IR<:[B
+M[9.+[9$Q4`]%XI&F%_'"T\G=@^4?Q!H:?96$R*^7,>'1.+M<"T#!^D*MA,JW
+M54E-/"=D5765`,S(Q+`2L$L/YG*"72VVE2I%N2@,8,@8"ZG+M5'P-UY;@^=*
+MDXK9AL7X;$J6['NUQJUZ>TJU[A4H2U_MT-(5\57IHZDO(V_)G_[J@ZRUH1XH
+M7_8>E/TO`/T%VU6Q)_82]M]G/U&E/FAN&#]KH,G:2[6'`$JI)JQ`E%VA]J91
+M\280KU'\+RB^@Z&U:KOPLDF1KVH%*Y#)@55WI\,X$1F+:!7.[B+9=%"'?VKE
+MCU/JP2?5XZ<E3(`'[8KH#)W?/3\<#I3K\V&TTWJ64[<I_A@(CW%*43+(R.AP
+M>&:GI2MTOJD;"E4K^^-T$0?]C1(VB!;,EA9Q8CJ,5)>%I78@OB8`#.(ADWHP
+MDCYD[$I"+LN`L&.VVFCK*K%APH"V:#GRHSV@74MP1!P#G4@K,%I;Y1*>X*7V
+M71SBB\7FP`[MAY@!/OK)^#@43_=H/!U+U,5927`YXZF'XKH^.8>ZP]958*.Q
+MIH"7K67E6OTRY/D:2[E6L2R%DS@.QH)K!3<(^_KZS9MHN-A0N5&LJW1O$[?>
+M5UGGGKXQF]M0*V[9B,G8H."NV.:NV[[!75]9UU!9EQ1=5[D)QY`ZA+()<KHA
+MNIX@F#&0;?B0,J0NW_$R'A+M4M#)B5<!:4H]+PT5.CE0D=Y?D@@/2Z^47@]O
+MXM0:7:O&"DKXC1*K71RE2OS+%W02:(%RK1"B:\:JTL%74":5Z\]C2NWJ94AL
+MN9`\-U"N2E>_/+2T?P%:B-RK/(]*8DV.]B/XE(_($[&(DT*>XG/)V?*#/`X;
+M*T`=R0&%4O'ERBN<BK3R>E0Q7?(^?`%:<8=Q#"@>5L(R`&GP"^N;'3MV9'-"
+M7:T(PS>T[/8M.S=OV^06:LW&S>:V54+[QAN]<F,BAK7IGKY[K^*XI)9=N)2H
+M1-IAX\2;0.MZWDED9=>FE!@RTA&R6U`([WQE*'Y/`X6!FM\+C[`"Q&M3GL<:
+MA<X[6C"!>NBI]W4=ZN8)\([0/@CQ%-L<(1QCJPD+;1Z2*&AJA;9RO<&^!B"@
+MR`,AXV@)0ZIR)4/OEH]0BXH@=IP$PBDVE>D-*&NTQF)SJ)^F-_"JM'L8BND,
+MQ6)$,9Q2E!-4OQLAK,$%^(:^":U<IDH_'`;@J)<`()PP%CD`W^I/'H.*)10O
+M''CKQ&V+08VJK]Q2N4%P5U5LWE*YD3/EFSNIP3N+$!60N3W*\SD09(I=E+=`
+MUF(/Z#U>E+A6+TE<*:H+XT`XO170GJ80/O)ZRCBT7Y6<AU"IF8FH59X:KA"F
+MS$F*H7SE^;743^+DZB73.*S?>B_3`&P0R`-)>KOV8A?AOZJNO1NO8N-P#,?A
+MO=7PI?[=,_!7_KL6^%MCI>X,J'L?NPJ;+`OQH.S&=&;(V)C`Y>5"P$4B7-J%
+M&]3G,']7,_XE"=S\!$+G`DJ!2^\F`=MY&PGJE#E.RIPI6?X5)BHJ+%4/$W!"
+MD<3@7@:\W`0.<O`V4\.<R&++B4I2RQH801_[K`"'+'N\)@X0R^G4%OK)"!].
+MGE?$\[Q6P$A_'^4Y*4Q1'R($Z6]<M)^(S^.,_(DQ,R^IJG4(+)C7Y3V%TN+E
+M6@C=>PY&W2IYC57UGRI3]KD='`>/7'Q`?SVUU\*MT8[=QCH]!QIH$RJY/@W%
+ME:\/A9>O'\65+XJBRQ>3@Z<5WS39UZ/XW++OK+**5_RS%>^,LE+5?[I,?SX7
+MZ<.OP=LT%(?I`66L?A(U1+<2X`-*F5,_B92;$7Z-R9=3VFU%I*]4=15";>6H
+M6GF46I;JYDRJV]_=RO2XH+T\H&7<9JCRCI:?8XDE?&E`^[0H'OAW%&B#P#.)
+MP#W8W<6`!?8F3+_4<KOL[R\+:`>+#/$A5"3%1_5&9T`I<:$HPCAO4MR`?&26
+M/RJ7VR%,%V,F9<)<94N1H1\)$RAN@,4QXN$9[9Q-T$ZJSO.+6\SA3<D`!/7G
+MW=B(O.J-E99KEQ699'DU31(UBUDU81RJIQEZ@ZU<*;:#/#/*8:K/?76U%1LW
+M5-3#'&!S[09ABWL&3.[<F[?!N%!5L:'2O:%V6]7F36(=S0EG<E^5O&I+Q:;Z
+MF0SW@B3<S]^,_>/L\A[#@"[O:61\63RC>D^75D_;;&M'J5E<:+0TSOE^VH'2
+MZEL%.,'I'81,\KDT_VG9_Z8L=GO><4A_(%KJD?U'4=7WMX,>U2W[3S4_.-;J
+M"'T?(T%VBMVFX-3%H]5C-[NIG-\5))7S:RIG?`$3FAO"89B"]5=)/6E54C1-
+MO!WS76WD^VD\WZP:8.5NO<ZEM;&,I=I.8N]VV2H=X0$=W7L,6C\R'F2P=R`U
+M7$$LG<Z&<8X#14X`HRYU.F5O-Y!]6/)VNQ7_FQY_M^.AV<"DBO>86OD"==1M
+M;.IM*%+&9+T*9M_Q+D'5BC.2U4.DD:9V.TWG;U]]3U'9ZL*EMQ7>OC:1:MO&
+MI/S;*S`#5Q0/,,8I<R7`R%57N:%R<X.A6J!>$8?`=(>\F2FZPQ<WI7/:[<"?
+M<JC_'=!2@II\J`]>ND+\N[J.E-\5.@/?F+P&)N,X_[\%4_=`(&MNNRJM?AU4
+M,4P=!HJGG*4U[FK,I>_'A%KO+09K!<>H4@.F/D%+!6&<YAPKU7J1`A_'I!V?
+MI"L,>,]46DB0.W[UL1S-6OKX,76_#2`'&$@UM`ZZH%2;]S>8]87.0DB-4PTM
+MH[`?`K3.T')XMQXD00IS]M`*[#&JB[EH%UH)03!>AV+O8*Z;"<=IVAQX7D]A
+MUX>X=Q'ZZ7?P;\]%;!8,(2X)G;UHOFGP9J6W/GA#P=P5ZH^'#<!;.LHO%5M8
+ML<BA*(0HA;P<BM&+30YQB%RA70[Q].*40S9Z<<DA.[X$;?(A-[Z`A%>G48A3
+M/C2#0ERRNH!"<N1#>:AIJE'$5W528*Y\*)>2N64UA^I;O0.P44/5GT.E]?W8
+MV=IET&`J5=`,<2_!QL@!`359#6')9L34"]CO(+G$&8>Q>WI_:L6.5*4G7T=6
+MK89\A],X4M-[%8H"'NMCF9D$#FGXZNV#%-(.F"J/,2/99+F+FIXGY7,1%"P?
+M.H75V=_]#BJB^><]^[&S=Z\`N"W[D0:,?C1['Q3@_1H1B%%#(L!25A\/%>X(
+M^2!E,8/4=%`*3N,<+9U0F_@"$'4DK@%1/^(R$'6C2HTJJ]1O$@Z8K.M4[].J
+M>$SNBL^_&4FQ^??3H`?>A-K@P.*X-NA$??<P4D5O&3%"7!=TM#0B0.DE:,[(
+MLC"0#T"BM0]Z@_I@<]0P]5NG5C&J6'F3T67!:Q*:Y6NJ=)(ZYFTH_#!O=,PY
+MFF"!"'7LS<*VLY2:D*B/1]TTE!RR%IOD4**HR`X>%:-%CW0(B9\3\Z1#47JY
+MMDH)18G)@.<6HRY#".NB6PE.T]^5B0.!@!25Q(P%>81-"XRF9.6NT?[.@S-R
+MMT$<P5S]798%&`>&4J*<K#4FT4B'2$@Y6A9#YOSS$9=$/6"5#N%CC./;1_\6
+M;R<5`"N'B!=+W$P_A*GS3XZ^DSP?V+ZU8CMN;<"CGF;%II@U=;=D_>;`C>F<
+ML0S<!4,__#N\!-[SAZAQU0/0U37S57\LH;_E+,9UE@'6ML7*,E`I5'\4=+`9
+M*'"-N5P-7XJZ&&ABJ#"H^]S'+^AEH)]H)SVD1BB^`64-O\94T4"KT9Y>E*2:
+M*=YH0G.)SR>@#HDJ?'9#.BVA/N7!*3";`,_3Z^RJV(\[,4J14\_3ON5AB[GF
+MXJV+K1<%M#L@(F)%O45+Z/%QV-^[`:<(L[&CG3`+G%C]'$\3EF<685DL1G;*
+MW:0A3]_(07//O6\G6ZB(XYJ3U-[%`%#[`7*BMX^MU?2>1\I^93;HQIPC=`2+
+M\O:E_YC'N<QH#ULH!C7R9Z2XVE3I^V_@$B8J?9.0&B#M,Y@67Y[&E[QV>3#V
+M$O;DN7^3CPUV+RL-@(3#3(J_3_\%`M9^O8C&"T"@"`*5[V)&V:_A^T//T"*G
+MULD[.<J`W_HO,(5V-TA'N9-"Z?L\$$]DD12%^36*\2X)*T$KZ)SV3XQ?089J
+MKULP&VCY-M"H/`&;^"?-C4']:N69A$Z:U$A7+DA'$/<P$)J$B;M"NG`S-("^
+M4',L,C70R4HC+]W""6<PXD;M_$(C0LR4HY&)N`[3B?%B3^1EP`-U]L0DRNR?
+M1+'_<CWTS44<E!'9G4:?X+J$UK+0Z`AACG08Z\X)H_0#U`B?0H]V[:4P9**]
+MSQAOD46X[DQ-@O\0C<FJ5/(F+4#G.;![)P)4.2.2%0X#\OD+:>4Q*\`GYJT)
+MW,8@;O>9N-68N-T*N&DWFKCEF[B-E7;SG&ABN/I2&%Z=BI\PGK*-!F2>1+&0
+M@>%#]@23]Z4>G`\XO15#G(Q=*%Q[F6E)(F=<(E7W,F(NN#%.S+BX8>`J+I(.
+M$T+B/-4;+<5)ATH8PH/HV2!>_0!1+C([2)R(!\;M$9/K!XA@J>:I69^CK""'
+MQ.DP<5'\T4[>"BP519G3@GS<B6]7+:!]D6H<8WCQG@1-8P?F#NE`_PW8@8P6
+M%^@W5G-0SI[.ISA<ELV_P9S>738"2VKCL`.LB3VTJ[,Y=];PN=G$?)S?V+5-
+M7Z#(B`'R-A`97^`@B-M-2C"VIPO+*]=>6H#T$^MLF8C?V5!T\\OX=K4P3Y7>
+M>0NP+M=""^+K+,+DS@QHH/=8Q)9$A#A*&P<C42_N3(4A33$`E5]^C-`-%S??
+MXA8N--^2)?PUH-W*2I0?>A);KUMJM\D//8&O70;<@.8RX-HCUX>;@<(68OYY
+MF/\ZZ(-T7&;S=-6GRPNE+CZ>Z??7)[#,0`S$HUV9'`G&6/IC1)/]22/"L#6N
+M#^8!7J^LPY4-79Q:DP/R.C:?[1C9(`1EKA]%"B61FER<>%DU=K%V-Z8J<74"
+MDY2@-JOC\-SDY(1KH`L\C3;Q"IAJ>AKMXD24-XTN+71]?)J/E-Y50GOU>B.O
+M?0C]E@3D5DYP*9.4%7R9L@9&.E8=&N]LFH:E=B!G'!=''1R-BM4!;/LN;Q\;
+MEC54MO0':$#S#Q"$^=J_S$\>T-1R'D;5/EW4S'&M!J%F,B$_6MF'6UN*-7(O
+MRJ02)ZUOB7:Y$2;]3KG1;E3GK?E4G2YOSV0J^"PU.J*MBV=UL4<7IZ%:(^;J
+M8@X,H66TRG($AMM,H^9R]P@K@!NV;!/NJ:MHI(W>X@JA8HN[NK)B8V4=+M=O
+MKMBR^4&V+UQ95U=;-]?HSP7)^]]S<2GM+N@L=;==%M\$&IU>_=15-!!?G9\@
+MW&SH6!QV<&^;DG=Y3[$6/$VJ&D[GSRA^N^SO`?4V1]V+RX=`_._F@<[H[8:W
+MO^8;NJ+H4*7G3J#R699'4DLIX0U]:^^3D`L^S3E`5KFIR1DKD6KQ-`#U$`*5
+MECBPW#?E(E[[#G(RO%H5[YMJ97O2ON&RI+I>,P=2*8B\[&N7WY(Z[4`5HP]B
+MZ_96LWDGD\M*,6^N32J^=GT/UD4)\/J_(WKRL72J6T`ILAMKVL)BB%6]=@R+
+MFPA<@WMC%J74'2A-"@4"<@44GU,_P093MM[9V\LE+61!TQ_,PS'",@07<QKB
+M/8-S$&\/3D"\9VDQKX\6\_K58'=Y0*N;:S;U*%J=99O?JO<HM%T@#Q>DCC)V
+M=2..8Y45,-L^4UH&4TX#3=']&G)1Y':S#J5&97&$";T+(@PRWVA&JKXSLN_5
+M-9`FGC^=\DO!'DYP=&6P1<]7`]H)D!ZX(/A,TG[9,+VP:19;/Y6(*DM1RCN[
+M"NS&RFF9?B*2$:9.2^SCF3#(?L3\'E%^736+*;1OSTWLBT]D+-QE1?D`='X#
+MHP5IM\TJ7&'&4=.S]R+;/&R<7T.:MH"MU?\IDQ,U-C78+P=[4%'7Y@&MZ0UV
+MDBD!E"F!N5BP2SL_EVG2.:#RCC6!C\5.>IK8J0_%FE)FDRYD",NE"V,=H18F
+M+]*9O"*]P=]7!FJDXCM;ML;<F^W13LV)K_DZ6FY`G=%[%F4-#`]AFG)"KD3J
+M`\FI,Q.IC2*0H'UGU]18`DJ92S])-C8CM<1<Q/S819R#H\XY5$"EV/_,I/TH
+M6=KN,/JN0A2JQ6V;=US2_(2M375;4M:F[D$X05?-#"U[-BXY+;A(XP`.%#=#
+M2F;&\)=9\?YUM%Q#NUQW8;$JII8+W?(#TQ)F'78RZW"268=+*;;+A7:EV"D7
+M.I5BEUSHZBK&W1QLP=`BG(1JUT&Y"KW+7@UM/I#][+2N[I1],&NS2:]@)3EA
+MDASU4'V#&0H]96\4%_[EH+'Z#C/V,&*GKD-H:A[\7:,>*H!'N?;#62@[-6#:
+MX[--AL[0_F,V[LF%EF(2)C6[Y-TV)BS*M<'KH-[%/!,V^>4P44>0VFGDJ0RC
+M]A:0*7(AKQ3;Y$+;&FT9S#P4:L7(9:JT[9VA^V1/7D?V*C^9=C$Q$Z9^:4[M
+MEZYKT[EJ7/I2:<9>JMU$6-LDT`(SM3&(=KC3JW/:%.RV+LV.CTXUU(QM6N/4
+M!F:QL=H6.A[,U'XW"]-+GSMWI[^$S)Y_TO-&<+S2\C@FEUL>;X='D>>-77]2
+M0^VT,A`H-\OM`E5>_8E@HCN2C)ER;6('?1J.P<\]@ZIU>RY*09!T2?ON4E]N
+MLOYS#=0I:+<Z0M]EPYY2-ZW&PN:\:E`KUSZ:26OZTFY0;<;I#4YMSDPT?W$:
+M2HD:@"'R;%FYUGF=.=&:!!2'XZ<5::Z(1YHKLD7F@HZB,9EWMEQ[XKHX$.A&
+MEIBGQ#9(#'!0IC5!%0R#A-/)^Q'):_I779-N8`TT[RGFQ2P0>*02A?7BG+A:
+M1#,.J%>##7=?85#1QD`U5+\F^]L!>0]2F?<H6YXHP]6L8Z6:B_C[&+!$E[>;
+M,/6>2NS"M9=K:<FY<D>H1YGV*FLE`$`V14#\JM@=T(X3Z%-(3*@69`1(+5"\
+M1\V%]M0Y[LW3#;L<W#O6GKF6M`SJD5'8(S]D`7KC-"ULQ#517*-3:V(!Y5K#
+MM0FC')13]VRKW5:9I&9MK:BKKZ[8L@6WZ1.+0,/HY1?3"!55U)3R:=#S!K^C
+M1I\+ZOA!*`4&[)=FF.MH8]424".TIV>8L^VQJC3QMZ@L38>DD0ELW93I"8K_
+MK/P0T2WH4,5\<M.8%)!,\]<B*GXG2*JR-6B$:0-<<&='^^&,=',L)?O=^IWU
+M&Z!F<V\GT]WY<Q?,G8_FNS?.RX/_;W#GS5^\8.'B!3>Z:^ZO-DQWP]]<M^8'
+M6$PFMZ;.\GKOFAGI3/XS>)LWU54*8MVVKX"X(`EB[Y@9R/]J^B:`8H"N^^1U
+M$][VRFT;H>6_`N#UR0`/0?L!O`5)\"+*RFF\;,EOCX]8#'ZEL*5VT^:O0G=^
+M,O1[KF5[_^GSD^#WQMO^YU>E<R!5L7!FV;3NSM?CY=55WE=;*YBE&9;2^?/F
+M7^_.RU]\?=[BO/GNC14-FS=N,@L[=PUKFX7);?-V'-YVH:YB0^578)^?W'WA
+M_/8XJAR@JNS#50/9>J>:?EE2&="SC=>D<TG_J+S*'94;A"\O[GI/2G&`^TV0
+M^\D[]KR!D\.R_V64T)N3"I[!OZ_N_B3HU\>AS[_!G;]H\0U$.?=MK#2A1ZX#
+M'EDZ+6%A/?=*K!$NO2K*(@SR6!HR%(L,:=3TL4GULV,VV7H0/U_O?02D"*.'
+MQHK[+M$[\SV+`8N4W@D'RA5AFEW9-<T)Y.6*G>@=[$!E6'!!O:O^M:KCF*WJ
+MY\M9F/B7CMXTP9L(_^\^EXN'[KG;7.M31%M;1C'P>81?=$08:!M;V')2_"L,
+M=P4S.U%)BZ;,[R$][D\[0^>%Z?(%R-4,$VH'X%K4O)@3+T3XHE5"5INEU5K8
+MTBY^UFDE!=X$P=I'J-M2N>W2+93O&=)"X7`Y-(\MEM]N+-P,GE`+]7M>3ZR#
+MH8V@UZ9NMZ".[6SUQPKDS]O&MOJCA8O\,2$+ZO-IY&.(FPG5Z4]2.0D?4!\W
+M;-U^:7SR\H;C$P"$[-!OSAAV6D>O];-_%JG_I#^D??93T9G??O<]K[^$7#'S
+M[9EO??93QX$2W7$@H,_LOON>UX?0:U55_:4*!W)=,+1PQZM`=4)Z`8))$D5F
+M_Z3:OMYW!8TG9"N'<_*_<6PO#;K-PP'&?AOT$(3_T0B7"G!$7<0):_+:H5&3
+M5\K4[;I'=#:X#&/C.5?AXESO,Y01Z&%5P(AX%=G'1Z"79NN8II72X.[Z#LSD
+M[5?$_B[O`*)H['?`B(1+4F6J;P"48]#C@DY+PU(,FB4%HYPX*XSY^\QEQH!V
+M+0!*$V.@.6&B#$PD_([^9K5YHZV9);H/8\0#G9DP=/5K[T[%F>0LH)&$H2XW
+M@OW%_,M)T8.!U*E(]Y(1CYB1WQZI@G8_G%>`3)*)=FSO"/V.PV,+85(V`#-"
+M9Q>EY:A'(HM!7NW0Y6`LGB>,:3WG1)S$H4T5WUD`#4-Y\`1`5AC"ST1.0KZ4
+MU33"3_':JW#.\,:>#[A^CMMS@;L7A$-9DQO>W/!6T)0-;Z#J"7='-L(;=*`P
+M+7)'.`SO3\'[(HIOAK=K(DOAK1W>9B..G=Q&-'N#YP;0'O%Y7^0:>LZ)7$'/
+M+;1NW\G5D[US)[<=S1?@>6O!^?^P")F=,"*F4_J"EN-!6R?7:,3/*4!LT<A4
+MNE`@7-N4%3HI3,9I)>($H4+NG@L%],2"L#Q6S@ZCG-L-./4%YSO<*>6<[W#B
+M=Z/YC>78>"S'-K0<GI5CX[]>.?R0<JS#RL$]1CSR,:0<*RO'8KUT.6N-<H2"
+M3L[=66#A4M<;DNVW?G$9T[=%>X(5QP3*M!*@W]Y\6FCH\O:3084WQAX]C(]H
+M@;!,FXB$[CVC!,\$M&QZ/ZV(IT$W!#'M:/D'2$,\=DKU:;*O&UC$T1*B_'U)
+M[(@B_29=/&7R6[GV(LB1M"#Q&\1-9?P6F:2+W:8Q?4#;AVG$_@1/]ID\>0V]
+MNQ5OU./M$XMPG4?,4GP#LQ")'L0L5`=R!E[$B9C7[CB0,7A:]IY%PL0"<Y&7
+MQSD.W"H'ST8N0_D5G>7KBXS&'*,P+D/Q]<B^L[IX1NN;@BLGI[6S4Y"5SYKF
+M9"G\K@1=(1T0HI9N\SE;?;%P6T:KM;AHD3<FILMHJ+-:_!/M4`WAQ\3YI\GI
+MW&^]]M]LM9FS/T.>5]QGRO/KA\OSZ_.'RG-4(D+M.ZV#IU_GYFS@ZJNY>?=M
+MWC8/G@:^]B3Z^&X.SB=MG#B:+00>87(;TMHX[8[+L;^CN$]7<CDMLNNZ8,.*
+M1E:A_(QJSLO3:;;6!#,__-/[$,N/<0.YN--'^YJE']/&RNWL$<"']B>,;M)^
+MEXNZ))W@>267-IWA/4U[-I=LR#E&+?^.7UT(]!]R::-'%P<@0QM\!"#Q0[F&
+M-3/BEP82D#9\XVNP2Y/J^T^3TMEB<0SF,;$VKM7;KWMCC@/'E'U+44$;U[:V
+M[8:.3S+D$](?+.*9YF#_''%<E_<,+87Z8VWC6OW]P(T00G0=[)\ECDH"A.,B
+M4JK3*5X+D7GBE9"I>?$.(;UY\3K1A2D++)!4\L:L75XG.\0$0ZD+/K(9P#PQ
+M$SYP_4/Q.O-/PG16]O>Q]?\:KD;7?CV%)OBR]TW9WXV+SOX>LF([:Z31(<W/
+M4M+`7^^IU/&QRWL:'XX#8O]@9S.^A:Y%82!_&CH?S&CUO>HX<'RP`Y<SQ!QE
+MWS)$\\@":!I+QR=6:AH\(W8\=%S(:/;V=T=6.`[X^N,MN++M!DCA:/FU48()
+M]!@`36WF3((EI*NKCD?2U%4_:_7U(R2/S^GX]O>H;4YSN^;`/-/CCS9.!^;S
+M>*.B3?'W>/P#C1,4;X_'.R!.8O&BP^,[%<R&FM&AC4+HH]/4:]Z!P4I-[I3?
+M5?P#CF?]?99W%:_F>-8;M70Y#OC[Y>[OR]Y797^[W"]?2/.^.A[>Z+2GV=U$
+M'^>,9FKY#:[V`5K!7&A1G=8MH[1D2E.6+BL:`4><4O`,)V0/KA^0_%%N<'U4
+M"MHY81P,NYA5X!5?;#F,P[*-[/Q`GWTN>;UD21*]GG/]?Y)>811A;7,6_C91
+M:XQ)&5F:S1TMW'O2/L\QZ/542O`G9G`/D/=7$C"NLIJD=O1_@GZ[_]]+OT=E
+M_S%&OT?'P]O7H=^\%/J-]U%2(S?_[]'TP1'.C\[EYIGCWIZ^:CYE_39S'(X7
+MJM3S)QP>YD["M?4GOS#,^H(3JA2*4?SV*MG:>YKMD53K:60Z@W.!QR:0K7SG
+M0SHS]+/7S,/@]R>:"YV+U1T6C]<N9JO2!P`I`A/B9?!=G]Z\:)[P5]2C`/]2
+M[;&)IBW#(\NA%-*U8.J":D.%ZGT*]_],D&)IE>)]NFHZUU]U,_>4.)V,!,CB
+MOWRB><;E$1XM^``OWLGU;H:FAJ0%XJ1R;7:B'+)+?N4L(%6N/OX4F@,\_@3\
+M+=-RH$XF4.VS"8:Y-C.RR#\/4)L7SQ.SFQ^T<(['VAT'^IL/86Y.J$J=;;TQ
+M>%(YA!!3YE]+K1<M_04W(_B&,<PVKXN[%?MZ+<Q!QK%6HB/8#U#)-GT_PL"`
+M>\T`["!MQ02C)D'C!)^2%[DV;$3N'X=JDSTRRXPRPB>P3,;7HYB*$LAYN-C_
+MR!?)9F_Q?REV,^\X2#9*KY2B7,)C/"N=:+(5:0B;KV0+ZGE^+7SLO@K[<1^&
+M;U[ZB]C659V%Z9X\2,3_HIBE:/J#HJR#I\JK6$(:@R$M=:(I('M?YL1VCV1H
+MMP.-%2O26DK>;&GW=.Z*&.8T=17;-M9N7>Q&L^?*;;7BIFIWO8#VUS.F;W3?
+MMU.HK)]YDWOSIFVU=94;YV8/M8^R.-AL]WDL4.J,F;4;RU#H*J"E\<A4LRX*
+MX32SNR-J!432)$PM%\6DSS.;KEJC2D?[AVZG^,:2=?QD8B#I\ZE-5W=1)N)[
+MJA![6V>\T>:M]/FM9CI+/%UF/!TR7*02]RP_;VJ:Q-)9X^EP)RIR<WC/Y[@Y
+MT^1FT6GQZ*FI8*Y@\7P\_M9X/(G#H%WJXN57J.ZOL/8_E-Q==SG9J>L3?P/1
+M832>,[7QKOCRMDN<6#2[DO7?YFU5M>X-M75UXG:A<N--U,$;JBNV;8KW8^I:
+MR8VC::T$)NY*)HCD@YNJJJH&MP[()TY\K@0'.O2I\ELS+\J?JKRLB`,S.W$7
+MCZHE=<7D8/02N$\/,ZQG42A@+GO[U27-:93:(-,=,>DBWS0K='[7M?+S&*Y*
+M3^+F(_^<S"A6>L[\Q&:-3`ZKTJ/GAA+*-*1$F**9K6T@)"Q2O'T=/5AN6A)7
+M*/Z^M'T(#<:C0>J7C@^L\KMIE%5^A3$1!:=DQ=XB.]">8?L%@Z/2S3+%J0;C
+M6N-L.QT'+=DJ'T%S+NC/I?'^5#B+56%<ZSSQB41O/`OP4'DP\B:QMD29^,B5
+MQ@L#8J2T)S.^W)V8F"7D4<+_!>"[6=H""1.RA3X)U>'GM":-,O:C,4W"EF!/
+M'Y>ZK_F7;.P'I^*'*:9XB[H?M9K\=L^[]>/"X=:.BQVMC\S`H`)/=UU_9PN]
+M<VAWV,K>"VY&MMO]:?[)R,RPXX!KL7PQ=%*X8L\%#!8FFG)_(F<>=\9UXK(`
+M<Y,!?#360I:5/QE(VL_<TV=+Q?$;V<QF`M`4$<W;U,>Q;/EQ-$D'9`?KQX9;
+MCUP\TOJ8@6O_E^-Z/C('<%UPBWP(`83.`[X7+X5O%<F=\4V3`OI^3%W#K4&\
+M>S.`LI?A6C\3YZ6RBJ;@FM]N.!A0Z!N0S69P<(TJ`:(<852DX9YV9!3;@.Y+
+M;$!3&\S(36F#DBS&[H<X34<U17Z<UXP3$39X41^W:]@B_1^B-3FF\70[I,_8
+M600IA,$#RB%\*+?*09M""94R7O;;C>`F$"5.Z<+XILG,1JN\#'&T9*"RX^K]
+M'D+"#>6@375]3W[\[(<H_S;B'HTC]`C)T&KXP%941)OGG?IBY)L,P,]Q@,\$
+MZG(<L#NE3EZ5-EX/R?A6:4FK19SL\>4(+H^"67=GR/34)83JV8\E-!Y2Z$OE
+M"QB6*O^P1VN8RC!,N)+X)1E)N'H_97H;JYW\^!GZV_<A'F'1/F1'4Z1@#B=>
+MIKR":!BR'1"V=,K[!R!%Q(%']JAVT)8?0[.\4KTPGE!])`>SF?7^]L.8V>\L
+MDA_OP;QI4@<O>3@A*GDLNV]6#F&1'L]NES)6?AS?617D0XB6@>)\Q8+[PX<P
+MO_R@33IB-[J0FDE^8^:1C@M6Q6.4#UB^\#BBJ2N(`1;'4&EJ5:B:>(ACX&/C
+M$$?T8^,01PQ?6*F9LE4IH2WI$MR25BBUG*E08KF$5RBQ7(+VUJS]E$/8&)X+
+M#@GM)[%M*72<_/CI#XG^H'\G&?V+!\*ASP]AC'R+'*(4?DQA58*88I'4HB+^
+M,>4%>GKV(["Z7[(L#+2\6-V'E5>6M)G5#F%X%]]&G46=XZ&DCH>VZ7%R)QIW
+M/.PD\X@W/S29B7AI6BHO?9&>S$NB4][/>,EE\-)^XB7"S0#>[Y#Z3%XZPWCI
+M3)R7**'2P,LPFK)@Y"67=)%X"4T>R\G!RWXKXZ4P0I)>V7(3,<\^8I[M-YG,
+MXT066_EBS/-YW6U(RQ:0>=""P$HY(%\7J=(69!(^+"T)(P/Y<X&!]F%V8"!Z
+MZA)"ECIB'I^MH5VA+V0@5A]^+S#057%+S`0/_8IX**?WG,%#5!/Y4!_][1_"
+M0[F<>(WR_!9BC?W4+3Z;I4.F3NTB#$F=F()KGS8@$I5_20XA/X&8N(E%*L]O
+MORF>76W)P4QRJ(?D"FN:;S]/&IFK1"8:!%C[*?H63AP/_8#O!NN@E>R?6:PR
+M4;I@V;W00QP7'&=R7J(RK!WD,7*`9[0M[[9)G7:CNPEW!@FW$U%WLW]'?B0T
+M0%`PF%G@Z@HU,F@OAY)1?A3/XRO[2:!F&+Q8;/)B<9P7^Q@O9B`O%A,O%G\9
+M+XK.>"O;+1W`FI8C'I^]W@%]+!V)`=-;X+/N4QH?[>K*PS'/IW5S&>T@VX'\
+M%8%V^#RI)<2X[S%6'XML)3*Q-_S:9")BJX<G$1-U?Y@8DVE=%V0CB'!9C$(Q
+MJV0Q%CJ_^P$E&$6!/]AP!_:U,PT$J#.M,2:+`XX#2+J12;C?!A\9\+'(E2>.
+M*]2]&-?FRG,<..+QYH@]R?$-XQ2'4A*3,^75H!S&/$%;W=.2-\KKOI@4C'%-
+MCZJ5?>;,+75N,]W*C!]K,A,ND.;5W%RNK<DTY^B7=:+=3P%,LF_`1)WEVE:>
+MC/;MX7+M/GZ(UXKA-K9'++B>[;0T3AZF*/2^P3,;6[;&`7TQV(4S#M$%S3/8
+MB:\PB3;\80W`/,/Q+(S=P8-R5&KG2[7+>=K\,/Q\,(@[$"+DEL5329QZ.J#A
+MTH82/)@6/"T'WS26K/)/@FA1`$)[VK289Y&C90S#1Q%/R>(9N9_"9>\Q!3-U
+M*[[3BOBF9]#1<@CMX[S=%*T`"MU*\(P<[)_E/9WF/85K8]X^3"EV"Z-3DWF[
+MS31GE&"/)P@B\FT\=B6>\8A]#LE&2R=]NM@O^X_*OG:@1/U=/+;E/ZKXVD/M
+M3=<I8I\LGE70JO2@(O;(HF:<(XO,H#615^6@UCO:0FW03RG[*.49EI(C013E
+MQ+N@K2T8H7G$@PY)L!A[!`=U\>Q(97N\,8>Z"E(5H17J)*!7BWA0"6J>(.2^
+M$==D7J=^C+)53B>VX4'+.[+X*B:Z6)<_"SON50@$JI]2CJ4D%6'`OQGE@/BJ
+M+!Z,^`"75R^-RZ[+*9WF@8$RA/O31H?V/L7&6VR'@Y:3O7A"DNRCG&G>@QZO
+MYMB+IK/PK<WR'LP_.2@Z3V@XV#[;G>8_*/M?+3,0`\IY)X[8+AMKUT@&0RX.
+MK?'%R*+PB0M`599WH7+E"7S-_'%\TUE^P@N0KCL.+8^@_#!R]7N"9\6-4G"`
+M$]!'B=@'4M!",J,/M!6`#NW7B_T9#^]'+>9(3(STAHSZ]K5EMEI*Y&!?(35Q
+MW9\@K-\(ZR]<(7X:N1O'82QC?G@8K$09J653&9%I*;`2\!-E`GP@1H_8[W@H
+M_V^H%)SQ!/OJ;Z;BIH9'JM,9+`^WL#&N+:/54@PQA2S\3Y$B"D>`]0L)R!58
+MQWZ0_A8</8*$,\0/`HR)1/?)^&'XGX#DE>`Q>6$R$[_I"78[0K?%\)#S*44\
+M#3)"!I[V@ECQ.BW'<&_F&&-62+K($?KK%TB/ISVB#91?EJI4%T\%M*56U(5.
+MR4&0/2A=M#MUGLZZ/9,D`Y-M_@['>!B'7);C,DID9WKCG"1-PJ8MH*.7=E8V
+MDJ/?E0:S%6>OTSP7[91Z+.IVGN7"TP(S/Y7?<CPKNM)$6T##XZ+0?C)(('2&
+MJ"ZU)0!9WI"=Z.L#/1JZ+-'2<L67@T<-<D+MCG^(^QH$J2;]B(3`83J\X8M9
+M/I=]`Y$\]'N0YG5!O0>,C#`F[,X&(6(1IZ#S1Q(G8Z5.*^;Q0:(^CV^@[KAT
+MT=&T4O%KTI&TY@_0":(%33/2O';9*GLUS+3;#1JPY0+P"LPK';+O;)NU-;.D
+MS7NVU5JT2NR;%72E!6$H&VA\J3=&*`V0.;6!F(`(>0=F`6K#\,J.E#*\A&5)
+M&`P,+7^&XA^8Y7<1K5T"!W_,\V[='Y3@@%FY?JQ<"V6?SK)_=5[@A<;QY6B:
+MDH+KN#AN9+42&8<^Q.+80M]Y72:ZS6+4`E`<#]^#1\OCIKS#]XX#%WA<?TWS
+M.VFWP;Y"]L>$VP%N5/8/X'%0?[3!0[K%+*2\@0!T`9X$1GRNQ,/!06?;Q#9+
+M:T9QZ]C"U>)G0$,SC8P#C<?AR^*/@E(A_EM\.W>(?=;W!W6@)AD$?PSWL'=E
+MXSZ-[HW.#$*=</\CU3B+,^Q?<#O!.G@Z#B^9=Q[ZG$?[:HMC[[568Z]KTG!-
+M8C1R"K"39@-6D[W]3"E@ZPB]:$T!#$!C$'2B_42OH^48\HPOIB[QT<!AC`M1
+M9/(T[P".X$&[)QBMGRIWIHG.0"GQD#E>:8!O!G"<CEXZ8_$\9X%-^H8FW'T3
+MC)8HH\ZV32*A"6]`*'(0!^?622A`5XE`)U$Y&+/H>`R`"G;LQ7G:<D>H'&MP
+MF<6PP0(2)%'4"=1G.8*V<-962U'A*G$0(UF,;P`5W@'+N7B<[K/'C4FBY/=N
+M[4AUG6S4U<1_6"T)`8+>ERAW*.8-/U:"N%PJ1SNTJ9;HB:CL!1)/*BRYQ23=
+M(J!4[4\J,X>*Z5/\_<GUBTP.F^%G4\*_$R;R>/AW%W$GI%][ZW,FC!F;3%M&
+MI]\6N^=5UVZMG+=M0T/]O/JZ#?.V;+X/?QOFU0L;\;U>J*NNJ*\VO!,O2#$K
+M94:K-^0MGI]L(SM4EW[O/(_+(C4VK04P,+7IJ:'SNZ:(Z8<KN/C$K53;@`E*
+MD$+15FQ*_DG/N>!8Z-\2OHO'4YI<D>?<KD]A](HFZ]5)96W%LLB)4.B\`/K4
+MC5HUL+YQT@IT\^RPTH"']/Z8[,8JR;;3GG\<K7!R<"V.&,!Q8&+^&W)'_HEB
+MM+7Y1#X&VM&@?$(^9EIV#K.C^^2O/"Y(PEQ5S]?^B<[8Q\CY(^X[*@M:\W5V
+MIG0+:N`W:L<^-_%;A*G6H($_))3Y-GDP,@_JOMO&YG21*]".$&+U/&V?F4GH
+M@?I(NVV<^"&TZ63:)!]-[CS-DW/EVCN#?-)9U2'V_P:R?IL^7_LKGA?I0LN@
+M(EY?<!!WS_Z>7(+B5MYYX7(IZ.+$3)B#1M:"3MS`DY`$X0>SWT@!%;VXQJ[]
+M`Q1GNH:]#BTCM3D<>02[G"5E\!7^(,Y3BWAYP4'HE[2A?L62</S^`-$/;>)Z
+M`.@-0P\REVJS!E&^PZ#`3J"/AZE9`"JT$9HIV4_PP!#9G-C_&*#\ANO06.BD
+ML"1?][P=O)&M.4#7+3@()5])<P$G5%V_$082'"&@Z:)0XFA&5A^4>(*QIC?-
+MT]3#RGGK,QJ'E'$P_D`![P97AXWF(/@WX9G1?JKH>%8(C@UV&HEPF&BPE6JV
+M\SS'#N/]FF7MXLD*FTK^A5GRUHHM6VHWN-EA@GIW7C9WGTCNDJ;/W[C8S;FG
+MUW.XR3<SF\OFN'IN^D9WY9;*K97;A.GU[LW;W/5";5W%ILJYV1A36X4N*V=,
+MGSN_:OKTF6X&J-Y=48?[3&ZQOC*;$ZHKW5LK=FS>*FXU_6-"+@,D0:PP\KDW
+MUS-H&]T">C0'#"H:*K$P]W;(E92H*IM#WTY0$W<C.M)TWU=)@?%_WRR@]IV=
+M[/_U')\PNS#L`_K9H\]86<(.ULR%=NW<`&_XPYRJ2G]O_V+(QM(O(;K&HMG_
+MRILG?6#H\OBB#K4#]<,NFMN=-2&;',Y6=:`_OT%SB[.<>!6D0CK4O0/4NS-U
+M,:9*SV%YVJ1!XF4*'ZO?J$J'*)ACP7HFHZR#BL."?NCZ/8[=3@74JGZH$I&V
+M'6D4@L4TW=N'BU>3#%`+5:F#0.T_STKHXG4415"!F..1I>0DYQ@E>`P3D(:H
+M2F]`".JOJO1+C-/%J"K])Z7:1F"<J.0Y6O9"T;_U#KR__HRJ[!K]A?Z^Y3>^
+M@=^(&M#[^[G3R#!F0)4^IHPWG.>-Z;LJC1Z-(5<3*/=OO='W_:?.B&=8+E5:
+M0;'I*,1!&3UJ]WBCP32@_/>]ITI_LV`:GC\R4FZDE+_]*XJV8R-LOP^1(?Y^
+MGKJ('.HJTDHD"3K`S,Z8A(X[6M[!-0`/5.T_L3O'-B_FA,NA_YH7SQ:RFQ>[
+MT<XH2\P@4_\(_LF6QYKGO!E`V8D&TI!*F("IA+N-K#=C5K?X$8:M@$]Q1J>5
+M*Y(G1C(PK9/2SL>TE`QA"U='>!"**R$=JK\CXR"/S3^/W0U"":0]80`CP\[/
+MS)'A,/1W,200_Y"Z$&7^FUZ_V+UYRY;*3<!@AA.U.7/<TS=D4XP14E?Y@+BY
+MKK(>7=M6U&T2D9_-9$/;^-,_&V.O4]F';C^EQ63I<-3)<<V+./&.+BLQBK06
+M_GH6!><KM`_'[Y&-)'/$J<T[+)R``R1MD9K!;I9'YU2IW?F%SM(S#?8NIO_M
+M*^7,#([#G&QE$*3H8F%,:4`[9+:)>+<B84H)@!KK8E-H32B.I,TL2I'NI81`
+M#[AOT'S+8D?+"U1(*36T(MU%3^`Q0*GW82($0'^Q<)4BK8L35ARR(X2N<WJ?
+MY!B^%`H=/9HE!M+9273$"O<LVK4VN:Y0NIAY<#%R^[8X8L*,X;C\UCE4@F4!
+MX1\D2YD%6.ZZ>`_$6]^:7%*B^M2BW/`Q\W]C/I,Z)SO21W-_\H2`$RS07SPX
+M_D5/:(YG.V`J9NG$G0[TONG/84.@+XIG$H`S@"E@`I%A>4L6!U:?^(OXAN$Y
+MZ1+VRN50%-GW:B]_RG/Q_>VD\;^/5`Q%0LMC\K%D4_<)-T&K+90>Y*?NOKX:
+M#W)H1X'"T=.$N0^+:XM=13SK:,H*M,?>9"?J-L)#-KV(3W;/FMP>YAE\J>^N
+M\L3YMPC/575Y7^!IQ]W[M.P]F'<2V*JU.Q8_`B0?6X:&H-YG5*G`!5WG?=,P
+M,C2&.<.E/#I..]&/T[X?*]X?JY5/WCG4?]6Z>+$+(E0@EFRSLF*[O,^A.4"7
+M]U5\),$,H3#U/PW225G_XY3S)`EX9S]AFH[7#ATURP#K?UKV'P34GP/LC8/`
+M".^&.#ST5T`FJ@FX(_7GPY_PQIZ__CS2NA;YB]FM(Z8OCZ=GO"&UKRO57DO-
+M,Z^AHFZ>L'7[/!!_\)@[?8LX=QW]&V++E?T)T0J,R1GJ\]P2:.WG8[CY)'5/
+M^`)MQG^##[*$"VCW0QFZA-$!K?PO?)(;(XZ5A249I33.&NZ#X>][>71&@(;3
+M4L%$[.F^-FDIO+1Z^Q6IF$(^5:05]/+7*D5:!6]5LO?S-JF44GW1Y=5(^HMG
+M`WA&&)29C_^,C=&C_>7/;#+F1%/T41CRZS^3,E1#ENKM]&''R.M4:0U`*RW7
+M?O1G4Y+FF#9RY=IN))V$09SAV0!KQJWUE2Y=7@:5A4;%_XRJ)K=U(I`"AL^G
+M?J#QS+!0\T:0EF-,7T/_.2OP1"\H.V*6JK@G01OX[*HT?1)J!I.)59D;-C_T
+M/<P9WDV>,S3OLEZ<A_K.[$FFOC,',Y:ITKQ)9@>2'[@_\?1\XD\,8&[HI"-T
+M@J,3[0![S?\.[)4&["4)V.).==\22`1@R]3GB^$M$$]^N9%\M)$<SU2M4/>M
+M,9(G$@[TL81G^Q()I\:-&B'B]=[D+B/_RN@T9X@_HX3]S\<T/0)^A<H;&T^6
+M]E(RZCC8EV"CY#P??H0RM\;"Y.YW^X8R:(K_?TB+3F$2#'W9EZ9_^".>H$Y+
+M+5OJ<\63;$20:(W>!XH[+8IY^\DE)G+3@+$A@X[Y<((:0PI>KZ6(G&P3ICLA
+MFQT`=(@P)H-5%-1GU2+T<:%*/9.)3XVS2GA!D?>L[!TP%IC(%V!""#U$)-WS
+M,I8&.EOZRPA5ID/I]PP;+Q(\L?>/3+HJ"$A]8)V^_-Z=HY7">SV%VYO&-5_(
+M!KVB<%VK4R]<YSAP))(9*-.NC*1(GR'W/QG@?'9]N0T!V3R%.4UC$9!=L0`<
+M"X*QA=>4:>]]PL?O*TJ^FVG@+'4)7L.$!V$T"Y`,50:O8TI#_US=[!ZFI/HD
+M,?G^LZ0[2J_@(3Y.O+SF!E5ZTXDW<%BU/T.K=TD800[0CMKEBZ0K8=WU9?S.
+M"0;-%']"XDL^PNZ=H'C%Z3@P3N<DJ,E$Z8(N9GDNBJ.!XL>$6[M;,XHC+Z%O
+ML:35I)''CTF(G5G>CK'*/@)M=1S@="O>N6$@\!^]242;G/_=#ZE]]17\#KN9
+M+0MMU[3O]B;I(ZDVF?_T(8W(H&_1MJG3\>R@C'N7,=77)_M22=BE>0`0KD/@
+M7D<,UZB0J>D.D)[A=X"4$&@[L&8>LM'-?QPV>HY@(SH.,^&('2.>B6H\.W&%
+MH\&8@-;_$:XN]IYD^O0NCG14,5T[!NFJI-T@I"=7=17;W8F).?GOH3VM\\5V
+MFY`5T![3>.9_PLTE[GL:<+P6&`-\'#H9G(C>._6&7*78K7<;<"!]]0$+R3VL
+MRS]^S$8U>T@/+J8]L@6&X`.&ZP5B1$\7*0"2<V\P<CO-/+ABCD!&F9GPN"Y4
+M)DCN,7:=)7R[BFU4HV+2!(UY)7-!TE7,KD]C?G&DW7F<<)E:7.`ISD.0>=IB
+M$T(>2[:`)5M*'E&6:E,@NJMXJ5'/KF(\'L)!S296T;5`!I;^?MD)-'U'&,\:
+M[KK"$^P3)L-\NUQ;\K$Q7._**M>("(-]58H_6B4'[%7R[C$R5$K:@:U</$V1
+M!'J9K4C;Z06F%UOHQ8U6QCTC\$>2__,>THE8/T\P=R&R.-/P\2;T$05UGV34
+MW89UO^5#WKSM"/VY9!CME]\.Y)`&,J/8)1?;XKHSVP]QO%8P)LY?J7I"70\;
+M%!H_B"_6R)WR(!HOGY,_1S::)*_F40C8I<]UQV-''`=.@G2F,WC]PU<04OB_
+MYU+\>_*/2?R+^K-28*_JT#*D'LMP>(GX]$O%-]]K_X?A\N-[O\?Q$;<#R+HJ
+M=`E^W=.'QI/)_I\P'YZ[.X9K'\O=A;@'CW?_3`,%'"ITOBB'%_!,%/6!+P?/
+M`D_"=5"O*\TI^Y^#`2%M&<S`#J(MMQ?DT'-*\+F\]OC8]]8@3``?4[S/J4OS
+M8,P[J/B?\_@/UMN9H[B?I-%<UV>3=B[AA$8%U?ZCBO^@I[N^0%F^1/:]H'B/
+MMD'#OK#(*EZM^`[.\AT%[#S+"IHF*.)1)?B"4EH@^Q^33\2>YC[[*3`,9$<#
+M@Z-UG0C&?U2\BAT%O0GM3GS']`=L6B]TU4'T5M5[31I;F\%)R#&8COERY&6\
+M<?]/5T$N51GFGJ5VQ?><O,P)$.525U?!-!8_@SUFLP<1:9C97K23-<ASNGA,
+M*\6K0#K1L=UY1\L#.-CA+MQHJO(RSM'R!$D6(P]@H6_/*=6N'QO/)&8K_F-Z
+M44[D-^S<?U+6];@UYSU&5])<K3B5%4L+._[`K]$*>U#L/@?YR)L1^?)"!^?D
+MZ1W:0,GR[%Q:EX?SZ(X>'I*E%>&E1W1\JL!.#XY]D%?($B4;TM>?I-MOEG%X
+MJ.[8^:)T'O?3$>^`7I=3IFFX)XCNB%R1>PG#E=SN)81=+HS5RIJ51:K]<6RB
+M-=H__A[Q>YKPRT7392/Y:".YH^5VLEHVP&/]L82B=*.$'"EXE!/OP_:`YQU0
+M(\\#.?6+6?)50&T!_8&<-=J?'?%&%"Y/0#.:>(`WH44.$IQQ4(Y2EE,$--V[
+MD%RPA6F_XE9LL<*<685V^8A\HN/SJ;+_*=GW8UR6\#XE6V#6C-Z__,=FU=GE
+M_N_+WB=D_Y.*_PEYC4WQ/RFOP8N8+(Z]6'5J?T_0Z=A+AKRB2^ITP@3:R3$>
+M,/KE%L!0*0!M\1E@%<7EE"<"\2DK;;R"7>J25UJAP9Y15EIL\`IE/*.LM=K1
+M0?U:BSTR+=R505U73%W'LG0MM;+.76JEWH5B)2BV!%!I;(5RI9TV'+V`,]Y^
+MGX8:HQ]`!&_/U5YYG[8$?U*M)]N+IY[+O^RWN$YCEWW=4"N/F./X]L/(6:"(
+MX&+?K4H)K[B>V_,!)([*?FW/!7A9)TQN'$5ORP1'9&5X3Q"![1"F1@IH/R5+
+MV0FM&E-<W]OS`92<:?''R/\"+I_;6_?\@<+@/1A3EAS<\S&"WH/*0%A\'U>P
+M<0,%]TSLS^WY`Q7KT_9\#B^ECI8>T+$;[Z6O&8Z6'\.C<1Q].=F]*+VOX7XX
+MPV>1H^7?,?E8]IDG[.C]1V97P@(*'"W?@6_VL<S1\AO,WY3(O\/1L@EZW?'P
+M_?%4]SI:[D:08]CG.F%.[ZIX9+6CY3.+^;'=T3(&8GKGT?Z\M[OW&K)U<8;Q
+M1A40]-THZ&VCR0B%K%MB=!<.!'YF1V5@AL?K%#(5;W19Y#_#Q;(XH(@Q]$,R
+M0*Z$*?<;E)!N8TF-F,PLW&F#NKOW7RVF+4U*V8_81RB[\=)ET\EN^+^/SB8D
+M%U<4QV.\Q]L-`XRO6P85UML=>9?*[29CO&[,9!;>B-92:)R!7D-[1Y%..02_
+MOE$CX/?NJ&'XJ:LL,AIP(*F6`\W\@I&7*N3K0_#\`65V>;Q186ZQNMN"-A%$
+M:BMX9<F_[_F8J/*BXOIW1NQ$WZWB*ZLB!U/AO$R&5$"5B'QD#=:1?PY/UF22
+MIS4;R>7N6>5V)G%<&?+*##XR,SD=\,@#E"[8/6NG7;[`4J[-`+&088?61C9\
+M]$$LQ]N=Y.5AF,_:N]\E11]%B_>,H>^BSB/F>,280WTFC>P_E$QE&8\7&@%+
+MV_]=]O60QQ6SBGELX;MQ,7WE.%HPJM%)7TYA8^_M;)RE;[>C!<^0TOL,84OO
+MPJ2X9D<+FKT#/UY@G'(E1/9.P!04\D12WJ<<+7@NO'?0L/,*.CW!,XX6;P:.
+M<6?:QH(B<V:1O\?1\C[RT-P,LNMT>D1(<V4&;K.=Z7T=^<G?PP1,QP=\6BDZ
+MR#<`Q=()D.-`EN*$Q&T%?`L_UA%Z%*'UI!MEGD%;Y-U.,?M\,6]QM-0Q@U3H
+M&\\#+L?>ER!9\VX]VQ%Z%M[.%^38'*'5F/\I([_O##2M9[4+\I?P5D?+?,QO
+M`(7\.S'_K9!]>SP[6K7U5J0GBG&*&><+>8M0'P?68&_>J6=#,&1`8U4#1X=T
+M73IN?93HH?9@>BNHMD=^AL.\,+94V_1;DOOGCZ8['H>IL7DL_/S2AV[`$-""
+M<47K$YY:!*#?`ZW*IZ#Z%H^P,X>`'E>JV5-`CPU?`O8B"X/M`="SL5N#R?"A
+M,L6\56A(:MOU/.YY)*IIUMZQ]S9"Q3($E?&EVI[?)*,R+GPI7*P\-6_S+8#+
+M>5(;&6QHPH_3$';AT":$>D[[S=>HI[@6X>[6[Q&^T?LDHWO:;@5N.ZO8OXW7
+MAGG/HC[:$Q_TV'@WE.'"XF\C-K3]9CO&,9R`.EJ6Q5"]'.#$B0:EAQ:2M?69
+MWM>H,-U'X_$DI8QVH5UM,A84![K.T7(%P&O,8\.RHZ740N,4?BT25O4^&.=#
+M&$578B=5)_$NC%;="=Z%@6PQDFIQ/`\,A4]BG@6&SBWV[/D(ZRB+/8A4B4T^
+M!RPH[7+:='$4/.RZHV6'U=@UMT'RCH]XM,I>F6=3@F=GV1?1KH]SYAL>_QG'
+MPZL8Y\DB66N6VR%)FFL1WDW[KMQ!<P-'Z#H#VEA4#*#F;^``CI+2]9PP1N6?
+M"TOMN/OM<8KGV7D5T#^*T,DO##-I_C-EO;CKFQJCBWBA@_;/%W3=6$1UA&Y/
+MEBH*6JO'U+6++;W_ZP*=*4$#GERB[%QYUR]X^5P1'EE("?<L^84X13ZWHBRI
+MI'+0ZP%`[U\M!N_GR@O:UE`"LZA@;.:[\@5*3>=_QB9C]12=V\]-@4FI(I\#
+MU']@>Z3>6$$"G`_0SM:!1,)4YY[21'U?_#P)<C%A9%,FTO&^LTJP1X%QPO52
+M,KDZ6OX5'B5RM(`BB+;?E2%E2K)6\?'5$!AY=$3ZH/[O4>QY>+1X91Z/)JW^
+M,SA&OL.F\"):%5/QIV3[(L5W6EZYB!^QOP:CB#\B_U..(1^P4<8^V;Y8\?7+
+M*Q?S^>V],D5>`@^@0X:(?3@B;^*1!X3W)J!@0V5FY2+[B)AL-3`1,B-7A.7N
+MR.049%8NMC%L[+C&T9XRAB?O`?W@;9Z\Y(O1+N_99IKEX=`@9#H.K])AU#9F
+M?JY??5Q>C=::Y8#(&H5N(CF%LZHN.1@S]@6A4Z'[:/'0@$3G;5:YA`S'X2R`
+MY0G&Q`Q%C,IBGV$XDW\2A$ZV.(H\F),X'K<G.("9H;JB#8=&T0%I]S#$T,OY
+M;"EX%G-`93/,'%2<>"VD@`'-*EYQ$+TO[0E2-C']H(1Z"3K'@RQII7G09#-W
+M7QL.0U7ZRYEM-YG3`;UJ'-4):^+O61$ZV?1;`XK@-_""&2:QPT#H9#"C#8\'
+M=0\>(4GN*M/N.)60Y.UX?5U8D4B6<^>7AE&6LU7'4+NX'NI]CU!NH"Z`?GN6
+M`3R;`#B^3,M*`3CNTO`RH%7N00<T_2&JNH'K/W.7Q/7??O5U<<U`7,5[H"6P
+M6875)M*^D9`>5Z:M38$\]I)P1R/.N$#4C^8^BK<__5ML1;_QLN2N(5K#X8+U
+MBR_'\:.WZV;1,!45KI:CI*"?+5UC=J.VA-+JWFAOS=^8W.S#HTFK<O!LV8\&
+MZ_#NZ$R:&T0+S/W$87SQT)O,I&=Y'@X6R"`#(S/(89-!/H(Y:X!X)$`\0K@\
+MAS=O>I,Y)'@V#F<@E3T2/*&G$/C8/;K!$43?21R!21(<D<Q#)D<0#UV:(S`+
+MXXC9NZ^CANRGO_&&1Y[HH_696((IWC&98C7#S-'R#4QR(:2#:M.=0@O+3GP]
+M6E@O@6:SSJ2LU2-1%M#LA>[_`LTF\X.!)L[8AZ,)?/:/W5^3S](!3_%>DQ5*
+MOXI_EW]=N)?FA:E#NX7HBLQZ6)_`M`IYXJUZ$*T#(%I!['I\,6$.<<B`@/<`
+MK4$&2<X^F677O0.]U8Q'O'WQ2P/,O1E0)W!=.Q@SQH#8KSXF:W.GYW-'RZHT
+M)I&7PV`Z@/.9&-*SZR6Y>SH.RC<S5>\/J`8VXL<,1\LN_)B+'TY'RX?8(7O/
+M`WM@`,S[_LRQ5YCD9:*R]UN:G&'((D?+?Z!Z.!X_\@S]\54V=\.@`D?+3PPX
+MH'G^`'7'O\?8FYGJB#=9-MZ$'S`KW$5ZYLU,9?T>`JJ/EP.*YWH##FBD90@G
+M8,(!-01O:FN<@A_-3!_%UU9'"ZI5O7.,C$\(F_'QE/!@[V68%^CL<+O'F^,(
+MC:(5&-?5()9B%F,=*(>X:#2\($,Z0A];XFE.F^LF.>F[&24X'CZ6B'Z)EGIR
+M0I3MN43X/[+PO13^1")<)EN&G";'HU(BT#A_"%U&LUA<$+"EE3AE;Q]+N@[B
+MVP#W`]TH0BUMR_D6.TPU"Q,0YK.UD^B5_9;VK$ZFG<G^?ES[.?&KO\C!/OG"
+ME><H_E=:5B=J33@)#UV$.3*1>6S9S&-`AXF+1(/17E3J$C#I13[!EE5^U6/Z
+M9;QDO&$S&1*CCA:\I\G8*,=)2W!`6?LHGT2@8;Q#GI%P7Z(=+"`7O;$T^!OL
+M4UP/)Z<'Y1F+`\7J5SV1FX;4&T];=6,A_,-))4PR$(0,V<EXPVSA1"4Q4S#F
+M"!W""\;ZU<JS\;%H>_+]O__!<VKPF!Q\.K[1\BK*_H9I>)@Q:#M?,GRC92(9
+MH[K2;I&#+^!&RRI0.9^+N&DD>R&O71;#25;N;PR>5-=.U&E/Y@6/[SESCZ64
+M9^=?;-+N)9QPCQ)\00ZV*[[G/&_7WZ(4+R%=N[UMXB*G.$WQ/S?S',YURPN:
+M)N&5O=ZPLKI`]OT8--NN^`X+9?:UUQU3Q.<\8KMH9SLLFKF7HP2?EATP3,N-
+M?%<)VTLI87LI/KN\&BKT@MSHQ!V5U7C35%ENQP?6,NV1+CS6,8T9[JQ@VS-_
+MA^))?%IOF*;=T&68Z??N,>:/P:?UQFF1L8KO:5RYGM#%FTFSN\SMG0"M73W=
+M5>*FTLNGR>4S]!(W%+K:[7AV1:[\!L2F8?!L%MP(P76Y\CDS.(\%-T'P@[GH
+MSOOIM#73Y#4+]$*W,E:ORZWA]`<6:/EOD!F4<0;X5=KX>4$7G];N'6/NB>`6
+MS'QS\\=)?8$[.#],.CN,^:A2.>7:*V,3&<5TO20G<F;(WD\%3;J>IF,=E^/4
+M:VD1S)[+-&\G-&.QN>N#=PMU></,T]334!-?V+-B:=U"VO,*0P8`D1:P=16Q
+M_8$BMOEC91^T@Z`#!0`5ACT/+JU_TRA=O!JRG2].Y\7+3,R/Z@TY`:V?=(QV
+M7-*\$RTUFE9RNV^`1I-VYN*:1/G*(NKJ?_P/ZBNYF#9_C'2CC72.ENN,S1\#
+M,O4J`%^=;@#/D8+MG+B!]F?::?_G*%3.LSJG?B'+)+\!LUQL1L&9:$;A,A-F
+M*<5Q<7"X_]..^S_BTTI#3C%P5N_U2?L_R['ERG.2IW=/RL&GE"",PD\"G?N>
+MDE?S>%I9?'I6()'F,3GX!*5Y3%X-D[@G@/#93A`YKS'Z!`?W<'T0TDE=3CGX
+MS$%S+^AI9:PBACUU2T%'WFE37#`;?T8>JZS-A!YSR6LS>'BUX6(O/.WPM+.]
+MD>`S79G4>>P^-U!HNY9:C+T?"]O[\3[CE-J=V*U4>-T^J)[41!M`C3;MK=?9
+M!A#K"]P4RM5>-L(8=SWS.CLAUG*IO:`Q'6A#8,<9\-"]H$MMRK"]('P;82_(
+M7)7'=;"V^+Z/45^V^4-A\([;1>&453+:"Z+=I$)>6?(<VR>2@QIM%27V@G0N
+M>2](Y_X_NA?4,M)>4.WHK[D75#SZ*_:":+/E4GM!_]5]*-KAZ69C=FIQAX?N
+M!06[40=)V@M"^[SA>T'F=LK(>T'5(^U5W3X<OTMLZJC"PJ%[01/MR7M!`0N:
+MJ)L;EZX7C46N=Q3[BXS8B;XON1=$^VS#]H+P:B':X_%USUIAE]](V0VZ]O_\
+M7E#9H?^[%_3_[WM!=W;\C^T%<1W_K]D+$MO_!_>"<MK_[U[0_]T+^K][0?]W
+M+^C_H;V@:4EC^+?WLW-J#3-0Y<:EAMFT^`TA>:A[T=6:7=Z^9E9;SRI:!5^N
+MR[3`KF3HVW%:*\:T.U[A:<5%='7R8RQK:%$<B2S`5A\;,VCUT<Q#6E54F_`*
+MS86-$\_2T6F(ND\SR_/UIZR6LQ+1E0%(NV!4*<U%QUS,EA,O+>D'+2-?Q_TE
+MS93NXT`?1E`HU]C6TNC74C>6^H9N+%'1XG1S8RF7+:/KR:OH74G;2G-VL_N4
+M8N6IR[6R_XSV4'IB%?T,KJ*?9G"$VPVTV"JZXM?80K*6LH[.O?SUUM'OA/K>
+M@YM5A+FP4B'+=@#7E[(N_>\O??U]I;Y[Q/37V*Z2@>>/N$OBN>ZEKX=G!N(I
+MKM^CF^OH7XZOY>OB.PKQ%=)?PP50]6%S#?WRU"ZA':5S:?'^0$K-:5XRAA/7
+M*3ZGQ]<OE*;0YH"V\R#1IA&$6TY:%0NB!'VDE9-KJ1NU[Z<9:^O]Z*-RX=^8
+M+S08<GPV^8'DPA+[4/T%:F5W8A]J1A)/7OAW8Q]JANPCCFE8@%X-C9VI`5K/
+MB_-DRL[4$)[L?/%+>?)#<Z-*,[B/]LV`N2[%?XRY>H9R3(_!8<96E<%A\8VJ
+MOJ$;52:'&1M5(W-88IMJUNZ9X>&=*?M/:U=9$_QU>@A_]23S5P\CL)X4NGWJ
+MP-?FKYZOP5]K#ORW^*LGF;]&Q#.Z_VOS5\]_@;_^<?__2?XB@L)K>9-WJ)J7
+MY'-"!OE'U)C$%6,RNHM#V6T:X:\EC;-?6%EF,!ZWGS$>9DCPWB<OC,1[C*\O
+MXY+9;Q%.[[V:6OEFJH\X)9A+1\.9UNSTG'.TD$:)\V;4/Z*(M.L7LE]+W=!"
+M6_7&!F-#ZUOX,<?8T$+]P['W]XD-K3]Q\0TMO!.Z]ZBYEV2N!J7L9_TT93_K
+M.XG]K+VH_[8F[6<=3][/JD[>S\(UX=[UR?M9RQ/[6;<@G(*D_:PYR?M9K8G]
+MK/<0RJ3A^UD\YD5Y;VQH#1`WN=I<8WO_2'K?\/VL$XDD1T;8S_I%(OI'R?M9
+M/TB$*\G[60\EPNOC^UE;$X%WFV5H\0TMT996["37<YBVD&UH&4>_^O#J=FL;
+MS&+$OA97AJ/EJ@2H\9C2Y;&M=0"=:J;JILG'9O8[#KL6R?Z^-M>B;)>GU3_0
+MZEJ$)Z,<(=S2;#GI:/DM9VQM]9-OIE@OSA#0=Y8!ST"O%^^,&QJF8'<L03\A
+M:/9O.&'!U4F0^6O_CD^EQ[!P'0C_>'TMY.0K#>O5K_`/0:V3=JY^HWC[(GGA
+M$>J$^U;]C.XA5Q+PB7*_Y1AF<"VBO2LC+\QM"HE-8X[0?^*^552M/#/\[N?"
+MGQL'#&'>DZ,LL^]95'D.9/J8/1[O27AFG"^<P0NV@^06[?JP]$&FM#/7W3@%
+MJP=AXK@R=.RNB_8U6O,O=1T/729"?G-VJ,>1ZZZ[SBUNNW];;2-Z%=E4N6.[
+MN[*NKK;.O:%V8Z4;8CEN\[:&BBV;-R8<C0BU+*F[KE84-F^KY,J\)?<L7Q4H
+M+"OAKMI0L>U:P5U=L7U[Y;:KT"?)SEK1754K;MM(SH8V4>+"VV_WEJWE*K=N
+M%W:Z9]2+]\V$@NLJZ^LWUVZC!%Y?Z=IO<G65VRN%S>CQ9$[M]LJZ"@'PHA<`
+M9F!%J8L*EY:5KN4`&_1OM+5R:VW=3@;F]M+"V[SQ&FRHKJBKV"!4UKGK\-(-
+MEJ2L<%5)(DFB2&@!<9LPHWZF6411&7<?WDM<3_=VW%>QI6+;ADJ&@+>H#,O9
+M7E$'[5-=63]BFM+",N\J`D&.FF;<Z5X_\Q*@OA''YSY(75=950F`-U0:3IR,
+MJOF+X,D)=16;Z0YO3%F_I:*^VCWC+H:SUWO[;86E(U5_`Z2K9VEN6_O-Y"2U
+M6[94"`C.\!)E)%J]<F7AVN16VB1NJ:AS#^DU:*32PK4<$4?EAADSW56`6^5&
+M))BM%<*&:DJT:K6O<.UMR^@];\?T'2.LB=[R-!T[EB\T?W1QCXY"1QRO>M^D
+M`Z[H,!SGOK;(G:ITUUATU8]_07J&/4[!)K7;\8#KP&`7'DL6%J!'EO'Z=AZS
+M:Z.>H8.7Z(2U3)7^I1P=0V!XY.<T+*K^-]E=3:6V%-\!;P^^BS[6A-F>H*MA
+M#,X>M0[($<DEF>E:5DI!`>1;',2=G4OS=3J]S&:,>=STC4/.5:__9ZJ@^GQR
+M!1;IC7A9O>;[N>DK")V6HROTC^"/,!F=4#V^[@MVH=(BDA)V.N^H2OL@>(3#
+MTCA,YL^_?L$--RY<Y"DLNFVIM[CBO@T;*ZNX'1LW;]HL<"RL9-GR%=]8Z5NU
+MNG1-V>UK_8'R==^\@Q.!@>NXK.Q1]M%NKGX[T#UWY5573YM^S;4S9EXW:_:<
+MN?,6W[3DYEMN+;CSKO5WWW/OMW8%=W/;Q6T;O@PH*WQ3]>::^[=LW5:[_8&Z
+M>D%L:-RQ\\$$FE]5B)O;7K<9Z/+2L+@MM8V`^O\L&MRFNHKMU4G-R[$6S;11
+MDUFL:7QZQAB'<^RX\:X)$R?E3+YL2N[E5TQMXC9L$^JV<.XL[CY@^OO_6UAR
+M%5NV5U=P_YLU!"@@3KBEWI6<L'G+QDJN;O.F:F'.!K%NR\XYAI0RPDCL<0V5
+M=<+F#15;YFQ!F;^ELFIH8@IB::%U&BKG5&S8@"($^H/E@4&@LJY^0VU=);=A
+M<]T&<6O5ELH=9JI$B%%J_0,BR-,$*I6`0'WEG/I:D$!B/1>7=ZS<(:DWU&[=
+M6EFW83.@6R%P#XB5]32,;*VHNQ^0JZP`*3A'J*[8-J=^\Z9M7"5DWE+/WK>`
+M0$N*JJ_<NAFD(D@X]G<;5J02$82HADI(L'D'5[6YH9*#0:Z.$ZKK*BLYH;&6
+MJX5T#U;6U7(FP@S9*G'+ECGU0NUV#OAK<^U&KGKG]NI*P&SS-DC#/@C["F[[
+M%M'`J:(>\-U<?[_1,O%Q9G,]JWQR0,7VVGJAKA;@<!5;H8QZ&"VQ+&QD!FTC
+M"ODZ]LY&%/;^@%@K5"2:J7('#!-;DP+\MW/+;\_GRO`QGRO!Q_5<,3X6<##4
+M<#`B<5X?=UOA*LZ[MHB[_9NKN%6%W^"6WK8`?M?#;S[\\KFE*[W<[<NYVU=S
+M&RKJZC97;*J<PQPB<K>502/6;9U350F#87%Q@N*$BONXP%IN6V4CT='*8@Y#
+MEJUE1$#"J>AV(&A(SQ4!0>,(ZEVUAO.N7@NHK.-NQ]_J9=PJ/_ICH_%F1[+_
+MQW_D.=47EGVMBM_9_$&3['_D_!&+D'[^B%,<K_@>.=_A%JY"OUQ^FV>%K7X4
+M,_*YPFK,>QZTS0K:(Q/"PR\HWZ%7H]6S=M6/X\XWQ=',4*;'L"&+GM#4I046
+MQ=<J%SH[>JREVE]_A,?:6^4B>U>1BRTJ\-*#=A@#`]H__L@TM'G*T-DAWP,T
+M)1L+KVD>>2??5<@,@`K)N4%^.Z;I6KK'38%+]Y"S@@(IFK7[8_208!GN%`'A
+M`P:/R(&<KF)VXKJ8G;@V_2$L88\"]EC*'@M0Y5:_W8T#]*I%U0BYAE.+2TLU
+MZ:?H4H`*KN'0#9=-%UNU_"NQE%:ES+5"#KAI/0E:VB*XJG'*C2FZJ/(V\K>*
+M7>(4G!C<GTEM$LG!^QLQ;3S#%39V;V.BD#?=N`33JBQW+9=730M@T$^FDJ5Q
+MJV:_RG@IOXI6;NC]1U>C<X6571FH;2O%2_&6G")>KK-W65$/!W3.%X,"/KK&
+M@:DMDRD(2J`3O39<4S[T$^H_I<BF_F27/N1^C3C-W?$/M&9L["&%E=TNNC>+
+M)HEV86)`>XOUO)+A*>8;,MJX);O$#W`O;E3-F(`FY[!R*;*Q>=$NL4[/()<8
+M5Y<KQ:Z9T8)2;((=`6TJ-(!,#H[CGCF<D&*6-T8IF@/:SZ`]E(`+G6]31!2]
+M2P:T!]T4#%-ZUIRM`:UI*K53[VK=L-49X,2KDO,48YX$\'!`6PE93!]PU`8Y
+MR?Z__]YL`Z*XC#:;G@$-`>@Z#G>HI6>D"^L<#^/VLWQZ5LN^LQ5?Z'H/E#OP
+M0YZ;D/0[^"1[MAL_,_RY(>G^.[_V_P,P_BN_%OCM,-[=3_X_6S;^[H)?-_R(
+MLAI'U=@"VN43&:T5Y^H%2^&O4K`4+5VC64W9T-=X2GCI8;<N]F&/5P>T.R[G
+MV)(ODF9Z\Z*9PJB:F0'MBQA=Q`HS_N1\RXQ\VP/:5<GY1ND9D-/1,AV%".#P
+M_0EHB&`QY4=.0/LL%TDMMWG9#`MA-MO@)`#1^Q>V;L#2N@-:5SRME=+F82*V
+MN(#,M`2!'S3RC`YHL_'[:?8-Z7'%57``SXTCANS]#L8PV#,"VOVY5&9D=QBH
+M_<\V)ID>")OMEQ[0WG<9O(KD'5D>9G$-!8[#SM#)%(MZ]-&"4E)J7]"V-&SI
+MT*Q2CR5BS6^'N<!8P$SV]6N/&M!\_<`CI0&M9"S[GN@)\(Z]OX0QJ2V[]1C_
+MSA)+PYKFSV\55C9__BU'Z'E<Y.TN@'(=>__9BIOH99:AA>>,5#CZ(,/R'2W;
+M(9LA8TQ<TN*X-'\^R]&"4K@IN_GSZX3+:64+BG>T_!"%#*#0<A%'K;<LY/>>
+M"9H8$U++0-9,29$;4"W7%/+^DYQN74`KFX(%SDY*>F]`Z[V,]7K=R+"O&`;[
+M(&7([<55K2'I06#^^;*4]"`@6Q,A:-ZDW4M8S(B+Q>K+\,HA2+$,@-\&D356
+M0_JMNHP)S'>)F`+:C;2!%XV+]<W-BV:+&T'H98Q`#%_:'\(U`4U+9U-AWN./
+M[KZR)CL@^S6M=ASK$[\6&0-I7\9A.,+CG0IE;!$8VM;)1@%"86;SHJ"8#H1Y
+M8Q@_+Z,[_2!,R$*TD(C[35K."FAC&70H2\L8ER"\AD"<Z)8BT=T*/2X6,8)K
+M6#P2L4T:J7*\43<;<N%/Q^+(<29A\Y@8-ZYX@NVW$EZCD85W0N+(6,+=<9@K
+MU3,"VMPQB2&R43.=K`WS_7WR>PS6*I?L8_;TAJ=JUCQW-R^Z6YRJ9\3ESK=R
+MALB=N,RZOF&*DD$U'J],=!RVXDW168[#11:T=9M8'M#0=ROT/GF:9VB]3==^
+MN/55KKBLFI(S7%8IOIAGE4NT84T?Q>M7#7?BIBZ;K%=8D^HS0*V!B_H94O0N
+M<6J24%KF-%K'<8!K?M-":?8$8S/16I)L)IMND(*QN4)MTUAX7N=H>1%7MU\G
+MI1,"[G2TL(-1L1F4`Q==>W]":\XQ7-T7&INNA%</1CZJLO!\_'BD&>&,,]:]
+M8T'*/8BY-S$;B(2\G3R:R5M:G8[+VR\F,FY?QO1?D!UI+-E""D#*V>(`<-,M
+MIOPV1JT=2R4]JRD3_5?!>%5NC%;/,'",BJ]J&&_0[*CFQ7>)&<T/6F:"IC>S
+MYJZ`]CK>!HR.-^,PEI4;(U=U,HPK#`@3$<)8A"".DC*LO4\8XPL,9F\"91I7
+M(='WJ_`=V4'V'\UG+ZH[NJ5=AY=Q0A[!7Q30;`!?%PXO4P#O`A`QC\#X1'$%
+M`:UO`DD8XO4:H/KM8\S!NJL`FXB+7!4F7YRCL&7*C%@J""!ECTH>//"<4?/B
+MZ\0[]0R\K@8EWD!<C+X[P1""`Z88?6`"BL^4=""BGYV0$-$#IH@NQA%U#O8(
+M%82;!(Q5''LSJ="['"$<'Z"Y8+!";1":+*!E6E+%916*RPI#+C64_I=EYA4!
+M#>TDZ:X+3S"Z>S+*L5M&LTF&/?R:*2N#T7*2E0,@8[.9K*2^76;T[3CLV]&`
+M;%#,!$0C`7-,O[9A@B$"1J,011+:84D2I1\DB=).>UR4OF(GZ05\-4W,9C<C
+M,)Q3[JU)8O++]]'F=O[Y?#VR(OQ?;P=V%V[31)4_H(QU'!ZG"D7=NJ5$L7@*
+M^<;G0OIN&TNQ&]!;H^6B'6_\2NL[%R]9O'X]=^?B6_`Q3/X\]%WF[VT*9NHR
+MW?.CL);:T['=H7'FUF2HTGU;<2GS1FWO$[3X&FH7)S$F?R*@31R/%)#1&[*:
+MYULLD!N0:[@>LVZFK/G:-^)9<UG6I[#D]\91@9C?F\@/F1U[?X$T!@(]7<?=
+M&',(<>S]`86O%\="1V6VK>9MR]8WEZ2OCRS#,SR(\2YT>+XX'CL'8N=$KF-V
+M8YXU*/$M!8@>R(TY)#?6XS4G@,R;%L9AHC%07M^\>+WXAHE1PS2$.T:W),,U
+MT6K(1"5X/0B@3(3T=]F&LF7#J:8CM!F9J!"EI97)7Z7`MDSV#NQXL,T[8%Z4
+M17`5,=IBSQ#6LP/-::`*&!O88\JTGK^C#>P.#1C`W+L&DKD!Z$68C1O)CY+5
+M:KO!AKX!SS'!U>:-XMDVPMEN;?-%N=7INF]@YUZIR<X)=JKXMQP<NS\AQ@D/
+M8I5PXL`0O!7WQ))PG`1P6NQ.87SKL?/=@*R;G]CF&YBQ.CWB##/T;78,,4HY
+MRJ#1,#$&,I?PY[O=1=G0=.>3RO^,B3IZ?Y>Q&OH\G4H!#T(`6:-G9=#)?)O&
+MCZ)KS,/TL0$^2'21'T[9F9C"#J?W[S[*QML@R/_\=NSB-!C[I>@<P25%[P0]
+MA\D#1UN1!>^$J!G%9B=Y[4L6"]E+;A;J>O]$\W]@#ZML2(?,@/:TS9PT<$OF
+M"/R2]2#`^8#V'18,RD2))4F]&8=91%LB)%4.+28YM%[84L-'A/"PLI:,4%9:
+M0)L>+TL?5E96<EE3C;(F85DWBTXL2\S&0>\';(X%P$YGP@B@<,:8_1$`;"67
+MT8PK;D"VR3.DZPQBGZMD-A%$!LG0,WXQ)S(^H/T;YD.-E_9IVORQ1?[8[C$U
+MHT#SC6IB)JXG11V'T;9MP''XG.?3IEQV>C]!JD1$W@&/.+#[;,JZA#/Y_CN5
+M-^\DH1,NZ/V0;R@$03E$S@K.,NWO]YD<)!])XJ&UP$,?6`2Z<,BBC`4AT?@:
+M;NOFS1)CZBNS47FFOYQP;0#M,19JP7VF-+,IF<U+,CC!)G79\:J(W^&?T34\
+M4N.C>"MY=5AIY-O&M/H&BEN."V@[YSC@'\!C!.QTNKUM.577B[:'7&%Z6T:K
+M%Y*VBZ>51AO>I(1EDM-*>S;SW3N8\!\Y>$+V12UOX<5*[ZF59T>ZS^E_/4+.
+M+VINICN/.;R/Z5A;@%=NL;D\7'%ZZAU.4A^?R+GAD235G4CI<'H2*>4:I.1"
+M4KH3QM@=EKELC!UCZ/8P4T'Y43,7Z)8SJ,B0K5,,`AK?O'BN.`:I"$<!:V14
+MF-'@6A)EZ%AT8.2Y0*=B7E.E.#RK86X$))U9X"D!]E4FH4;?;\CV+#U3R83P
+MQA[V2*_)Q+%BTLPWU.>/4=<>HZZ=$RY;@U960)!1[7]]AYGDH.U,E'HYHWF)
+ME1-RI4X;[O*=DBY8A$DU:>7:SWE<MR6=SG&XF,>!VW'8$M?ZA_AX=BI$K?(;
+MH>-`G,<2Q#FI#.A7NQ@VZ-,!,AUF$I%QR7*^0\N$8-`)Y@_//ZI,^P-D[L5+
+MN<T\2DMX`6!']V(,SS&92GS$+-%NE.A*V$6Q,ODO*[,2LJ,H#B>7:3-T(DA[
+MN-UP63VL_S+:&'$!']RB!-`:286FGZCZ+\H!'BBET_NW]9W>BUQ`\P[B]>5X
+MO"K`#VG7)'@'Y#@]E.0JRQ9!Y7"X%5;)YT+G4P6!HTQ[_-'X4#HZ/'0LG0)E
+M7M1U0!YUH'YA5*!<6P(9([.A'3]M/4:#(8TYSG)M4C8=O"9C1RRZK71!JVN,
+M7K`@Y;ZPU+IGRZSNM^!EU-ZHZHW)&:I7EXOY3F_L;JAY-M0<:J]#[4O.4^V]
+M48@=.I=,J7]K?&RCZ3$>?76$TJUTKZ&ER:'XG"J/5OD<W6M*VR)[@DY4H\7T
+M@[C](`5=%I@O^5V6(Y'Q>X(NBLI42].P,]52JW1AO./A9RS&"N_11EKA[7N8
+MY\XD_9[<._SW&/RV0UQTA#CSUPV_5_?B/GEL9G1FL:OW&VQ..&2%_&\VG,>X
+M:BQJB06F->?IZ)V;TI@K0'MM-/F!`!@-*[+,9<A6F&O20#@MOORS-"N^_-.+
+MIQF'E/6=."`#\NQDR)E9J0M+#EO2PM(GMJ2%I;]F,DMO7+=B:#=FXF(0F2/4
+M6"*ER>7"[&UR2KF0_`5('KF%V5P'M,6)S!&G$78-A:%YH->YK+0LH+T/,V`F
+M2V%RCEM,)C4F^T26]IH7C$@/VC@Q32ZRJ1)?`*"L,EZYDGHO0!*MK=C+>`T8
+M;;M=A@&Q@)@.O;(.>!IS'(^FH;Y;GB,=L<GE.7)WAY;F>!;O9(PJJW.EG4Y.
+MQ,`>OE3;CU1;GBL7.5%1R$7_!!BN/^#4K(^P0HQ8&],DI1TN3IR(IO0/8M8`
+M1+HPZS?))CVJ;W=IQY5$1A?>PVWS@.:QB,[X*ZMRE9U..=@OOT-G$_KD;E2S
+MU:+,CBCAF%:(J]UHP<G?4@3YFMY@H*0'G9QPA?2@BQ-R0-6N`4*-PJ0YK<A5
+MJI5"@>BHQ9A`U=!@O>\BWO!+!7IC4*>T0B>[H#+4'DR3VK$\T/'Q>N@UM+X^
+MJ:,G#>3(S`Z:4_ZJI[6$[RQ)Y^(>`MA&'WHPZ1FZGH0\CR=_<I52NW$T#\8M
+M[(UH_GE/9_VUX22YA;>=,ST<)@AN?JS\*2COQ1XQVG@&D)/:^SU=8A8#IR^S
+MQV]W'^8[J+B%?-JV+4]O93;;Q<G%1Q5T>CV@['!ZWG5([,HFT@'+T\4Z3]`N
+M;.WR]E"-8);BZZD/*`MEL1_]9H]C_D_;O#T&NF=I6M'?8L]+.+37("7:-*+]
+M]]D6UQ@SQN/5Q%&ZMX=!K7M9$4%[[!'L4I<3[SU]^$&0XGB-Z!A#HWH9[V8,
+MVND6P%RHS:QE3OE81Y2/NXE)W-F$/K^!W&UXH6;]=;C!#!IG--SJCSD.'&%:
+MG!*$N=LBP>8X?(1L"8L\Y^I^CPL#_9>`91`,@!1C]==@-]XJ!P%F-U4F!6@:
+MS($1WH?,V?K(8^`O'B)53PG8@`!PA]N9O,.=5HQW8))_^;&EVDTA](1@1][!
+M^]%*]0:[]FBK$<92.1@E'P=!'[F"W=N(MI?%]F6EVA84`0'H=7OG4J>>N!QS
+MV%AWQ4/FQ4':,]1WL;R3:!4]F'0!R%N#[ZS":Y`_Q98IM:^0W\;364#!,[OE
+M(V6%:]`<>M;#!E?;9IZ3RVUX`OJD.%9OM&L>H$2#/R(3R@"$OMVN'7V8[E9`
+MR[02>^JXF9!_>^*HH5%7J-TD(T/P#6O?LCTD,&F#/R.R0.Z/S%?J[*BCSZ!;
+M.F\-F=9@9X<JZ3&FI)\F<DC0EHE3ZAVJ)780$#M12LB='1?3VKQV0BO_I++:
+MY3D7G(+WV<%$4##6GT8CK:6MMGG.[=+(V7^R?+!]*4CHCC:OTYS=YQ^G%G9Y
+M/@U>Q?P'M/&3@``7\9.$C'RRF2]$]SGE-L^GN_Y`A:?08O)^\37-S#06&&4Y
+M*F/DAGUGEU=K1LOHCF8\N^'OPVOXUM%5AW;M;S288^L5$^DO:/71U9U%"R!A
+M:[8B:L72Q::FF8"69;`99EDY`2/G>)W6>_'VES9?M-51@@EWG]&]?3I:16M-
+MNQ\S=R>&T>?N)J8WX>YY##AF%@BG17(TK=@)(R^=UPNX#-?L::M`4MA5GGT4
+MVU47WFO'E96NT6Z&GK?L=A%S)M-:HIR)K!SR2)(/P[NGV-DT22EV%LA'.CZ9
+M:ND^$55Y7##^%4=%`F-!(XSR.65[6"]VQ>^=29W;=>QF=[XT`=#M2B.[]-U>
+MKCV$WBU*[,J"YPX:^ZR*S^59^;![%Z\O?=C-/I;1QS(R+^E12ERSO"Z5#\4@
+M:RDD,.[WE(^DE=O+I'8^K<1>JOU4@O)*R)WZ@M;D^X-93U,?CP4.5O@VLK$>
+MY77*?-MPO+-VF\JJ9[<S.%/EJ2%)!HUJ,>_'LM?8`]I*4/[Q_B<02_)NYZ7N
+MMWTI&%=^BUTRJ"+09ZR;".:+$MV);%RT@F#_"EHU-#$$#IW_)M/&?4&B8:R6
+M(S0+6C+_/!91SDM'>.2/;'C*Q^+6Y.L$+SOOX!1FT\$&87>DRCCOL%VH:QQ%
+M!Q:$S>C$@,XY"!,BQ>C'">]!>Q#-/HHC*]%6XT@L#&#)KX+K(24[J8A[A0G,
+M;CV3#C*(:YGA^PELR<8"P(UNS$;_(HT%^>>3,MH<(1\21=`N-15P0H524E!0
+MJMW8A`VS!-=SNTH*2(*6(-_;FU?/X"/H^XBNST6`2F-!Z/SNJ^/80-6IJN*?
+M6H]!J73M>'15Z'S3^_#5F3ELWXNG<2__>+Z.S2G@N;!R\K-C5^IXJ9/:,P.>
+M\A'3$7[,<']O9^>H!9RJA0N!&#R?[[;*;R]/U$W\C]!Q`68N]N85,WBZBBBQ
+M#L+(0NZ'\<3KS.^_WN^*"\BD>,7O1*9XNVY2XVC/.W5CB6T\[S1D,]M]=O>Q
+M*5?-?W'Y2O<^R>_,$IVR&)6/`2-Y_-$&RS(\&C'R58YF_F3\Y/[![L&32<6P
+M>`:\>_"TW"F_,?@;$'*6%?*[F&$H1L/N\OVG!^E^>V[7!!P'Z1)U\F1*AT\C
+ME[&B!W\GO<L-_AXQIS@2&##[V^54\%+[TTK0)0?/X"0?KR4-NN+I3T-PLWC6
+M@LO&XE0I>(83)^OB:=3-CS`M#52YWD<XPX<31?R,(OKINLJH)QBK<YAZH#<V
+MRQN-C(9/.@V"VC6HE6<\XNFZ48K_]"S_&1KG\/2P_W2SV&-Q/'L$6M;QK/^,
+M`NH\X(F.`4])P1X8%V<>L5RPG$,ES'(DS7\ZS7\*4*%D&@PC@+H"FK]X!B\6
+M%K('UY^6_&>XP?6@`)\&^/';<,TQS>B"=SO^XD1SIQ=/@HZH.1TO'I??<3S[
+M*31<2!?'`P\Y%#&:KV//].)5DF&8/M2-9T?-@YKA'3/B"(=G^6.R7S/.O7@Z
+MZC+E-V8>B62%Y2,SWV@6^Z!F?F@ZC6K7+9_HZ(69^UAX_L&)9W"$V31T:AT?
+M.&>>@-IT_!FH3O/X^NI'J:6ZW#VS'R_5G.75(GC7=CRMY00^/W%"PH8,=:G5
+M$K%:NBDV:L1&C5@;Q0)#6KK3T,TB4'(!S!KPZ+875/0!F($DZ;,X__"BRRYR
+M7(,^=J7HU`:W%+VU<92ZK`?`_NH3Y)^3[,XX:H-9>/>H,!U[K.-7?X8)Y,MN
+M")YY!-WFGOC51_*Y4=A"&+DUJL!\Q1^-ST.&\,_7*'_@5Q\8Y9M6=8GRHU#$
+M1\GE#T#Y?S;*Q\C*@2\O?XA\R>H?E21?V+_^PM2Q:G2C.5;)%_*/KRG[_>QI
+M,#"I4D_K%_K[W.^.R^<2H;_K&'Y2@."ECE,O-YB7SX6.!R?([\AO&TQJW'`6
+ML8<QT&C^U&+S9%;L>^MC[WECJ863Q8/UO9XD63[\GX%/LIY\W:7QB:7@$QN.
+M3[L\4C/0UA1ADGK/U._A=T^R3O^LR'/O>6WO_?GT>[_O:3[K%1>K2D';%_I[
+M%A:0+HY]_S3=]OXR_)HC>+_X>SV`_GNYT[07O\5S@Z>ED]S@;R+SPV%569J4
+MTWOQS>980=T8(ZT":4$B`3!4\O&>OJ9A%TK1OQXCJ.>V9#PS`<_WA^#9TX:7
+M@'\YGGAUMS9I*)Y:4LX$GI0V\N`E\1QA_-LUJ>F_./XY$_S7SUP((__-@!DX
+M^E@"O3]Z:T,&B#*0;P8[7D#GF7@N=B!RG<&'_4P.1%/XD.0`Z`$8&1PP98^6
+M<K_F_\OX_\K^JU/U"T,_P,:5WTE#)$&@V2W'0#^H1ZGZ5?I!XO[#NOA<]<J=
+MB?LC$_=_4KPQ`<!4:6:JD>$]7,>V_L_N2"2;MGSC8O<VH;:Z?N[MLQO<^7/G
+MN_,]GAOFY>7/FW^].R]_\?Q%B_,\[HT5#9LW;G)[=VQW3^,<+RZ=QN\]2J7$
+M\V_YDOPWI.97*'M'NQ-@4/YJH7;;EY5__5>4C_F_K/R\2Y<_?<?BU/_=T^OC
+M=):3$&_?>("66?#N9;^&ESFJWF@IWB*I>OOAUX>WU(:_38>_;-H/&^D"V0N9
+MXOC\D^%PV]+'M59^?I%T(7WW9\A4/3BO&U9RZMSQ-]MY3GW>68![=]*$`CRD
+M?4!R&<_QQG.<\1QK/#%YJ2IE/VH@,@X0D:(98KK<;_*S<95I2EG;MI/L=APH
+M2@<H13S^2<,_5OQC@3]6$ZKZ?$X!7LN\3D#(V;LS`;)I"T.PZ[AYE<(&^%57
+MUM5S[#'WOIT5&S?6&>VZIV]:>LI]>W^IA:I*?R#PTH?XT%ZJAQ8,:1>,U0%'
+MRVT@G-3]',Q4U5`4'?>$SEZ@]R_PO8=\!^G[,8-QAW1MO;%;RUSR-A_"O%<+
+MOV4OLQRA,(2JH0'(4:K]1J2M(=#G7L&UA=_C$F'H#!;P>!_\+5,?[\='WDGE
+M$(:FWF.[HDS?3VFEOU"[[T>8VCRJP1FJ02Y@$;H;<^Q'</I^A!;0CB(_TKNV
+M^0%$P*GO/TOQ/12_XV_&$H<C="6$UF0@FU.<EB^:M0O1Y68L'_3X,8*)[:`]
+M7H=N*2-CC7;10G6&OUCU)]T7C&,/\?[95K&U,MX_[M3^6;UM6/],KAO2/U,3
+M_?,X]<_CU#^/4_\\/D+_O/U`O'].C]`_XG:S;VX1S+YY30UA\Y6J(6RS4ESL
+MM"4O=BY#FE>E1[^3Z(6?42DYD/FAU+9?]D"\[?]4.T+;Q[Z(M[TWI8%7/V"L
+M53A"LX=TRJGM\;:?_$!JVV<]$&_[4Q?BE\8-D<\?;Z&[GU-E>N;V%)E>MV$K
+M"+SZ6CQ$M]A=N&6+>WMMG5#OWKS-+=979@^)GUZ?S6VHW;:M<@.="D<FK*RO
+MA^#%;FYMW4X\1SR]?N[<N=D<!F%J/`O+8#36;18JW3/J*P4Z;RQN=]<+&ROK
+MZF:RA"R14(M'A[?M=%=MWE(9#ZVOW((E7C(OBU_LWEY7*]1NJ-U"YY#%NDJL
+M!1TSW"P`#$'<;@+$(XC;C?J8=?O*S'/-W&;=B+8?XU)HN_Y^%'U.V?]CQ>N2
+MO4\I_AR\K-";*WN?J%+\]BK9_[2V;QLN+(=QF3E/.[^-77;+PPQP+%YO.E\;
+M!=S0^TUR6JB@ATK96LTU<YSV12WF>ZS+V\KLEE_5F2TLNQ0Y_3D.)\8M8=7[
+M:JDVB]PH/4*4'O0J"E[J*GFN%B]3I8)]),Y;M/JM1'N]'_%L?IU/<@.8\EXS
+MQ1I*X>P]RI.M?1C)\Q%M`Z1J*[>U^C_5&^VJV$^W:9<[`?,KH3)5BO?I*ME[
+MK@8=GCVBS7T`65N@Y=5I0.;JKSG<?WU$^T\@3P.OH[SDR1-'Z;Y7>V\USAIY
+M;A:G2,%69],$/'?U!Z#:$Y6M:/=[!2502IP2J!W"IL1]Z@/:\]L)^SH3^WU;
+M$O>KUW#:8_`IE3AY1!HQ+G%"\]=2#=V876#9V\SL:[>PRC^#VW`$!M*78")]
+MH2H]82:;`\EZ?P0]`>A+P2<X\>H:BRH]Q:(?T0[<CQ?AOLIQS(YY$_-?0GWT
+M,'E`:C8NJ&0.I1]9DX:;P*7:G^]'[>I5==\_`J2R&ILJOA#0_A&))75;0,6F
+M74--_8W[S:8>FF8+:WX/)19NC-=F9RU5^<>(;!(5E6KKJ/1F;<;]V`:NWE?(
+MF=\CBK_9<R*8IOB:"V45#[OM^1RW^'?/4*7CPV"X#!AG:T@T]S8"C!JW*K8'
+MM(X:7!5]I$-+ET-;R(WR(](?IKY,VY8?9*T-@2AN[OA+.I0#P<9NIAS:`2FS
+MEAYJ5_;1S<8XK2`!5\,%]/V(C?;-F@2QP2BYVZY0IA!D$M>:3,`)TX'4=V^C
+MJO]^&-KK"5UG9(HJI3\V-+*`(FU0+78B4_4^!^H:.NMKUNQ8>">^G=M,($+G
+M@POC33V&E9<W#.2?-B<1B+-W#;.+]S\ASP=.^F!O#_#2!\W!/UC%T?C=?/1B
+MU<VZI>$J52H:!NJ?-C.&)B>`827XXQ$H11=_C+0R=3,N^S\U8H*G,,'%:DSP
+MY(@)GL0$[U?SS!1"%9\E\CM5G6A\NQ2U`)U11X%<&+O5C"HEJ:?NVP;(EZ4@
+M_T>"YXH4-`>?Y83KPN$:"X$-4C@"%*=#4(U5V\!"(%VV^)L(C&R/:0<90>&T
+M+"P%7^6$T=""4'`U)>41SOIJ),?'-!62TD16_<F]YG'-^#PT+LC_I9*V13J]
+MGUJ-*1_0F04*;ZAF9WOMH?.[;@]7*9G40R#M4',/:"75AAZRBP=5UNA^:5&>
+M>*7NV',KN6SY94`[L<F43%W<U?"7_#H$M)<WF:@EV>&EKHN,([Q<.)2_6FUJ
+M,EF1Q:0S1Q8IVYWH/&)6#4\WQ-^H/0J)RLWA/T;V\,0:P@FIDT<SM%\;!;)%
+M$4/=KJZM%^KG5CX@;F[@YLVMHT_.>+JWU`L5@N'K(QZ(CDU,-R$X>,<CJI)3
+MWU>QT6U&U#9NJZR+)R/UH.*^+97N^W:Z:U&-=..A?",5&VM!]":/M9D;@7%"
+M3X!FQ=:;[9R8JTJE/R2]L@P?6L<F8@BYB\X:Z2%=F$=M@>U7KGV+[%R=T(#.
+M<NW`)E2Q>N\P;(:TGU)67CI$!3A"2W`?3VJAWN3$;"S.T7(M'J<F%#@:U5S:
+M5))`3Y*Z1Q<$H`=EY7$,T.MRU<>?(@46B%\OT^[?A(KPAA^2?HE!F@=Z2WMF
+M$U*8F<>F'=V,R4J3DGU2A3I#0/L7XG=W2'>T_"\.MY94_U/RXV$$;J2T51OJ
+M93!+?7X+@(A4A&F`GL[U5]W,-0O9ZO-[,'@%ZM.8T_%:R9A2;=GFI'P_P`0S
+M@:^>X82)BO<9AIJGR";8U.>?Q4C[>>_3XX0,]?D.^,)KN+]+8V8S#;WEVAU5
+M<99K^2+YCN,]?8]84_KT^ONP3W&F@@%=(<%X4T.[_H;:>[-)\T)V%P419UJ1
+MW.VE6EMU?!)P&P[(>6JHF;)9JJ@ZN(=@JVZFN47S1=3+GZB,YQB+`V]V0)NP
+MR=P]G$OV_OIR?J=]C;:-T4-D%#M?@-?/6V#&*ORK%-7%TY&?AL/-AQ!FMO!#
+M]G*U\%TCQ-'R,YJ2X(?;T?+3^$>6H^51$M7AYEN`FL@9V.&)0XV.'67:S$VF
+M46?$&1YNSRDL&"&;O4P;9^`\*3S4GA/GV&T9K1G%S;=D"V.:;W$+XYMOR7*0
+MB,:O=/@2%W=F(&[%&'`!`H2_RH/-MV8+TYIO=0M3FV_-$BY#PX4)!,2!J;(Q
+M57JD-RP/0MZV$%9RR2PA:\D<P=_[&-5[#P1QHH-U+3)N4GB!>"T,Y'_#RRF,
+MGE-##UW$#GRZB@80FL$Z(Y5A-83I(RN^*M_V*C82MPOYO7G8[Y2/7.KD,ROW
+MR(<JH4EAEZ-IHE&,K2T34,\&U%?U(G>%FYLLG#B.42<AWF[T79.E0+R*(8"&
+MA9Q:8BW5SE<BQFS.[>S%C62UQ!+9AN/3(:)J1TLM/!`H.\]!8*8.!?-LI5D!
+M?Z0.],822RF*F9P-)I'>$KDS&>84<N3G;+Z5$ZQRE-+VW9?`!">:CQDF4"S(
+MS/@!'M@^M(-]_!H^8#C)"!M<BY=?F;8/"6;=>S<M8@VGO:\^E]6]D4G7J"XX
+M/5Z;B5.DD,;!#RK,D6U49$Z86:A<&S;&MMP:7K]1]=G6:-_::#"O<,88S,XF
+MKTGAO^E;=G!S\[BYTW=PT_/F[QA^GN/(>IJQC*-1/*8&[:I_'&XM>FU[>SJ.
+M.??VP%CB_B=:J9I-*U7_!K@%-)IK==*5!%'HGF8<?-!^VQ,<:,@HP=;_*[R*
+MN56TZR"HTC2$$="V8\TZK4AW-SL.9):6J-*U$$.^((K1NN>"$3J+I2^@EK`#
+MK,8_X.;G(BH7VH8!GN)X$=<."0:D'@>IU6*8/*`MDBHAPHDC94/L'8[?!>.=
+MGG\>I%DS^M$;30,?VIV7OBU=N,'Q\#G.,-/=\B/FB.&%.WGNJW[/?LGOI4O\
+MOBS/_\G?JY?X-5MZZ"`PW5!8B(T1^BL(A-!Y813,R3,[+<L*.RV<?&PDCUM$
+M3XN2FK4.`-;D@RQ1@V^6:_GW\%RG]V]<S=7EVJ%[F>+H`L"@5QZ[&O==:N:6
+M:S^FB)K%Y=H/[C69?3PDXCW]]:/D3DBZF/S?PLM<#`;)6JR^LK8`]9%[X:\L
+ML?>-]+Z.WJOI_2[X6\.7D].SPVP"&CHOCE=8!I]-MBB4/E+H..P]!@0T^5Z>
+M>5L+G13&=UJYHAJK6I)=6D8.C='32H9:PN-94!Q,DJ"4\'(AKU!Y<J$-F$>M
+M?!7;Z@C/3=\X)^E_;OJ.N:G_<\,7KJ?OF$W_<].OQU\M_#::;5V:;/]_!^GH
+MQO9_E_<,>^#Z']=\ZQRA2!6UH>OJ`57ZIY\`LY1K7J.NN=(%R^Y)3$4N"Y`?
+MFVJ\:*NW`?ZH/DWVG4+K>F]WJ8KWG[RY1D4SY&/PU2_[CJY1Q3Z8IIQ2I7__
+MB;%*WG</`^Q&P)<9@"$)`XU_>J>DT7I*MRZ^J8O'=/$H`_&Z">)GR2"FC`CB
+M-"TDQ+/^VLRZS<CJ@JR.;^,Q;A!OVMZ>Z:@KR5X-OOKB7WWPU1__ZA]6$/SM
+MK<6"'(<S2]327TD7ON%X^![3?K_EGTDP3"_GN9G&;_I7_%8:OYE?\EMRB1_&
+MY7U%WJ_Z%7R--/_3Y0.ATHB&]K"K.S/S#'L5.O]CO$,P4#`(HA8T:$1[E'&J
+M\COH8MGW'-K>."%Y'IG+7`;,U@S32XC_(!$/719QJM)'&.+%$(W=*U/"I+V0
+MK7M/MV66M+2+YZ7@:0XO`#W-)E&GQ^W&#SS.I'A/+Y.]+[P<\/O]@Y\HOA<Z
+M/I\Z\XTBLM,[K>ZR_$WU:A"O"N&8I[/A&MG;3O<,/5<N^U_5/H;A!2HA=<:D
+MKK_1,:A7/6)[W>\#='>;#9,<O0LGY$AQ$%D&P$J)ZG3QK):%XU?ECU/M@:5@
+M+K?[&Z;!,^@G=/M5+#A#\3D=SWIM:990^VY+R?<'@W;<>;5('7B_!.Z.4KI=
+MO]5]N>AC5<QMY2>&]*9GS=/*_ER//Q:<H-!U`9W\?*Z(;N3)]9S;%1FRK3KL
+M',-#?ESPM4M'<`L7QFX+N^B9K"3RSR\K5;SV@E+9WZ^]54[&[IV%EG&*OU_Z
+MZ#/HCK9,OGM)5N,8X"ZIO5OV#I"M'_116U9SQS^T^OJ:/T]O=$)"2O`S3.!E
+M\1;^M27IC:-AN);:CV/X'%SOL:%)JTUZBR?:`E'O6C*Y(:,YV#>Y,1OO?.+H
+M'*7TEDWWVJ2+=L?#LC'&/U_Z<S;&[UK+<\O@=Q?\`O!;`#^W\7/`;[L19OXP
+M/>)3J+=:BR+?#!\&.N-:N_GH=5X[-$AK27ID:9LW"I'&_;\#LB\:R0\?MA*!
+M1?%4`YWJB%S.\K+$II6/C7U&LJ"#'`]W723K0\>!DG1U:::M]<2,CM;5&3,O
+M@+XF77`UI+?Y!EH=B<,-PW2]=VZG?4F8"!?@-NB*='57-NY29EBBY-*=#%V:
+M'TSGA)HU`;7(!OTVH*W"?O,/X&:FI;/YP0Q.\'5F+$8;1S)MR39130]W9LPM
+M=AQPE$B?.W9/E8])/0YUWYD)4"7>VEILZ?B<;^.S6S-`^X,Y9%O+9(R""9@G
+M&&O<#T.Z*FU)5==,>@.,]Y[K>,.Y]YQ\(G1R5Q:>A<DY_CK=PPDIVLDSM9"-
+MP38,#I-I66(_2.KCC1,Z%YH:1W5\D(-6H5QD>GC/!13[C?:.#YPT`*!M-H;I
+M7*.MXP,;*>191Y`5O#%#&89F&J;_#,>/"CC^>@I^&8X#1P`[QXL=*0!6)7:1
+M*NKK:S=LKA`J-[H;-PO5;MI"]!N^BNLKZQHJZYBO8FY9;;U`T>XMM;7WB]O-
+M+9MX:EQ2XLHJZVNW8"8O.3C.<\_85LL`S.06N[GLX?=Z'%A#Q*R*/:'C0C[*
+MR=FRKR?OI/QV8H=V\(1\#*3B655:^&\H7-$&#VE9%?L5"?>`]3SM6\A5WC-R
+M1MY))7AF:-YB7NJTJ=)BS)[15<S3-IZ_9^8[<G]'-*V@M*S&JHU=!XJ\<=5!
+MO!Z;MPF5==LJMABMX(^[<3;B67#J'N"'I43R,#_+4J4/H4B0#(J$!I4>9U.V
+M*GV!0:/P[&4K,B0?'F[OD=1`CY?2Q8.*]`2)39OL5"2<O<N+%#J@@_LIY31U
+MT^XI1Z46U-5<]*(8L(E_"L%4KQQ-J5&VL+GK>RP;+JBE:Z@>,,A=5#0#S=X3
+M[BBXU'^I^/UU-8)X*A4Y=);HC./W=H#A]UH`E]``)Y^^$-6FKMO-<Q?3E$:<
+M2PIG]!LQXM_B$:.,2>;'D0[RL2*,PT751KNFF$G$IY,KM#9@8C-"A:(C5RBU
+M/M.I/C]FF,]AF(?#VA03]QL`07VA-FH$W-G='64CX<X@,AR/P?"5C$MJ^3]9
+MQ0[,F"C\B]]`(:Q]SV_T;[IGMPUI/P%3P*A+=%C*^D'Q*F;C)]I'.&=_(U!)
+MJ-.X9B&^?A42P@O,(S9)/I[B(#_SF?2>LAZ1&U^/`!(/>>TF"&--@A%],IR?
+MCPS'-?2,,J[;EVG_=+NYJ9X,8]/7@,''853=S@\UMH)_I85KE]VS<O5MA2N]
+MW#RQOFY>?75%7>6\+;4;*K94<BL+5Y5PMQGMFFK/^<E*))T7C$Z9J4H]O\`%
+M\5:@"&4?><6QLA66,>Q3E?H@`00&;>F.AT-68T%]"GQSCI:==!6FK:,G/4UZ
+M&E+W;H4`FC3C>'.AXX-TN9O%E*;MPS-:9=JW2XGV2B0]???[H/C0O/H_B`UP
+M\0075A>T:M$UYDK/'!8.5'8V'C99E2X2VB?B01FJE/;\%WK-5+QZIN.C=+D_
+M3<("2[7_(&;!]\ZE>5-IRPAQ#[59#%2-`A8<U!Y*@&,Y`)Q\,05:XS!H5)-7
+M>F\P?&+9.&%NS5147H?@<?.PG+T6YJMJ'BXQ'BAERP`V4,\\A!=!&5)\=-6(
+MQ9_J/<#:G#(V[[;,$VWA8GP*G\-?Z*E?&GUR;A8HI1>F[DY_>2IV!Y80I>XC
+M^"4PJFN/K4+>CP>2[FOE2F31CIMKM\P3)^%]>7;JNWG"7_$(31B"A0Q:J/HK
+MZU/Q<<"KZ6I"'_F4>E]=.K&GU'*N3)-7$1$@ZG^D)AN%(O56Y+RYX?SSC(+*
+MM;F<L?TMI).:2'75H('X_/9(NG;[&CY^%J1T]>W+UXU`[Q>6$[.AB7NZ[(O)
+MQPQRQ!>J,KH,^<#',V=Y45SP_QN6>L$J+E2>QQ129T%`ZRDU*>-;`84@2.T%
+MI5H'LK+YV?M;UL8PP4[D=0>T)\V\NVZ-YW67:J&DO&ZZS(+RIHNWLKQ[.G&(
+M"&A^,WL0S\D]"',IEBO]*:*(6^)@*`!T;3Q(2763.]57D"E>0D6$71#CPK!/
+M]T-8AADF3BFE'-0LVE]6TD%Y]AD!4N&;,J4+:;NLN(*:,-7^;\N?FF5#Y,^]
+M+R(CVU9=4OYL>3$A?W:;\L?!>'@;7LJR\2MESF4KOX[,:?$-ESG;?4DR9S>A
+MNMZ7)'.D%T>4.6N^\;5ESAC?5\J<M&'0OJ[,.;[B2V5.T<JO(W-:A@'YFC*G
+M^^O+'/>*_W&9,V'%2#+G)B3SZY)DSG67D#E"NO;ARI'E3?(^?)N7CF#@+9KI
+MZ/#%)$5\8<TI+C<M^UI0U9`N6D5/DJ29:#%-?D(1Y/\D:7/[\F1I\S;B*UVT
+MB#<ER9J\E;QI,/2OR;E!WDQ8GBQOOF/(FXOI9GY3WOSQ&Z:XVI8J:4XM2Y4T
+M=%]RLJQ!9A@J:RI>OK2LD98ERQIKXOSR/&[>RMON85>2U'&K5J_R&K)D3Y\M
+M=:]_RE(\AF;CQ.R#8R"D]PN.G+X-PV4"!0Y!9J)Q.RSI@#*4WXO6-F$FGO0\
+M9F<:T,Z4X#[[X5=H*^79963<'M!^N@Q#VUGH]Y?1AKLJO<&^*TH2C&7<T;,Q
+M'-!^@51.ML2,XT<'M')(>7`U)K@MH*TH8?>]DSEK\X-`HU.4_90<9H:OO`FP
+M\2YCHTJV@Q-)1(=U2J+Y`+CZD[XODLT^X_^@.=<N]WGQN<KO\Y8MOPU??="R
+M:PO+OLG%6QM?C$M>X+5PY4INWO"UK9\60;\]_[1!<_KS>)9$.U#,<WAE.PVD
+M)I'B*03C_5X\[LFHIYDC7Q$&OQ,M!+2[B^-L@9V8;*F&UL]*,)9\YKU/73L6
+MK^Y.";.\H00'AH8D"!9=8@7[$V!GOK'G0B>$-V1#SW^/\8-9&\V+9O$K#GVA
+M)]</'72QKZ?ARXQYLM@P%8P:`4I29!-E&S"^'DB*J32S]1L!:R$`?<.AQ'%\
+M^W=D*8$126XYXO]NXY@`^O)Q.)6/_&N+YS-F\OIONP0__;(@E9_0%(98I^?P
+M"/STP>&OX"<TC@FG#/?:8;+K+K[D<#]P&(?[H3RX;BER6\9KQ%VSO`8/7H6]
+M)-E8Z`2OP8/CV/?[MR5XT$X\V/NO'/._?%U)*A^.#6AOWV;P82\N>$":P[<-
+MY<7)<K?4;D.AYGHMF1/%,08'?H@=N#*,*2:GIG`:*7Z&*=!?)*:Y`M/PE^1G
+MM7@(/R?/(:^^E;E`,*ZWEHOR4N>(P\:E<[>81P/-.;,3+<%J,@)*T0R]FVV7
+M7^Z)TAF.:\(>,29D@FPF_TS%%KDS<CSL.)SAZ3)WY`=/7]F?=&)N6'D/L?+R
+M]?"7E#<9?2-;Y4$L+1U+2V-E_2>6)5]@L>?D[B'^KI+M\2Z#<M#KASW9ZX>Q
+M&#>``W%J\%NK/.*`X^%'N+@K,Z<:Q+L7!U![*ILA^_OUD^3DTH[N_KPQ\9[(
+M?33.V2)WA5/K@O<V4V5P6\T>.BEX//ZH.-YTJ;?_-M,*X0C>6QZ,B1FK2O"@
+M,9U'MLWL5/`Z!AO@T_`S'/K.)C-Y<E\OO!G'71R:E/A*P-Q4\3Y<1EMOIB6:
+M_/.T.=D/LC"LK^9WCBK7#A4QXY],)1.-E3+13@FW?^\AFP[T*>CK:[440H[B
+M1&T'L+;]1FW-A0HT0"C-$S+E;MRRAGS]'M^`.`ETBMW[(LYPN>/PTKE1T!NH
+M(6QX@+\OOL91D!<7:\/F",5+C.5$5GH-5Y.ATM42T-RS`8%.M/69&H<O,/A8
+M#QNK0W98[E\5:F]Z/V72,FS=_W<W?7DYWH'\\U"4IS-8Y#B\=FY47VW;.5HI
+ML7E*<IK&-5_(%D8KF:U.'9KQ",KM\C+MFX5Q5+),5,+%T,5-AY.]^(Z`2QGB
+M(AWCV,YYX0Q%.HK2L7"V]-)*W*$1L];TOL/&*%P:^P4&1JS)-E@UT[0C-_.&
+MHV00:F0+NN-F\Z*8OU%FY,<:CJA76XK#N#\J\R]C1P(+;E/$&"BZFX;`-9)/
+M,)(O?=EII+^%I5^8FAZ&K[3=/S1S_;X0U\Z!!`?D0K>1+X..]><@?J>7H"B/
+M:MU+3#5H'=9/>KD4D+ZZ(5=Y&2NJB#"LX][?9S_!Q#]:0N=.5?3A8I/;*(7?
+MUO40YID6YVQ<W&WG<&$5]X^2FG\8O;WC,>X?H6T_6L(M=AS(:&D/3KL9[?"$
+M"62!?O.WL1_&OVQE8CK\,L*E\Y]QJFY&7-!%E3WL\=GK)TM!)P>2+>B4%R91
+M?F03[A&E-2Y"EQJG9[6\\D(G[K+-!#3PM\3X+8\XPN3@R^8X,#$+R#%6+!];
+M#F3]R4A@P]0,1>[![JM!Z0I&1T$_)8A_6)T_6,366%,Q]T;E=Z[>[D9W$5?2
+M#D\PZFETB=],3:9LYSVBL^Y^N@TO&SC(,HB'4#UJ`&T\O_T;',=Y/,[!H8CK
+M^)4N1^W-,$4CJ6*7NU=`'7[7BS?X@<R(>AYPBDXE7SX',!VTW8#W\F)XCCA;
+M>0`$I+,^!XMB-TLH05=7)L*.B"1S[)V6;R/8R'Q"-M<1PFMIE$8[YG,1BBL!
+MNRX+Y2DDWT/VSLQ'2^2@'1".7!8>BNL03'L(!GD;"KID!ZY@#S^R/M2_J;20
+M2`JGC3A!Q?6J_.2Q`T0N&PC-$=Q3E`=-Z8W-[*>YK=P_*^Z@=-C8>LU"TQ]E
+M,OR%J?"=@2'2&D0U#(<(%X@WI`M6>1*5E^I?*ZD.K]W(5`8?C@ZX]G1S.!PZ
+M+MH[,]@9,]I;3BJ3L9N>%UA#XI/D'UFCI1OE#,3]#*728N!&5A]H8=%I[)L"
+M@CP4MH1)T5M3=8@U1M6@!JE#T0FIBX>!>+3BB^E`RS@(B$<5;S35MV=RV;^Y
+MP6S+_./0FHZ0+JZ.9(4[,[F(#WU94O'>,&Z>1(8T<+E^H]3)0UUE7Q0U&B?Y
+M<Q7>I#H[R=NDI0.H"KE5/(QV8GU?(O\1#R^/$R8_AU?)OO(FRB*T]<!;$KK0
+M!SXWJ]SM*9_A>*@?T2B9;6G'651W_LE!]'9A.2X?2RNQ`P\[7K1!TRU52EQ5
+M>H'-\>(RFV=UKN/;.*!`6U3)-M6^'`1RDALF]"XE6[N*:-.QJJO(9GII'C&E
+MQRIFZD5\9$LX7$7N'6>F%K5[O<HO[^BQ#H,<N4Y^Q_%B,?IR5/F"I!0`<3]`
+M=+RXRE:E%-FJY&(;8JIP57*1C>%L,#TP1U<F;:RF[(AOK=U6+U34">+VQ>Z4
+M^U^S,;:Y9+C\NQ[GL&]2D]BFQ>1B-UEKI#5_$),#TV8%W')@QHE/Y("MJW@V
+MV204SSBAR<5.9=6,EZ>&(FOD8X,?='S"RX%<Z4)^D[VK.'<^HC<>:&;/[EST
+MFM^0"8'XH@1R55=9QP=6.9"C!&QI`6=:(*=,^^-B9I#%2Q=T<7S-%'5?_R_Q
+M1)=5^R'00F1W6`ZX(*$<X-,"-CE@K^&T7RS&:1/9>EJ5@(MUE+)[VJS=;G0G
+MN]M6OQ`*2#BW*/_-`GCPJF1_\PO]/?3$$41'U@?0#N:]K='?_O"9`HY[;VLL
+MDMTEX2O:==58M-]:$G>+W+-UPY;*BFW8KD)MO;NVH;*N:DMM8S:W"9I\+C0U
+MMY4NR%WLC@=06]^;U-8-\P%MHF<Y^(QTJQ5J.UF5EO\G3-.@MO^Z@/3D+F\[
+MGG;K\AXT#C&BUH)GN%1O>ZGJ/0I)5>_!4NVG'N.H[:[Q4K";$R=(P:,<SE6.
+MHC&DUDAW171#8^$U4=4'\(\E`R>6]V%YVM2%J"*]0-:4P;&J=#^%?@=PZ*5Q
+MRW]*\3VC%+IE[RFE<)KL/:WLM$E=;CEXILO;LS,G'<@%1N*S->XR77Q!^Q2I
+MR/>,_H!-?X#'@!X,"#ZC-#E/_$4./M?E?8I4BJ,YGN!30?2Y#L#7P$#R5)6T
+MY$%.*)>CCF<+@9'3L,0?.UYT/0CBJQ#3_1A]7`*D$I>ZH*SC(ZO"Y^$*2HE+
+M69J'8J*&#BMBF5NN9PZE2UR.%]?FV4(GQ0[=^Y3B>\[C>VK7MS'%@]?CPN5C
+M(^[EOI=G,H(\2,NBN?KS2`MZ@UMOH(MH9X.JT)5!W#>^QCA8ITW"P,PT8L2!
+M)-GJ3$!NRD.;-I15G'$IER';36>F:!P1`%BO0Y\$".I+"W'Y8<"R>]3!@B('
+M]_W!X`!;%]22;+?Q'_EC$#=N;JC??/VE/#(L7)P_?[A'!I"6PC3;4'L!@E>U
+M>8>XK7YC5?UF`^3U0T'>N/B&(2"!W]\'J._MFL8C].8W[?+2:;;WMDRS@;SY
+M_9)IZ^Z`=]ZX]P_8KPJD7=5HSEXE>R^^M_7B^U[;;]</``LJWH'D"A(^7UZ]
+M&Q<ON'%X];X_N`MK1_GK-V^JKQ1JMFXW0"R`_PC,C?/RX/\;W'GS%R]8N/CZ
+M?'?-_=6)^@`8F[)R&@\*.UTXQFD_N)ZMA5!@CN*:)H^5O\G+%39YLUU^P"GO
+M=+VW,S>__77(NW8:+SWHQL7UNAQML9%O+36.3<E6[N"5^VQ*C5VI<RH/NG[[
+MX7LUN3!$6PID^[37A_5'"O+77P+YO!3D`=D_@;2Y`U$="4]`WT25<$4L'X,,
+MZ_Z+.!)^6VLW5IF],S)V\SU)V#'^>"\X4*7X!ZKVO(%$X.]_;VL_.NN)O;\>
+M1/(`^IN!Z8,O)COE93Q$G*F,1KCCS'])5<5]EW1?`M2P:`AE$EW^X?4$OA5;
+M<%WP2R`L&$;;=ZR3_R"UITD]L9E'Y1Y#SN67ZA^,Q#_W?)T.2VD2I#7J)Z>\
+MCI?OM<G5=GF[4][A>F]'@IZ^3K>D^#^:;4QM3I,RPXVYWGB52ZWLK>."$SYX
+M13K%4FS]R'PML/;]+O[.@[27NEF24:E&&"GV*G\WBQ1E57H.Y*:RC\I2QE7)
+M^Y*_RZP0\(OD`!X"7L``A05,K)+'FN\!2+W&&O^"I&MX91_#RPKH&J]%B*[Y
+MCNCN8^A:1W&IYUU2\/WH.L(WH-4`Y8,^QG?T.*C($Y\X7CQIZ4[-:N:/9_]G
+MR*X_CYAI,W%D-^I3!&"<CA?+K);NX?8J*?8OB?R]^69^QXM%#(VR.!K)4)+S
+M7WL=ZU^C<:"E+.9[$7P4QINM")JMD%>44^PK@Q(:'S:6T/C*9@F[V9<=$PZS
+M=TO:_YAIM-]U^7A(J)A5/&!-:KED?!MGQNMKR1_!OU+Y3-/>61=M-;IV-F^X
+MQ4]*_6>:_CLP]8$14H^T_CO#G,PI0>>>SW$)M['@4G=%G)QK'"L<-?)=$6ET
+M;X.X9+`+EZ_%=.ESMS!OL,MF?&0)5PUV.8V/;&'"8)<;/H1Y:N'G4M32`(&C
+MQ:M:C[5F%$N?W^4(X1V1@UT%2`2A]^"],^.NWFX*0\7;T9*+.Z*?NQT/CS<.
+M&"AGW\7UDD77\ISK$C\!?LWPNPM^3\"O&GZE\'OD2_+\5W]+X0>X%G=F;.MU
+M,[SAO:[7%7^_K]<6?Z_H1:6'O3?T]L??A=ZS\?<J<N[(WNM[WXR_YQ6W>5U\
+M]Y),Q\,'*3`/`WM_SK']]6-23Y,4=0NV05KE$*["7*W'VK4,>QXT,KZE3<LT
+MWO$E4L?:6^0Q9<OQ8(;<T9GA*[X4/1P!B=JA926N\4@Y:WI"8]=X3.K,N!MZ
+MM$G,Z,RX-3(VW-Q1T#H&Y](9<XJIMSLSR/XO92T_F49774-VMKB8#\5,*G8<
+MSL!YMN/PD=(UVG5_TW6Y`_3VMHDM)\4/Z>05K9%<>@_BXG0&+XCK"N@O[J*E
+M82J>99M4XCB<B6<@R]9H)V,&W%40W?AAZ#QJ/!"%*=9H+U#L\,*&V+].)^;2
+MYL]!`TQ56*@'M!N!X=2EF?K@[Z\<P::3Z0)Q`&NGTVD!T/VO4*RX3UF$EW<8
+M>K+A9T#U]J,N3(=Y3N`0M[YOR/F#)<GK_]-I70,T;#P%CC=>&&#B&KD!FS1R
+MU=]3AIJX9[9Y[/F1',CRLO2[*;?)49SICI/]1_'T!-I1S3PAO]'Q0<;,-V#2
+MI;JZ\?5=&=<Y-$[,(#^B98I?P\T0N^+O\_ACN[(BUX3#$!"<JA3;9J*/_;Y9
+M`9B%]NV<L<?;AZJ^[M/PC@;(I_CZ8-HMKX(9H<90['.O`A3W59_Y0I?]IU+/
+M<ZG^8V4P:2NK&:,=A6&XF@-1HWTR`_NA2SI8P%JG!J<7VEVSL'*YTBL4+%XF
+M7]SSD?Y[W%W\[BQVZI3%"'^N(;``\@&(*-?J9Z#`Q38"*!-GX5SJX`A[<H]>
+M#?,=*I,L?+Y\/^Z^JY-H\[S791%FX'U<7X"`=.QUP;R*+9_=`C*Q'K]PIM6[
+M.8W\=TR4_3'I0H;CX55IQHFKZ!GC3NR^JWCN3?@);I!W\%L"OUSX]4T%667A
+M)/TNT=F5@?CEM_=>EF;83/5>P+-<:OEY`KS%\?!?K0;@TO<9X!:`<6SJ__SO
+MOUI.O_O+?_\='![YBGQG_C?:(F;DO3,)Q@OP_NH0F$]^11EO#HD_"M^/P>_'
+M1O@S\)0OM([M/6Z,$1>:CW2WCNW*P#WI7NXB^DKJM#1W9="^>/_?V'<VW=36
+M:1G=^UUZVNC.ITY+9N]#]!P5">)Y4TL6K;UW6NR1K?1T1RKI.26R'L^JT5H!
+MH]@7X8^DSQ%'=670]UX\6J[?[0CM0Q;.0/6AMP["6![Y@HVY!^UMHGRWBIG-
+M64WDHSTZ;:K-8D"FI<1[(0R'Q,:<MK'M'Z3A!W<$:XAI>J^(PV36-_/C>!FY
+MM)1<\<L.C#S)KD^&K]7^=&K<S:YH"NF(S]A7H^NX9=^`EH5#QQ%:%AZ0+J0U
+M3B.&>JJ'&*H`0)3";R7\\+T8"B^.'#+6FZ\)MSE*6HZ+_UICB8/47D)SA:A%
+MM+!Q=!:N:FLI8U_ROKAUJG$&=LCZ"WO$4"$S762Q1;98:3FNL`V4:DNOH14V
+MW,2<9/JIL8OI<AYT!,!###M+IB;!S+XT3+7$76J`_=/T.-B<!-@,`)L53L"]
+M-0FN]<O@%IAP'_]:<.])@LM_&=Q[3;@W?RVX39Q:?F\DI\W*#RZQ-#JD8,S2
+MD-%I=4?X,)Z3UD'K",9T\?=0>L97]H#Z<#-\FPB\.@U]7^KBQ$3I/)2>:9;]
+M,-H,<XJW?XCM0'R\23[#="Z7?#*\1B-Z_^#'Z/M['`[CZ3/?P(N1,F9VJWP'
+M/CMED3GDMGU)*ME[!A+,\IZ1O7BI';JZPI/4,#Z>OQH76,^`/IC)B/DRQ:>-
+M!"(-+QSJOI0N6`3X:E=!"^2?#VCCIL5]X0EK:N:5:Y]?G3B/SA=%TD"^D;%F
+M&&U)3^'0ZH\!!K/*]#P,L;H-^^X8WOV@_1QS]S/?"I'_#!=+%ZV[?Z`]?C7/
+M)5^ADO)O7D-%W;PZ<=N\C94-<S?>QVRG\&A+$LJ/3@'-@#FS0AT-X9%!VZXK
+M5>]3%)1]E7D@:$R2LQVWD`6#\;,DJ,F9%%*#5'H6%Z:77<UJ[D(M#HFCQ@:1
+M^]$W6D"[_DJ8?G:1HS3.K7A?D$/;T<?;_HWPMRM4#7]MI/RHH;MT\GV"$:7E
+M2HD=MZMP]62&OA]]7:G/[\H!5:HXO53?CTFU!ZX`O4<IX?5N:*<<NBL-/W`O
+MP:C*>`Z=3)::CK*P7>:9=)>\]O_@96BBM?V/6)GZJQ(N#<?EMT?N1W]*Q5>1
+M"\M[\'W%5<:6"'3K'Q4K3%8]A;SXL>-`469!:0))/(*IO74Y``9D`IJ=6M4%
+MU3F$TUN+Q_N4^+Q2R'N\/Q9_7J[]\4IV[.BQY'Y=>\>J0I]WJ![_GY,16?='
+MB&S#5&8^QL.,H+!F=D#[ZQ4,>QL0X2PR$L@HD:.1/-PKK,9;JP/J\Z\6H`7M
+M[8!:I_1R(8Z9F;.A!>UAPR8(?9^:DX'RV]=RY=ZU[J7LR94NA1^\^^#I@^=M
+M\+P-GEYX>N%9",]"_#;RP)/S&>_PY$I\:Z=OF+YQ\?2\^1N-?<Y$S3[+8>JF
+MWZX^_\ADO)D2_^K"=/1-,D:<"`UNQ_MC!#LHZ)&:L+2;Y\2)4J==ND47?P>S
+MPG&#[W5Z8[/H_LUB/K*,_$[$YAR46UM;!WLM;W1<2,?KK:;./$+7K,WLQMT]
+M;W1F!TB'-65XW6:I*GWV$3E,8:T4S.7-Z:"QQRTD\S\@K/H/ROYG4.E>@^H,
+M>JU$^]!'\.9<Q7>PXP^9KZ7U>_8JWE<'_X(NL%_%DY)X:+SCPM29W98.D%"R
+M3?&U0T*8J;`T1XTT1Y/2+.-U\9D:78M,32Y%CI?RI04L^UHEV''^\%R9=O`R
+M*H+.&'B?Z^C)A`_%]X)\#/-:WJ*L>)S^F.)_Q')$]C^"SNLRC7UHM;(Y9;S/
+MB[>6:Q)NM9RFT<1O6R%=N,SQ\..F#N_J93I\\T2>VP*_E?";#;\<^!7`3YO`
+M<Z?@UPZ_9^#W!/Q:X+<=?G?!;QG\%L#/#3\[_&(NF$_`[PS\WH3?J_![!GY/
+MPL\)\&(3$)EN-LZ=0A'4>SG-+V"0J,G45.`C]!6OHXG[##Q`YN_I=</S(,JW
+MWASR7Y'(CX*F]Q_0CC01AEX(>H];3)BVR+]`G"TI_;\:Z8TP%X9]/Q4&A96D
+MAJ%[G-X'4O.2@KP^-8Q4V>6I8:3*WI`:1LKVE:EAI)Z.3@W#K>W>S[F4,&JW
+M/Z:&H0E4[XG4,%2^>@^EAHV"1V1;XIN.^-^=^!Z-WZL2WVCJ&[DE\>W`[[F)
+M;US+BUR1^,9VBHQ)?(_CS*W:TZ`&G"$%IKM4^V(**3#"9>B10G`IWC-H0A(V
+M'1RBN2M3$:X-CY#[T!2#3A!$FN(_(W<KZ]],/K]N3XB+\2ZV!`]Z$TSVM?Q<
+MT]MB`4GJ'&4?+AJHJW3#:6B65:J,_2TR,1$.4R+]5^U76IM],2OB,H!W;4XQ
+M#GQ\J?_\[XU/7K]-TUZ=\N7KMYLHO:W&JGTWGC(YOB0%'J]M^0IXDU+2<]J2
+MD=/3'*8*=,`J68S1I0;1*MQH.B<=L885,=J6L623L+HI?\D<1PO>1=XTJ<4X
+MHK)DEJ,%96XONGX*AY>L8[ZT>S^DS_"26F'&$M$1PK5T^5C5]':+W%75\9<,
+M5!S@6^I91-]I-(][NTKZ./-\D6X1UE2!3IS)P;M5Y*ODX`"\.86QH!@-5(%Z
+M6'6UM6JPN^K*#@CFX\%IR<$V830%)P59A6\2&+L<-8%D,0@L)"T>8A/F00A]
+M1::'<1N!8$0FAZL&O;'E!8*S:E0VW7/J>+$#K]8)2T=X"28/O=T7413W)>:&
+M><GG?\;2YD3S8L[1XK"2ID^B6XP&R';)HJ5/PM4D[>]!UZB2O1JY6"C5'L7/
+M0;^&2U5IVA\FDCL89"_IJ+O&K6G0Q[A*R8>..UK0>8_\MMJ8@\[T#X^3_7C1
+MZ*@V;[=QV5[WH+>;CA1/3AQO]G<G>5Q+(W]KCA:\F1852G2\XCNE70]CKN'R
+M9X#N=3MU_FB_(U2$SE>\-E8K83+:9\)TAU:CT<]ED4P1HN;YM&X.WG'$/X[R
+MHK0<03XQT3#"!V"HPL:(1F9&57N>/.AXT:N!,CE0K8/`J;EYC78W"(;>5>A3
+MVO$BWE-T.FS,7\-44ZO4_@]0.RGJ<CR,ZP?R$1K?!O["QK>##IYK'>'WU"7"
+MS=]CEPA_!GY[?/TZ2,O(5+3K\?6W9YDV/K[^17A&&_UO-?OZ,Z%]>M>AW2&T
+MS;A6?Q]\-U^8)>0T7Y@CC&^^<+/@*M?ZQI(GT>VXZM8<[+L9O>O0=5E[*OMU
+M7*\P%VA[J,KQ.C]-=78['EYHC==9ZV=U+AC#<_WV_]YOQE?D38Y_#-Y;X;=E
+M3")\)3P7C,$V&IB&GJ>J`;U!;W\4FL'1<B=\0`0'0T_O:N;;.AYW*\7U<T82
+M/,.)-E;-OH'O]E[-TD(C+$<1XV+ARWM'L7`I.,`)ZX'2/)+W#(_4MH#NX@L0
+MM5WG0NVJ.T%N*MZP`.2F^%`1"W:KPL(H71<VH(O]H)3VE:[1>I&;.HS&AWE$
+MO&OH6&.P;Y9X+WE:NN-2I;XP?DBIDRY5:@^46K-NC=9@%-EC%'DIR'<,A7SH
+M;R-"IIJ@?3Y1#-1I`A6`#KI_Q<7;3;13U3;CU63BAI1J7@J!]\8-06#)R`BD
+M-"BZZJ#"J=DNV5G!H;![8E_1;+>:@"/HJ*CW3(SX#862JWGQ;$>H"0)0&O6B
+M.36N1W+EVF<<<ZIQ-+Z6QRY=P[.D3D5T*<$<*;I)J&^:+D5O%O*:QDG164*)
+M%)TC%/4^8[1==)UP@W%`6XK68JP(L6@-'NZTS@D=%[*JY!56\M>`6_+Z:!@I
+M#LZ"Z%8K1-JKKGRK2JZS1N[%^"LOTOM:O,,>8Z]"KSR\U.,\W^$6K';^?`</
+M#UMKD85`Z;A_5F3)K9(?M$H79XF9S2LLULC$L'1Q#KU;(MGP?K/(PWN:6L2;
+M%P3%[R_RV>2W8""6+JP3IBH9L@7]?73`_-K1@N>?'8<G2B"FTJ4+<\0SJ=99
+M!D/@^(>)YH@NQXO%UBQO;+#[2N_`E=YH9"Z=5Y\ECF<1`Q@1PX@)&+Z.A2O^
+M@<&35W9G>:-0<N0%LHT=UVF9TUEHX:J48*Q*WFD%A(BO(7R6$3X0#X_"0.K'
+MY2[+.B,N:L3UWJ+3G0`C7:"TI7;;IIJMV]WWU0H;JN=FI]Y_D04#L$.5N//,
+M`'&V_1+ZDBV>Y84L/FGI#E5N4]N"_ZQX:$0;,Y8IN^D)_ZC*^KA-UQ!X&U/@
+M31P)WF'G5\!+Z']8GR0-T*JM&#NT1BGUMR7KBQ8M=UCJU/0OVG"EQ56:K&-J
+MSM0\*?<_V5+OBP)]YJ4AR;EA\_TR&[LT:K63[L!@)[!O4_U/E2EB6+]1>WN,
+MN9HV%YH(-)]39:#3E&FU3G*-*7L?4UTAA%6FO9J-()YDIV"RJ>5Z+Z,-T">(
+MHG4QK/4X^/@U&(Z6-U`,XYF*T:4@%?03K/1W%?$1QX%`)G!S\P<QZ8BM3*O(
+M3BQ$_E29*$]J"V2TEF<P"YUROBV0V5J>Z3APLJA,+;>5H6H-F::-@JIYGR"-
+MZC&/[XFZ58EJ14>;IUX?N5U'/\4U]GC54"])K9HN/JD5CS9J1T=E\=8+Q?>$
+M(CXI[_IVK!?O[Z'Z]8]A.YK!)SAA(AU@0._F-;PN/H%`\ATX77H2KY[,5[Q/
+M)!86DOOQM0QF9P.B$E1(6ZEBQ;_:_NP1#$Y2_?]FT&1,;\@):+\?@VYQ3XS!
+MV[]S4NZ%2MB_9+"N?PSHN%0[,&8D>Y;IXM"UNBLS:(-#CDH]MW;T\.H+.:\6
+MPD!VBYC1C&M7E=(KK^*I<:BT17MH#.[,XC<Y,SS*EVN;QIAN%V:PM3Q@LP7A
+M<+DJ=7^.8L&A/M_NQ66JXE&T6(QSF5MJ\(J"8KY4>P!0[2RV<_!Q*1])>]*'
+MXM?M3<6O>[F)W\G1B!]^Q_%[<?17XG=J.>+WT^P1\#MA&P&_E/XR_:=MWK2M
+M8DN2W[/D-?C#/!&`=&%JXRA%ZH%`94$XDJ$^[_[B"W2XEW('Q!LKA"O0M0.(
+MG]]"UX`4D^9]P03L+S-H)V7(Y2/'EI7BI0W_AHDMJC3?2/SW&3PW?!%^S@:N
+MOIJ;=]_F;?/@.<+YB7&$J[UY<9V0WKRX4;P,/QZT<.+8&KOV+QD\F]-@>]I`
+M!\=Y4IC$;*W=]'8P0_NYC;@;?:0#?T_KQ3D&W2\;U181C<:T/'H.:&YX1@[0
+M'<-0I.C&?1]A0HT%TZ!PQR=/U08)&(U<03X!)]306;>E6>S,V]ET(SZFO4>O
+M/,W$H(>_H*L*?L4>[^!#RP3<:IJT:*993=%9AD">M;'+16(1\RJ'_V6$1#4I
+MG5P4RG6\_*!-D<XNQW,#\CYZ]B<V#X?M'79:B73+M9<S>--"1'D>L['E<%<X
+M[-G-"UEXX^"-H?/B.?@Q.1MY`-JK)E/;G&DVN(K7'?:'L6;]>H--FY?))*@=
+MFED<9>YL\<+OL%6S,PVI%>7$T:"M$,IXA#*L9.#10VM`^V?>N#(`NRF-+D4?
+MMODU1+X,6FC"_>L,%"__G#62>!F^7W;$8NR?GL&%PL3>X61ZT%6C;,WJ3*DJ
+M]L"<G;;LLK+8EIWM("[]19QXSLH6HX/@G_V$=NJZD_30>&%^2]RB3]N=8310
+M2-\U@6Y<S^70O4:Y]D(:<7JZL1:<?+?XGKYP7LI>5!I`5!]_ZFV\\0&`?B?3
+M'#VOD@Z=@E"N:;0X23K4#:]3&R^+V,VK<Z9PQII<K\@;^U$<TTLL^GY,#0VY
+M,@M/SS_V-EVF@RK*6XJ*7XX7+6KX<W1,>\'2<-_-HZ"-A#MO1BLV8:TRUO`%
+M6;7G0J9%6)K\;;,("Y*_1UF$:<G?;X)^SPI?HQT#XNZ]D^E]RLX<^=`C$*P\
+MD"OO;R4,//(A`5[VZ%3Z[#TZ%3]M"'A7*GA'".=+R@,V>?_V$:#,,*"XAT!Q
+MID(1:Y5"WO'B6(R#U#=C&#PG#\F5I8:GHIO>J\-J&-<]]GS`]4,5#F')ZF.3
+M,`C/)(;UJ?&X_2QN8B)Y;R$B7,CO(3R-\NB=RKQR2)EC3?"+J.BIT'8&S`PJ
+M;TPXGB!1;._[R/8[;3)%)94T.ZFDKVJ3;Z2TR<RO:!.'T28PQB35/^UQ1""R
+M)K6^-R1A<?D0>*.-ZJQ=Y(:V5"B_Y0@NXIGUSD-7R6F/(_6D/8ZD([^3K\O[
+M$:)\:`?2U'*GK(;Q\RV(."=_GO8X1HY7*?(0TKOE7?G0$_BU'[_26.;]3\+?
+M_.-H&W)H%[+(K9QP/9:+'\I$G*Q.ZRS&T3F=J^HJS@"F*\9E/JY0ZK3+E`K]
+M,;XM'<+"8>[S%O;"(80J=:6SOL!Y5PBC!Q0J3KE1WM_RMDX7K+10<DQUOD3O
+M$7>@,:4)5:B!?B8\)B$>=Y4ICS]!#8"9RV2U&1[:.QS;*Z<O&"ZGL293`FER
+MN:TMH+>6\Z#N6D#=S6B;V%J>OCQT?/<X*81@[8I99?%[4@ASV:70D_0P:A-:
+MBK*%>%FG5C,*_11';WJ5CZD_V?CV,!\V*?;/L;3X)4F<(8>U+MZP",#3=!/,
+M<843C'$)?47*W6E>6RFE_@X_?#X2A]_U15KJ_,6J/?!EZ;]'Z7.&3'EN2<GR
+M_Z/N7^"C**^'<7SV0K*$A5T@0I0HJQ#E)B2(P*8H26030`(AD(UWN20!8B`Q
+MF>%6$I;O9)%A&%T;:&FUEE9MK;5*C2#*Q00Q04LU4*K4HD9+Z\2--FJ$0%?V
+M?\YY9G9G<['V?;_OY_/_H=F9>2[G.<]YSG,[SWG.B9'_4WIM\S6\.^2>\*=1
+M^NC>ZYRE9Y:4*M<J\LX8\92XHK)<J*B:X!*JT#5BR:K**MZ54L15%?,L1IOS
+M9ADFC;<O6=B<=P@%N.B*#IVRT1P4L&@>"*J'AH5#L`KML(9@5?(@!=LAS2'U
+M7HL^Q^!:=2CLR\4K^V&B&9:(]ZJ],7.6S1;K_Q.+]SCEZD246BA=%W!K8S_?
+M:!*N9)<_FW,0+^Y\HUF(;\ZA7H.&O_YQ65I@EW(2FW.PT6':"UU`@7L(,[]A
+MY>]S?U5UGTS@'/M-F0PP;._FBEWW"%<;@P3[@7L`P!SV[3N142*9Q:/FX!'H
+MOSWS)[!8]U>5GY2@ICKZ^MCD*%3\6'R>BEX"@@,CGW@DISS=?B'J+R5VK9U_
+MT4*V*`1;B7CK#X51)6*-N1K]A.!FX8I"KWH]PKNY$&=S]!(0'!<H_:%7;1W`
+MZ49N^+^3$A<9QKF"TSU8O2]WUY'>TNZ,I?M[718R;TQTDW9U(-T%N_MM_II`
+MH`067A2"E6W"^K($[K>%<RQ"VM5Y`=5-D"I$_@UFZ6()#GMWHKQ+G'FW<)UT
+M&<]^*-`A-IOAY5[A2_P4)D@7@F-8NA\*"6&"$AQ.W]6"0SQ,4/FD,!&=9>6$
+M9[5P(8X^T0^"3F:.SI,3)7/;8+)S%\5+>MM]F3DO<;P<)W;=S2=O3A"[)O!W
+MDHA4[/HA/TGLJN:GMN$UZ8#T91"`PY`Y%&H-+X0O*N/^FD"1-)!A2VZ*`CJF
+M5S%,F?ZB%H:`)O`5,A$*.D:);(K2M-%`TR\KSY7(.>9(I++`&AP<Z#-]"33O
+MWPUU?P9=_&#=E?GH2`80AQIO'42G$HG,*V):@_+T.9T'9R_(U>VJ&?V_G-=Z
+M(3#BS!IAS?F,@39^)?`EP(.=!X5O-L-F!MKHUDG\H.UQVY`SLI`\0GN3&;D8
+MS<V/5<31_;'[WPC#M:;4(XQ7%X0ML`IONVSA\&XA-C7JQJC<MQ@@H(N0X#1<
+MV^4E8]=.IW)*'$?22R1W%E0>#YK^%2"^+$%A)A($Z?`OV6/7E\3$XTFQ//[U
+M-S3F*ON05&BX1T5_QE(S*@SU9UT:C2,N,%%;JO`YD]DAVWP%^QSGJ"7W&B--
+M3"9,@7<[_`X3,I1#4O!;O'BM8-&XE$\JO5<IA*;"/I^O3K-QFNJ7JZ0Y[FYR
+M]D,PKG7X_XK,TGR9G>RC##GN;E\T'D:$YKAK,2!2CGP8@98X]N]2B2V&$9/.
+MO%$8XWAY@5G'Y5[^2LAY(^:,32HV6Z,H-YLAI5`/3;MEKAVK"'GN]3%_`O8M
+M<_2@F3YFXR>2C'&=NXFWE6RIN3S.QP^#5.-\07L`"E-888,(Z>'2+JTD_RF'
+M_PG8()2@FBTVA\:Y3W`Z<5:R@1:*<2<(UYW/LCL%AYQE3T$;+K>0E\2!FBK5
+MK3@(NG&,S[2[A(F*.,$.W%9JE4WCJ5_FR0MMBI7.&RR93@96L6[+4V\&?L1^
+M<-8P%D?MGWUM(;M:!?;PY'"J^N8%2^2^UI9V*[1A).4O6<H27&3@/BU/JTR>
+M2MH25K(?_7,L-;+'+C/J_W_-QOM<9[/G<1HWA3V2L+M$1-.D6SFD>3S'EB&[
+ML;HY_3C-FA3*+]Y#3I&%Q//9=AN?`QWR\B0^PZ!2F,'?`+][A`E>+?L2/;MP
+MI3&9,`"*F01EY>"X"85E6ZES?&S2[*M(U3NEMQ`I?@+T]_1)?`K\<M7Q@#29
+MBI#-LK"S1(J#00G:6H)WB!;^(E8_S@DWR)#Y)&2>Y/"/AMX&XUB)%(\C&/80
+M]R3^B[:!3%Z9F+^0)C84K"O%VXQ^`+O9IQO_%<Y5]A*\Z&1<`X:9.:$_X(4(
+M/W.JC>PT6\Y-$C<D<OPTS9`<)D)5'=W]JA<2R)F)X1;TE@GOP$Q66#.B,@AU
+M1Z`U"H<#:6$6F<'WD^<D!^-D&4]N8>!`7XS[L$"9O9_4]1<K?!MM$Q&F$^HZ
+M$>9AP0X=`^\=`K'ZHU`#/LWPE87]$XKOB"P@U?DFO;4&Z)4-_C3`UIABTV6J
+MQ;-X$M>,DWS84;N!Q,`,0:>&3V92N(5\Q[!O]0.8YJ4N@T6YV''_9`=15LZT
+M64R*U8^K*ZC*!B=,V7GA!YWJVS`OH'NRA$"^>M?7^&Y%.^_"0"8NT.R)`@3,
+M(XP0-]BXFBL`FC)E*YY1-868:OWL#9TH=7[0B8+%HV98=Q!W#:(Q'><V),4W
+M4LMXC^UD5Y[:`>VM"]R'$8\,LW`1/*496\,F_:/9BMV&`W)$3-3%R&:[V?_X
+MET6S^X)FA[;2*"</H_'JZ"TS?2BSV#SHEG'X,K3M;:K<+7?C5RZY]X-,*`8+
+MH)V=0O6)L.;%G1_`KB^0/E:)'(^<COX,@(V>)1C1L&W!S^B<FP[;2F1'B93;
+M15%O\B=+MMQZK4^O!D"=BLY!TB#T1I]P=8F[H*MR<(F<VU7BGF^NC->D47B\
+M-BB`D8(>Q"H$6^)[?<)1MR?D\#NQJ<JI+Q(>[A:''Q6`VR[@J(S69G;J-O3;
+M>U^G/ON%A63"&X$Q9LAS;;IIF&;+1J<\.3@"Y\:9>-HP#16O+W80H\@%(9AS
+MYHN7P\(GX4JG^@D$ZXO2B:R?PZZ3BY8RBY6"?0;'$ZBM^.S@$,PH?NS%L"A2
+MZ"4O7XVGKF*#@3!#&*2%J@G`JT&[]B5GN\(MRM-=Q/:1<86+'5?^_#D-QX91
+MXGDV)\D%3IB%,H0$6(+_&9@Q.""`!\A..6LT0NTTF%OM#>X/>\#U]H1[^S=&
+MN&-Z@8NTR+63+I+9?1RUH?2N\D5:`_/Y0FW%5'S1AZ=I&RZ-LFH;!#HSM$3W
+ME;%R\_?;`<$ZY]!06)83X5<J0$\\$0L=I1R:1Z1#2:'3JX[M9&NY)/^I31O$
+M@\E702)^4+@>7U3[OZBQ40;M_A>FD^HPG`V'MR.LPOQ2LU<]]W44R$A@C5=^
+M]^RSSTHM%SYN_*R?5.>Z2K_A<Q7V+P;Z#\`/S2(5Q_6TY6;DSP2HCX:8,$@=
+M2&JF`IZA+@O(XA@(=HM8PMK/E3HU%^V4932V6J7WI"8+E11Z!74EOWXZ3&G%
+M@YB&X]\0#XXFB",8/LC:U\2@)*.IY^^ZBUH9C.(U4!4ND_IK+5ZO2COEIDJO
+M79R&<Z%-ZK(06+'!FH<%>8BL[/(";Q>;4[-8^G5_UO(E*]9\/&$B9%E>J4FO
+M2"^8%WW>#7,-7CQ0"748%)$HT_<]W5]_1F.G7IW^ZJ^_I1WQ9MUQEA!RUQ-J
+ML](:T`XWIG-O,H_F!XL-J>A[2T^P[N_1M$F*=6VD&J:6GE6X0F.&I]IC\(_`
+M^@[\#?XOVBQX-JGS[I4P@^EPY\7`E>JQU&;B`UJ?]7IV^5A;I%EY'8XU!DX4
+M`BTDR4AOV0.K.?J9=WONK#GY7$K5I)2J^U>7%TTL[XUWID(ABOB;8;B;^NB+
+MZ(0X4C7A]-BD_@A:U-TD.-0OOZ1M5)QT<,I5Z`M-/#B!4,O&<Z6Z"8P!PE->
+M5<3G$=I*'*V4>I4.$N\%R*56K_K&E\AOR02F`Q<0.3A\SWB5$UXU6.C&^QY8
+M@V[TD%4+4V$0EPQ'=/=^;M$4<:_.4[_^S$)''".8\G<OOE86Y^8A/>BV#;^Z
+M8A+'?I$T0*24*N[&![D;!>[&<N[&8@X"R\J7%G&3JO!84/_J98P[_ZF%V6OX
+M%2IF>;I2&Z0+$=O2QR^T*+,M4BX>5HD-\:/1T,FG=`(U7%]@XM:9K7+&XNY/
+M?:P#!S#_J6IM[3.4[0G]IVIFLWM<^>ILX('SGM!FX1IVLH)V'+MLDEFO](4S
+M)%[OJ0O=UL0Q_7>F-BJ^3&2\ELVCI#TS0Q&/4.`4*$/RA)BRPO6*>)Q"KS&&
+M.O5UKOHI\!#UC;<QE5<1_XQ/V=.9D5>H+FNWT#E/ER*>P6!%_!L^"A7Q0^WY
+M,0L^QQ[M5!(?U$J:@=(P[2X;V7'/4]<CRQHLM-')[?*8(]P8OEGT3^Q'2?.Q
+MGP^@N5<2\4MFO[@(BA?IW=K#?L9PRIL\7Y^+X$7UJ40PZ(;S6><3#[HHP8!P
+M/;ZH]ZO825WS]4Z:--_02;OIO_S#PJDCHBAABDIN4C&_'"I27%96I?/<2J/]
+MXW_T1"KX:1](#=*0>DM/H.,%W>@JHO@R?*@);9:([@?LGL49T*';;F'W(/9`
+M8S[N>"UC4)[Z)#7,;F:(%C>G+>HS`%DBL.P0?"AJ@?Q-Q7&%@.`9+^R="UH.
+MX&1\X9.3GTD%N_/5MD^U>7P^VZ"?$L9AQE]!1@WEX9\:Z:A!8VM=Z3V9TD".
+ME29<WJE9JC8:\.N"\>C;G!^0[;MU%/\!>GCHP+<_8^#;TC18+@9Z\5V._I\^
+MLS#;)(-0-A9KER0.EA6?F(1!"*D_0K)F!U\)H%_<MG7LS)`)DK$.'^*@0"VA
+M%._HS9ZGH3'W_9TF//56.A,EGQ'DX\H1GEJH/DV-ABWR3_5!J]$G67E)"5>^
+MAJLJ7HY.Z-:M6E-4OJX'[#O_CHSR%''^8/6LA>,T'84/4.,U7(\QI45*_8SY
+M2$'N4YV"'Z!/^J6J7O:M2`M,&YYMW7`%RZ:>8KU`.AIT!O1XV>G8/R3,B9<2
+M^%_A6<F;P<>8CE\OM'Y+_0Y:HW]YH.\;S$<]:B\!V1VU<U%73]PSGTVAA/0(
+MU%MNDNK',/9#@Z7#F\4)D;XW1GL+I@:\ZA<FEGA"-/&@:&*\H^U5WS)IWJZ;
+MQ=0(E"G:&T,'4I1:%-&?C*.=.E9G/"';<<1KZ5[5P?GJ1Y]&JFKT*V:HJUU\
+M$@N[3-<><(:3&.P_?6J$;>X%MOB?8?MDA&UJ>PAAQRGB#@;[P1C8<;W`ON'[
+MPC:3OB;"KF.PKXC`'NNKB;M%&.55KT>Z$B$!I%==SFED1I+Z?P^3I^\@-NPH
+M-#H[2AB,]V=).=3%7Q`O]>>_4@YB@TOUT^=3,P@)S>)TK5606^O_86']QH(W
+MV+L,\EI#?YC32J<1:>>E=X(U`?'2=4*\>-Z$/N[1UXG=Y[Y'B/=M,%TGF#)A
+MDQ.?`Z%\@7AIE&!G7#>JR<0%\Q"=!$2L'S"Z</.V.HR"F$S'D<$8-P#CXC`N
+M):"'7<"PK[!C?$[W/3`<)9;KZ:)W.,;3=\SYWT<P>]Z""YM3YTBL'9=A7--H
+M4P7/;ZB*S7?_1]&>/TH191>-]`H^5-??<;S&.'1/D$;.[K1.?2-$'3!:&#'"
+M'&"`&<^V42XMW^>?6%`W15^!-!-TPY07\X_FLV1#L[SX(0)NS^=HP?\&#5/\
+M1O'@F$4X@4U7ZAL@2A+:Y>IV1>S*9UL0//3Z^FE%G+`(K[B,B=,]Z_27/>W,
+M>Y!2UP%IPR+^-GFZ)I=:%5B%>"["$NKSCX$$0D>SIQ/59_!VN;K&JA]KX5I_
+M/:YGM')56<07W_3QP)O3;Q3NU):V6+(DG/.J*Y"MZC`-K/[>,Z[^9N=Y\U4?
+M%*8<1+QECQI%'7T./TBBTR3<KLU',9M'58K/$!M4+*VJ6E<T<=D&<DG:TP9_
+MS0=1F@U1'S538_:/.!MI\G2FI3;`O!+!YIT+[RDY8;'+5M/O``K@\F#3K7B^
+MH0O7'[8B.=JEZ@YT5ZXNM["^Z80-S!C8(5$SC%#$XNM"=/U<(7KDJ>$$E@Y-
+M10_I1B1SVGEUA0GWTQ`9QW+H5OE3!"Y2/6%5480GC#I23YS5]H&LBD/5YTU4
+M1?2G0J=B6,>NFZ3JSDBSDI;44%:59D\':UFHSDYSM#INO3H38.&9.0JE^DY%
+M..M5#V(CB;-&L04LJ]](K7[)?=0/!]38^K48]NA1^<_?2)K?3(RHS4J+V)LD
+M=N9SQAX7L__[&RY_>F9JIDSX+YK1F&]Y'_DT6O)7RB*^Y,D9UG!+,[U3-!HI
+M6DQ;.I<LXHN>8G%DNWE'S'83AYX*:,6B9=J*5?M(J4IWI:S6>-;@_^5]6.O>
+M]A$-8P.4>EM**,SVU/6)\*I;)_"J>S_!\0G1HIOWCEJT1=;D"4]1<L.PE])T
+MV^4Z3%%*38PMGR]GD>D!Z,'\P&9QM%;IX,T!&!`<1SBQX;)$H6K#A[21A;U.
+M:B%2!7\YX8H\]2>M%FT0L;'AK0#&18Q57XG'MII02%1"^_S-],&H2N01_J26
+MH2B]"<92\1F<Y0[BKTEP`#M=FX*,9E$O?T+'0ZA5V)OMEV?_:C%4BYQ%&&HE
+MH$E_M&<M/@>`J])D>O;#L4BBU[QP_5[:GWR$]-L[7S_W@O&L[3A1#,,D&JBV
+MQV\SYZ`$[[Q4=RSF&[H3C7M*MBVO$)U1-T)/A"4SA&?;83_WHOXI-J%X^DGV
+MB:J@=:>IR48;89_I5M;9;M^M?90]&DJ:'2UI#)3D/JO-3?K>S\CSY6<LD99(
+M0E9:>8<95U*EG+H41P3BX>C^2VQ/,M!],F1..T].[<<[_,5X7%5MB^H3BQ>_
+M%8;J8\)-,":T_8;9RH(,ZTT9#C^Z=V/=C(3E!Y<@&HY:\JHBXH><9Q?QTB:*
+MY.0$\2!U(_YV*;>K5T?/(;D.T45+'?.P&R(OY,OY=JE`10<R*F,'.X,M9MBM
+M05D;G+7B,NSA5!WAN_KA(!9-*W6TJ>R^FSJS%0>*>R*]>TE$!MKV!CI#/'@/
+MDXU!1<4&<YXZ#=*'*3T9ZV@GLRPTZE[1JJ_WTO7$GQ$7+KDJXG'N'*SQC*7I
+MPQ*45D@(R;D=.FEN^[\BC:/V?I)O:/-5ATZ*!5;MZ,M1B]=[V''*WTS:?<@L
+MO?`<M$7W7C=]\N_;*C@_;6,R&[U-/+:,/!V%$Q:\S,CB(_R#Y_PZV?[\H:4'
+M=5_^4-^8S9,]'>C_FP9B1!\E3J?D:K5/0MEBL742MH!J=O!Q_WF'']V*ZD5/
+M_Y!MR/4V.\586-QH!]9]D<VY$0;KC@7@T"?%^L(ARI3:VWH[)_P\.)?1)N-_
+MH:(XV)ZEP2*]%]E=^FEV3N>Q8\>OE4PXO]_HJ/6A87<<5_.4^I=HE_G!>[BJ
+M""EU^\;C,497OB*$O*H#UV!LBLK%W4V\;\$84UCH\JK?G+7H#N=N@ICS.6/,
+M0KR48X4$9DIP.II@"$M@%9QYZFHL)\<&R:QTV@$IGXVF1+PAI0U3WD8I[9#2
+M1L([)\>OI_0;H^D/L/0N+#H14KHHP9W1!#]A"9P(<.Y9!.B$9$XRZX\U17]H
+M>FI^]?F<L69A*.P?*.7H+0O&H/02$VMDZ61DZ?J;GB4=@&=@Z4D`-B.,ISQ_
+MBT1>[=L\AML$D<D0Z:/((WHDK<''`A]`F28A0<IQ86FX[TX(KW.I_WR/%A&6
+M)BYV1EB]M(HOKIS8V]HY:@]SUBD+IW<M9!8RCB7^[$:VME6'O&MA2W+!@=<&
+MZDYKLP[*'LDL9DH5IY4#;W0N-R7V7.[O)Y&MG$J=<7D!V^GI9RSZ6/@"#`.P
+M``UCH;H;NC?_0KU</$@K"WXPQ)LG4AN\P&(4\BJ'NB#XP-6]/7:O@8Y?M`4+
+M_Q>M%@[_;1;$@D9;A]\#'Z7IVJG]+Z"JDO^,KM'@J!V(Y]\4T(0OF$CRG_XW
+MJN#AR3[6+TQO37Z\(WXSS-?^+RE1"V%V&.,*U4>`9@JED/SG*+<*O[0>WX??
+M7M6$RGW^$U0R+6T80-BBA?>U$(S;N\'PJG\Z'Y/'4>O%B9I6,[[T\?Q@7_J-
+M#O^]*.:^G8VOQC$<YG!V-]RW$4?<GV--B%+A?5B_4HXM[VD<W$L<@&CE&T*O
+M^JM%M]GDJ#T/<QF=1[/LX<GJO_^L\W62F`T#FA=G?*%5_1LT>ELSV414WZ%%
+MRAUL=?`B#OI$7,F/%C9A=#N,7]M:T)$0*S@CC\%7?ZY#=_A_B)<@=""KNP%A
+M(+H/Q'ZT"]A]]J+T;`+;A42%.<Q(W$0HIFT0$1)))JSMDUQ;_J*3J\(0&GS/
+M0*[F;X%<21%:O7.J=UJ]`'G:'B-[D>J3\!X<V9T.NTY%Z%"%5@TBTT/OE.R;
+M#+8>9'#J9,")2>L#>D=YN`77[2CDBL;43R!R8#P.&[^X",4W:>GO@_12A_)T
+M0^2DO<>:\\B?<+^)"P3)T]YCJ!AX.C)4'*0E)1L3^K-Q"G)H'5I8I-0?0)(?
+M/$!;NT%A^E0_>$=;1>C#VR%<?7C#0KLV/DPXR8[ZDOQAX9[HVC68A>N6.H0A
+M$Z1N$/+#]?@T`/I;"P/D\JHK6:'^,#\X9G7W2X[&'"&D3CQEB6@45S3%<7)N
+M2%]T94NY';VN^#I[++LZ>EEVQ3?%I0>O#@3@H;6,$,)FL75IVC/"8$3@C;<)
+MQ;8KF6Y82'WI[<BFXJR^=U\WGJ,C2)[?P*'6&+7==*/]RQ/8=JTWD4SM[_A0
+M3[R#-9.$%N83=+`LHHQ%V8:>N*7<%JEII1DF2_7W2"W/":7Z=*'CM>Q!D._/
+M*)%L%3^V2;G'$=$W^42QN/5"8>D0EN#/Q`GVL-""U?G3:3SE;%'][Z!(:0KM
+M1^WA^=8-#J^:>5(7R/?'.VV._<YPG'@I#'WL4@(/^Y>7(+6[N>KDMI9M\3G!
+MMP)H6PXO1[9C!>3<%L=KF5#>#__$9J'JXQP_W)?;:E,\I_-T9+)U9$ZH!UEC
+MN^NQGGR<5_WL;20*HJ04'XHY\^@V_QY[RX*&HMF=M\XD+F(VLU3;]I(M&S,)
+MY:XX17)%WH8./&VZSZP8Z]0<DSVLT>X><)5<RG*MS"*C_>^W+,QIFJ.VQD2"
+MN@O1N>&RHW85ZOH<Y(D7AX?KUU^%R[[KWXXLE?`D3#U"FH$(DFD&XLF8(@9N
+M1@[XY*26MCIR\]#,V\F-4+)8?9I#4YN44SQ4R#I;,_TJXA,W$R,Q,.*?V")\
+MTU7ZJ=A0ED^<#N,]FKSUG^)_H'A^`3GV8(Y\]?@I/#'##.IJ:CVGK_H7X_LJ
+M+P*-'RD>;*!A99AX<!-5?(4&YAH`$[S+J[YOU:6J\>I1'!ZN[WZ\G:<^^T?<
+MYQ&]\M2!&O=H\`9H\-X^@>=A2%Q)K+@*.230F_[$L\>99A;SU28V1"0L%;0/
+MQ34AZ6\3##G#BJY\V:M-,NFO=BE.>]4*T[IWERYS,3"%&PL\6'85N82[5KHL
+MS\1KI'N`5<)K[>IN>'K5'[W%-E]H9U4LNTI':3U5,(EQBKH:>9J(0+''K#*Q
+M$D#-AG4(P,6K%D".M58UZRUVW%Y#7N*AN#0]P$X!=M7%`KSJ\+>T`54XU$S4
+MXR+M2=P7/>/H9O^[&7G=#J0,>//57[98(O9,QW2[)YT;4A8GA'WI$_!B,R><
+M9"M=TB_6M3'&<2E5N-*%WW'<.'P;!R^Q=/RRR1(U."Y[$L-X[;8&Y4XUR''.
+MN6BC^$$R+C3+'4+C0L]!CAWPYX._HB:<+5$G1!&_F,YT`CKPN5#=!Q0(3@_0
+MW?3S$!0<1OX+#6D5\=\LZ79,.E`1.3=]_O"MR,#.J*0/$"ASKBJNY`S?*\NK
+M>$[3L4/3](::#0?<T'.5H[:>1@V#1)V&C9^3Z*=!ZV$X1/\/+G@CO*OU-FA>
+M[+ZH[MOL#UW6;K.(!PI1)N`Z$9GL43D7]@.:[1%*B:X$9`_.<1;8J,)N8,OE
+MR")M).G*=UZF74'79=H5Q/;/V7E>VAL.4,3];EW>*C8AC6"I@!/XW#?U_<XC
+MX7T("BH1WH?`U">_96L:^M@.3(6C)PICV2&#XE=9R>WLT8$/=5Q(UU?=3,8%
+MKA$/8P2J,.WK(/!V]>WC^C[O(&$':=KU-.V4QJD^&TGS$[(Q<9UX6*4T5X;W
+MJ90F4=UZ/+(<1,53]9J0)M6A>]VJ`SY)&_^RM@P;RTW@7/VY":[^D7G)>*8R
+M[ABP<3T-!^?YJP/HH@P:]%J]$#Z.;J2K.+]C1$`_*<83`.K@`YE(:0G;?S1G
+MDV-".=LN>4+87-FZW"?D0VZ81O*&,0[_ISCY.=4EV`\\':6P&;^B21\PY>H.
+M*5ZBT23L"2GBJS]`IH<94GWT!";OBAJ7@C4:BT2_Q2>BG?Z!H#F0Y4M''[KI
+M_?EO%/$()LN7"MK5;YHT_;]V'.-ATS>V)3BXQR&6OZ'F9J7"Y,4<!]_`KMZ)
+M:,UZQ.K-@ZSYZA,$QHD^92FJ&:)HL^CI%*L[S8Z'E^(]R>N(]QHC%6C!F>-H
+MOLI?UM=HUY`2TG4P`*$B'Y+)Q7_CFSZ![_!-[\\',=;A/WR96E4[2XK,^RE5
+M+GT_/CUV/[[H*&XE0Y']@7B01E!A(IN=2-(3WH<QZK=O6'0)81QMFRFEHQ;/
+M$V%93(OT`Y1Y8+ZZ\KC6;X7?*PHJU2[4=N@QTF/IK0NG)-J<VQ19N2447JAU
+MO)-OX.Z[A;9<T/WX"9IO]FN1"XW#AG^KV3CLM\V@>ZY=;..AB#^^!3LSP]\/
+M,#4P[[].PBF%=B2^P_@['F=5?370]@UN2EG$*$?MIY?U5"X^@;WT%^Q&W\O2
+M/MR-:[HU@RC"MCV.3)-_+ET8?YABK7AN'\WCNS7!4;L#0:/BA`@OP.?K7\>*
+MXV:L.8/=JLPQY:G+7M?)(2L8)V7:"J%:"%6]%4G"MF\9MB9K/&><QHC`[RU(
+M@XU;8L"W:5HX03`MP.<]PL`%S20\8$,">\<"_>&::L4ZG,D^,O*D7;2Y;#V*
+M&+13@UAE"O.?JKDA'[!`^866ZL77D<08H*X[2FS/DA9:=K53*JQ"OE?=#NGD
+M76>H/B0RL29PDJ(2=+MXF%#A[^[!@EHI/+6>7<.B@1\AL]C8Z?N=!706%:F7
+M!M;AQ[:5J2HZ,>VRC`,;HZ)DDV@I@T-]A4V=^7J4$VDP?1^MGU%*5%;0%G&#
+M7V=WFP[]N]L-ZMBUP#^.Z)<?Q(/'D64W)^$Q3"FGCCF.*\7CA9H0?M,8\>`)
+M3%!SO3=<CV_A^F/8,;C8=-7Z>;Q,8<'%XL%CM&P=I*7O:&`7`2@ZH[$5*G>"
+M)E9'(P(Z5J@O8E_6RLE3?]X<B\K/(9>;<JW]I4PYI'@&KQ<3-S'V/PYC9YW"
+M5M1"2JE=$5NHA-MPNF2X7T^X3S&L^#&)[V`+C2V[CCKVG[KP_K51EV0]]"-^
+M=)@4_9L]YYC7`I4]VO$R&&V:8`Q6"CKR8=-4<"Y?;3U&16O^ZJ<R7^)BV+S.
+M+%V2WDMK<*.K',$6D!?[.Z+^7-\70A]<(S;9,MQ=F_Z!"C1G8O3-C?.D&?'Q
+MV'7K+;F)<G]T*%K@E,SZA9&+IIH$*<L*GXBKZJ$%8@B2*/;ML-,/J.-QLFN&
+M!;*0=MXMA&JND@MM,+_`2@?FD':WC?]`;+!F0\SF#KF@$_W\N*`\JM%M2,\<
+MV"9T2":QT0K@8+8(_CZ0=E[.L>/&YE=X=\86GK)7+6[0Y^ZWLS%RQEY..!?\
+M'U@;W(;S6$$(?8L/)B?.K9%FUI>%3'K<;8\2=PAE>.K]'.FJ-))2`C]*/,@M
+M09:T*?7M$!6<K7DR_8=9OVR%]];GX5DWQLLB_OJFCQ=N\JTWP9)&$5MOH^,[
+M#,^`15YM'$`9AOIH$^-U]OV=U*&MWS!5C,ZXH7&*#S)]PNN9O@26NQS6SW@F
+MJGHU30@[WI:Y23QH1:0W#>3'1!&Z6D.ED)62IU[J%U7R>$4\&**:]U/_:-#M
+M8.BP?I)2%*'?BE5%O=C_>96AA[H3FIR_%'7'N$+`;[_)@)];PX]/!5RN]FBJ
+M&AU>U=F`D@:7AZEJ,"P7]XNJ:M1'L4SI@24SZ*/I3;&5`]L_13`<_6JTA=<J
+MXNL>VF6\@0_U'X=QW,`XMC1%W^C+FD7"$Y?$`7+?78\)U#M?UWDO%0G[#VKI
+M$?";SE^A54VPL[PT/QUC[\CB&H1?'(YH8W5UTPW9_`IJ5:O]N*C^AV'_]PK)
+M.M11I`O/#Y?JD1[-(J>A&3G/Z/W>P:A7+(;$&BGP!@(AA9V_F4C`Z86G)_0\
+M6_OP`)ZRA"1/9T`;)UA^37=JS'*4KSQ\2#\VQKWBCY$[A1!J\R&=#;JGF%'3
+M/24<O$=B=4\QT*![^C#3/7V(^LK@'#K8Z527XFS0*,GM6NN]Z:@=C0<"[O$.
+M/U[EC94^XJ'_-6SG]QI2H=IF<O@+\=28-.D_0TD0]>5L<FQ\%>UC\(ZE5^TX
+M&-F5F.@<FCI4A%5_JX\)CMI/<.6+V:\@/^X.&%3=8N?]>%"#1P9A3Q?%CB3@
+M5^(%3BI2?3A:PB_08'2TDIL:(A)683@S<#G3I+4XLR`?"'23?:%;M2Y.B)/J
+M.["'1&&E&F`Y&*PT//=XD6R^0A:'5SWT*G:(SOO98K7WJH30+Q,NW6M?XF(*
+M>.<UIK/IJ'V,ZR&2$Q*H2'\FD="V!!G8IO$D<$G:>4GLNA_OD2K_DPP3G/LH
+M/Y_NB(9\[@F"$[K\9/2L-UD\:DT['[S>Y^9@6>M.X/OYW"YA,$2[8'\!&QY*
+M$1P*531+;],.:_1RA";L8U8-8LX7TWO>GSF_#R6QE^:$PE)UJ%`1[%ZUZTAT
+M[Y6%9OJ&A_%8]&-#\'@,+K12^)N&\*'Y:NDK-$!*.39RVD?WRQZ$N8W10*MT
+MH[*%*MW(WQX(^-(G"%`!_N8F,R>EP8P(%<:S4[1PD.!+QSJGLSI?HZ<@_S14
+MYW>SM!HW"B^3AT>]QAU1V9+Q;FO</I(M*>*8%72LN`*'L8%YZMT']<T0K\MP
+M>Y%%$`MC'O7/!W2QPZS2!)3$#WE5'R[Q6'=+=5<8*KCNAK#0!;%*?6LA#A@%
+M!RQD_N[;_1:.;CR676:;#AS+VONZCYO_$DX81H0'YZG/OAJ1NNRE88X&/,$+
+M1=V-G_A+:TQ\47?L[W:@<NYN/%#1^K96I_=>CAZJW,]&4!II/7BF@F!D`M8-
+M2'ZX'I_=8(DO1\Y5G/L-YRKZL`Q<@39_@4XXH*YU(%4^W4<)@S_"]0_03$6P
+MZH:7&<W>A%@<6W][0+M:DZC1F@@YZMO(*7">KAL3)6GLOZQY"VZ[?=&<NSQ<
+M#G<[ETOZ?H)F]'%96?GR!ZI6;2SF5B]=OVJUL#H:@E:$4HIRN-6KUO2,N#EM
+M,I=2E%)U(POEN%[T-;:_".TH<[G0UW*[%-&4BU/RN`.&@T:\0T5;31?I"B"5
+MO>J!5_1-_8Z_T[*`S:D%(=9!-II@E-D!(=N'^"[E\DLW#_==RN'';;;5GN++
+M@FNA'UVZG;\IN!J>#_#C-_?W75K!VX/W8?AJ""\(*/(`AA+J@7%'X"\CB/9I
+M%'F@%LYQ3@A'F^Z9%.[0PZV4WLE1?\5Y)N,(NYX*W#"8JO<`L.D!U+,XPLQW
+MVMQ=-4/QV.8&BIZ'XV\7!$M''2^\N^42;G4WIRIB!L5.?-5`,(+RJJ:R@?O&
+M:`!T,N#&.S%/::)2/P$8T(NJ?[\&SNO1B]&`D@G6Y'C5?K#1UJ/^;](#Q95K
+MBLMZ^-'XXUX+&8"V&FT>HE0[XJ*L/@-+UER477F`G?U88=D+RS?7@E"X=W\9
+MW,1>]BCW[:5QZD*3#R\S)!KOPK6%V#Q8.D;]_,7HA39'+9HK+QU32KWEIOVX
+M/W"B$XN%+NE!V"'9SV>.-O-6WYS15NPPEQQ$R%NH^SDQ1&4A[)R*U(<0T%0'
+MI\_5FTSL'#.P@";`D#I_$"HV=6BK@05D#25C,EKKUZQEDVA/4^E&'35Y<H_F
+M<-1B6AQ:0^KE@;@*+FG.GHS\W2%YK<K\#&E^(FYTLD:+K2941_]X`+HKSYX"
+MXU2)V-5/B(/T4TS,1K%=SNV2YJ/[CN`U`<UX'$WU\1AD0QS:I4J(;Q<]-FO8
+M`TQ@(ZLB>-&?(,!"J--4DTA&VW'D5D_927D+ZAA3]44#V<5F,Y,5WX8%S[;)
+M9B#`E/[<^:S15N$:YJSL4<RBOEY/^S4I"T:M:JMO[F@K'@E.,UZC1+.D.P?B
+MLT,]NY<)-H&ET;[$WLCM\=?W,A7<UC[N>%__/#,"(F=>7R)ECG:\W*%DF_+$
+MQ@PI-[00:HO@"@&7TDD(+:6>S=V),'??!)M4M,EA]VW(Y/B4K.YB5*4B#&,]
+M9$JJ9T5(#UZ/AR:93NQ)F4E29J*<.0%[5Z8]UC^D$;^MOV=Z\3,Y?K(\K42L
+MF<QM<@4"TE=RMHW."+*M4E.^>O8%JC'%5W_B54^P;W$S'4.MLZH/V-F2;3,=
+M0ZVSJ<^R%.%U3O47[/5\#C1":GA=HCKH15TQVJ%?Q81>PWP5TJUL3/0@RU6H
+M+H$7RGL5B7.UOH<]21-)Q)PO39RHC?6&2O[R.3I/0LZJ?0S5XS)38/7]**ZY
+M@6!NQ\N%TTN:<Z9#>9=,0B+L'1>J`_HC5^=,:5M.NKGB);-052+G3"GIUQD&
+M-C>M*RXUD8V/3VPL(?`=ACO\D\GHAPUZM]7A3[%HPY'&=O/^@+IN+N"Y*R,U
+MSTF&PJ?$<VU=3(_6MV"JN:V=O9>(FZ<`3!.>)E^R\H,9X`Q^IIPSP9UIYZ>=
+MSYEJ1H*[U,SGF=@*ZKD!6F5(^$&K^I<$PJ4YD^2B6$P<UX:7._14Y;X-H[GJ
+MY"U+1V]&4D*67\5D,0"<A3422K!I2O;J[5=HJ`7@;4)Z;L"E!>ZS<JQR1J*4
+MDRAOML$*IB,X#L9("])L(R.1E&EEF[+!U""U7;2[;OM::Y<-5@V)MKTT8$E=
+M!,A1B[-NGCKG]QI+;I[,">,UB@M#PP\FJL^_$%F+;<3S-RQS60@MO^!(#3FF
+M6_D_X,,LW*$UXXCXF&84TG6`:<;F4UZ@YF-RQ*$]6C!HQ;9CK(0U6.@$&I2(
+MZP%!!SQ&FP2;G)'DFSZ)[P\1CI<S1IN.-IDG93E>SKD^@_R$YJMSH8BV-JRP
+MO-Z:IRY_+E++L'!MH;KHN5B#DMA4M,QN.XKR=V#ET6P0:+*:.4:;X8P5MV"_
+M`N(\"GP27$:ZD,`ZM^KU'(L\)#RO-^Q5NK]/TH_\G5ZHE!H<CR&G(02-;`$,
+MDS!.AW&M(LY?A'3R/,]LID'$ECFCR1C9*-)9.X"&=<3-R1S?[P!>;T62(R>X
+MHU?L8NW_/\,L_10XT5#OM4K696B<M5=B7XB9@YD((CY0(BV<KMUEZS8&_/P9
+MFL!AUS)BRV4?KL6'QDSB[W.:WK:<;J3O^2P<*M!&#G;%_D*"G&/3^%'KF[^D
+MQ9]-W$A#8:557<(D;*P483"Z_9@[VG>$?/OB7$XK+]8T@^6<1,8.!3:<H_BA
+MM'B^BX&4LLAYH9$![;^W1"PNCZ>T$R-I"]7]S^GR#T>AFO8LTWX`(!8:'V/L
+M"TTQWO_^#6-7E+HBAZQ#+O>TL^U7BEAMMSC\+V*7+>@L:<Z:8N4BC)^5W/93
+M-CY6V\U"0K.G!4$&4P/$@[!"2!*[DM"^>:?CY?Q4J:`%V`2VCN+1R_#.QOL6
+M''<TYT*DW1*'!0KWZ3PU!Y8(X<GJWWZG<^9T3,4G4JI!.B9R;J>4F0SE^.9.
+M-6G.:J)3RSDZYX?@R%FNGB07$,L<C63*3T)WD+,ES^D2<0/KL!NHPV92AQU$
+M2>>,EG+/,KS)L;O>;`/EW+.6N<XFTZ1,*?<$5O>UK,D9DN=,Q"]\+X[LPT*[
+M:GT^8B+#4?N"29\Y7,((WV;;1.$*W^;^'/\N\%P*%PYSM^#2E&]V[,^)A]'"
+M1OK%=UFC\M0K,<;M.5V]E*(&]-.6BOP4C1;3(5%_KSKHF<CZI=[*$'G@]Y$N
+M/KWM1?T.`]-[Q\8TX6@E+XP2"8LJL7C.EF3`XH_&').4;2V1"\Z42-[)Z+>'
+M'T<MY<3U8`)4[)PT/YEL:\+W`&0F.2M1RDYLVZ&U/#^H9H)O<YR5OQY^\=(8
+MXP`^7LY.PDNJ2G8&)&>Y@W<1?D3\D1`/$8Z7LW$0S<[(0WTRR[/4%;`\MF8M
+M9?M25)]GJU72I:H94C(;Q_NU\;"TF=)/L(1S6R+KU!`G#)"$#DD(X?8F@"M@
+M7*MVA#U=;3-I.`L@Z5+9$"U6J[B_%U0LIL7"+"=I51@B>T[,=F<ZJRR2!]CC
+M1).9(X=#1<#%)IX)S"J`PQCK7:753/"$*Q/5CY_1)2'7!*?HO6*\/M+^38_E
+MD[3N&<]%1UW8U:<SV=H0ZB__TM+$<<%S`9K8721AZS+5.-CZ>J&*/B4E.BY7
+MBAMBSFR,-B/F/\F,#U;;SV>,MO'QBK`'VTA>-P.^S=B)8?$^QXNKA:3?Z9*8
+M5=$N^3A%W?B,+I<=9AQT#Z#31V;3N^!QJ3`Y.()2AW^C`W(9IM[2)7C)[\\`
+MZ0#YET2KIX$26+Y&#`>6R'%2S@2I$=>R.6,DSVZ(38"9)]6W.6.BD.S;#.MK
+MAYR3$>UC0CPSBG^O/G]ONA+;?[<[;XS0SSU[`G^3G,$BJMO8U',3\#5:,4PX
+M0`XL1P?HV\</(]_R)!^3X@]$Y@"Z,FLPYM!-_^F7VIFGT[TNN?H&)7L,U+.Q
+MU9R'"^LO?T-W.AC9!C3G)-.0.P?P6X!73X`Z@Z`L/,F2,S!))\S7I58O9OWG
+M;P$NI!HL%=B#`^3!<J95RK)!ROG"5[*I.8.9*8Y:)^UA_^&7["9"SBS&H38A
+M3GGH-[0:^_K)B-B$SH@60[_+,>$5`NR1*O]K"Z?GZ:_,NM4S.B1ESRB1:JZG
+M*<HI92<U9R>S16KV5/J%-51SMIW&RVRRI1PU5M'M#.WH'CJ?('^_:VUYZJ0G
+MF3B_`W#Y(N9,(IKG898'AHY^V%$L'CN@D!=>ZU0?!52E;-2'BMB7B^CZ>3$+
+M+$>\:"8,?4W#$#8^*\ET'/:1TMPD.1\5+(/RL!)Q(_#,J![Q66Q/E665CE*2
+MZH]D(7J'T$KNOM+.B^D<CW;OTXV'\W/<7ZXU2V^C8\=T3O@[$8/1PM6?2T_@
+MUJ_GJM9Q0DD5/)960&`"-X&K7,=5/LA5EC,]EL18/1;Y%U$]%E0W"==GE.L'
+M*F+&`]BJMSQ)VJ.[F)5*%!_C?32+E?D:$0]=A>?.F'04W\A>$O@#D'D)*9)^
+M^JO(L<(8U"RKOPW"O>%]6)AZW3,HZ9]5CH7AKT27,_18*\7.+D=I(@OYZC=,
+MD75Q.;OB?LI1^P#>*W]7.9@-8%_!;A9ZAOOZUX[:FZ`N4ET>))1W(5"Y'C,I
+M!^?$I.,'*/*\);H.FYP'K])<6RR2U;^)JG"0+!.W:'GJL%\A=G<8L%ML2$C"
+MEW<HX>>_Q(3WE.LG)F_BKH[5H4V)OH=)SZ?MAV;MGE_!$E+!(<B7?AV#`MX6
+MY_BS3!F#T0^+RT"=F.FC'+73V+P4"V/_=\*836U@3+_U.]//ZY'>^YWI\S0<
+M#Y%N(U*-.C61!?_%PDKH!BN/8,%+3I[ZQ!Z=[M"]N]7QU-.Q^9+T?(X\M62/
+MW@RXZJE'A/1;4K_#*-)I:J9&8`C=:0"\P0"8M"31=RS>"6F/N1,B7@PY_.BD
+M5-Z'$4K=W<A0[QGYTH):-%KL?3UB__%M-'9IC]AF0^R<'K&_-<1F]XC]R;=X
+MY&6LT]-/Q?*U?P+*VPYW,6V?KS&<JH<^"6AZ0S^BI0O4?63!TMIV$N("RM.M
+MQOLHD7'EIL?PP!O'$E1I.,612D-_=<._(_8-XP.LS_>V3_OF9^Q`_V<LWSB\
+M5\QTED86*O68*TR_ZE^?T-<.'TH=N@RH]WGKEQK,["C,X*5N,+$7J/Z^86I'
+M_"55_-)EL>?;M_TL6M^;%/'7Q73`_PP^5.L3R'D9Y?H!_S41(V>E'"W/DE$?
+M"N-5TQ-X$'Y(4\ONPX;#>S^-E(4GZ)2QX>>8,4/K392'L$QW<>E<2E'47Y;1
+M'L;#`*@T7A$7E83(E=6?'\/3'`UM^'X=OTV*>+<67X^->FQTN!X15,1[,1B=
+M":G+H/3>O67Y'F,F],[\`K>39^7JL[%*=G/SP\)92'<'@1Z#I2W32O,\9HE:
+MOQ@]!^I04EF\OF+B\@EK76D3)[O2W.Z;)Z6F39I\DRLU+7WRU/2;;W85+5V[
+MJFB%R[.^PC6:YNH//+B"^NL7'[1]U.H[-\O7F2'8/SC#3/O^]8O@)+'=]D'R
+MZ#ONDDXVMB5N^3@,V_8MC69T[#EHRR?AL,.WY2V.:YV9G_>!%16:M)FZEW.D
+MK-VZBIJ<ZX3=`MHT'9[CNS23G[YY4.TI_CK?I7'\QC8T7^*[=+>C=@2]W,,4
+M>-OR<+.%ATR:L1LR[$Z'3IGT,DGH?[[1[/#?1%\3'?Y^*,%LM#('Q6XAY*A-
+MHA"SH_8S"/'5A"<Y:C%1&][&#@1RM@]'!+H@LW`U^NQ,HDPH18-,?`++@*-:
+M[2GA.H+S6_@HG>15__0XRG$BF.TC>+Y+DX2%F',>))%R.]7?/&[1'2=WXB7P
+M,-[UJZ6TTO'1_\[S%N(->$AXE&GFR@5=F+*!]R"H?N@CX\[L[<.@])9@7H#T
+M0>=@O2EFYD+'D3ATT-S)?*HVDV_"3G^83\ENVX6S'?2BD>AY(P&(#C`L+]ZS
+M8'M<]O2CCMJUER,GCT8;K#9:9VF;<5_ZM7B@?5_$$C$)F4U9:>>WF[-FW,NO
+MA@6O^*E)JNZ:<8_0G_92ENUHK!:VJ>DW"NG;YYIJW^1O\EV\EY\H'C7[+D93
+M)635ODGCW?2`XTB#VV/?=*7C2",\-P]&(00+$_J1/(@*$Q['EHF87;P6K;3V
+MZB\L]CSZZ"X+EW8J+9QV/N"^O&F&,J,:;>`H5I1:<:B8'5(//:8I9H?0ID"^
+M:M]--Q"G2D?1'QH>&"2P`T&/S4JRFY!D?1'/<[.#S]%6+H%V^,C?)C0>V][K
+M..O>A4HZ3CSQLN>IB\/,ZC<ZJ$N4Q78:]TC8^N,GF#:J)F(L5*M_$A4PQK@,
+MZW%>\>Y.**+`27I1@CU?_=?E:"%X:$WPIW:'?W5/^!%]!`/P#3N-^.\T@+83
+MW!]Q;%<?@?O&C_O&.ZK_M!,3L>IK#@%VP:"I73V#024O<_%LCHRM+ENU)AU_
+M8.">R!6O+UZ^M@)'<5?%4GXEN<M!7[$)7`_;E%O:7;%K^Q?JV)&23?ULM[YI
+M'D6N:MK_K5^@IE48K?_QC8:G@*+@LHBE4D13&<YA23_%Q0+3-+:2,4<Y#B*8
+M\K&FNKQCMYZ&F;1OIM4\*Z%3UR:F-5LBPM3NG*M7X\A!ZRYM?3T%-:BF<\)0
+M11Y&96#<J[0$&9[:(-,*)>80+"\<:Y8*P]:'%?MP24'=9>FXV&!F9ZJS\))N
+M4AE-,-(N7+JH'V++T&L^TW*'J><M""MU*N*U+*7ZZDZ:^-JRZ!)-OFX=FY)K
+M8/ZU2P?35#L.HR<5*OQD$\F;_HQQA$I3[5@3Q.'FQ<@-M&I3:Q\S<JQ3/'I9
+MO)3D>`CO[]`UIPEKZ)I3(!':M2[0\V_)HSW#*GH)^T]_Y^"/M1CM5W)I?$77
+M1FCX'I6P4%>KP9J#VLD78(0ARU_J^3J#SL3/:`4]&5LOCJFJ2_.M^F"$5H``
+M"MJ+5@\8^H57$6\F9OOAS_"2W.HZ)$=R<*%(UP#,CD?>1/TU8BI-A_]'/V%7
+M;_?2AD<\3%RFGR<V<RA!"@X)1)QK"7'L4%<\3*S/#]`8UU*G]43EZ=/=%=&U
+M?[?=-HLK*2NOJ-C`\1LJBEUN;G;>C=GS\'=.%K=H\<VI4SG/HEESN$6W+9K#
+ME9<5N69Y;N-R%]V6QRW*G<5IFBS<LO)RGINS:(%[ZM14R)N]B)LR<<H\>.0N
+MFK4`/R9G+9K%>5:M6`E]W5.TBE]5O@9"TS!TT88JOGBUR\MYBRNK(-PU+?(V
+ME>WWA35"57$16Z,6K:IZ`%>IRU*Y96F`,U=9O+I\[=)E9<5<U:K50ME2'E)6
+ME7!5Q=P:GEM3Q:U9SA7Q7-5RKDK@*E=SJ\JXJ@>XY57<RBJ.K^*657%5R[B*
+M]=RR]5S)>JY\/<>OYXK6]_2+G/X(JH<LP<U\[FZYKF@$FG!NE>M6TLLYO%U2
+MT)JO%*CYZJ'=VDE%-=J8J^Z':X65B2:41>]65SR*YQ&[Q4:;E'M6QBO9L+;:
+M+38-=W]9=?-V)T1M6XC:-&-]&VR;8%@K..M+3^='2._E2-5G,]P7JIS;G=N&
+M0P(;16T2/H`G>OLIV"T>3<I7ZNZL"*&O255-P94;AB9#Z#UZJ&,WSC%G(>A^
+M/2A$W#;:WU!SK2R<50XN@XA74-Q(6RQ<^.WVS;G#%$PA7<:S')],R<IBD\6S
+M9+;2=*5NK0[ZMS_1K?%HT5:EX`R4O4%/L)XE8*HV7>A)M.`,I)06CI'>$H^F
+M0M)->M+<GVCUF0"AF_70:7KH%`C]'SWT6E8EJFB]OP*%'A`Z5,>F)EFIZ[R*
+M'#F?5?]!![:[2]B)+?J#+#B=3^G_]F-*GW:*5&M*Y(+3E&XA5*(%2MNFEU;/
+MTJ'#40<Z@5XXP?'"PM1@',G56Z@ZTY6"$Y!%UK/XHEGLE&4Z9)D2A.J?H/0S
+ME(+CD/YA/7T>2_^J<Q"C$V)SG&$S6RDX!DD?C;2[EI26/%K28RSI7*6@`9+N
+MU)->VM6M@@TLW3REX!"D^XF>[E3W=(=8NOE*P0%(]S,]W;/&=%"7`U27/*7@
+M)4CU<SU5;;=4+U&JQ4K!7DBU1T]UWRZ-,UP1SMB+"1_%(Q6EX#E(^Z2>=G+/
+MM,]1V@"'WC?J?EV!/BL*0MOKGH&W;067(>RW+*QK>]WO*.P2A#W'PCJWUSU/
+M8><A[`46UK&][@\4]A6$O<C"VK?7O41A7S1Y`DND=[8TH[7%)L_.I4INNY2[
+M`SKVEJ8]M%?8GKMS6^[GVW*_W);[S;;<B]MRORU4"D*$O+`SP@H#F5GDMI<H
+MCU)HI:LJU/XLD5+P#`1U4M`M.V/)^(SD#?EAX%`*GH(T793FRIWZH>D@V?-4
+MVJD+ZVS;LDW!?H&F;),-O9^'A1V8[DN:D^RI#-;V@CW;<,<R#ON/EN*].KWO
+M)"IU8T9H?0?W4MOBH-M0_0*7/3O%)J?8[/15[USI>#@^C,ZQCA0$2L2C>XAC
+M'MW.&F1?I$%>9@TBO2,VWP.42PUHM/I6*7@\7R=1?EUL51^7AF-1S58H9TK-
+M.P"ZV53H\?Y/\Q;<F>$;YK+NP&.<J%/U'NOM$DG?V\+&%IW,)070D'1(T5>5
+M5XM-5G2GUN8X$I^G'ON1?E@UF!PK2AWCT9J\&0\]"M4/=T1]J6B3%"UOR2Q&
+MS[(_VT8R^M+^BGA^+5N-39!A=697Q'D5[#L9O\V*R*UCWW:9!C6ONOP1TL1#
+M&U^AJ)!.%SN$(.G'VYF$PZ)E/;D]BES,_$\6_BN%-6C$`\U1KEM:N6;5FA7I
+M>#]TYLS>[/\!WB5RM5T\R%=`B#!;/+@>7QQ^/T?J0&284JG?`R5[U<$!%!%A
+M2E*A%5!7<R_BI+X0("L`%;JK=9L&1\@LM4%^-+YU5J&C>RDW5`([5&:"%M=D
+M<AT"1#5(5;-P@G8?\?X.S*<D?SNT#O4?S_:RX)G$S)6L$<K*8L],[GK(PJES
+M`TR-<C@*]4HY=<@.--:O?LV"==_:2V@>M'&"0Q$#Z[$RDW=HIZ1V3LA@;A=^
+M1!'N'9;()1W^>CS+>V<'MHQ7;<:GV:N^1EF3Q,OFFCBO>J?$-.[T8YU8'/=O
+MU>QRX%76,NB#P<&E_;WL-4_U;"=#.M&\^*\P,W_^G/DYU[I<1<55]U<5\P\4
+M;QASTUC7FG+>55%97%6\AB=OI2N+756T#KLV(5;^MQ75P7T;Z,(5$K_?7EH5
+MG]F&B-(.+[:(Y:LJ5A97_J<BNNVM/_#K'5$1_]ZCK#(HJ]3F+527:]1AV]!H
+MN=^O6C'U>L"/];I[8_>RN-[J5;QF>>6&"OZ_H=L`@G^P!_P]#T7@<Y%QP7CG
+MZU2M1;M`@V.KQO&:&5?J6;DA*;=C8<03T$B-?X!K;R=A1AE9$BA!_8<?/!3U
+M43*1>1#O*$2F^TS6,^E"6]SPG][:;<,?G!:0/<[9Z,O4KL9MTY1\[4VS!H>Y
+M0O5I3.X)9:!)^AC_&9K55NI[Y17%:SB4V/+<ZJ5E9>7+8;V.SD%Z^.%[7[1H
+MCM?[2;K7!+0/`\/?IE"X;889)WV<KW:K\[;KUF.NP,\48M%^F&H8'3*)!S?A
+M2(+W$?!%#?F9\F!!BWC4G$_IR6I,A6:Z41B&8#ZD%AN`8-YA.L]AH87*>]Q/
+M]HHN-(9'H@-JZ,WN@A:AGSOW-#]&*^*G?AS-J%B.K?,?(7!#$)Q/6_IO0BZ7
+M,1&@TF1-2)!S6V1"HVE6@HECKU*=#W\+'D=S[V@']15:"\C5CTO5NWTS$_C9
+M`5A6.(X,\K]9W6_;6X[];UUH9#;H%ZI/;J.*-JJ#Z+:77$<VZ(=L7[S]YL;/
+MXL1/3+`S].R6"8[P"H!!Z_%7XI62Q]77'HJZM.!GA#V/!Z>QB%]3Q&Z6<7SU
+MX\`,CX?K$4EU/)5G-QW$+P`G"9@?4/7-A/E@#HJ`J#:X/3%4CABT#*J(=PJ*
+M`@%6SJVL',>1V2:Z<19;NZ$+U3<>,M2.;.SWK%\<8-$4YP),8;OT.-:PQL0)
+M3R!';NLANUJQ!<\;&*\,T!JR130V9+/HT]X,-MX-^L\$P,<`R)06Y3OZ/4T6
+MXCCB[.XN8%"^VK55KTS0T8NO`%N8\@8/R41IO(IR#;(MA>+DU(3&VHE3HB-^
+M[)@J^72]8/YVV80'AK.DYH#CR/!>_$N41K'IP[]$#OJ7F,GJAO<UI,OP!;S8
+MN[^*J_X#/"$N&]T2'"77(.@6!*?Y-(.:9.0?C1/SC/;O-Z,8\T`>S,[''B+;
+MU/-DSX'&UGC)`_N(0Z]9.MQ;I>,7_F5ZJ_&2O?'BR+%O60I>DF"/(30T_A,V
+MH<=B(TWO6H27).$EV?-2U&:64OR,CL;2JJKB2I16N*Y+J;K.5;)T55DQGMC`
+M@T(FN,I6K2EVI11UFU\&;-9]BZ-C8+'!UWTB^,D67&^(N+XPKD^HOJZH_:\:
+MTD2"78!VOT%3MB-;)B3B5SRM>?E`C/BM[`X]&[CM8G4[QUO"'A661/*]9R,D
+MC>%_`%Y*!OFNVF;IY3PN)Q)O[C7^AAJ]CFK;0U'_K&*[+9+$6F/1)R_`%VWY
+ME\+FV99?RIQ3H?65^_QLS85G"7&ZS;).'>$8_S_51`RQR\2C=\X+9_+4P5!K
+MTC_2YQ\\&8X*G[OUU[75M'XB+1"O*OQ/-_VL<*K:'V;?/*]:N:7;,BRV?:+V
+MV497&^VS#>"^RSZ;4&OYS_;9C/5MWF3A'"][['DK37',7M)G6RS=O$3@FIW9
+M8NJF_[*)M)E01=-)]@_&,.;1,&6LI%V<8;<28$U)4D.OROMPZEHBDCW5G"T6
+M;:F-JP`O\9GR]-E_]^*S=_@F:A]F"=]H/SS*#YT_9-JX!7986$@%=@D/)'"S
+MJA38\Q?*"^WA4ZCC%8N:[.G"2SG$%-WH_Q2#5VK!?3+"`1B)!"->M[B@96[7
+M>#.:=Z66-_Y[YHUDG-1[):@"-@0@Q/!R#S]6_]K8([]<D"A[DJ2"1,F3)%8G
+M<XZ=:.FB\1,+():H$\<9/J7W,=1.S$B6?1.@/2.^*2FLF<+P'SJDY`QI$_6T
+M/?@Y*8+:XHW4A)*G`SG'1)QCZXME&%NL)`O09K0@SZEM(DY2FT;@A'DNTO[&
+M]>U7&VC213=>_'S4[2[H,E[^(3MKL(XU"3<#?:2"CMBH3E@_C2"3I-$V`[*@
+M$SC^>E0(U>(Y0[R=Q0NM,JJ[P@ZCEE8K-JF>O=BE^FT547,'W?0?#.C",($O
+MNJ<'"N2ZN6U1^J7!+QX3</'<ZW@?K9KY>^LW.QI>V19)W[9.C]_>>WRA'C^L
+M]_AI>OR,WN.'Z_%/]QY_89,6/[KW^/?T>'?O\2_K\06]Q_]$C_]Y'_77XQ_J
+MH_YZ_,U]U%^/W]I'_?7XW_51_Q]J\</[J+\>O[&/^NOQJ_JHOQY?UT?]]?C7
+M^ZB_'E_31_WU^,U]U%^/7])'_3=J\?E]U%^/S^NC_GK\OC[JK\>_W$?]]?C]
+M?=1?CT_NH_YZ_&_[J+\>_^L^ZK]!BY?ZJ+\>/[V/^NOQOC[JK\>/Z*/^>GQZ
+M'_77XW?V47\]?D(?]=?C7^NC_NNU^+U]U%^/?ZR/^NOQ)_JHOQZ?V4?]]?AG
+M^ZB_'C^WC_KK\5?T47\]_H]]U'^=%C^HC_KK\;5]U%^/W]9'_?7X^7W47X^_
+MO8_ZZ_&E?=1?C^_?1_WU^(-]U'^M%O]J'_77XU_IH_YZ_($^ZJ_'W]A'_?7X
+MI#[JK\>O[:/^>KS01_WU^*-]U%_0XHOZJ+\>?T,?]=?C%_91?SU^9!_UU^.]
+M?=1?CU_01_WU^$E]U%^/'])'_7DM_I=]U%^/O[*/^NOQX_NHOQ[_1!_UU^,;
+M^JB_'O_#/NJOQV_JH_YZ_*@^ZE^EQ0_LH_YZ_`_ZJ+\>?U<?]=?CQ_91?SW^
+MEC[JK\<[^ZB_'N_HH_YZ_'5]U+]2B[?W47\]?D<?]=?C;^JC_GK\-;W&5ZU=
+M+A15W+^\LG@I7YSNJBI?_D`Q[Z)/%+I45)8O*RM>'9O,=:-K^=(U*(E?4<QC
+M#C(^UPU2N<"[RDM<JXM7EU=N2.AI\Z)T-6SQPYIA0+':%A9N+!U<:BXUJS=7
+MH"#2IMV#5D37C_`DYT*YA6L;1H)A,EVBV5?;#<%-GB_-I`_U=3G9N(0=Y!4E
+MS9ZOZ/(A19PJ9Z>WGO8\^GZU7%>+N$$1<PC^3\HUPS6.6IR),=4\+/))CMG?
+MF**N+H]*\]>O?`EMK-]5'M%-XHO1BI3'N=8"FTJQP3(Z),7EJ6Y,D#.!7:*[
+MK=04GDI:2NJC$-Z\=:^V4Y36I8I-+FG=:$7<@>HL.;82V?/5UM82*<>*6[3A
+MA>J9-6@[)7B5(I;^J+LHZ\2:&#,1,?LG2YF%6[D$>(]^L%:5E_5-,:2C2V.1
+M?:)1[_BM!]@F>4.JLLY&=_;MV%*H\V;/$QN=L!=<6,J%IY&9B0GA-/7M-<R\
+M1!(:-(N8E;?RKXN7'#77-L<Q\\+64LXK9R2&6TB8\:O56H.17',.RI%R[;()
+MJBV^1L3A4W4ASD)J1]WO)9]$Y=K#0B?YZT8/"FGJHC7=O*[UHL_Z52F[N5R9
+MJM38]/TTNY0I9]M+N4+"#A#%[:\YOU`]7Z8SU3Q(`-'.<`M>82RPA2OM4HO8
+MX,PC*RSAR@GAR6H+U2C9[0D)5VN"-_$(J\I`?\.F_G1W]DDSR39T3=<8_]^E
+M[.IC`53-*6>DB@VV/$WL$-.NXR/I6"+=JH@SDKJ[//KB*G;&MRZU4-T(=0I/
+M4Q^`!SHT.683-R9SO)T4Z+*2T8>?-;QN@GI;&>K+W0*_A>JT,DO$;F+Q&M3W
+M6KYT^4KHZ/1P+2W#<Z4-+A:%3NH3N-ADY4)9$1W?T3$4#B,4\_U2N8J6\DN_
+M9]*2527E/<_[+ZUD!,M(11LZ![0F4<2"'X=T??+2":KT0/2FH4T1-T%DL!0Y
+M89AV75!ZK_%3:Z&Z%--E6YDVP@!%_!4F1'M)A7EJ/^PY!79E!AKJ`\K=3&G9
+M>,8/AP3G2IEYF!?WZM;N@M<JXI]^3%<[UO^X>_?^O)1U;Z8]0'7$@^1TU]I5
+MR_E5JXD$)>7"FB*N9QR11I.:&Z-[(=Z:XG6NRHKE]R\32DJ**SFNES%A_PHV
+M)LQ)E7)#\BN(OEQH1_.F4P(P`MXF.QH_-DNY7?(PJ27MU(4O&S\Q6PKQ2B$_
+MU#V93Y"'B$?'X`7#K_"GOR*>_`E0[=:`G#U&,LM>5S"?VJ!?:4P;?(Z)KD3C
+M.&GJ9ZO8&(.'ABF*:-_=!\E>A71M*/`(R'CWDFZ0SYD@S7>A;"UO0BE'X/+%
+M1MM"-8YZ4@A=-,3)"Y*D^58Y)Q':2U[@E.9#Y9*E;*>\P(66B7)&2]E)\H(Q
+MTOQDQDKR-J*!J;'5C&[E6+6%+GF!5;8_*LT?(^=8I2D!I-$"FS3ET7".'=XI
+MT32IT&[P#1D[-\XO86/4W%2-R/%:`0]:I0Y6`DP,1'.TM2''N3.MPD(8L]PY
+M2<(<.=OFSDD4,F&T<N<X!3?,E#G),.TX\Z#5U!5E3!DX%Y7UKP:JHPS4*:\=
+M+0D=<D&B-)DQY.T(=^T8:()?`@G)U$H2#C;Y3JDPD4+L4HY3N\5?R,@!:5S,
+MVH%4.)I)/:6<,<:9J9?Q>%DQ&Y:FB0=WD/[)4#H>4,,K4)*Y@YT1J[^%+W=3
+M]4TRA4@S]DI?-K;U0RZLPWT+7@'I$%M'DLZ=U/CG3Z06LN#;U=^ZO9NM/>.8
+M\,\BK6QU#H,_F<%WS]@KW-!LW4L=/J8@\9\C#Z"RL/3EGQN@A&L1?(?AGG4W
+M^T<$'_U,D'&W0O5M!'B4+KNB68=$]UP[/PEFOML#I4YUX(H(<_-!::-5JK2A
+MQ=^Y=ED,8*7-4EV`3F^3.,&FWYP#SG:\G&F%:24)X%]:;50SZFG_<7E$S8/A
+M<RN1B[GR&<]L$L#L2\4%;0&4O9LD,S,!LU"]&;@2\APIZ5:&H8!=R]G%9YC$
+MJYUIIQCB,.H-#;@KK'BYW<;;I*,RGAI^(0V/N8>1&H6R8#EC?[KRU.PYS<Y,
+MSM`4G>7"VUY9HR5/JYPU1O*<TXQ@2+GMR,!S;8JG)2]?SK2'6Y3BXY%S68`?
+M`=^QC,!_#\!XF!4#4K[WA'X&$H6WYWO#LWXO>'G?&UZ_[P6/6\9&;32"K8-D
+MC[/470#@0H*QD/2X(C`B`%Y;:N%*^^'"Y5=AP]K16,;C2[\OSJ;OPCG*`[<O
+M-;K7^<]@S=^'!UQ&_;\EU!=*7731<"&PG%0-+\QTPFF=+[>TN_K%G.O5+R$.
+M5Q0.[Q[DMBM*`.^TY'8IB@NO].0>5[]=1O=?+\'7OHY+="'F$KNDXJ8WA_(L
+M7EC/;9&4<Y?P?H&L8#*YOZ1TP5/TXY?5<:A1Z,?L]Q;@%+`+LUIV=6)*&J3D
+M38$0V18/[T,PA3(7;M$NNK0B,:I/R)ZSDF>O[&G%HWG/.<ES`'VZ>P[)GG;)
+MTT#>68^QS(IG;YZZ;Y6N=CDDKU!]F=G8U/V7-_M#6B6.D$T=?ZOV*=.@!$.6
+M.R!G6=V>O<(X.<OF]KS$SV)YL.7<E;8JL]0D*YC+/=>V-DXB`/(0F,B/BX<)
+M-C\JO`\#88SY@@JW!Z\*%")JFE]I6S`A4*C^S[?,YT&.K9`.@M@:S,&^$^D;
+MTJ&UM-J/R+,`DFRVXZ`?B>LX1`^-LAD213K\3^#=06H<EZQ@R[D5:JD=2R_3
+MY8U+D<L;/<;47]T7,?_FSR$;._8M&USH;L7QT`"K]CV!??_;PHR/S;'BA`*L
+MO=`E'K7X/@G)F1-HRZC,,H_!'0).7IE)L,]@%HT=M9]S!$DV;6UM/.[<VBK%
+MB4U6.=-J_$1#:@[_3RPL9:8M-LYF=OA_J,?98\$X8S\38S^38C]=L7!=')\<
+M?M#E#3^8K-ZVE!G4RG11;4Q-M-"`[]&Q(";$@IC`.6J=:-GSP0D`9DQ;F)DJ
+M$MTFA]^*6Z5,:ZEKH9QA)$@[IL'L&BB\96@R!DB99*)MF[EGNDP;(T=9;W'V
+M6"#.V,]$.2[RG@0+KLB'"[K-ADC##R$K>'9Q0S(G./+4F^XGNDB9R<SD'53(
+MV/KY83+=%JF=<`W$`DV!I#CHXKS+=,B3VEY!`4@DUJN>O)^MYJKM8C.SS68M
+MM<602DBCVX5JL6XNHU8PD1T6L6$";48_U&.$46UW,=M,<4:"C#96<P+98"S9
+MLMG&*HHV;-%.HS`(3<#<?A]*.ZS12A;:M!K&HG05)`ZO(\ND=Q23#E%BVT=L
+MG&$Q7K7K/FTK3][@41>0]%S^<%^D&L]S6C6L5(WX:`5W<AKUL3_@L28*+9A!
+MJP?U_'PEI;"9A55,I(&QBR*QBPFRDT)OB83>2J&)%'I#)'0,A291:&,D=`B%
+MCJ;0WT&H9B>MNPIX3_O/=^G^T,1TLV-G@V-_ETCWMV%I^(E)*@BQVZDV=6*1
+M7M1-M'+KSY:$MP8"?M1Q&28>=<*R.%R/^DJEB23V^N&]NK@%?0$D4CJA*_@+
+M7.M/%9N<P5V![F:4;V."OLKB%:O0C;"KJK@2MI;%#.\)!KQ_=B?II2?"JH)4
+MN%`X]QC,JBN14>@'+S/(=7OQZH)<]QP^2LTK]VPU<5ZU=#G;\HV&'<T:4CDG
+MWLL]AW>"<U7'RV&INEV&G5G=`51M$%_"W'EXE2E<CXH1>/5+JZG)*P]&OZ@N
+MTBOR6KVP00F?PKL2U7?C1N],T*'49?PZA&YO?G@/VUD?-]Q/,-:IZ0Y:(QBK
+M='S9]ZS23Y9%JW0?+"U8?2(FV]II[OQ>-3+K-8JIS0MWL=IH=B2T*G`KBOG[
+M5V]86E1465Q5I<MSNX>N*E_.E[G&0*AKU1IHU9*ERXM=R\O7E*Q:(522X'=L
+MKUDXKE<?TK\HM)`Z6:E9W7`7KGU.ZZ9JJA,5L>,W*%Z=?A>JW:NKX`%K"?0T
+M1*:`M!O!J,ZD4&C>RM&K;`V:!]V#=^D7^3(4,>X9A--Q)\&Y%N'(64YFWSDK
+M$49[.2L)1G8Y*QG&\`-HKP+EIYGFMB=H_)!WD<MA!<N0%'0?A#X5_H?BE,/D
+M9^C=T"NX^OOZ:86\">6M'+S*I6'"W.VJXQD^,GT!5L,4T4U8W<6PDN\D6?MY
+MNDIJ0G/=@\V.V@+@'<?^+*?8T,';3$?',N=%1UTBO;0*/JVV']R!FET-L1=%
+MR3Y%Q:J*XHF+F'F*B5.8B8JIDU+A_YM=J9/3ITQ+GY+J*GU@I6:?HNW)NS29
+M_SC.(/.7YXVV2B9IH15/"CDC_)+RR@?^&_BWZ?#-1OCB)32\:8`=@;]@[7\N
+MX:9IAA+N/)!E@!P/D(61P>LB##>Q`'B_CA3ES7?32B[\,14<_IC*J^(K*Y>O
+MK-0+[&[1PYT.+S$6/0*!1?+BT;;M\T;;TQH"VZ^:_E?!++5DU?Y-^/KN6(TM
+M@E^Y:DU1\?J^P:=.[0[^OX,/^)?PJU87ZR9)@&(W=:/8S:GIDZ<:*)8Q9M38
+M:+;^TR;>-+U[V,T3I[C&9!57/E!<5KQAK.NF26E3)DUW<RE+72G+7"G%KI0[
+M7"EWN5+NY/)RN<S<V/`[N935DU**)J5LX%)FIZ?DIJ<LXA8MY87*HJ4;N.S*
+M5?A8O%*HK,*7PN*B-<7TMEA@S]SR-?A8)+#'4A[S8`9,BZDP!49SLXJ7%Z]>
+M5ES)S2]?RUX6+.?+\;FHN()G(9G""J&*Y^8*91O@9TTQEUE1N:J,RUT*C<YE
+M%R^K%)960LS2-?0$B`@,X2`,S(U9,2=DV8"9,2MFQ#SDD;>[7.-P/IN4JQ/5
+M]V#.L`@VG$\+F:O+.$6<_'L<!5!#QPU]O(GCQGMLS&<-DW#,Y%)2)Q=Q*?B7
+M>E,1E\"HR*7,8;1TI51P_;D4B"V^,679C4CNU"E%O:X/)N<SF5(N"M_H@L))
+M&\DY;;[I*0[_,S;T9&B#.,>1R>+E#8Z'?FQCU_SK$Y]GU_P#UCP+5S3G_QM_
+M._\?P0TML'`[X"\9_EZ:;^'L^=&X"OB^8WYL>CZ7/8WISLZ#O/"W`_Y6PI\5
+M_NRWP]`XU\)U0/SI[RC_&)2[&/Y:H9P]\+?-4!Z&XY.#L'-0[@GXNP?^,C0<
+M4K7G<2CO<?A;#W]CX,\%93\#91?!WW3X"^?:VG:3YG+B0G%S4MRZZ\2#LQ_D
+MR#>[O+N";!HK\B%<?^0DR?.V;*+OK<#+"]M&_1?YEACR!?OI^9P#OBN?$_*E
+M&O+5?^]\]BUD=U7+]T,MGR)NPSXH%R9N.5H63Q+A`R/]P847/I-.-EXD`:ZG
+MJ[%KI/36V*/YZK.0JVTM&@;`O(5Z<0E:<00?RPO_80]N07+Z:?>1(*TBSGD.
+M"FJ[*1JFE1U>9U<7(N"K(S@I>K@;P_O%XHH[IFLQ_'-K;!T6V`[\[MEGQUUH
+MD]X]>5D2NJ3C@/C8)GA3$M<J5CI6DMX>VR070$"^%N!N%/H=P2,JKWH"X+7M
+MMAKP>Y3@YB1GY*DO8.0/K6Q/9<#1IN["F*4Z+G48GO]_C0LZS6RS6WO2RJJF
+M8-27EMBZYS@!1Y2;M+UGB>+X8XAK>\2BM1?L00?4],TCTC.X#[H.[Z&Q%`.T
+M%,P6(TOS%$0L;+LE4@:TZVY$H.UNB[&MGZ"P'$L/_*>IL"OGVB;K.!6J/\;O
+M+\WZMR+F$Y\,,.9]%NO1K*=1ZK81C7.2Q(:+<F'RV*/(M76CY_P(N=:22\0V
+M`V4;+XT<VY*G=D+&M@:S`=YSC%^2_&\*_5[!J^L+5;0-V?88)9+7)8M-"="#
+M.=Z5+76,STF2/"$&?W5(>M<BA*0.*B`4O$ILN@1MRB*_P+@N+0X+EYK&OBO4
+M`)X94M-X`'JY'[\4MC4KY'6)6YJPMUUH0E&Y,(9UN2\:+_7#W".I0L`6>-9M
+M;5$2_<0<[PJC(^GB>TG7V&IU-PD)1U#AF-DT1W>4!N)[5?1HUH8.^'1:OT#M
+M]`M3]W:2%R2+C?%$@FLSI;?&%R;!#MI`XI!&XA#:RA,;+Z'K&8IMZ]X`4N/8
+MD\Q^<=LM)AV=YQ@O)ZEW8GB*%OY=X\EN'$\N<%$>^XZTCV/:/W(]ZY2XI1&I
+MSJ@(/;/Q<C^]:TI?C3VJ6/.5Q*-:7QS;N%!%U<.VA[AH?SK`^EIB/P23IZ)J
+M:;`T(&X>`WA@BO"Z,<'1P#\N\;)IG1-#9!$U)<)3]@;M&HRMM.;!O2J=(`5O
+M_8_U>8[#.XL78#O5B`Z8![IS$_GAL%+9/F3;X$Q<M.`:AG/X4S')\6[G=L9S
+MZ(ES<`V42)>[['0+UPU38B$YM,/5FWZPFE(674---^3_8C;LM*J/RX(M],H`
+MMN7S'(>ZP-R>IXC?[B?S@P#U[_/P@I635%4&$-Q#AK,^KW:'1'"ZOZK".[C;
+M3=O,F;4-?+\L]U>57TDM9-1OWFWW+YZ3Z^%NX_(6+)IS!Y=2-8G^U_?2Z[OY
+M?YZ-]Q^)A!S=DE`.2B^'PJ_@3DNSN+G,K$7(&!$7C9ACYC3_[_>;R7P\+0\7
+MX;NX$T\0_;N9L<LU>?GJA=MUL=\2>=]N,NZ)[27M"N!^]^261CS]=+_E$-O0
+M3)2RLZ=#7V4;[G+?EED.=$W',LM^3.P^6OE.V^^I0\8:T7KGPGM*W9:7R7*(
+M3:Y#4QOAR4K=HQC"[`-KUE/_,@_%"EY5F(<RA<=)IN!"QUA;4/*R:P]:ULI3
+M7\N-V`&^#X61AW$OS6T>ZO`OH,\6,CNZ-0MK<=%"._]FH@;^$P_O)H--@Y2Z
+MLF2H[B[\%`8L5+?,8=[)'`O#1!SUS#PJ1FJ4E-V:\.!?-"K9%JK'8*W%:&BZ
+M+%VP4)'A?2W,XC#BK;X/K?I3R;^-1`D[J":)\B[\=),+9H>?9)9^C'*3^,3A
+M1]F$EOWUV;KABPK?YG""4&ILJRU'J:7HO>HF]V5^GNRG%DGUW9K`XYR7#2_"
+M);SF*5*,5:E#!F-9*O\D4ZVE.B0*8ST4)*8UD#Z+5GTWPT##YR;L/T0QEDLY
+MB.@H]=C-0Z],H!ZEV;W:U,WN58^^O,Q#LG&?^Q;!FBGAP;&]AS]R">:%W!!I
+M@"U9$'5`N`#OVSMJR[!IWS-D>OO"NU+';#FWRWW<\3]H]%WVV+=SV\QACSVK
+MML%1^P-V3+.]_[8$"GI3^++M!A.GV0N34]/":(LD(2`V67/0^L@%\>`\&M/&
+MR?680C=-%IZJ-D+32W&L'^6RTSHFR&X6YVF$C!@RNS$GJBQX6K=9YM6-E*EQ
+MLW6+95(J66LC9+CF60?(3XU4'6(]FA_@2[^%C\N"5^&;\7B!JQ/GS5E.<Y[Z
+M5C86@>?V,N4V2:@D`D,&JBQ\!>,5J[.M]DU^&/I<O(5W9,&HRXACJVT0VIO,
+MMV3%T(9W!F+()WR)VUHU5N<AVIQUM]'Y:(!YLWM1[YS\>*T^N2$E4<&T%B=:
+M*C=#U&D8.;1WH3/8!/,%[IHUCB'X=QCWO[<Q8^]'+<)PV'\_8Q&<8I=5MVLI
+M><X&XYL]9YG3:3HN%JOM<8Z',#MDLQ20SPF/W?&"QRDU6G)M.,1]BAN&W--R
+M@4I>G6WNHXZM>_1YMUW.;1^?ZUQ(OC<2PZ<D3P-9(SWA;ZBI07-<B$<[NATX
+M+@_&HU78F!^7!@?ST%:7:?,X0+)1-4N>8[+0#FNR8=`H>*0D#18;K>'<8V+U
+M,6YS&RY7`^B4NH`E"VP?!K-)7#9.C%J:SP'06"BHP.8N:'<\M!R/XCU.DT>5
+M"TZ["U3'_]R"W)<<3^Q^4L4*6O`FH0H$B'=LG4,ZA_`-$.QS'2\4.$VPZCH'
+MD6,<6Y]A1T*-JH7HXFF%)C0!']F4Q"Q`"84=LH?.5@%`@[^A.C4L'/,2.?2@
+M31@4FP[X#9).EW./!6_JD;ZFG_0E++IZR70,,EGH$`!05<<7M!)15(O0&A;4
+M_&YXH)VP;GA`T+$>`*=!:3<!77NDK^DGYZK!I&Z9I"\9$L>D7$C>:CHE%33(
+MGG-C6Z@=SXT76KUY,6"J)X>%<]X8Y#9A$(*-IF.XI,NYYX(W(V]URQ&A28]L
+MYR+HG",G(.VQ9+B9LG0C!`MLCR%%.R2>B<6G$V_WR%03C]2X6HN+S:OAT`XD
+M(;9/1OV,(5+!<;SB3FZ"S#)]2,[@(N+]B0;>AQZC!KX?_V/27OG?9D'F["+M
+M6\;#%AS_.F@(['1[NAP/V<A#)*P+NUAGU<Z+'\$EKL,O<A'M%ZK"U:CX1SVW
+MH$L>`A_0>>E#,@<7![0Z%#@;/S,38B&84_Y3'1!#+6EO=8!N!Z,S]MLN<A7?
+MY=B:2SV9H3^'[6D`_\X8_'?TB7^GAG\'XM^IX=_1._Z=<F[']\0?D_:._U@H
+M"D>BSM[PEW3,1A!%D3DX(B=Q!J`7+`@$>O`&6FS^GKR!27O!2R,*(RS@UM9.
+M?IS/`,T^^ZZ1_W-<.^2V(/S_CX[]+=&QW\5&\<C(?PYX<'QN")AQO&!SOUUC
+MEM[VGZ^9!Z%COR3\KF_\PBP)V./ZQ.T:P$=+TBM>N1WC<Z'SG1OOZ9":QL-6
+MZ,LJ5DPN#!A:,3?HQ73U38-(.5V]ER-TC1=";L%9=27L,F%/QO1@V0']F0OD
+M/D$6.L8+G9CF*ARJ.R2@`4LE>>QMQR\PWQ7%C\><;\?8OT]',_7,"%)J5G=+
+M#Y'TAL7(T^EDY0%M@H7I3/U>=XVM*E/JLF3;Z$*JE&W##ZOV8<4UHY(1L7L!
+M7Q_-@`T?F8UGED-&`!WBY#C(,S[;5DBVHF=!AK$UMACS+#W6T5<!*BNQ%/6-
+M&7A_II/=.<EK]G3Y:-0(X8.Y>\M[`ZW2<>2Y=O@LMBI-1.=U^F9W[DR\ZN)5
+MC]["%`;"U0[T@7[3#,V>;?`FL;J3X[^&KCT>A[-.=`@(J]#QGE`&>4O_[4QF
+M.LZ$QABPXYL0^^[.=UD]=#L)8OL]A5']/[>%*VGVO&1EBY9G),\!-+=GBYK;
+M(U\`DN>0Y'E.$?<TA<*2YX2VY-..UQ6/DWP$>9[)4RMN1:(\)7N>0@[HMA^)
+ML?\UG?DLW3R&$X:Q0\9F\]5Z\[3AF20T]_GL@4[A!F9K+[PV6?:.P<$!)R*Q
+MNB,L)`-YPL(P1JM2NG61AZJ)ZQ9+,+)6V\[GV*W\!+G0*KU+9JW&"AU75G=2
+ML:D</U4NG!$3@;(8RF3CKT)GJE?(PP&'\5ZGELHD=`R&[)Z.J`V%WOC[PC2+
+M3A-D\7MOZ87%8^RU-$VC.Q-;IA=_Q7%"L5R!?N#NVW*KYQ0Z'V?NM!COBC7D
+MH'"M576D,U-\-4X*<*J7W5I`(@4DJI_K`3,H8(9ZE@5XU3^[+5QO1E^XCMO8
+MLS53^X9G*]#V7YD]VF\(X/Q7C^VO7YSY*WIF\/##%+GA>"C\@4D+N'S"%\JH
+M&OK!&6J=5ZE591KP%?DX2]BFR"WT]N'%OU:CL[*7[+#L^.OJKH^J._ZZ.H3S
+MZWMIYPN]'TU`WPT?MD4*$P8L4.0S+&NC_G;F),7Y0B:A7\Z';4'S!V=BH8KM
+MMH]FC+[KSK^B5%;JD"[U:,;_IOY3+=P'5/^3T?J_27B\'UO_&`K@Q`WU9PD_
+M@_J_^?WK_UE,[=^,U/[-;K6/Q]I;`X'_IO[S,N?G<+=Q\^<MBAJRKUJYM+)X
+MTIJRJDDI\R:ES)^X?"F?WCUB/L2Q0+S>4M9WGA[1F%.3S6V*E<V]/`7MES^N
+M6YPG2=M)CK95*+>L?0,'6+*+_Y4[HIN%PQ?E4?PHL<K31"A+<)#VUT:-TW],
+M'O7:4#]:$1O>0MEJR&W19':Z;7SQ#8A@08K83(G><T>OQ,0I=>]`8.J;TGO;
+MCALE=5B.]/9\Z7A&GD1B)W7/5(1-4CV2":'.'L5`.2/94'<OZ1J23(K5H&T(
+MDZ_GA_=A1O4$#@\$H\D:E]XT*]7$R;MVLBH103Y!IO*3B@^!P74.E>:;GN[P
+MOP"Q3;JX#P4;&P,HDT@15O@VFN8)5V<QV9-7P_@^+(WD=3A'0I+YPM0L(+8>
+M?^LT&KAC1918<84?A!BQZ@4=@4!37$HP'M=99EAED!Q%:HKC(NV#F*H-Z1%U
+MPHNH14RRLJRPGPDX61U@<7DC%L6H,>QF&L728!?%PR)"C6/?XF%B&$?M2+PW
+M@C;YJ?W14);R]'JCCZ/8<_ZYD\D.)<=?B^;Z:D9$;#'99^,R,,M6`ZM8N=H.
+MFS5@FX=Q`,/]V$98)C2J(TU=4N/)B[C>L4J-K1:4"=DLE7;8-KF'\8NJKU86
+MHBHA`!L?I\RRF=S-L#AL)B<=05M`>H=TO-W5H>JGI$LPP4L%7>B\.M[T9?`%
+MVB-@$19/U\DNQPM-IL;@SV!-7S.:X_N3EN&#5F85KSUFK0)UH^J,(W>VHSFA
+MCWJY:NRL7E>B[Y5-5"=7;)VDXXVM>"_6DD45<O+>:I=6H0+[>*?4TKU*_0/&
+M.CWS?>ND.TB)F1-?3$4!5R);*6%UL\COC"U/O8*$;.C71,ZSHA\3@V_`V+9=
+MDTHR+$`8.FU_;96`>X"0F&YB?GY;)C-N"D.@>Z.M9JIN$@LWMB%H2B2X,!3G
+MTY]#TO!:N[J+LMA$3]>8')9K\TEXABOMZD9,(H34RLE,X9$U36YQ5=72%<6N
+MVY;R2\O*5[B8(P`NI0KO!U96"A4\V=F;F,"-6[-TXPJA;!S%I52Y5E6YUFHN
+M`E**)KC6X>W!XB)XA[1:DI5+J^`;3<-67<L"UY2[5I=7%FM7PB<F]-2W]$[2
+M[R>5)JF7T\BSDS;TL2%I`#O7S#TKI95RA>K=4W#LP\^%Y.S[5+4-^L(_<92"
+MI9DY7WT?^B"[X0&)T`'YPC3-\*K+X4=EYU*;4I?=0LJ@@V[6E`T=_@P\.:A6
+M3?R-I::PH!8J=<F81JE;@`^Y#N6Y3.R>KRY(0Y*V/4A9.KG-$V'Y&\U0V3/#
+M-2Q#!AM+T5,MXF^#%R7Q1VAQ3+6FX>+YK)1I9Y4?'P'W4$]P[Z1J:_*V+V@,
+MR.U"228:J3V3%F[[`X;ACN9,6#BMT>#&Z4C8TU+!&5C:B]6GP^A0]4R8SU42
+M7X/RI7?1W_"#]M(Q7DP],E6SCCY&F$"=O-^"X$)J`]%M$C*\"]4M'*>+Y#=/
+M$R^%';7S4/2OXWQ33YQ'I)*#H`R\5Y(]FJRTS;<BVO-M@'8.P'9OL#D>F841
+MK!QR.']H$M&E.=-*63QGHVJO/?=#"3?BZ1$J;7F3\F5O8CY=&+>JDZ9A[;N@
+M[U'MT:JT6!T*,UU02`ZK>56<1!9JO8GL,MYR4KA/SH<U-ZYP!T[2;E#:W9G)
+MPGRM$"<48M<+>6MJ]T+BL!#^6DKJ:OS$"GR`A63;C?P=O`O'O(*T<#!=N@2)
+M(+7%:R]U:F!A=Z$&)K+"8:/1Y11.BAOM'&]9$.R/@-<FFBJM.8C7!M?F(Q`"
+MQ$5J=+L2'_,/=?JJ.$VKNVKBL@T5Y96\\9ML.Z1,'%>5T*N?SR?'XZD%GEZ%
+M4V413[=+9&YK:PJND?(4T74:UBCL5(_6`7EJ&,<^2JCYF*?,[%VI:TDF2^7B
+M07SAA,'YZ@MIVMF7P_\H+2?(-PYYD<G3'8QVT`>M(WKQ%J>(UR,6X7J$J<9/
+MTLP40,/.%2]9A5N9VT+F^:77[%,-V8]/C#HW3$)3A=!@-]$Y68B`=-'2+#M2
+M;9PA[%!E%J]^.4&W4!#U;Z@?!S/ZVF+I>]LXM`5)9-%IDJ<^EAJAR7,1$B+]
+M]]!3$9_\2X3LVF'J-NP[%-\+V8FFNM^DU`;I@M'C40\2O'$CECX!N';R=]5Z
+MV*1(K?\]7JLUZ40^W6XX$^QY_V%L]PHGYJG/3M(=40.]Z81-/'B((@N5^M.4
+M%G_)Y#2^J-)XRJ`;CU#$O`?QL"VV(J<G,(,>2?XP[&9%!$A(WHWKICJ$(Q.T
+M;E#RP_7X[`9LLP;,Y57MXS53(OQ@!A7_`9^,(YEB*"QT=:?59S>R^?G4N(@!
+MBW:C8TB]/\;NYV\8@[81&X@.(Q3QM??H-GPC/E1U/%Z?QKC@@'`]/M5OJ:NB
+M4@FL/?H[>_'_>$,$'OI_I$P-XU$?H4&K!,NN<1#F'Y6`'H(G3.HF%U,($E6=
+MOUJI7XSD4@=?UC8R?()TH0U9,8`Z6@Q_5S?\QT3PUYQR,WP83VL`0^,8R>W0
+M?L@7D]&)X<SQPFQ8?7/C=8Y)9VPO3N?X!*^Z&WH#ZOJP(0@#^WO54;@QB`]X
+MU37?:B@Z:E'&ZILYBG]($>\_`Q@5JL(XS1,AGJBNAFC8-$@'[Q!PP[:,)<G7
+M,+*A&9FYF"0>*IGCF^GB+_EF]N>_4<1BEG*,$9B+`<LN5*\<1VAK`Z@D+@'H
+M4GT1E;$2W\5[\+<Y>&V`^3*\V7>KB[_1=VM_?HPB=D"<N[FJGS1-;+9J2'G5
+MPV,C1?%Q6(S0Q-R<*"(A'V/S66.XBLIROGQY>9D^+D7OOZ9@RY[5>2[U?6JS
+MR?A0>2Q(/*OQW%GJAV.1YY[JF^>61^$ASU&F>6.1Y\Y&>.ZIWGB.Z^4NYC`#
+M<JYNR+TW1D<NPE!G(PPE=@IX0O^[,5&&0E_4[S$>138XJ8A_?I]:;LV8*#D/
+M$@MT;4`0[[+H!8;HQR&:Z5]@^]]*[4_)O.J8,1%.X:W`)3E>]6K"D-N(P*P;
+ML:U#&SAM;Q_FLZ3+V-X_0%@W(:R)BK@#4KF/0GNC\HT.&CTROG6#[C03MAAZ
+MJS>@XB$")WRUFV@H5;E_WH+;,N=YC,(5DHH4H[>.>;?=?]N">?,R%WNX2GV.
+MXKK=_QG%ENUB!C44CE_(_Q-Q27PP@'8[T5B'ZRSU:^(1#(S(-"9`!`L*U^.O
+M/F6MO@%G@EO/$KTR@#B%7M4]!L,R6-@$'/^.04//8]^=UT=(+XQJ>X$:SZM>
+MOAY9,"/"0]"N/V7MZBTUK43O,.%Z*QIS^F8T";O%+I-0$8VR8]3[T:@"BD(M
+M^WK<N*JO1:/2,:HE'J.0".I3T:B1T2@;1DF1*$?MG6&L;>'U$5]QG9'Y\?[[
+MH0^B2[7[JX1E5?PJ7N"+N9ZVM*ZYSJ+;!-:VB:EOHJS<*`-Z:RXL']/.TQY<
+MT[03ABCBX0^P5:Y!I='?<TR&X-@_1"KH4*P_`B!U6'UE1E8,J-P.U/9=G!"&
+M/;2[(+0Y!V@))'>6FE#2#Q.E^BI4+^B`1:H)]I]"R*O^](9HTS@5\0B66IJC
+M?L+NFWJZW)Y0S2%CV5K)UJR\L,?F53.OMS`7HZ33YO?B5KM#MRO2XV[_H&M1
+M;FUGK"@7)#+&ESU.;131R@E1.=CVOAE9G*.6ID9J'_*0B_I=@6X+PK?FYGN!
+M>([]Z/]'2?3)(F97$O/RU;>O)Z=`S,R/4VQ*1`O[#6V_9;PF9]OQB,\LKW7B
+M$8`G44HEH4V/!2>9G8*MA&:6!5*WDUF6X/*`3&R%H\#$WO#"A<0<(Q)/:DC\
+MF6$LUR&'R(E'&6@B@BQ2V.(6*Z+DU"T?&/B.KRP2*F+G@!=&,M_+G:,C_IA@
+M+=3*FM2AU1=':LWY4D_Y!P"0#Y(UC)FHUR3>@Z]TFM%]^9U?:E9W7DM^F.JK
+MH0CT_5Q[+1E8,NI\11.ON):<-)6:,>5=U[)UU8LIM*'K`_Z4:\E9TT$?P"^$
+M[]$$8@Q6\15X[>X?(%*-WUS#;%2(:-E;RAHCBTYZF<`<+@"-Q09.-XJO.9V)
+M72<57\-,<PA.\LDQ;+NI0;4ZCK0H8@A7G]:`VV.O<N(2`4>SMF>T-5.7F9^T
+M>2#:X4]L>T0/L_"WM;'[C##B]U,VF*1;'?M-;5M8_/9,4PHB<XL/A^-[61*S
+M=.MVD]@ZLK$U;OM"$^W'8]/=O#W3;/B\GF6S1++9(9OXR<S&3^+ZMVQ?:(;7
+M_BW!(9#*DBD-TMU.R!FI,;[3O1';Z[*0>/Z-+OYVJ-#:R;`?<Z$*LWVTP]ZZ
+MS8RO<:-GVGW;LDS;CK,7,T!.%(]:I&'!@33F\'':T2E2F'Q^7&CTP2C+SP#B
+MK!T%(!,9G)'VAFUF'8P),@X6CYH!3((!!@X2P>L1+O1?R&K>AK'.+$@VP%@6
+M#2JZO^Y\84UQ[M(5JSA];D1"&5I83&;V0CQ[\ARO90_*4QVC=,'RCCT6E!F=
+M)F75G?"^I;IED9WC'%L?HDL1+>J_K]%\PM"*]$$++GJGN2R<%\52+>BT)?,:
+M"^V781[QXXTA<E-3*UVTY+:@F\S<VBV-BP&D],@\.R)=JXA+_AX*OXK"&*E9
+M.DF*P_R`L%#;-HC=4X`L<F9JY+Y_JKPESXY7:=DW?<A;IAB#IE#0#&/0#`J:
+M90S"CV8/[CEACJG>B<7,>F6*'@VO<NTK>*U8#V%?&&B+"82O'*EZYQ8Z@ZG9
+M)V_!BDE;ID?P:FRU6NA3HBBY>K?[%7QQ/#26C#+42ELR(AA3XHS>$H=,6N+9
+MD;J@T#FWUD(A/=*?,$7J)^?NE*MKW8\@-HZ'/Z))>1N+J)7_0)A6;Y.MM^JU
+MLMXJS[HU8F(!7J5+IJ\@*&+`(PMU!=;*\VZUCD^0<@.94JX/"I`?(A1RMTFS
+M!L'<XM/T_2WP)6E1N]V/,.QP*297!Z1JG_]4S33,D[L#?1KM@&+L,H!+W+;U
+MJ\:WG%N_DA*WR1[?'"C"W[#YP^``0+49TB!DT;/-&?;LC*G>(V/0&$QLO9&P
+M-;=KO/0'(G;!3I1F68=%JCQ,GC4L6N5A5OBT13]M6$SU3O<K"&KS@6[P9\7`
+MG_U_`W\6P4<XU)X6XF^W9W>5'3O7K!$DIKP;2A5?PQA.2&@FTFJM*;XR10LE
+MCJ-03#M#3YMA3#M+3SM;#_74*D_SX1@%Z1C_+TDTO_3BWR<=NOWY8_T<NQK0
+M$9,^T)Z?%;BYGZX)VXO?BPO#>X5GSU<_N]K"-:HV&%6-OH+$5I,^9UV`!2->
+M8]_)@,?:K/Q%GW!_1'`'!QU&N%-/JCKD6/P*^X0SE^#TCX5S<U]P'+W"$9)D
+M$7U`B`U3(+.I435#[F"_`-I/Z+DO_>.POG`YDHRX#$#_7C%^E2P19(QPQ#[A
+MK"4X]AYPK+W"^4&?<"82G"&Q<*:RZO6$\_45?<'YYPB$,[`'/OUZA?.[/N$\
+M07`&]8`3URN<Y7W"\1(<1P\X\;W"&=$K'"'1V.;4X-:8]D9W1JV;N\%Z)[%7
+MG&SYZB=7T;Y&7]C4!FB2TOI()/\C?>;_68_\-BY6!X?I<QCDOXFT?O"JS4".
+MTA;'RW%Y?[..QG/E=ML'R:/5E3`2?'!O5VFKX^5L<VQ4+D5UE'9`E#4V:C)&
+M>;K.>CH^;*2#@5A]**._T:-#<:U^&A<,U5V.EZ?AON%EV#QU2B<=+[PMBRT0
+MXWB9,S662+FAQC8G[#L=+V\V2]4=$IZDPD[1\7*^&54OJSL=+UPR=9D:\?S6
+MN:48_=5S_3V4"8%F61TO=,C5JN.%Z@[39<J(09Y.4U,)7FFHMI5(PV5(KSI+
+MI!QSB>GM$FF=M9N;46,[Q`]E+@WUD]J=5_54>!*J*B?C3QJW:DU).;=NU9KE
+M*[F*RO(2;BV_M*QR-;>^I&HCMWYYA<"M*N=XOER`GU5KN.4KRXJXY>5K>(ZO
+MXBNX*KZ\@A,J5W!\,>2AC&BT@ZO:@(<K*]9RRX0J[H%5965<"806K^:YI<LJ
+M(6_ET@H.0Q\45O&``<^MA,W6HE4KUBPM<Z5R!57%E:ZBXI)5:XJ+7%4L='*O
+MH6G<'$"_<C6SVEU9_*!07,5SA:O6%)6O@S0;BUW+5RY=LZ*XBLN#NJTJ6[5F
+MA0O-0E2ZBM=7K*HL+N*\JRIY`2#%AF:O*BNF[&6K5J_B(7AY<7$1A-]6(6#"
+M[L%S)BUP59175:U"=_"+@"85@.(8GM^`YL`AR]C8P%5K*.RVE:O*B@#(*G0=
+M?QO0=-4:`=X6"545Q6N*C&^N,:R^8[F"RA7H`A0+A%;0'-HO!N*O6D,>Z#/+
+MEE:N=BTO*U_^`)=56?Y`\1JRHL)E+2W2'(:ZEB\%PB\J7K$:`#&ZE2P5RG@N
+M2ZAR%5=6EE=RMT/3(!'*RB$>*%91#DU$M:V@\CRYBUW4A)G+RBMY]KJX<NGR
+MXDE9>5K,'("P`LBZ:@WLI(7EE&TA-O8<-+R#9^S<;&@80;N0QDW2]Q&[8_<1
+M/W"22(/$-[<U^S>%F1(2[KV-KC_;GL<]19=)&*J'HMGYMMVTN$>E8#^N-X+K
+M`PQ$",)7XH\:&*(97<?M_-RV%72O.7>'G+NCR31)IEQCC^?1=;=[A^+!3AF$
+MJ-<-(07!MG2"'U-DG+Z?L&UIQ!(D!6'(]#L'?7/36U-FF&OVKX]!I1^BXD?X
+MVL;GH!GOF&YI1+&CI%2@[,>SK8F;V)1AXG!CI8A[_X52+/OPR%5`,ON6NT>"
+ME5WN4[A>UE##?\T>--V$^G["'J]6$5-B)&LN985,.PG`;G=N+1HBW>G.]3EJ
+MVU`7R+.MG\6$UAP1E77NDT^O)RT@]DO@GDV,5H%TB-`0."`M-5H43,9J`>OP
+M)M/$3/R3\%6GZN)AQFW?8<CJ#:>J[T91?)8V)Y!C$F9,.X\K_=P]P@UTOO2X
+M:A\6,53OJ%U!:7>Z'<(Y3<V1TJA7&-+<AF*ES;:)PA6^S?TY_B,YQY8"4Q9W
+M"S<1]M(PA>7$HUKO-B7'EJ?>-]A"5->0;1YB8;ZE^62TUZQ[LS42//@P\@&A
+M6$N$?,I!38YPY8(=XPML8G6`XVT9[J.;$H(;`F*#V7VT^D'Q,'&YH_:I;Y%6
+M.\;GVB1E)=)M'[+.>&''R:<W$<WI%P;XFX9J3$PT1Z/>2'#,`@R'KYN(]IC;
+M._9+Z6UO6-BA/@P]2Q)VH(X#8"'TCW`]HC?6LP,JOH,J7NQ$8=+CZL]Q2J;V
+M$H\Y@9FPBFU[$4?-YCTGV*54($8<,\JNU0.WV3:U8Y!VD9*(]\D@TL=Y^IZP
+M00_,T.L]=MWA]"3QX&Z4I*.C5'Q1?S,(#TDH#`DM[M3>8,-R3P#OW'8[Q94H
+M14:>^NM!*('?K4O@^:N;Q<>UO%X-]M<.VO@8_3KBED7SS6G402_T,OO&,(&C
+M[A['7[?=G#4C7>B4+@;C\=N6F;7=--W,?^US<\*'OO0,\LTW(2!>3A<<F*"?
+M+SU=>$-J"28%'$?,[@[AE2Q(I>]B+IRY%A6IC+8W(\09,X#,CN$$CUXR[;IA
+MO,&T^^G"@W7TSLCK]GRVM!?%VG+]-`&IZQ2KDUTU`PY\BSHT9K2E0PX`_2B=
+MU8CNJ$4I&NP@&'VD7<]<@L;;8J.S))F^Z!XUD;@?#E-YZLR!.`2$+D=&L2R2
+M_F/^//5'V'C^<YH)56D?&AN5*;&%8"AYIGXF'.W(C"R:86VU:&=56N&M=@-X
+M'05'[0=Q4/?#&+REF5(?;B<+M&=CBD*#@K5H#%11T/*JI!PG.[11HZYB=2*W
+MR56JD3=1O334B"^P?=NM.*P<1F#A:8H8ZL33;(Q4]N%:UZMA.<1AB;BD]ZJU
+M@Q'G#JK1Z"C.>.X0WH<XJZ<&8!=+4JAB,,)@6G5#'!+B#&5SHMQL-`2D-LB[
+M,%'4/:%T7&JZ\*XR'ZJ#]EJ]ZN$!6-R>2W0-FP"JEZCWV1E@^3#]YEAUN[D[
+M/NV'E<+<:*W/+1_>0Z\V>*7RV_Y.1E^P-C(9B`VG:14]B:WM223C<*Q>U5?H
+MPX'947L1S4,\BID9%>F(GZS>2H<?I]\36!+5".T!GR`3M!A36<.4!/9A$T%3
+M:.5)"9I?>ZVX\YMO%0]3^_##HZGD!.9X6TOCV#&H'TY_B4@PUMAD81/O3%BH
+M`&D?X7'X>`0SF;!P'#%E2O0F=B4((]V$J$/\!63T;0S?X_"CZ&ENVVUATO'=
+M9LYR[T*^<SR4A@,UI9:)E<=3RRI[R0,L:Q4-UW6&_A+M4V.,XX]60T>MA1FI
+M47_7W\*UG6=K&P9K7SM92<;WMGU(S"8SER4>)KX65K,N1JK)`7H9Y:A]B-1R
+MD_(T-)ZSQG1JAW\%8E3MXO@4AFY8<&E)B^W=DLZXK'<UNJ!WF#J=,)89%K:R
+MWB*B9^XZV/KHT0E,>4]"X2T5T.QOT?I9Z2V*:/Z&SG2U]KQ$JMC4$^S1#K03
+M5RS[,!C/A@8'ML=ESTAG_0J/?SI8&XJ-WTK*(81P8>P[TN$&:NX#\`O,[$G.
+M0,5TQF)A&B,4,HV<IY"]9)TZ^PD!ZA5DJUI2CA&_=$;X13R6K"/&/R!VA:NG
+MZGPY`%OL8KPV_5%W_WL\*I`CN#8)ZM"4'>;:%C`>$JGOF80$1@Y&T#T,04B7
+M/C\:WG8:V6O?,:W^`UG]86*!NG=*'>/]&#.6R"91*@NC54TXG>_?%)<>]D<9
+M?;Q"=%&HBL2Q8UO<C8X=J-K/^%C:]=*E;MS\D@G963Z,Q!U/@Z]T>"^!/$`@
+M*41Y+CH0J=L3#,P.;'YC+VS."'8\3B,8DKMML:D[K\N$#N-XF4JU:!@<(@RP
+M5(N&`6(C[SL4H8#4,MZ/87F`%CZU1JZ.Q_4],0,E#A/1U!)L+$IAV44-02AI
+M>:X$-.='VKXMZUMLQ%Y&I(O]#",2EH^8S88UA!3/AHRUD_70/(U6]_77:85V
+M@F/6(]@=@_D!UJWINIEXF#J/,!T6&>X>PSP;Q8,NTM?#.@3CM$+N!+Q(#UQ3
+MS@M<BOI7CCUK?]',7!S0360\9G?V.&8/X=6ZCCQ4&_/*V?9P"]F[$2^&^?[B
+M11-O1YDMPWTZ\U$<3`W(G@[?=#-L-#P=&1+=#0[NDPLZLM!_B9,B3>23^"A>
+MX/>T1UQJ1-9@N;:`=)ET@H2A/O<F/L'GQCX`JZY!N.#:/BQ[NRES>@O_X9P`
+M!&),NC;VX)6(`$3.V"3\(WB0[DAV];(6?<6D*V?3&:^W4%W"1;6'8N1?)E3#
+MV4/+U2O"]?BBKN^'R]4]D>7J,Y&WQR-O3T66L"2ET7W0;&FWV6+6;9,(/D$0
+M^N-,+>.[5B*JFAR\3`YA,!0V3A]8<<&[9R.G7^@X98JL[/B1XD%"0!C&,*'#
+M/8IKFX:=#98B%Y`762TF)T2T=H15>A67:)&[K*1BR1;6YS/L&0[_2BR)\+#*
+M=81D.FP.U'>@\=,:VD[071]"-CQ9G=H-33_JA;1=C^LLPJ%I5GP8Q@9\-0G.
+M*+7:<(Z%M?/P7LX)AK#1`\6Q@P.]R&.!56:F\X-0P:F_>)`@\E>SXGR;XB_?
+M(^QFY=`P^R;.I\9(1S22SF.C.,$JL`OZ]R5<X`^#?4$Z/\*7?@\_('KC)ICV
+MIO]-?F!3'!<L@C$X._A-H!NMFVQ16J?IM!ZC18ZU=*,U_R-U`PPZC*'7!@(&
+MFK7A?H\I%2F[$"_?8?SE^"2Z;[2)=R*"1MP`*[HHRU26V>;"WT6XH0WRKZ%J
+M34JV!<8[L<NTKI\:1M#9)N7I]@LQ]WF,X\;&RV:8T#5)Y-&O$`1J:9P7!K(%
+M0!6SZU9:I/8SD?(X$\4,[S'@M:$ECT"S)X2VK>2"+M^M,->C)5Y26@F1ALA]
+MPJ1L"O]<5V8Y1R\SA0%-YLU9V6V/(6]O'^3[>.2VA+8=%`>KN,WPPO+MT_,]
+M!R_;XZPM,^+736_V=##Y2:>%!`F.(W%R=8<RJZM%\G1DAW,[>1M+NO8?VST=
+MV\QM4]@=!TB7+38<@41BUV3'0X-1%M*()DGEI\S?HDG2D)E;`G]WP-]*^%NO
+MO??UY^OV7:$]M_V'?'W]_6^6WV2VD1Y%D[D_C.[X3(#1'9_VX!AZ#J3YI\D\
+M(IA$S_2@$\??[/`V<S`.UB[;S-E9X=R0PS\*6GM\09>2501LUR45M*N+S!IG
+MV.2"=AS)@M_BZ2MQ@NEHVU?PA>M=F$$]74H%+%M#)AZMU7>I5[*<F.=EDJ9T
+MP<0E.;KI4,7X__NW@5^'=*#,C:D5Z7=Q=A,/`+\6`&?C#&?UO]G;_%P5.(+X
+M26\%W2A/J`[Y9G+\U.WQV\PY4G4H:[YPW=BWL(X+\7K#@\C[C53!3A@?#E-6
+MTUN4*UTXRFHW]KBR/BQ5=XF73?S`O(7J#,H$R1^F2I%GO;[]_UV">HW2ZI7^
+M+S1&!WAK==I&=?*Y4X51F3[W>IPE[Q#LF<V>+O1]&+P"QCA/%RI/!!,"])Y`
+M_8$T[W`.!>;OO\X&NR4EKR5X#7S_8D8_[?NWP4'P_1I\)]/WF^Z"KIK!LB?D
+M>,'394*/@IG!(T`?(825F!:]I=73QM(DJ`),PU('=%7>1OJEZ<*E[5[3MH)0
+M4[:)HU%J.+3*]H+0-J_):$XIYGSDTXMX:1^58?M+XG,;F3\IPT4=J0X#>YZU
+MO<#R2>+>C;V>,S\"\89[YNC8-8`7P#CX/X7=(S$TR%*$!@L837`H'GR.YF.\
+M0KF`R8"9?AC>:]@6]RW.#YA"?1<8E%1U^=%AP5FHA0:@VHJH&-(]3^D2O>KO
+MPV:\DA(PQ/V(XISBP;TTNPQ"4T14*^8"$9`_`"EB])^[8NJ&'I@"FHZ;4?^]
+MRZRME8S5\5W^CNK$:]4YSP]!.X9::..W%*J(1?'1I&<OF>FBGX:UO="`<Z$:
+M!X`"`2/.X0N(,W-Q@:W;NW_(OUY@./?2#LW??@?B\R\9VL&NMX/MV^[M</TE
+MK1U2+O=HAP2(B]$1BYY_]HV[0?\541=L1I03OPOEQRX::&W7:5T0ZH76%<C+
+M!I,$W>Q_G*>"PVN3O.H7'"Q);FV.(^%*-MELPUN986`%KWJ1?E_GT)/F-UV&
+MRK9=N&1FMO11);\W_[]Z_)'>XU_6XUV]QL?0Z?PW9J9N:)>SD]#5378R>KC)
+M=J%CFX7)LFBG]:&4Y9(SDYLSQF`V>:%=O&1>&\_4XP8JXKQK8/&_4+8&POH5
+M5]V&AU;>EO;IEICU^N9OJ(=+ASM#Y`TKQ,0;S?YSD;?6R-M9[0WGBEV8`55U
+M=YV&E[`?/_VG'+55L`&1%0RK[K_=?YH2'8^N;K=IJUM^+LXW-O1/LWEPH5H0
+M-NNWIB8[2`M8-COVVWK)MS5,J$'>\`)K.#[X*NYEL9@4AW^$&;'LT+!,>[-7
+M),5+ZQT/M5F8X?6Z'0-HE1,X\@\SM[OC_[_^`E_U#,OK)0S_4K_Z?G_?M^P)
+M\+?^2_;76WR&`9;:1QKCWU.&-(O_0_HDB!\+3^'+Z-]T*,]I*'.V]GX&_OX!
+M\58#S"+MO<$0]LLOS9R!W_X1BO#;\_8(OW%NQK`4%IYK#9L9L[4-(IF)[TU;
+MVV_AS?>FJ>V7]#2W_92>UK9'OR5I!FXVK*_)Q&[*K*P6B;BQK>I;)L/'8')<
+M6)>$"^U=9ZG3Z1VLC:G<0SDF0]*#R9CT<#2IC886U&DTP$N.P&O[$4(!&+X_
+M?2<87#6U56AI64(<&)EI"0U7'%?:YI'=LWW8=V#7%4:)HW(&/M3'!Z#P'\-E
+M"O"]Z6+92")XS*;;I(B$4R6_I0%DRYO./FM@P`\U6`+G&VT.O_SO</A\HY6_
+M2O0XK6C7*2=4(N_"UBF1G&VKT8)%-(9%0'@!ALLT/DB'C^,0%:X>S(8E9I/2
+MCX$7Z)<VYJ/"^XZ3VQNJX9KS9K9'=Z!B$X4%KXSLU>5=F#2J^83F!;JU75(W
+MHN-RA(PL`!M>G:^5<@?-OE8&'UER!"0[W^@22FB,E./Q2@.AV%O)-"K.,(Z*
+MR.0U<3`V'L7S9)M6RE<7NY6RKS],&K\(Z..GU?'0#22T)&+AV/B,DXV-L_YE
+MYG9^`7NKS^&OW<RUJ@")>!U5)HG#L<6AF?BR9O^)R"2!N"^PNA5,L':<2<&8
+ML?1E<A2JRRYJ79!_3SQ,F1RUUR%*B?(N2K/K!*O1V$*K:;A,7R9JU[;-%TD.
+MC;;X]F'24I/6].%U(?6M#C-SI.6H_;,-+?O3YKT;OO@/\5V2]F9P1J8^F80)
+M.?X6&B52"C7"O=(50SC>C@:&U]L0TT!`'SE\A\8@_W#"BQB[A@I&[M=Y<G-(
+M.MQ.7(CD#<YC1<KQVZ$M,7R;.1R?)=&KAL4/"(M1A:J[2R?4,,;);H+DJ.V,
+M[P.'7\D*IAA/T["CMA7MCE*>IG@N3'-\\(%`GS2Y)^W-",S4Z`R\5Y=+I6:B
+M?W4:'1FF(XF=_Z2SLW0AEEXOF11JM3<O&/IH+#TBY?4RXPM3_S.MAA*M#A:J
+M`R_HM'H^4F.I:SP;E:B+L/JWS;B@9]Y"5$`.7JL3`FW%T]N6-]&DO[(KA)A2
+M@1K-'+5W,9E0M']2MSDJ'OV+1)U3O)3K>.AFL[;,Z!S*NE)@R6<P7[69.?V)
+M?Z?A?>]W_`6T/SU];W]EG_7^]UUYON_?XN\!Y_]U^>)AFB6%@=$Y$.:W\V^8
+M^9%;/IX)Q`U6!Q3QGFN0TS&!XS7K>HF20C3L[8+W!?3X75I\'HL7NVR.AW?@
+M`OHOU"=HF*ZI"3;#O)/!K_5]_!H:@3S_AHDO5?S?8O?S(R,(]T2G*=\_+K,Y
+MA?'<MO@<QMRLGV#OJ(D/F\F.8G0\7M89TTU@STKLZ/#C$J/VS>H;%7\H4IIC
+MZPAV'9V5X-B?$\Y37;"F:;-8M?4X"\\/L[4NK'+Y?N*E.X1181H+:*P\'9W9
+MSM$H:6.E0Z\7*J(CQ#ZL%XI8L7QMLI=I9F9&3^UZ+J=P)4[)#NK4!4XY*U0B
+MI09=YQM-6AA-QB1_CB:14ED7E*EB8U7Y,'9+Y5"\%=?D]-'VQ-<X)GRO_FGI
+MHW\^:_I/_3/=\9#?I/7/G<.U_KG^4S/WS3]AW0O/,NW=]^GW^\.TW_?OGO\R
+M_?_V'Y;O^WAF<!KZQ`,^KT$^'\?XO'++QZ]=9J:\`M+Q%!\,8K>@MI1PIW3<
+M=RXD-?K>;/CO^;WRRS[X_<[+R.\.Y45<0T"'GA7+^->12!KYEQA9[P#Q^BKT
+MJB\,G.Q^9]U?VE`2KB76>L40O5,4\Y/%2Q[^1@"G3U?OPZJF]]0ZT.Y]YYG/
+MN_6=>9&^TZW7J$HP)JG)V%<^2(*>$>TF?TWJUB]HK:/L-%._8`N?K1TT5U(Z
+M(*&3':GT#^AARM.'0CWM=Z#=V?VIDA#*$"_?)PQN]J#&(^?8/UVJ#F4$;0'=
+M?%6!;<M17+IMS^W:EC#776"K^8:\EUIF!RO0N2TW'@T8=04@'D]9JT/;[-,<
+M^YT9XJ4;^:&;^_M/\>\&9V)?OW0O/S-X<P#B\+6?NR!4,Z#9$[H1!UE8DZ(,
+M/NP)&<&XW]OT>;`>^:T@1&M2W;Z7\5\/>XI'SY',1,G,<&>F"C.8#E9NIWH_
+M,#?:GNH$E"JEA:G-F5,P:LO1;X&4K^&F)K!]EB-CFW7X@@WGI<%I#<&%\H8I
+MRI1JA`MT\H8?3$4XFS\S,^M)#-0-RI3AA?E>J:`+(^=^AH5W2FEH0WEAJBR$
+MI`>G`*BX@*:+=RY&%R^"],!S$?DCK%R*9'$3QQ03^ZD?P61W/MMN%2;!KY.?
+M#;\V?J17?:U-6]4(-_M*[!>:LVTDC\E.PH=OOMTJ7<+#Q2ZQ)I7CQ\K95G?V
+ME,V#O>H?Z6">CV=L<G=XD!P'*9WA;&MP'N[+2NP?D2W087*<.]M9Y7#LSPB[
+MNX3X\"!,@H"D[!F0)WNZXLV0O*G-V5-P6P,PO%F*-TL:UIR-5ZRY&.NWW=K+
+M>&XQY.]FO/(-_.YXH1H-.2#I*_".^=@N-`9L#R['P:,ZOCE+\ZO01;;F0\'Q
+MWO#D,%"XH%,]I9HU*TNFR28A-/9"OCK\<S:T%'0"B?X@5UK=%]:]71C)L4?%
+M8CO';K2:TF6/,W(`$=LNPB<D+Y2K[>Z:V95H.PC/@@K#:V>IZP``T'&`E#U+
+MJIEM;..^;?Y>_PGQ)CHZWCQ\(3+,@^T,2^`EV'VAGZ'P@];2A'`:1MX#D63>
+M`J/#?'*.;)(NH^LNNS2Y9,L<.^<:^Z!5<I/+(?E!:^1<0\G.RR/HDYA"LP8=
+MK2C(GI`E<Y;TU?B"4'XX+0\3_?A3HIV$)M`[%ZH?!:,8"?<9L'D[:,1&B+,\
+M:`WN"N1(E\8/!NXWO>NE(@]=CA8IC&/%A84NK:QQGU+_@-XQ=B%@3C61,V<%
+M[;#6M[-;_S'>*KK)0__9RN2A;#^0NJ4)K^C)7JMX,6*\=QS-3Y8LVW@VUZ0U
+MN.-JA@8"[H3-`]USK=5_SQ"/.MUQF_^%#HMZL5Q+_CS+BHK75VC./&_J[BYT
+M6GKJY%AWH8#CWSQ.-.+Z[0=_[<GO4?L_@+YV#K$%V4^[AR2V%QEXQ-Q*0P'J
+MNA>JGU';D';!QQR:ZO(\4Y+"=93<PF7PD7L$B2@4.0H_I=9"M0M&$M)%MXE=
+ML,W['5(T[$4UZ.Q_:K"$'QKA"$O1]!XFN)<2V"$??V=ILCKQ$[.N<<[/6<G!
+MFE8=@4$Y]N8<)W[B]:3-=HZ?(!<\+@UOSJ'NV9R#Z'"%ZD]PO,U)DKJ"$XR(
+MZL<5A>J//S:3>C8^6:B4BHT?B!DTEBTM<BT5^)7WEQ6O<:U8540V"OE*?&`P
+M/#6[A*D&&A[Y$`^\4,=&GI,DY;:B8^J"5O%HDK00!H36+4=)!+,P49[MDG+/
+MEIH6ABN2E6JU4'T6<?&TAX6SA1$'Z$EXG?\;1-KH>KZ@53+'N)KWG+D%Y\G-
+M)6'AC)S;"AW'J_X=P16TREG0G<XTP;"(KLLM&_KA(VYT"/*8FKI#S;+%@,V*
+M]6^/_4\,.VOL9"BS[4DF4X$:;G`V>_#2%^>N/EU]'>Z=S\GYB3'`<T]+UNV9
+M4NYI]\5-4-099=:KB6[/V:K94-W\0D5T7OLM;"`^@C8^PH1USF`V^I4H5/_X
+ML<XZR<T>%;LI!;_T<22I#1>&Y$0^N3G#12N'R(E$VGFYNEW<G(RN_SPJNC4$
+MPG8HQ<<,XR2=5FAG28:&_.:L/B]"9RANU;#@[V.JR]E6M-_#AB\(G:UDVR!@
+MJMYG^&E*MAT"4B(!UX?KT>9^J;74J60[\Y3L1(B^_$\:R!.8P3-VOS3F;"OV
+M?MTRAI*V/@IL=^0X]G_9BT3DG[Z+-PK]M755L)_OXGC!`HG1!1(?![].(=EW
+M,548[IN)Q]8S[Q`&;E]@$IO-S1XG;A\QG3`4/E`ZB`GCX1VG>!KF-"OY,)-U
+MI)UO]J!3-Z[M&.(C>51_0[5-<ZZC7O"HW>[2R@6JX3JMF<S?QOD:6X+YL#8[
+MB??^='DB)<1+Q?QZQ_XWI5S5_V9UPK;C.NANZ9BXDX]7,M]$(BJ9O]W6Z-C?
+MZ/8X:]QH:'.3W2V$*N.%06Y/1S70I9.&:^#:3EIXOB`X(;6IB>C9^(S/43L9
+M)R_(6)U(EF"-EY5@=2M6=W&\^<*'9(=C,%X+10/W%B4G3`99D+_.]F8_,9:_
+M=KU/\WMIHIKQ`8YV,-1-E<67\'"6?J4<J^Q-E`IM,,E(A79IG1-&A'^.5.0#
+M>)*>^`=IN#3C#^3SL->YWZC',.Y]QLH>N]0H?CQ2J4,02N)VM(([V7^>KX`Y
+M*MO*]\=Y>*K_O/`5A-TC>^WN0BLL0+PV=V$B/[,49CL;.D@=N3`_/$T=BLM&
+M""A,U$9?/!NOL7,UPP*%ZOZ/=;&732ZTNKWVS4%Y&!H:A47@56?-7(R^@@'1
+M+7\UPY2AB(3?E`/R,%CE7@M=VSW7*0R6S5)<OOJWOT&YP]#?VM^E=^4AP0\"
+M@1PQ/++FK9Y+OEC8*7\E>N-^H,:*!LF@!X;7.L-K[>AG`5:"4K:-Y+0UTVG%
+M:ML\0#N:#;X-XXO7;O%:T9/4526X)N2'.EZ>:X6$L^4:Y]AFJ<O=6(-K-)0M
+MF.9;Q72.WXUV?8TXM4W[0#M_Q>[2\_QU?5'E_4LK*Y=N2,<KD*[R$LW\;:]V
+M<;QGL#I.-(Z2KO5TLNKS@T_T$:=,GBJA'XS$*K2%)*:;A;M@4P#<CC8,[R4!
+M)YJ%Z8\F8A)P`4Z;*S86D748K_KK]Y$SD:O3:3(6DA71=\.WJ#")XT$_U/S(
+M4]=#*JAZ/HR3-[]/I:>=APZW=A32&OO*5:7A0I05%22CYX,N2W42C)K9D&1=
+MJX;94"@C/%F]C&VDK\9(-Z=W/KGS/3HEQF*<:Z_5H2>A;R+4.HH#;)R!@*4Z
+M$0IQKOM(,Y/8"W^([<G&]0^!M94T>SXCQQ#8KUXMA[BM7Y5(A>:5>!>0?I2"
+M]GRY+G`-Q\%C!SY*S2OW;#7!VN./,%/@U.W"J1NMD*+2:6Z'G.N$1:B<FP@;
+M5MV,]7RK7+?[&K*OB2#RE(+/\L/UHPE^![RAW*#4XI4'8[U<.(?(=:DX$)D'
+MZ=GQ4SQJS??*"VWDF0GUCDK$ZL\XP:XG1@U<&$.\<KX3DUC#0KOZ<^">DN8<
+M,][']GRF%)_YS^/5/_YBF`\+_JISV40V%<Z*!%S-IL*;(@%V-A5>!P%&/^<<
+MMV95%;>AN*RL?%W%4KQNO*&"*RI?O735&JYH316W;-6:(FXEOQ2O!Z\LK^+9
+M&UD<Q,\JCOWVP/,6P%,\N`<HRO&3TLYC?SOX^#7HCW0:]H\_ZG@!Q\R:9@T.
+M`AYMLHF;IL&8\&X4N\IH21.7EZ\IX1)<_2>D_X#I+#AC;=K]\30;M>SCOT4;
+M@H/PH=8!A24RELI*NZI9G/Y#CB[Y-8LS?JB-"%>2WK!"UF@5M.6F*&2F5NF(
+MV$K5[O1@I#KUC+;@<-3B=4DQ;'8\@KH>OL,(813_)YF`2`0DH(A7(RK,6JV:
+M_H$Y8FSP:;S\T(I6!QU'AO6B"QSWOG;.:$/Z=+/SP0_WJA+>9:C#"DG65]E(
+M;\J)+>^ML^:HU4K4.\8RS^('6G$&U&O$MJOH`H="E&FV'D"2L$JK/'3%9K'S
+M&LTOXM/G8NW`&JB?^V>@_OFTL'@04Z/8X@Y$CF#*B0?$2Y9U.21352=H,E4;
+MY.@Z9>:L\&P_16/7!/(-!!0*#B,9H7H,WQ/8^UZ-<M8<H-BO<7J/Z+$;\'CC
+M5'<\6K[MAD<^X5%QHX:'#W*4P=\F^+N'X3%-VZ/=C,4S>25]7XW?@Z+?_?3&
+M1)0>BZ(4NV>=?,K,#$*\?195BAK.1O63C'O#`9!,?0PBU8?/F@U6#]!R9@^[
+MF1^>))B*&+H&->-#5->!>>I-9W29T$W,_NULJ'=O!H*Q!O6837T&>RI91NZ?
+MUD!24K)YJ]3?\T.Z7XH0U!&02'MMA?:2Z+4TP:O^[%U&@B0T(88^&43G1-+%
+MHK2=IS$6;5G*A(DDSOLAVRR8C38VO6H0UA.2>`<RH+A8ZZ"*>,]FS)*'&9LU
+MP%YUSVE6HCV8UM.>ZKG-,?94M2RK3YO[LJ>*^.B6-=<4\^O**Q^(V-".W;L_
+MT(+Z<1LG?<MTRE?A!19LI!2!2Q$FZK_&%WR?F,H9P"XM*HK>D<`MJ*%)!P!\
+M6,O"*@":X79V3O$J;95S;:AX/Q=6Q=*L71V-;3;A:^!CQT-[..V<8D:JQLN+
+MWS%SZ^%O-_R]]`[NKD.*N!=15OP==)_RZ)]I[`JNB-@UKC=&/TG1SN!LW>YQ
+M6.A4Q%>,27R4)#&8$C"D"0L=BGC4F.Q.2I:D[,+/GOY-5!P=9B5\*_E5N@M&
+MW^+;`$'RM^,QPXTRQ33%>HKM*ZM\&#.]@G)(9B&M41%/(CKY:@-)P,]>UD<N
+M;4[16R6FC1]Z&V<M=3/';.4N2:.I9!D^U-FGD$4Q#FWEXE.]%WMV@:U_W8[:
+M&#W'"+QI47AXKX8RN4[AF$IA-`MA7EJ(&"SE]NCO7_PIBIBK&V(OG-01B]C)
+MQ0_-3F[[9EP<BB?-,79R_\$9[>1^BW`*U>R3YFYV<CM$!,%-IN@;#-&]V<FE
+M9%Z5TXHRV,D=B+.P&!*QNEVBWKNY6NS=G6*,Q=S@K=BG;S':S-U6&V,SEQ6#
+M-G-_W&(VVLRU8<^&?=,1W6HN8:_U[>[SU<]/X("&M%<WOT=CIHKW2FD#>#,>
+M[4RC^C**CI;76='!\%F,F*H.BD0,$)LP0O@TV!@0#U)+PHQS/0","K^[[7].
+MT)I9*]K*B@ZH`[#L)JC$0'>-3>A`ORI>NZ!&89["<;:C-X$ZC25X4FTHY;4_
+MPEB%4J]M2D&#5%#;Y/'A,&+!1?#C`+Q$SHK3+59[=L.7=6NKX^4N19[@Q[.2
+M@/2NV(2L,OY\EMGJJ,TDA^1H-H$9:&V;03X['_>J#P!:"A^'OCRDK@7^ALUM
+M2MT>;->"'<WB'HVSI;J=M1%;>VVOP(];>-RQ%5]6FN@`&YV\/HZCZM!WS<PV
+MA6,'[LQ,34V>/1B/YBO403"B.?;'-;;:'/N])JFY_WMBD]FQ?UCC)Q"0;>I_
+M%)>0QVSH)*90#-N%_.[0]_TE`GVC":'+!0$Y=P<Y-I1R=Z#7\X!QGD1_NX%F
+M<7<M8]FP9V<X=[=#NI7D$CLY1^T8O.L%526&(\'.6/@U.?R7.=I0U))RKABH
+MI6MS&CG:/N:8[146K>3ND61,T>1IT"RK8*J`U)QVWC=](H_W%G*R?3,G"A?%
+MRR9A@&]ZJA#GJ_9Q_'IH5I-$IC7$PY2/[Z\`87;Q9&,#?YGU&#TV?C;[9G%A
+M89NZ_$],XLL2"/&R9YNI(Q@O`^/,&F1J(@N47DQ8^39*E6LE81M06,DQA0E1
+MEL_B>'@!P:M51^%,2S55J-8B5=**^T"=@9!6:$$#C7P0,Z=.Q/]@NERUYD:<
+M("<NK:Q8RFEA/8,CLVM,N&'.C8VH+*ZZ_T&AN'*#JV3IJK+BHH1(GW'&VI:0
+MCS-=4)R"T3;].&A;FG^E+A@3!@5@_CTNS8/Y5^TQ_QZ:ILV_IX$3NN`O"6!-
+M.:[-OU].9=,BWMM5LTY$Y]\NBHZ?9H@>=<(P_W;J2:XQ)N%.&.??#D.RJ<9D
+M?_TCS;^:2PG<"WA+[:4F/?I7I[2N4#U*%I&-SV?8S(Y:]-.BB`L0D/H>%-3V
+M-=DW*#7!P%Y'OL;X*Z1+M:<$>\!_BH]O_,Q6>XK_1LJSP][@4LS>8$L[%TO?
+M\<U(#YNRCT-<U$S`CR%'NZ9"1,ZK6@BM9$`K.8H6[%TUE&:=H/5Y_U(.YB/+
+MO\GTMN'>;W3\:S(S5UP#&90MLVUH)+J'W;>?-.')`Z588KN`UXHWGC1WLSC6
+M0SZQ##(IU1U2M8J2UW92WJRV^6:F"@/@$R4R.1+LT#%H/=_?-_,.AY^9%&V/
+M**\ZCIS\+VP=`M&'R`7MCA?>=1QI5'AG2]L.&F[:G0[_CWJ'-J2'%3TFYRU!
+M"+,3&O]IE8YVWW%>E2_EGE,?_:.VZ;2C<FON.11E]&+O$&7&"I_VBZ`5?E\+
+M>["^VQVU;SK\Z!J!*C]12'*O5JN*Y6J5EN-`,$C7UGQ9B^?X*;W<@;7GJX,`
+MA;[L$?+#")S4-585&Q*EQL:+9O&B=:UV+SH9Z74^[93[[2I'XS]A5H#U<O^F
+M+/=;E5_BY-FK?.7_D?SC&"[8G",Y@_S#/C(J_SC^OR__>%V3?\Q@\H\9)/]H
+MCI5_7-\LIDIL-]\L3I%T2<AT29N:1K!]Q_>7A8QK_B]E(3.BLHF))[Z_+.32
+M\?\@"ZDF60A6+E868BCOR!^_ORP$`<7*0E8VX;J]:.1_EH5D'M5E$)@:5V_S
+M:'>#,&-D(9VW:/-&J-',M<-?%_RU-D9E(??\*2H+F?VGJ"QDRI^^CRSDE<;N
+M>!S[MAL>!83'IELU/'C(L03^*N`OC^&1'K7&N/\$BD.BWT_@]Z#H]U:M/>V(
+MU6[C:C5&'G)=HR8/F7\"Y2$9)WJ7A_R[P<RI(R!2'73".";K>R/2X0.61GD_
+MZJM)GE#`<20U0\ZUPW-PIOLK(<E_BGP\6YLRPCA&2["^"2$-(?QL\!3J$W7V
+M&!$B^Z\8^_<-FKRE;"3*6\J(G@/SU->;='E+JNYSJ"]A"^91?W!,%[:@WSO4
+M]L!U@%*_6**#@Y#ZXNNT:E`W`@])0@A%+-/>Z"YB\<TD(41(W?FZ+E]11.O#
+M)"R1<.G5JN`[AF"JJ3C+U6&,/$0R-XOSX(V.TL39V@B`*Q)K['Y.JL\@4(L)
+MU"RI;Q\V9Y48F0LAYU4O'NU3YD*`M3,%&CXC`I>8]C^"\I8O,KK+6_0<!EE*
+M)$_S$=J0*Z(K\ULRT5#U!K5/GCI.S\Y5&D?O;OD?.H*C]B9J7=S_9[)M=B;M
+M_[%"(L;A_A^?ZKU'M?V_;V0?^_\H//X:\:"/`%^AY1Y^%`<4BN1BM__=QI,O
+M#T>Q<G7#ZL5&':O(YA\_M,W_<P_CYG]K8W3SCS(^E?8?N/<_I8BA3-K<SVV,
+M-M<A8K(PBT@S1#S)..WTCY`EDA_&$O;2.X84JF^_CGR&X8S/DA[6^2SQ89W/
+MK#WYS$Z`7,2^SH?[YK-G'H[A,\+/JS[:T">?$6#C&&3<_Q\R<Z6<.H!-*ZK<
+M;>\_OK&/O?^0QM[V_NK!9N.6OUM9:8=P9^&$XAYOUO;[(_3]?C+M]]D`*F<[
+MPZGJ^J/:C"K\52UJ[KGK7U',(^\NVS!NHO:Z=$W5NN+*=-?2J@>*BUPEY96N
+MZU*JKIO@6E'.TUNW\?=7!_5%+RVN1^@*.=HHWMH0U<;1QN7_KLC;YF?F>B)A
+MWQ=?%_VO@>`W5!2SW&3*=DQ*T5@77U[N6K9J10*W&%Y6+UVSP84C0'%557$5
+M)4C@YJS6+=E&+<RZQB"L6RA>VY?,CI6[UKT*W=#?<IEMN]'ERZX3:-1++*O3
+M>J;'9O'8)7_G9=)E+I'SX[9^Y7CYJ.0_&PFQXMGDK@::YNT[\089BCTE_W$R
+M#]:*P%WLCM=1N[2K"[Y+Q,.8W,0/U3?&*+QL>S$.^^9*3`VKELNTY*+?3K)D
+M9E._/,;X/=%_OCHQ)NNZ.*;;[L<,"I]JE2BK6)UD$C)2WY0/([BH%%9Z^\*[
+M,DEGI3JLJNDKB;X.8-EC.R3"6MZ%-9`*G#"NUY%U0R*-3R.-)%;4H1/(LS@*
+M[%(I#M\IKFY3'=[E.W-9ORA\6J<Q$4[RHZ;@;$9%\3!^<(Z'[6C0;Q=6UDUD
+M<HB7<"0C>U&2_QB1HI5^>R/.Z=<CQ''L0`,J)BT!_JKS@70EDA_)[GBY2R0Z
+MF;6XR<:X%FG7.42*4L1I*9S&%!U:;E2&]"2Z_9C<X:\G]R!))H=_`)H1"O=S
+M^,UD,<BV$XW/ME-]\`[@2A->5MAWK)<J##96X=I(%6#-@33G;]$J7H^?:NTA
+M?31*,88K8MTL&!Q+4]1@`\D3VK9KMGV)+>5=B(ED%H]:)7IEK!&5LB-KF`C>
+M6"*V?!@Q-<:Z*=RQP\=%ZX'IU5(<7`Q<U;:5(_N<27:V5R6BX&[C.T@PZ&B$
+M!)NN8]5G&,1BR'"H'A`FQFK[C;D;*A^]&D&%>K3.X*Q.>!.5Q]M:[NHD?F:A
+M.A8*A85&DNHZRI8,:,O-'GF'#M"BT?0GKYGU1CF6W)9J9O4S.6I_S%'S0TW;
+M3='NBT6K?WM5;RBG%BY`H]`\_%W\;&V,=G:]GGN)H\JH-QZBUHQ26Q\/6"_#
+MV+;E9KJG:V":!1%<QL0RC4NKX/XCT0HZVQ:@X>3Z]9#"X3^%-3Q,/5HHE"A0
+M/(R\;Q+LS2)?QV;Y8`)[)RR,V'5C,SS,01Q-;VD-HQ"S$8^*#5:65?S$,K9%
+M&TZ;31=@>'T)EP&5R5[8XWIP"33R(M[?.ZVUZ1XDJB(6U6&/PQ&I<ER81G?Q
+M<`LA.KATE")>2SG_T45Y6%V#JP(!K]Y!5.H@>=1#U.@(DG@`VH-JH=/''AQ%
+M<K@D14PGF(]VH:::85AN)9K1V"?$A6DX9`-@6,%??T/-"..`5S502^RH'8+;
+M=D9M1ZU"34K#KT98&FZ9C@Z;S7U%\-O!CV-Y3#77BM6))F$$30!7A/>=H=D)
+MA^<\]2<66C`JU/+:V")<A5LYUG>>?#FV&QL92^I`TV0]Y+G/7=;VPRAQK2I>
+M6KE\I29RU:9G??[MYHMP:#W3L-=7)";A:G43KIN[PD)D;D2&82:P`LTBLAVN
+M3THG>M7T`[H@9;!7+3@2L6O$FZ6W>TH2A&&]2=DL)&-SU'Z)E?L2C6CYR4YJ
+M37BBH_8L\=-!Y+I"KQH\K*MCU^))^4J4!7B5>ISRO>JP_6:N2;3OXB(=E'6L
+M.IHZZW"JC$Z=T>X2K9`VD1[$WV:Q-68BE>N($M3>;0@#]KC_E0Q1Z.=S3Q2<
+MF6A@\'7?!JB;/R6L"7-T&:P)9;";#VFBX4TN"H!-P+'ST#^NC;8Y:;0Z`@%T
+M_CH/N?ZQ;]`^GL$1XO>6QT>8@WC#&BLSOK#7L%0U"<GJ\D.,,8;$,,:K;(YQ
+MFOE!NI(H6N4/OB_GVAS[37F._9GT8\8?"R#=-!^W4/O0G*]7?>&EWB316PXB
+M%28`%?(I`*APY!N\*^@_Q><V9]FP(5"I;*Z=#4F2&-MJJ`IMDB@JIO.T8.<!
+M%#Y"%-3EG8QN'5'A.<D>EACM7[T`"U3/<P2TVB95[VWVO,0^[.[JYQP*SK!*
+M]7ZI^JF`7(>TVOX_.!`TJ-:T-VL;^)OEZKWHM&\/RDC>E:OWR/&C:M\JPU&]
+M]BTT=\@/S=R^5<M!JKWNQDI(]U*)-*_Z@%C]'"<D^L,U3KGZ*<=K\>[&ZCB(
+MDZJ?$SU/F<.>ET3/7BMA\M*F+9B8KV)X53^@5+\J53\3D'.?F[-^$5YHF/$(
+M8"%7/Z-,60"XE,BS<@^4N..JISE>ZY*@.#FN1,(@*OI61'0XRGAF/0+P]TCQ
+M6/?%CUA%SYZ0V'1YSH;7PI[G6%&;'E>*=^KRKRC=7GT>F*>>F"<;F"=!O?Y5
+M8AX^B8X&AC#&DM?:MKR-AP-2A2UR'\2XAZ]ZOOL9@?>5;O(HH_WWYS7]/*=[
+MG;7:`IM'__D:)TF`IJDW`J>9IHU=9^VF7Q[U?_)\C*VJ.SE-+E"UH:JL?$6Z
+M2UCSP)KR=>CV8OFJLE7\ADD5E:O**^$EW96RGIN14G0KES(Q[>8JM-K%W9U2
+M="\9\%K-)7"3BHK73H)=455Y63$W,-+?\/J,`?N'?D_87VC&CL`G%2IB8CZN
+M"4:IZ+]SRZ=AFC;LTD7QXWA9?&XDQ_VYZQE8^=QDB=SK@%7)L:_#X0O-71`F
+MQ`TX^,Q(O(M+UB5W=7V-VZ$0_*(_5K+8*.Y=B"6@2_.O\6#*_3)*K`]]C9,K
+MGM36OH=W[?=U?HU=]3D8[0&I]'P2ZF(B=<L+*$24<1IHL$*_FFF(*WX!^[#K
+MO+@'<'#QR5IP$U!9^FS\+L0#-FU4E%4\^!0)6(9HOBVA0V,`K))&A.OQ31&S
+M#:`3"+2=@3;Q(]1'7R`;67,,:?[Y/#M<99#Y*Q1QOB'V.,7:%'$A!0IVU;LO
+M,KF@)6@@6B==8":B=7P=)O,AW8C63D2S[H^L$X7;-?@'`*&VGS%Y_HP48;1<
+M8/=M-*T61F1)!78OK)0QT>TO:O*Q4R^A=-GK.-*0ITY]F?`(>^R09[NYMD%X
+MS5O*J2-?1DHO!;!-_O`%:$(-P0([&FAG4F!6]&$8MK77R9#\56QLG=S'B=Q.
+MO4UR96H`:=?9K\F0#+#)V*-2BTSIX&U7*X:+B_-1,>@<44+]FED6*34K?LR5
+M5VI6Z_^@D=J)0Z-P92G:&H4"[+8\UGKJTQRQ;BD:9D>09%&T,%S_.$;.V*]9
+M!ZDN8XB9^>5H!5\1O=@XZE,O:))MV)',+;VU4'T=`C(D_PE$LBN*;`LANYR0
+M/4W(GOF:V<M!9#%UGE>-_P/2\9?/05=_>N_7VKA/_1/Z>#?_;[\E`2/,,[('
+M'5S&2758&4G>PUASX&_CT>A`G"0^0W)IK$Q8*&P2KP`RF$H'*>+Y`A(6#GL)
+M5WW"[PU,:^.OARJ:2TWJVN?HT)YDB'3YZSZ\$):GSM^K$97`\K-UZLXLA=U0
+M(D+4R'?U7OW>F'"E%G3T=RC<I(QX,&?'=1OF-NE#6JS_M]^B-@YEE&(RLDR<
+MGLF8YV_/,-K0,,1H\YQ!#!OY1_?Y-E24K5JFW>=+2YTX9>(TO-0W=5):VJ34
+MZ:[4R>FI4]-O2G6MJU@JE$7O],7J8)4^P^[EH;OD42_AW')L'W/)<9Y'>RO9
+M26Y/:'.<?G=#&%^:K`:?1<8I38;V?E8C)F9"A\XBODAQ$H-28T/SX6MMZA9*
+M9\5+'!A@5RM80.1Z+[DBA.ZF/O*L=EN"G%7X*31)W4"A=@)AXV"WPZD3(4C+
+M'EP:0`F7URD7)$G>1+IY8<.Q)QW('EZ;B/<P8-\[X7=T3(%7-&`6"*^UJAM_
+MIV\:!^/GWZ#!"M6GD7&RK;)81'HP(0M`3M(UKGK0;]QO2`RJ44`8`1LN\K&<
+M*)GE[$1$R,QN8"T*$(U?>S&6QNF!@+O&*>`M?41!?59?^8\HQ*$':'?+[W71
+MJ4WVA-S92=5/4&L<Q_F68;5(6+Z\N*J*.7-"/UP;*O"(5W,?-8L.?EUKRGG7
+MLG)A31&WB#F>@D5KN5"YO-BUM`S]K&NNIU:5"97%7($V)QL!I;M&X;7$6+GK
+MN%\3P^*QVP_HV*WC3CQVXR"XZVDSUP%_ZM-XYG$?A`<G*F()/J]7Q$WXO$81
+M%7P.RX?1_T[LU/6C7\)=1\=OF8R8EBZ3UBZMG+2A8A*BLFK-"E@&3$JIFIA2
+MQ"TO6\/SRRON7UY9O)0OYN[,2W=5%5>N+:XD^2L[\$81+%8=:EM13ODGP#M?
+MN0'>$@B"4!2!4+)\#5^6[LJ^?Y%G<?8L?3VQ.'9O-^UIE*WN_;<N`7Q.>U.7
+M/X.S_$NXP3UXG$:7;+>(+_RM<MT]R$WI_C!_O;AY"<<[Y,(E\EQKOKR0W9R0
+MIQ6J=P,O21?8;9CW60YM*ZP@4$E&6'0S#,V--R-;,860(:CD9=,E$.+%R\(`
+M=M7F8Y20&<J^6BFTYN,BS/>,SOEQ\DPH[E/XFU!:ICH1A>;2LD*U"5JP.><>
+M&J]R5K*:8IW9Q4A[F*HM'L;?1,<C:%U$W+R28Y>]\>*M3:F[Y:YOP_E*72X]
+MR/"U5QW^C)F<L-SP6S;Y)(N7PT+_TG#;RQS9\8WSJL=>8'9%N\(._QZL?1TY
+M,$D?Y?#CI1=%::*S]]/_IJGHWVPJ4I3C%'J60EOAU\XFJ%V8+M^KEKR`FW],
+M;MG52JH#=G<+/\"K?@[-V;848,`$4#@[7_T3?#?ES#$WY<QVRKM.(-3">27R
+MKI9_H_VUPKGP=X=7?1ES_9(6(E[UV:?9Y?+"E5GB)9/CH5^9"-J^<Z04M`D!
+M^O^!B+X*$9MU%[>[5,*U`540PFB%!I8^N_`+;_S\9JL)J+3JUY$;/T*&=B4G
+MW<%?):;;^2O$C;9;!(=2YT7ZJC7/LR'V,#$F'U>HVJ'<`[@H;GN?\)1E-(0M
+M#V[\;*1E\,E+TJX#5/XAC7WE^598WI`^!$8HNW#;FQ^N7V(B:SSA^@E8*Y/A
+MSM!4:N5B+-YHKS=?/?J4.7HM"+@G'&92MV;-'P-"-O&3NB?IAF"^^B/&I6V/
+M4+Y(<JVA1C_%&@K:)J2UC;RK*])>6M@=T-``G]WNM2'_JX\]S2R5?#<]>NVF
+M6H]0"N_)-Q(+&NPI:#!"Z^FG\(;X$CH0%T8H=;NI>3YZ#KN31@EKVV$T.X07
+MU-?=HQ[Z362A85?J?D/)`T^B'2C6E$.T#CQ$&L[>I'0:!/J1=R#<:._YM\'>
+M>W2@>G@/LT=;`Q6QR]E+Y#QKGISE#+<T9R]ATRZK3"]Z"HOVF,GGDDV]=$D_
+M8^YV_K<'-7-@7X&HI<),-AMO:V$.;!?=GXBA4*8-'2?'2?'!!*U*<9+9JQ;]
+MBNF`2!=H7CN@[R(W5-R_>BF_?&6Z"T?I^\E/(LV_$PQH//L+K&,2\XDN"\GL
+MA;169^&HZ#2,BOQD="A5,X&H=SULLXUQPV@D=?8^CCY)=B&1VX^]A`R>^:1>
+M1:]2$,I7"KKRT6,-;1?4,Q>T;1[O1G^A0K(T3!Z6E:^^]$M"58J#H/!4LH?^
+MTU]1D#P(@N1A3=8$+JVA;2K=TFNE<7K314W)B1](SN79K2[H"W53&$L4G&GV
+MG&5UMTG".;3'+:BP49>$=EE(E(2.4KLB='K5"WO8G?VY2^1,:U@X&Q;.>,/U
+M=U!1YZ"7HTN74LM"&=@<3]7'0%/=H-1-68)]NZ`U7+E$_<LO"4)SEL;$MK;"
+ML&:;L%/=AL[(F54%84E,K8_LZ5'K)W_9O=8&TO[SEYHRB9`4GBKC3Y2RMWY#
+ME%4*.O,9[NIZ7&,+K:H51@@\JC[>FV[.UI]3/V"LH8A8CN_@,5KU#R=A9YXZ
+M_;=T6]YV`&>-X(``2R7%X1J+>@<P8\FJRBK>R(P<UY,?K_JYIJ0YION<C!QF
+M)PXS\ITPD'%8H=:N459V=N-I:$ZM!@4J\<:2"]UX8^AW\D8K\<:YTD1%:)>$
+MTU[UW!/8H&HWELC3N:]^!MD4B&&)T4I=XS)B"159XN@O"`*P!'4Z8(DEI#+=
+MKJY/B/+#"KF@$WF1\</S3]#E8N2'1.*'#K7N%^R^,?!#(N.'&`[:]$0/#EKZ
+MB^X<!#-26#C-T%>7_0:Y0E6_N&3D"FC"-<7K8UN0VF^*H?WN>LS\OS=Z:&V[
+M7&];E]Z2D48>W:V1E8(SU+:UWW1KVY'=V[9%,XQ!;7N6VK:5^OTYZO>JULXG
+MO&KH<6RE,WH[GPX++9%V/JMW_7[=V[FVB-KY#+;S^S\G"(:NOUAKYX"M>SOK
+MK=;T>+=6ZU!_]_/NK4;M/%K+L9-RN##':*V=-U`.%^88;6CG$UH[;WP:V_F,
+M&G>1M7,#M7/LKB"J(=_#GLJ:G_Z?]=7AFCYI03NUU9FON[45:<`9V^ITL^<,
+M3;@>E=8YN>WRPME208>\<)X$-%N8)Q5TR0L72P6ADF;/5YHX#'JYOJPHZ,A7
+M[WN<Z3OA#?LKE;JR$EPF](>N<0!UJ]I$K4Q#3Y=E-&>,'6N8-%B644,$[3T,
+MEA<`%YP!1E"$L\`(LV([O*U06^#)A=9"6FYI:53[4TCM=G4WC3M.L?HL1WJ*
+M`V@..*O6QJ%FTC&]KY57%J$^3+>YVZAS_L5/_L_H_RZGT3]$]+_CJV[TW]^=
+M_N>`\)&^TD[4Z2BU*=6=A>I'/S43%VJ=0T4+,.'Z#.TBOD:3!-8YCD+G$"\E
+M"`D'L*\&\P.H<XE]I6,%]940]I7G?T8`N_45&1H8.N<P#;;:\"LFC11"ZISS
+MV)4Z54\_)-^9Z-('-ND]Z><RT._Y'_^?T>]L+/V2ONQ&OT/?DWY")_":5_W_
+ML?<VT%%55\/PG9\DDS`P`XX0-<HHH1)!3!"%081,S$R`DC`$)M&JU0@9(4*(
+MR;T)6"8_W@3FSF5T6L!J:Y_:/K:UUK:V*J"")I1FP(?:B%1I2]MHJ=XX:8T:
+M(6#,?'OO<^_\)-'V6>M[U_K6MUX6-W/N.>>>GWWVV6?O<_;9^_%'QX`04&9A
+M*@@S1].7ZS8F8/;`8Z-AQM:1027?F*`O5J0(&=]5EP^R-M#+ZE'N_P%3,/U\
+MD!&"DPDHUFW:V#`.S4_VB>3;J_\W<O1/$2(:O)0/1\%+'@VO?M5%$<&H0OG&
+MMQF`RE&4H-LM_0"@_!2Y:D(YFW:ST!9#:+=0DX#.'8^.ADY]C-D1'L*AF(H=
+M-PXR>.'IO.9+IYRY7[=7U=\KH'/Q!OL]5>NY<L\M\5V>6ZIJK^;MM,/#;]&V
+M3IHV;%RW@;TTV/D-&QO4C12N#+((D`0PM6^L5;-?/2;YOFKTJ(ZYN-L\6J%L
+M)VKE%AB!+]UW@D(V;ZFOACSK@'XTJ`79UU?Q5?=4-6@M7K=E\V:A=N,Z).]-
+M&_D-]KHM]3SDJZNN_Z(<;"/KBU.QG6K[U'TC5-ZEG:.&:IY;P[J![;!C0^P;
+M&303/82G`7NR>6,#22WV:[64=51G@U!7MVD;Q6U<5SV7<]*6G;UQXY9-!`*N
+M6.TC%2TT;,.RM:,Q`A\9!>-&\;9/?TO=?[-:=OZ=4Z]N\9MQ#VX9)"V&)Q^>
+M7'ARX+'!8X;'",_P-_7<(#S]\)R!YS0\)^$Y#L\1>`Y^4]NWZ_L^X;_(WP?A
+MW2P<Q/!.%GX$PM%FX)GQMS$D_AU_:T/B6?SUA<3T3?#[]9`X"W\K0N(R_"T+
+MB37XZPZ)`?Q=$A)_C+\WAL3.36RO\-0FME<X93/;*YRQ6=TKG+^9]@IYVBL\
+MLC=IKY#!!PTG#5W@-S=-1PLT[B:TH[40+=)<AWZ]AX;0)^AY_NO13>+0Y_S2
+MIHGBT&?\,G%HF+\I>ANDC_`S\,1@:G0E.A2A/91COPD?,*F_1O77H/ZFJ;_I
+MZN]$]5>G_DY*21_C1^G],(DGFDABI7WBFSY1/38+.7@+6)-'V*]'\0S0M36\
+M!Y"6,$&3.".@\X&MZ^NWQ>W]S9W/;/[=>%T^_+\!CP=NF+<HWV&ON6^#>CC`
+MI9[3K()VU11J7F]>^<Y8>V)CSSPN"^N9_HCVV4[V60;[3#_>-^\_3&;MF+:"
+MQUA.W[W]W7_[W2\?3F[?%5_6OB1BO^UAS=9,[,9*Q1S3:/G,6*.Q4GD\_GXQ
+MLS6S)J;:%=7:\46ZUU>FE/O\2+P<*K>8%6-BQ1A&VV)+G/\\!'TRJB?EOWGT
+MBV"05.]/'TJRG?.K>/,OK=$SZSG-C_X;.W#QDNYZ*&['T<D^RF0?&<<?Z^L2
+M^2=_2?ZDMGX>2FIK6[RML^1TG)L7P5P5<EBK>V#)Q/,U]I9%T"/;2QF:;]11
+M_M_C=3R67$=IO(ZIK*3VS[]T')+*69U<SC^&M7*^$G(70SE;1Y+P9"5$3'ML
+MU%A]4;GG=R65^_.1I'+1DM&9X:1RL<%O#O^'^/>#Y'(?>T3;WK]$3H>_V0!?
+M81(K<3,#9AJS[3H6EJD\Y@HHMB8[)"@5RO,/4:'`\R&_WXOCODV#KW`%,6.H
+M@*.<078'SR?(,WEG'UH4%/T*)TQ-Y.G\-M[#ZOL+KA^RT(\N]*SBB-[2CJ8?
+M^WY!#)7L&BST*,T/X1WM,\#<D`QY+Q&+0;GT3+?1A'9?(<OMF*4[AL:,@4-T
+M48[A;F,^$Q:U*DNQ6;M))!)1%HKELR\&@5^MT<GZ6(\4H6:S$P[X\HQR+$3^
+MLD(,FC%VE1@O*2>*/0N@CEZ4>'_O$>J]5*""]N0X=]@^#2:-U4_C0WXIHYS,
+M_N/>+\.G>$D_@Y)JG!H-O'3O?T8#A>3Z?QZ?(U?$GD/5J9IE#,=7/J+NB?W;
+MN3(SN;P_?C9.>=BEX;W_:7E_D)+*DSX;-8?GA[ZTG(3_/RE.G^[?_1_1ISN3
+MZRW=K<TAM=XGOIR&)Y5SL92\%CPUI'7@2EH+%L;W=">S-6;=+FTW&==S2ZS1
+M7*G\9(AF:?+`I];QJT!26_WQ,5R$%D`K%:M6))_'S('&9"TB.^3.A@C?GO]T
+M72@)Q.&8]ZW_"(X7)[>M0_Y?P%'[A_8*ZZM]U?75M>NJQ[=9F.S_;B<=PJ/!
+MPGD=9P5/W`"A&9<4)ZMH7:4R+XB$@LPST^D[VAS,WSK:YJ`Q2'=$KZ^L4+HD
+M:GL-FAHVR5X;DV#-JF5!2X7RE)1D53#UKE2JGH!^9]P4^A+.LK=3.BR^JY.\
+MP\CL52I]80T#<(V;R>PEHE=`W/D&&$Y$LH,VNM@NH4I:!A)`2SW''@LP:D]Q
+M4GOJ=^`UVAJS<H6$]+6372Z>*WOMXF%#Z[O#DM<N>W.U<*[LMX?63EM?KGP8
+M4"_I`O26A';?O6W,X=]O<?!5^X#DR$_&,#O$!>%X-5HS(5^_<FEN:.VDNZ6*
+M6W&WZVBY,IM!&\TDBBUZ3KBJ9C+;^*]4-DC,/+W5AX[WRG2:W<30[M.H'E/:
+M*:TV2O?CI_(TJ0(M@TH59KG2A$HAE6:IPA9Q9Z.A`E3,J,@A/1%[Q)U+I]ON
+M66Q3SBZ5K97]N5+S'<ICT(?K74>O=QV77-I&:\1U2E./+3V-SE']O7A"9H\U
+MWAHJ6RB5'ERM%,%G(6]/>4PXJ'Q=4L\Q+.TH/<D5BR&6]M,DMP</B_TYXE+.
+M[XNXCI#>U^0:?8U>Z=R)_92FH<+'"?^57PK'Z(IPN`8`WKX3:SU2OJ'99VR5
+M2W-B!4IF`)5CC&PELZ'?`V9N%"H%^$Q57L0Q`J#I9!>S_0XR1F:%\J<=[`S9
+MW\GQIIC0J1Q#+('I^6P2?Y#@_]J!U[_[*H[]B0D(5KG45KXZ<7FZXW/U\)#T
+M*(YR*7H4'XIL2K28I$.XWQ/I6!ECA_EBRRQ`?1R14#$-3:X46H93(%NFG/*J
+M7#5EU2R6$NGPQ#1]C+5JB.45(PNE0WC.*8>H$N="2EN].':_IU(NARFMEEEY
+MJR^FEU<M#GG-Y;$7Z(O51MR2L<+$R"?,DE?864JYFL08?)BE++_?&GN;3>-I
+M6FVXN</F:]\5!JU-<N5B]0O"AXY;V:DP^R9V?[;TFGC85(Y:?;=2Q*TPI",=
+MA$\.RLS/T/"`%2A5YD=*YJ`\RG:DGJ/[.X<01)PP43R$(.(L[6B<37Z9D&F:
+MY-V%L\0;QEGBW0-X@U:4_-F2_XD:>\C;6:X<@?%E39(G2V]W?9@F'2K$AKX[
+M_57LC_3&F^]+%^00QF6N#0$%,0&_[N\-"9W#+R)!^.1'\EX:@<,YY6Q'N[=<
+MN1<*]2BWM;/I;!,O`%/U70YUW2P=/XD/FMR2HSODB0^:O-RN"^&PMAW"OTN+
+M+%SSY>$8C7D;C7?GH8&DQ)8S,O7=0658=OTW7D\AA'&$,$8`L"VC]+64+HXD
+MT&,.2O,DTO=MULY<F/Z)T=)^.2+A5Y$.=ZR/,8=(H;T8*@]YGX5.:B-XA_2Z
+MV'UW!0S;TG:5#/CSX^7P7:C,THXW=U('$--I=Z'O8\PY9+#L^-E(`@BW:MAS
+MMV.RI>.;(ZA"X*D(O8#[@A7*;T4TC]4JA1;#ZVIX?S!.@!["X;H@'IX#B(VI
+MRD_;F8I-RQQ.6*:A=DC855&N&7L%'+:QZJ!=>/4X4I*?3HQ\F./+Y!!B;T2'
+MD[5BM5(.Q44=XB&<OUQS?*Y`86;2FB!]XQ"F]MU++M#"\:*)I++^.>>$?C0G
+MEF)_0G:1FJC')!?-`6)5E"\YC7+1?,EI&B6+_G<+,OV4N=`4\BR,%"YD&A_6
+M\M@;"=_08WWVUK0PA4O!*A?AY\O%\\8FO_2GV7OD@ZU`O=X-A_,ABQV>@68]
+M9X5?#C^9*I<9)4^NM&Q6=`WVQY,K+YLE397*C-%;\)VEYTC+[-'K*3T'K?)3
+M^@QZ-TE390^L3$;98\45RP,+DQG%VW#2GH[FUS;9_D4SHYI-)E)DS(K=J,QN
+M8^I'%8O%!W(X-(J[T",7Y9#*1862UH9:C;'69-?&HS3GOH!?6)Q4;1&KEEB&
+M:"NR#$?8P%IKUBM_:DTP!3>'Q'#;:);J5ZUXW8#6,G+)SM:UN')]$?$$>Z#/
+M;.&_NB9=6_BW4-]@V>\4)E0H#BBGKP57_UZ?5**'U49T</Y[:M)1ET81L992
+MFZ2K@2IK6^G"#\NR?7*-M1)FX_)V59?2?]67-J</[;2I"RCSL:ZNGZ4V62>E
+MJ_JJ$;>5(C,DMTTN,4KN;+G$)+ESY!*SY+8#P7,=]2@5T`YE>>N_XR?0AC/P
+M$R!JN_,]H>:5E<JG+7AMH@>XPXL(!G94B:`QKX5F0&?FM]"P1^]"?'+#8E9H
+M!1G6O4PF_D+<BIX)()+A04@,!$AI>M-.M#``JW5,R`8Y`2L1AXF'.@*3"W@H
+MY7$"XQ%D#HY$IVN\P2O-*F]PA'B#(\K/FQEO<"!E[V!9$LY,VL[\FFPSA5:M
+ME$J/AU;E2Z5'(JZ#;(VWHB%I6.-7F7"!7V6.N#HYHC#9D"#Z[9R0+OIS.3X#
+M$DC#NO0XTWF,E.2RP3@2RY0G:^ITWJ.005YNC#4M"U7F`P]V7"4_N/E["TNC
+MM1T3XJOW-=C`R;BP"\>35W7&>Q^'<8F]H?J($%MR.2$#*B=^30>IRFU^P,>O
+MT4%.)[XO]VM\_!3(EUB/%^GH+E<G1W8JY[!UA;IX*791L$'NQ+IC5M<=["_6
+MA6&9\'2RY#T-C92\O4"GZ5RNGR"Q&Q%1\@Y@&_ZR7;7>8FE'>(;PM!^B]VW7
+MFC8!.\+_O.^'!,.CCM(>X8E096YYA?*M9G59@"95(V`R9:<=E016`[W2E@4K
+MM)4M"+/H&'0ZX1)`*EN#U,0XI&B@_;T<[Z#.D*(F%J?8H:9H;C@<*STH^@_&
+M^$NT84A:,RP=6;CXE>2&JI\9?TW(Q35A%JT)<\:N"0]O2UD35D8*5W[IFJ#>
+M2:"50#ROYZ]NR13/@PR)?+9XWL!?'75J=-TD+3-'"JU$'O*Q*<O,R;0==5T\
+MV43;<XBVV\?0=ED8'KMO\)>M8VC[JF^HM-VCT?:52;0][QM(VV=\0S]F#R]9
+MUMNQE>FTD)V4CPFA@,5S]7J4=Q[0JW?Z#G=]D"9Y#XJ]TU\BYJ[KS7>E'KGT
+M8&9QJ!<O]/@[0T)OG*]SF<1.DX>8.E>G1_G6`\C4M3]`%)<NHP$6+`9X1HH8
+M6B-3%/T&W:\E'FBAD?\YU!MQYAJ3":]S%LNY.LS(/SK9FZ?D/H#+C17+11I8
+M0!_.NA%1D'T?<5GILVE:^>B]PR05S8+JZ14=83T[OOY^31-;__TX\!UGFQ>%
+MPQ65L7EHB?7);;18R-YAN@.26!ZP7$.\6Q/RNG61CK,M1ZF:@;C\G[C_UH26
+M;H[2_0`K;?$I/]V&EU,P2F9_R>9RPR([=Q.>]=5NL=]LG]D`+YNV-,5/%B%J
+MDS#'OF'CO1M2XR!?TX9M$,8+<K.T,T/T(U1=RV]43UC9$>*U]IGK\R!_0X%6
+M7,,\M1#M;#%51V-%(QU.*;.1277UXRT$0")T;H+ZN"'7H*="+@?:@+JK8JY$
+ME[[ZE0+$*W]_RJWX4D7V]H<`J?&<^J2!G*UX*I1).+KG1N4,\9-BJ()2.BB>
+MGVS9N4+'#C9E3U"UZ;6<UW/:LT%@#X87PJ]9#3^1E.>+'MPPSME.E]SR)#*]
+MTPA#,]K:58A/C_7]DR,=4&9?^D:6>?D79>XD0C.D\&G8SX&0^'7V0?87?(#Z
+MO_X!O!R#-J?OA<S13*JHAGW7NY5P<;Q/HU^+VZR.M^M76\>O)CH[D7?W0Y`7
+MB'['UB\<`&M(_&]6X-U;R8-4W-I@,GY?S<?W!P_!\'A8^U,9P&<;U=NEY9Y;
+M%MG=ZB5IH;:AKGK=1M_&:O6*21Y'Z9[Z+??65VU6[VW<NQ$U8:K7JVE;ZGD[
+M.^N/:PU0@G9EI:Y^"[]EW99-J;%HHH?%E`./RU?;&]@E&*:80`EKDH_KUU>O
+MV[*^.J$[$6_8NNKU4*5=J*UJA-K)<&)RFZ\;K0>0VJ,QGSG'F:4L97GMNBV;
+MZR`:3?^HI38@DPZI+,?:C9L!<,"Z:UW%8E&3H[YZ7?7&QNK1T0W5M2H0;TGN
+M8WUU@[")3TZHKAVO\]HM(WJ9E:J:@/GS1LM6D^J)=A1TAL,A\V\Q,K0[Q\YQ
+MCOE90KI<G&6,F@O%H<F-[X;$XZ'/Q]5#_Y_[R;ZJ\F3L"Q"KDE<1"T@;YU+5
+M)$:OJQU0BK+Q`K-.A3IK?:<X=AV`D:P*I570!)18OK(@1E<:US:2`,VB91#'
+MS7R^.#3)TH&&2D/B/0_1EW,;XU_6&16TZ`.1ES0R<[;5\6P9C=JN*#)8#YBX
+MYAQ9K,/]F'*3P]IL*5?VPC(!&?\*+8E>HY4(+?1A`6,F<W%ZS*.\QA-5B,_2
+M'PK)EK62X2C6,3BB69-QX6AI4.'X)7-S>6UCU::-ZY,T7C"YGKMETT;`$CO(
+MDNL1E:LVD5FKINJJ^S2]F?KJFNIU/)04_T8K:QW[-AX_^H-$H:,_24H9-8E6
+M?764_O>6L7CX3`H>F@`/,QK?C6M[C]41*]I")L[17V5KBT[/S])L,LS5&(&^
+M;BS8/P"2IB(!PG6[/M+#6/O$EX_3TE^DW%*/C$S_2_]L6%8*Q/3<!^CR*@-6
+MQ:X+T_/>"-F6AVS?A/]=[QH@-:\'LOH@X$N[5>^31"SD)=JH5BM&!"$;K!I/
+ME2^X?#+E\\7HAPG)OC9J0,S0G.F+4/RM>I2&`1N*[F?;<&9WV\A/\&J2L>/$
+M]F?1MU3O>/Z,DOW%S:O%>XP]4!K,J.DUA34Z9>7]<:-U-,?0SY-$6<3FQ9S`
+MR[M)AM%+;K-<!-(R\MDH.;O-4KKLMN*=2[=-<@/*]\/@@`0=\BO`8MI"[ED@
+M!+\'&%Q1J;P/E;"C\K_<3U(Q0$B3?!=#6)-\TYGDF^PP+<7^P68ZI95%ZD$G
+M?Q&*?G6+Q<Y9GM5RD3G60^=2\;.MN#\_IM)#850-2DY+M:TY93,S`.,U![,"
+MI<-%[<?X13")WTZ9Q%MCP71W.SN+OR*\T#4L?,B<[BJF!I7W'`*.ZT]EV(W^
+MY"$A_9Z-M>NKM\Y=0_H]\T;[\URXZ(8;4_UYKI&+<TW!E;EFP)E@]L(_\AF%
+M[7\6/BWHO/TWK+Q[UFVN^^+BYB](+2Y<62%OSS7+?*ZUH'-87IEKZ^K3?_(3
+M80(&Q7<,G_R8UQ5^_:[Q[$E\>A^R)TFJEFCYJD+979MPS3D)3]PJE1[$J:'4
+M\V_\5U*ZELEL@@E-VSS>238^SITJ.!8.@RR#MO.-!9D]3I#;FC],R%JI.%P+
+MS0@]=_(%<H0LBT-$&*Z\$EZM[$WR&`MBCI=/0X[F1:H_0I3+AV5A,+1KTDH0
+M@^7[C?+N(1(RAM-67L9Q!J=),OY:=`W:2B"C8YNIY?<%,:V6`<?+I["P6]JZ
+M3R%G*`R1G#\$K76$C*VR=Z#M,)8:,C[(PE@@B)=U1EFF!ME^52)#*<W&EF,:
+M8I/A3U2DW,0#/\!=)S347]>PH:J^^KH'MM16;ZSU;>&N8_=89\U(.7_94D,H
+M"K-U4NBYV_=^'D.CP;<`+6E=LDC0N5N77&?9P^`J=0R<QC-;2P<Z7@W)-9!9
+M"IW"N&.6=C39#*.Y%]^3$/RU<R>D%TYCW*B52Q^[&56]+#O?-J!!,?Q,,\>,
+MX=7*9YMQ4ZIY+YF5P"CE&&!&A1H^!&$TDG3Q%G57C,^*4/M(K*8\XB%\Y_B+
+M:D!&[JC7#%!T^,C41(7R=*U*J<21F*7=@[;K3&@,HV/P-"W?O[X/Z6*%M/<,
+M5GC\/MJ"E.D-BYF.2K:'3'^!%A_"ZBK5C/?A):2.?NJ/^2^)_JRA>`7C#UD3
+M7RDWX>E8J5G2A0[9DJ)SU6BG,70H.RG>K,6;0H=RDN('T:IU-Z;<;PX=LL=3
+MD'>AAHF.>9:=->CNPFE:1NY<+3MOA]>V;<9Z';Z4P8LX`IE<F.D0]@`0ET>-
+MEXYY%(6-AQKBL3EZ#5PR=3*O2SJ*MB)PO%&6;C&&;(<0S^`CPVHC5!PR%H:,
+M10:G67:$;)]CDJ['0,`R$&@<'?BM9==A:%'!":QKM;%Y+AMS%;X3R'']&5:%
+M5/QMJ]B!J4:@&$6.2F/+B?AW^3)!()@![X'V+)QK)0PHEGWLU>$T61ZJ@+J*
+M(']+#WSI-SLJ(0XO4D2H+32]!;.!D#BE(0\BLJ:KM3,`6/;I8`%SLB''#1L&
+M^2&=92>J@E.R24U&5QU_YIBMHQ*S9=?O<?FF*FU%U`%3RTZU0>9F>YA5$-1!
+M1*!]$9($M1SHM+GE'?BBNST+HP%NCLG-)9`O]/S;*R_7)I?:Z-]=2&JT.I=>
+MQ#BW,0Y'$VMVD6-:RXLJ,$W-:U]!2`"=\IMUYZ1#IVF"]=,$LZN=?T4GE9BU
+MS@_I&B]F6R-\6*;LD1+:+Q>[X_U[3@-X<QF5#M&ZCZ00*UNALG/8&%I>R9"<
+M5G7TL.S)T1]"6RAKQ&F-ETNEM>S'Z[#'3\</D=!&30['?J\8]?M%<9?_+_+C
+M$6&M;I3<,[6:=M6"D]M/\,7R<V2]K'M^V/+*X8Y.?QI1U)^2:;.)P>(=J?;:
+M!%N@QWARL:[1W'IA-I_AQ#*$[H13[S'[5T^OIRU#U$U#3S1C?0_\&Q\,]Q2<
+MC;K"T#;O\.@/IXWWH5'][M*0;9_E%==PB/?T.`3;]DM+@A;@<]J/"<\[!&O+
+M!%*!@Y7;R/2*DOP5I;;_@W7$5V_`L]\:+D0:>2;E8MQMZL*C]V.\5_8.AXQ_
+MP/QY/5V]:3KX8Y0R6AV+!+>SYJ8:/(#\QT@B_TQ8B2'';/RKUU&^*YPUBRG?
+M(<K7<8SN+>&Y#I2MFX;@'1A/QZIT'=L>]9M;'=<*$\@IM#.Z)(SP^E_:J<L(
+MZIR+9PN6@K.5JY6S6C-0WPMM/.O/3<=&Q.6V1!->NT<]GS2W+EJAW0`MVH!X
+M5Z,CEQGAUD6E0DDD'?>VB\@;"K#'Y<H)7'108Z;C!/^-H+YH\5R!KTG#5!.D
+M/I^4>B=+K:A)C]YL>26KXQCTZZAEW]%S76/Z%1B#/_9(.D*%-8AT%\N5RD3A
+MI,\T/0QMO$ZP%*%N6KDR1,G1C(C;:L]!XW&)<\Y4_NSU*@*_ZI-:<VWJ-:.K
+MW-D'IG=$5X,(]5;72!I>2G*9NX:F2Q_G'0X9RT,V^(L6"SF'RRS,8EDWFS%O
+MQCAYN]XU.KQF=$4]3#R$RRKGHT:JK\6,5G#ZKM.S\YH1/=_2=Q6]R%ZK7&Y<
+M(7D'H`C)-4`(-P`2&P7@;X:N2RH=0C4N2_N'.C+!+#Y@O,GRT+OPTN8::EVM
+MX_K>TC$]5ZM<:)1<2LA6"`5":V9[!R20"C$`?S-T;T!1?3_%S!`H.(8?;#6O
+M<ISWWXCX>P(^,GB'H7?O&>7V*[9^Y_,8++;(!1O1ZA2T".=-ALXU)'8;G8[S
+MV_^$!2PSBUV9!W[V]-/7G.N3WGIC!)A3Z:@*%M:MD*V#)MT;H?MUS%B3N-6L
+M;]$M9_#LD][NBJ5)_G[Z+"\2LODQN^0=U%T(&=].?&UL#,W?`<6';`(:"(7"
+M#]SK\_G8V.EI/`:T\>"S=(!_!K'+@*7J0^9\::3C+$1T&UA>6"6.SG8-`J0/
+M[,Y=_JUSF_NE-PREU`:]7-K?=7YZWE&I*V3['57^&D3EO;$-RLO`/M<9\UZ'
+ME^Z,%VF<O5;'"E/SS4`O=)U0H('H!@1``%1;;_#VA_9<R@-$83Q"S5!(OV-A
+M\P1IQ,D^;HE"[\:#--[-<ED-'JO!:\.+GJZX'%JWI6'CUGIA4[5FIU_LOR,)
+MY__T=;2+>)0PW6627,?IX";7HWP'[[AV2^=F^X]+?CQ[%V/ZIOELY^$)(^(1
+M2E3'4YPT2*XCLG!<UWTS\L:-@-]',(`VZ".H=UBA3$1&1K4S_SQMX6?]`$V#
+M_0ZME[F>8D>AF3!?F)U'%+7:]^+6O7"T0C'%6W14\G>R%EEVU,28"Y*9K4OF
+M\/;6)3?QEZ$3B0KE!Q?B=0D7]=T28WH@(#4-?(25#6'^3,AOZ<"M"'?(=08^
+M&DA\9&FWP#<@,"^>8^D@ETZN'LCQ>G*.?XY0Y18R70UD.U)")BTC)<8``73H
+MW"EI)_(;D9V>#-5NE^M(H;1S;09)<)A\-R6OSV""9F3G!C4D1JR2_R!,A+8N
+M9"`CK@.,*CWUZPSR2($-C@E/Q80#4NFSRG4$6=QGAU:R:.6RSQA=M,NESSK>
+M:KY,]A^4IHD18[=.YU2="1WLUG'12Q`N!Z5\L1.2@-FS0D!R'<1L!6=E_U/G
+M(GCZ).2R>?AAUX6TKMCTO`NAQ3!E+TC>9^*T[REAADK[GNJZD`%?LGQ$]&#V
+MOF]T^)\2TFA9"XFG`,MEX[/CDXX#,==3;?ZG/H6N6A["<>C[+=$N`G;3YVB0
+M_2F.O[9O$\HH+K.\2X=0/O='J?3Y*-K%1)E@ET.+>RK:@#H5S.(G<((NL\-C
+M;+Z:Y;/LV[4(`1PR2U+I,UWOZ,6##APLCO\Q<?FG`>3_J^^$!]EW!2?ZT$9W
+M2EZC%)I/,SW8O@0S`X.-\>+!)7?0IW,*8AUX.NTRBP?3;Z4HL^P?FNU_2K<]
+M;(U.!)R9[7H>.6,01UC-(6.(8\R]O&LAZ[%X<"'K@0G[GHXV2TN?+V+-MSR\
+M"3?U$/=0JDG"3H9^:]60BKP)[$P@+V)H=&%8U9]@:*]C:,^^'$Y%^]$%'RG$
+MFDO,I/<Y46XQEQC\G=`Z:2OTU=S68D:+OI:=84!?X$/:NE'6B`E'8FA<X-R=
+M>LX@'$$?%72&!25<1,H00"#^?"<>&G7B30SD`1\=5U>^[S9B8"M#SWGV?!ZK
+M4,KCMVLS:W25%<J?+J"%FG%][OSB-CQ8W87;,MNOC8@80.+'-EO0N&-ZHJP*
+MI8,I62J?_C-N\F;MUU0:G.S__3;<?'CDQT@&]7<E])HF*JV(]G_B&"_`JFW.
+MK@B)NS[!#?2Y=\;M7.+]\S$.<YC<_8BZH4*-1>VI^/?I['N84$)11,0>T#")
+MI^(A^R$M-$L-A42$F2<DVM_`(GYS!Q41G8]^N;`$`)_A7_';&*U+%O'6&HS<
+M03<04"\FLU+9/,+@\I?^)$#3NF1.WO^^E2E3<!+P_%2X2%M9@-,.\0SN:<TI
+M."&^G(LMXUVXU1X6.VU%*.%9-/07_DGGCP4GHKFD9.#839MA%HASP/1I2:=Y
+M.FC9MV?1VS@Y;=\"9B+T_+<1<R6\IV.MC-U(MR,=.K)7!=P0W@4OLZM;<*6#
+MLM-$NW`Z2!B2C+^.OT=0PVK;K%"U,LY]G.I*PD'E8_0D]=R>0<*>2@7MXJ;Z
+MOTZV?U2I&OX+(R((ET1$##!2^NQ)'`[;YP18P&Q\KU"/2)LYU88;++:TUU@R
+M"R01-JFDIEFI>AR)Z@Y7X%ZEVC0LIS;&&A>7"Q-Y'TGDU>[S)6<><\;OJ]!K
+MW+7*:^-EBFDK+(%.QH;(^1`1.DA["I)_P+'`\C#JM%LZ'DI\@KR^V&+D6J8`
+MLP/\+'SA:'][&7SA!\9CB%31_4,<__6.$\U?"\TG>6X%,F7M/5AL(>5?@D'A
+M)CRG^0.C39"N\R32,2A<%G,-02DVZ?45<CLUJE#]E(_(_@&Y!1;2X6C&"HOD
+M(M)JDDT',EQS#Y_KT[V&3*M5>JWKPG1I).^M).X-E\,\^).1=QY('TB/NJYM
+MV>&V+F34RSJ.;?^4Y$5X_\5(S-UVO@6B6SXZ\-OG?OA-++;KP@3I][2ZRBZ;
+MY#&%%C.!%0I,TUU@*VG7`2D0"&B-2*-&Y+V-^;<:I0O8"OBCSWM#,A&@TF"=
+MT2T,E1D9HTN5Z-5*XO)P7I?LMTFKLK<9Q9+LC!>1%>DXNWUS6#5`<+;+(,Q4
+MV75@$^)?$P,`<VLQ8Q3."_9XIHS43,0EG$?9:(!P>S>Q":X!Q_P'6S8[9\]_
+M,+IG^?^QRAA/XA\PS#^P];&VKCWHA0#`M<PFU>5`M"XF^0<-_@'X*K1G.LH]
+MD4+:$'+,:R$>RB876J&)`*)8B54NL4*CF_O<"+$F6"/M#,-@Y<L=5Z]AU1IV
+M9HJ&_SQ*V5WZA(U7Q"FO63;IK`Z3=OC0]<'T@IYQ]SC2U^!&NQDHD+B$VVZ6
+META#CYT[C]=;PW+ZN1X(G^L!L@KKM.6777GII)]A4O;B4I:T+X$;$5"GTS:[
+MR";DRD[K["*KD",[S;.+S((-"-WL(A-4XC3.+C(*1EDW6\^^:^M'WC>I.4WE
+M2,IMC*4/>4^B58^WAU^<P*%J5\WBD.N4!RW#*/-)Y:>=.4+LF`>\1`TL=Z@V
+M=FE,73\L'9=AM!EY7[HCRB52T$WQADT9>$/_->V:JZ4C:F`:@9:'R4I.#7#Q
+MBD?Y:2+#:P8\UI1+E2]'I_;_')U2&%Q_KV'QLY*_MR/6+$:;PO\':S(^F^?J
+MK=%1_XY]'N_?![CQ[N_%3<.6MO\S]=L$S*_[&$B*[#K3U:N'442OS^WRKDMQ
+MECA*>YOGY97VQEQG1/^9"9:'&E$7WW4&OU(;G!UO</MMR/;,AU9OP/D7$DY2
+MAG/#\1YEXPF!2TG#L;[Y5_"GI:#FMQ7*'Q(YSN)R[3\I^1^/N$[>!+603U/9
+M]83D>K+O>Z1+YCHIN1Y7-:,+CD5<3S+%5Z?L?S(TGVTL"$]VG&WY5\$)('`9
+MQ#^\^:[D?3+D>DIR/1H3'D5W-OXG*Z72`,SI6$_(?[(28I7#PTSHLLFE@8X3
+M_#SIZ'+<?T>;7!W'_!FQTB>CA]&.3[.9#G??[,US/1E]5@WK(/RDZ!_D++O.
+M$K$XZG`-6MH_8*O\3P"4+K,P@3&<T4RTJ4-K?<$Q1YG)\E",5L<P(S-AN3T?
+MN2`LH`.=ZA2<<%1`)IF6V[#DWQ/IV!Y3W62'90HG/N&_)KN>E`]AI*%]`>V8
+M^_?,9B')]83:?=<3'LF["R'@-\?>#KE.>A`":%*4YK%-]NY"*'0"F5![0O?8
+MJ2[@U2I,+3M%5]CFQ-8_O!QW\)?2^>3CAM(GI=(G'*5/6K[?:=G7([L>[U*F
+M.PX+=JGT2;1APT!/<`?J&LE@LLF3T33:GPC]:%,LX<\XE??XH)39+WG`KFO.
+MB!39"8&!Q6,*H.62MU]92!>`K;*WG[;3.M(@#^1'OJ+(SJ4,A4D=BG0V#AHW
+M4SI$XQ&A\1A@40-R>P$!M\ANZ2!U?S8!Y-(SE'DGRR65#A:@K9WV!6IF?IVL
+M#D#IX.SV`@SI]-@<RYY.J4M\1R>ML(_J0-.%Y`X(R\84D#>Z`#%B@\G)FM(B
+MBJX!>!U2N_$P7KAB<$WX_DWE_U8RG<T9GZ!5608=U'$:&=_6Y[TKB;6/%**3
+M8UCIGHUI%C]3=2:6QO,1H0!>X,A3G\?*/<K5(_$/4NR?I^0GXZ;J!V>U:X&I
+M[?[K5^D#-H;R;OR[8FNV;,)YU?X6\G<.4TL:\);1M!7;_AE7UDFN\[M0A#+[
+M8^BHUU2N_%>,7-F1[?T[$SH`2;97[L/\GWVDYD>>VH"[;L-X$*'<19\/X^=`
+MR!PN4W-NS`7Q)<GQ1HAO4>`/?STLX,NB^6$(^W%/(E8*>2\;G7<[Y46?K851
+M(^Y_C;+<POZM$6I+M]2N%:HKJ]>OW2"XZS>NJ>)75-6ZJ^\IK:IWUM675FU;
+M(=2N$#8YA7O75->M6L>7;6DLKEZW=.E2;N;<ZQOL^&?F]>OM,_/GK5\4_S.N
+M#2'?"G;&4)0M#J4W`OPWOO!Y+)J%)[;/9^=#6"ZRBD,3&K-",J6@70Y(VY7M
+MHC0;47Y/;%ZLWABK-\7JS:M!JMW\`IGHZ40I1+FR+-5$3VK][RTG?*VALWE$
+M@E:?^?N:FA--\,2'ZK]%]B1]Y=PD>O*=Y71F$!)Z.X[Q!:T.CI\CE?;FGY!^
+M'^A)TG`]NDQRG0'Q>=_G0!J5B*N?KB8(`ZS66+Z2X4%=K=-2>OX)V7]Z]+=N
+MH]AM"HEK\/-T]9Y0R-N;]Y8TT#5D*/24U^B53U>A5G[/>++CI\N8[`ABH'!Y
+M1TR8K'5V*JZ->+_P%53-BUK"KR`_"SG27L$,RAMKZ?Y]GD^J,_LBA9,(O25/
+M#EYI]^1*6^?@_6;/++S?[+%K9V^C[];'X;8]V?\[-FGW=@XO**)3Y:5EZN7<
+M6;!J=Z"/*;J]&-'CZ2C;=5YB)$.[.OZJ%BON4EO:T651'^Z\D]\B2_O3^(X[
+M`FB7\*Q[HE6XND:'PQQK!/[]\=C;L"Q)W@`9$VR/"9>(_D!,N"CZ!-DQE)L]
+MDK]=;EXK^0/TN=G(YZ(!PS=PD]_;?DEI0&S.Y_@"N6)Q4EST2FCVV1*SB<\6
+MEW+\1?(T^'AVA96RZ+SMDW%U;-?YS1$7R0H1URZZQG$MR$SM+"*@QN-/].*P
+MUG,<G#Z=NF^-9I7Q1D6%XEK#;FCX3;YS)>9+398.=-IWMF2B45@K"X\[GJOC
+M<"/1)[9,XK;/#'F?*+>\6CFI7`F5:A=RK#[9^Y2O[5UNP-=V@6OE)V%9;:O,
+MG*GO#N2MO+W(HE>L]+65F3DC'0A,0,MOYX`%C%X?QB+A"U;J@M*XMHM=3_H+
+ME$WZ6#HOO27]WB#T7`2,F+!'\C\J^G=QPD:"UD0K/UEN\DA"N]RT5A("`(UP
+MF`T5I,>:<J`CL;=21RL+1PO&G'@[NG&?-#`M,#!?E2N3!X9`!M'SM3%4!Z-Q
+M(7P^N\DJ"0#5<$$,FZI^@?BWF-VI`7Q8,KO9*OG'S634^544LPO;9?^C#G^@
+MA9>%1QU"`#[T[W'XVYO6QS\T>-LO*@TX2A_=GB&4.;Q[&I;+WCVS@3W&JS=6
+MW5O2`L@*<[G)2/W(P:NSA8[*?!X@D:^\4$(S(U*23^R"8`)J];>^Z]0[6PB)
+ME>?^1!V4A3U7OH4P]3]ZY>\)B]OQ30@`A'$3!Y"]/1F\;]"AJ7@!IKMX/@:,
+M!M;"MG`KK=(T:LST>&,F8&-FE3#D$TP1-VN/W]1ZK_EO4/5LK"UL:4?AH5+Y
+M6YGFT]OL:#+69Y#'INAV%#17KM`NC'7,&,837VLRUJPN'[^)F=!$2_O'N"?L
+M-XT'IY";65V.MXLZH78(VXBJ&EN3[ON.HD\)_]>W:/YB8LM-VR:"I.MP9K=,
+M;KV0Q9ME7<`:TUGV'8Z:PJO+E8W+52']IIOL<9]LLV8VS(%U#Y^\+"XY99%]
+M\WW);MM&IZ+"/%-^9BFD%7\SE555NVZ+4,O?G%A/V_I-J7XB++<PL\9^6^N]
+MAH$DCV]7*?>7,8]OV<D>WQA5#;`S81ES2Z06=]9ITO-3U:V\D%AW$+>F+<M(
+M*8T930NA;P4IA+;O5]>0]5@U=PVGO%+&]K!S07C*DQ,%FD-BD$KZ+>)SLF]'
+M(]UGS(X)MHK8"UBF4J^68>TXZQ]5QE-41EM2&;B2TOV7LR4&BV#QR27I.WI]
+MFO)@TM?36=),E'D\P1*#V&OQA,3#5&`^%!BL-(CO6L0+:4U59-5PY2OL\@_O
+MU'-WPQ.`YW$UC$^R'[^^7XXP.IW<J.^FQM%%^YVI<02`!A8'#,N/^C]+N8^>
+MJA,^%RO%\]UA53=4%2ZT6YG)/OY:5H[GX^]O)/LF<3K)?2@X"\QPZT*.GQ0.
+MMRZ<*^C<A?`F@#P"'&1#5NO6V%P0&2S[ACK."E?C1/Y,S[S*=/+9;/R8#.)1
+MO@Z`Z]N*=8%$Q'3(R:4>^=8$L#NZZZ]+_H+M,+=C(AD0>'BQ3FL:'@`,Q5S]
+M>(C+2FG=:N*V3^_#TU"0HV.6CE\D]3T3N(#_8GVAF-#68G%K,;`*=!)'/D;C
+MM<86D)_<1*W=G'8W4%QXLZ7]QURB$6C6<5I+)MKXF1F]*AP6AXRX+3Q(=P"]
+MP\$B0ZYEL1XD4]<`\\V>:!#`48P8D3>@(^,'<,?*WT^.0D=#`#78.SI;G*)_
+M*,9;U;J]0Y(UFD?W=P<Y],V8P*;H%+K$94[&.E528PKUB\LV;EJ20F28L5%&
+MHI+)U,RYUS3,Q3\:;=&GT);GEC#U<K\YM'?X<_)"][DVK"J-F;CB"VD,\[62
+MY"Y]!NNX-`2<7GI(S.A"@3$D3NPB/V&W,->9,6'YF&LH6T?$6(S/:UV\8*XP
+MHRV&/6ZZK#+4@6T"D?-%F"'=[=?A&ZJS1Z^17L!V1J^J9$Y&F<$SL0#K43]2
+M/G72M1MV0UT=$/I*^38>!?ZH_W-U2BY;M6:M<^5RYQK7&J[^"VBP?#-C8[71
+MMUHZ3E.5:P]CUZZ\A5V`,*)5H=]0PMV84*Y<YT1?/L.?Q;?!?D0*3K$7,$JY
+M;3G>[XB1JSMR;,/BB1I7*-%"U<J`I1TGF/11*_G@!*SWXAP<JSO&V\L9]5:4
+M(EJ+NY1)8J].ICC@0'&LB@GO@\7A&[J4=$A$6U'D]O19^&-I_PR2NW70=;6@
+MI4YF2XG>D/A^C1A7YSB53]<JOV^<RFU?4/<^JA6/SD/;=*W;=!SO&:M[F.B7
+M]7_5KY+6I="OT'/&3Z%3&5RW:,#=MPVX-[:Z0FE?JM?&X:=+4:Z,3@JK[X\M
+M)9L$*62;_JE33EWN9]$T2YYNWM'^2<MO0L29E32C[,K+;C:CIHZ=45<BKZVY
+MY=3SER6(&B[9K4<0V>XH9/>CT:;!,3$VH?E(#23G*G<@CGIS)>\SK#9?K+#0
+M)Q<6XO4=?=!ERK5T]AI:[]'O-!7I9;<)P)2K@]<1>&V]QS`@O25VF\7(H.35
+M?*A*FU%S1_2;=);V3^"]92)9MY[<YR$<@!>CI0.MX8B184O@)NR`\%3(^ZSD
+M?;*\$CD'Y0=NU5NN95<.I.JZ\R(5/MEE8VNU4H_)W7J,LE*4Y'H"^L=B:>MT
+M1Z_L?<8G%1E)6C`!JES@F&D'YF-8C)PEI9@GL;YLI2!1'WI<UG57U&0I9K66
+MF/"$PJEA8&@^=V'0B,$/7&-KS.HC*NW*$3LG."*677?@YI0WM[O(S"&D)B;W
+MXVD74M%<L=N2Z(I'V:/%3L8Z'M+>+L8\.6J>.BUVFGC$+OIS.-X"!(OZ\MO%
+MJ!&1$V]4+C0J71J8[<K5'+IJO(0I@6Y_7ZAN@:"NE'+58A3S_5E,B]K"['.E
+MR:XA*1W^T*'0*(YYC+V6;[$"0_X!7.30:\QH'B7YO!=-,U5"9X\MU>RC9$D#
+M??]@:[0D#)'YSG1<)OFELE=Q>(>$B;*WW^$=WIX5O0C/[[U#_@GR*E->J1*]
+MG/1J%;FT7ZHTD5T/19?@BD*[GSJ*ZG0G5=\DJFL$-``7\IXLKYFD[%J*-H3M
+M'*?\>C$9FHF(QK.LFS4<MG(&M3)'?)FBA<MEX4C;>[&_(6Y7*!5+F9T2ELC_
+MB]F6@V)O0+(A'%%N6*Q7C5%!4:>6I!HQ23G_6X!.&[$8VLY.<<'(]"/B67,7
+MD`EC`#'KZ1#N%4BN868A`3>#335ZO"RO-"UA[GHU6[;$C=TY,,[^3&(LNV^D
+MTM%`02=O;*TSZ2O(W.>?ER":X`T>B&TTZ9//]XWQKP,WZJD-N,-98U"F$FX)
+M!MDU+-\YE-@3C>>_-3F_3GGOIG'RQS//QLRX==I4I$\&4=]/%NG)QT#:&GC#
+M[74N@ZOOB_>R;Z>6OG7\]'NU=''\]!(M?</XZ5=KZ5>.F[YU?7U]];HO-'\T
+MVO_Q#:2D7E.L#"R(:P3QUU8JM^'Q2T1J7HRN*]E9C%5R%X:*%QH]RI$%Y$B2
+M^6Z\-"2&7QM]Z?8[D"/Z#<EM?LK`9X5C;O-9M]D@G),KS+H+4L6LD'C'E1PS
+M96&4ZLFIY%1FNE#VDET1MUG"&Y-6"F2+;JM1UVR+N/'"`T<>,7-E]RS)G2_U
+M&.`/_I\3<<^G6>=>R"Q,?9&]RO+Y&H,)K9%7S!$?F&]HO%(NRL\[*@X9&J?)
+MNAV]74>M.WJE#+%H_K!8-,>(?'B-D2F6XMZ9:L]T,F!./.]HRY6C[)]<SY2,
+MH-(ZJ-<J]:#FH]OJ<-L:<J%[P]`W,KX#3-9[!JH!YQ&>]5=8L?MRAE:3_L"7
+M]Z]>K<J+JM0=)_ARN6D^WF056T#$NJ@2[7\<,9(X!>($U',:+8("+>QQ?-RH
+MEP:D;EPG*=N5E,U,V?@_Z@1S7M/\O(^C/PN/T]?4-OQK7FH;OB8WV7`C+*F.
+M)N0AL)8M-R*G8RBQ2B56'5I&&<[[&%T8EMB$WT9*5*A0>WY'4J")-?NG>,$@
+M'!ZO+<GZ3_-4NS-F=7OV1N5A)+U=N`UUK0QL'9\E7M#QDZ.7A0G6LP%#WT#"
+M+U?DSZZ8D_<&TC*2"Q+7&$;5H9O'$*K97*$T8\;#L[WDE]=#%JJS4)2[DME.
+M*['F]3A*LAMNA-XU%D"'F0'7/$J;`VF5\YLO=93DUU_L*)D%\(*XROE?:,>V
+M0C,89`8AE&PJ8U53HW.DHX8BJZ/(5G^57&^5BJS12V$=6S%_^T68,,=1E%^?
+M*=?/R5LQ7[=BCC3`+I&FT.6Y!6S\ZLSHNO5[UZ.MZ&]?KT^RVY9D_S6>E^S!
+MQ1KG5RBOLI'"VS3JM!2;$?LJE.6:)$_X#>T2F^=S+:]A,G\$YB[F3381-^K\
+M+S]>U[5:76OB=<U/KFMBA?(7G;9K<"G5TD.UO":[YSC<^7RJS?4QYVVSU:J6
+MF>DP8[*X+0<WIYVHLNQPVIHNBCB)&M7H5BM8*RH`HNJ*,UOL')979Z.KA-;X
+MG(44"5*<5N.!I"5WE/V[ZPA7H3H='9AVO3,=$&9V27:H;EBNS)8&,H\FRFNR
+MSFXRPRPRQQ;():98CV-`N`2MLY5DRY5F\;!1JK1^(=XDTW]6IUR2+_8:Y*99
+MNFZY,A>/]#P56+`]UH.(;)&:YNBZI:;\\6UVI\[]C^>J=H>L';'F4KD^?W;]
+M'.&2<IS`K4Q1E4W@=U2Z,^0XUQRG.['Z.9CQ]GGD&$97/P>ISCD4L'\]_EQ/
+M.?-LFLMX39545\7(''->$IEV#:,]J.E2Q4(HONU=R-`B5<P?9:]Y'#IR^5S-
+MR'''V>9\`-?LDCF"K5+YQ8CFS.)]Z`[J?D@?.[JA/P!"'<S>[NCOP^/:]2<_
+M'NN:T@X\8<$;2(9<C<%(P?<?7ZMM$.-VJ\LFZ4/B=E2MA&5SA55:89;J;0G<
+MC9?-OBBR`29*1;:M.7*16>8T$.C$(K-1\^"!N,'F,RIAH9(5?>2T;;U,7FV6
+MT^,()SK5CU3;V,)8V]CGYZ@+*ZS:MKPA6,"W3F6NGLU*$&:33E5$^3);_R^,
+M6P9ZN38K[B\K`Z>JQSS;`VL,]0=AX#(#&917F`TK;(ZC+5.D(G->E[3"-J;O
+M3.>MX)C#8]N>F>>QP9S7><S2T7'PX.(Y2?:_/[TAV;8U"/T;PKC1XC9YF#GP
+M?R[0IZS3\5)^/QL8=9.JP;K_!OWX]."GLY/J$F*:MO-29B1BJU8Y/Q>8)+;.
+MZ&$=8S386@GPB_5$KPDSJ^E_FJLU%>\'VI!_)./IAR$^V<_*>&OHE<GMT,6K
+M742KFPF7G!E`C5F7Z[5Z^,N8!?@JK&!R6/-W<1B8KR\=_VN2ZIH9+VR>ZN-B
+MOA9QI=ALU`F7H0[(XS`?/`@35F$/L!.CSX=3ZU@=KT.U?1EQTUT:<2DGE$*U
+MO[A6JV4IJW9BO-JYK(Y=\1R7L\'X1CS"S.!=<^TX_4R,?QZ[?0ELPOFT)B\S
+M`/86.P.H@[1'X0G#$X"G%9ZM\$3T='"^,*)'KWC1_(@>N?GHK(@>U1NC=F9*
+M.YK-#+9'K1$]'@)'BJB'T@I3DMX+FQO(]DP2+Z0+DR.<ZM\GPF50(,+1MX5T
+M^B]Y3&-A.#%/@R&L/JAMCVA@!W0+BRW9G)#%;G-&OPYR:ZPI6XD!F01F%M<K
+MY1LH^4\,1]+):CF:%36BEY0,_O(FX%_2^:SH+'$HDY\6O1+Y)4PML46GJ.$H
+MU)=#<7:TIS*.!D"*_L\LO$9A(EDZ1WEE/IJFP[>;4>YMSHK0"T<G`!@B$)&]
+MD(:-]S8(#775M>LUJR%SYS/+(4E.AN8O6#3_AB0G0WTA(`YAN3C7*',2_#VP
+MA4L(:.\6=+)FLO+Y^B^Q2.)85#!_E$62,"MW;:X)<;NP*&AJ/\;?NC!+6*N&
+M5T)XF1HNA/!B-3P?POEJ>!:$<]5P#H2SU;`5PF8U;%R8Q3]AV<=9]DW)Z_E-
+M<GNK^"]N;[YC3'LKY>VY)FBPN7*XH%/=6`^MBH6#^H"NO9-?&2S2!9P8*@H6
+MZ0-./806!HL,`:<!0G.#1<:`TPBAW&!16L"9!J%+@T7I`6<ZA*S!HHR`,T,\
+M;!*[3.V=PC.WWO6;\<?_*^3#@#:O.TYH-C]TG1[R=I<^1S]J[P/_X68JGHXN
+MLL]LL,^Z?6;#G7-G"GGXEI6Z-F=AX<QR8G[2@</U*##_-Q3M\<FNJ=HA(&Z?
+M/3*']F\\=!NQYX]D4-"DU,W2BI'RU:4\N0FLXM%\P4,SQZW[,JS[:JR;ZECS
+M)[4.\]@Z4O7?9A*O*XE'KTSF3>/IT[7TXRGI8K\UB21<R&6\BEYR#:`5)-<@
+M6D%R#0'S`6Q7P=F"8_)N;*FCWMR\2/8/M+V/N\QAZ6A7KS&TUFJ5]<]RCB'A
+M(O$!(\>;H`2':U!(<Z-S"*?ZY0IS"]D].I.@J6W]:%,VJ1D-V`R_38S@KH(/
+MBE&'0.H8POU2^AL+X=^.3LM#>,TCM!=MFTE[!^EP=`,:IHV]@"^5[)A&N?8Z
+M=0]7V[>\$_!;%ZE4GH$$R_X!,:*O5)Z`,%4$;ZA3)YB%7(?+*DQ'+5(J3NF8
+MI2W"JF\2.B=(:5%+*V[R*R,I9[-C^OCP#"8I8!]-8_OHM2;%.2B.MQ5T]F%G
+MV;Z<ZE15J[6Y_LM@P/RCS%5AL/T5[/FOYR9Z_N.YB9ZSTP$0'EB/;R?V.`<6
+MB-91_7R<\1R)KJKG&(CWLY@RPVH\T-A8>Z]FE6W6##S1L%>M7U^/_@5OIIG1
+ML&7=?=7\K,9U>=RZ+;6UU>OXZQK7<4WU&^/^<6%&5ZW7PJR6NBVU#=5VOEZH
+M14>)Z[,H"Y6A%K?^WGAQ%";[@OB'WP(_FR`:2T*K1%L$'C]?U^BKW[(9([=L
+M6F^OJFUHJJY?1+U`2X];A'JU$RRNJ7X+=(OI9Z`S1HAM&&4=CNEI4.YX.]5R
+M*?)>*#9>#>'(W:GGJ/==23R&%#I)%U>M4D</!DC[XJS3I!,F*;^=0SNVEO;T
+M":B52BE%)KV0>?;!*@A;^9DA<=E?<&OO.>0]Q.Y;*Y2N&?KXW2N!N!Y;I./@
+MYZI?"HT4F83,-C]=KH15EI)I][CC^.>:*XNC\=`1""VFT//QN$ZM0&J43-\Y
+MBHR6A\YDHKL0:DW7K5+H63H:CN\[2AU/?8[X&^DXH!40PA`0#ICJF4R/B=*0
+MYA1;K7@WA:IE^2S_?;1A@I(%]+;/A;G%EY$@<GQ508SLT>$1!L/P4*EY=<@%
+MC'[I\&J9R&:L!X];L\4+1LO.?9FJN\K<7F+J7IJNYZZSZ[FC\/O!5#TW#QZW
+M.))G>7A7)BI!\C].(N(HKJ+!15R\/*RUA9Z06/D7,AJ%/5867\7.VPX1X"WM
+M`WH-]FAN@:`7Z7A&!8'X\D'LQ/;+Q)>/8,#2\=VDV#3ELDQRRXQFYG.N0@X)
+M$]@A[ZZ?F30]!:;$46/%*SS/80[E[9G:B4JQ+--2E"F%CA"R0?O-L3H3]"*6
+MOSHD!Z'IJV,OX-@H+^)-)^J4Y6<$^;XA`XU+1,36$5$0WJNP['>9/<H9X-0E
+M05-B):L!`WBMR36(9PZ*1VU)]4Q:YL7#0'AMCAY^?FI[5H?$O0QXU(+GAN+#
+M_;,0M>"XD>Y.6WT1UWNTMPZUO^>I5$MOL;.-<93\+]*=@U7]/5_>@$]RO2>\
+MW7&VI3)N/9DP&4;JATF5N8>PSQD$4/$09KC1TO$=O()RB&:`I2-$@W54G2)*
+M"/+V;?B<E-64E<!E^Z2.)^%5/8P<PNV34A!GFZ]/0IF+0^(ODM#C<CNM,PP%
+ML%0\&,3+V?`[A`W'OHK^]SA^]JB^[I[^I7V];$Q??PO5]K4:R"?+,PP9KT_#
+M:8?$IG6Y7D]5SG;9L`Q+^[0T&NM7D#+XVJ`%^B:C93^,=ZCC#!:H-L.<:(;E
+MH;\;J0/QAASN>\-(<Y,A<*:*UOQ\+9"F+$LGE$:W0\NGCT+I8;1P('9>R;@]
+M!D1QJUG'7RH>ZF1#TH7SX]`!]O(\31;*+]R9@O]7:?B_6"X=CMUOCMUOBMUO
+MC!5HFM8A^8])B-_YZ6C$C]$:S-K"=KD9757+K[R:].`<+K.E_>_85$+J6$%(
+M_$<2@OWCT]'8/*)3[W%3F_F2[HZ+88W51SJR1QA!\$4ZIE*PQAKJL(TDP)YV
+ME3X%-(EY#_VDKH]J8O$5S'./R\P7I\[Z1&,_2&KLP<%1C57^BXX8<OK>,B3T
+M=F2K',*1>/-=:>]I]&IYK-G.4MA4D'KD$/X^=FZ;6>J67CA-TPG_<BVPVIR.
+MKS:]*@6LL8=>0/2J4/XG!QEA;#LS"]\EOC-=O1"5V;X7\X3H>S(`7\%R%GJ4
+M]AR&CSD=9_T7Q8=7_`B1'SFICK-"?NIT'$J:C@_EJ-/QN-JROL?.)XR=L@7O
+MU.>JSQT*>4*'C,A[(;A)VX*!^W?8#"0!V<!`79UHA_&O"1#_X1/XL\Q`0];7
+MJM<67=IT[D!6P">KL]/GT/%?25KU)[)5WVYI/X[7:<2)4"HS*Q'6]#\RC4)^
+MI:(?U/8\9ZB?NU,^#]'GE\/GT=*D;TW">C0<X[+A!2*@Y0;5M>-EG](=(BBN
+M>-SBEE!Q!7]-`/3FRU!-YEDBDD-()_MS:3WLNX@X?.Q<T&-H?=?2>D'/FP(]
+MQN'%NJ;*I`'Z2D@L22KOGY>.*N]Q5EXJJGZBBY.+`W<C/"WM>*<K#D&[L)@!
+M]JQ3K^?S$::("7<E5=1^J8H)&D>D_!?\[=MV#IB6L?R7'=O))WWN&MW.P1G)
+M?`!_<8+_XB]6"9A@CFN(Z80T92XV_^7C1!EN)ZXFP=.H4QL-AAX?Q="@O@0Q
+M-(,*,C3(PR`_,S1U-#]SD"-^YFF@^GTO,!F#:)[&R!$W5F2V/"R<I<WY1!)-
+M><<*H^7A)6=15B(:3/T2[A`/$>,H6+1)<S-*3VOB^J7(/D:+-7O!."5:_C+Z
+M1/K@``AN]N0\KT.>Z)_4)8TX!<FDWNK;\WE<`$N6@Z=-U<<9ISQU4@:RD6AB
+M$#]-D$_&SQ`A3=EC^-JJ,E>YRTV_R\N6K^6\GF+G6E>I4PNHO\5:1+'ZZ^06
+M<@NX&[D;N+)5:Y>[;^-N6>UUE=_F57]+N>7TR[&_9:MN6>8L*W%Q!?.Y@NNY
+M@GE<00%7D,\Y.*C<NP9*Q5)*/5S9K<6K2IW+R[@UKO(*MW/Y2LZ]JKS455X.
+M&>#OJG*NOJ::JUZW80NW?F/#NJIZ$(2V-?!5/+>^:AO99:VMYNG]_BW\>F[=
+MAJKZ>ZMK.1]?=RWZE,<`QU=O@DQ<PV8,XR?UF^HX%'RXI@U;-C9P3%64JZKC
+M&^"/KX&[9\L6OD[]6<?Q6(8/),'J>F[3QMK[N`:A;KT`)50W5:T#40PMX&-I
+M#=S&ABW7\@U5==S6^?GY].?:!I#<UC5`]=?6-G!U6^JNG0>?U]9#L>A&@FO`
+ML@5A7=VU=57P6EL+K]68B@'L5D-](U=7O\4'XB-75EVYAFNHW5Q'?Z[EZZ&F
+MNOJ-M?RUF`NMLX^^_W41N[.U^K.V"S]"DK%3,JHSJ;"?[??.L>JY8HN>FS69
+M_>:HOU;UUZC^#JGY^M7?7O@]"<]1]?V@^ONL^ON?/D^J^1]-^FX7A%O_PW+X
+M4?DVJ.]W_)OO/9@.S\)_DT^#C_W?Y+/]FW33..G#\`S`<P:>4_`<AZ=S5)[G
+MU=]G-'BIOX^KOWLTF*F_[>KO]O\0_GQ2>-._R;O^?S&N7_3<`<_:?Y-GI04M
+M!;WW`3``:.$O'!*C&/X["W^"X;=9^`*&_X>%]5$(O\K"61A^CH4M&/X)"T_#
+M\'=9V([AAUDX%\,B"\_&<!,+YV/X/A:^`<-WL;`#PVM8>`F&2UBX&,,WL?!7
+M,7P="WLP/(.%O1B>QL)W8'@""Z_#,#'E(?%=[-<G++P!X]]GX2T8_C,+\QC^
+M/0M_`\._86$1P_M9.(3AG['P(QC^/@M_%\.[6?A)#.]DX9]#.-H<$I_#W\:0
+M^!+^UH;$5_'7%Q*/X._78>W"WXJ0^";^EH7$4_CK#HFG\7=)2#R#OS>&Q'[\
+MG0NL*OX".W$6?Z\(B1Q0G^A4D(RS^NDRJ_DLJG>OO2CI,NO&=4#G-MX+?^Z]
+M%TDAQZ\#2KEN$U=]+\8#^6VLNW;Y<JX.*#%0_2T-G+"^;C3]FZ32OYAXP6K9
+M^:S&1BS^B(A?*R1OA:<.'CL\&^"Y&YY;X?'`LTR-+X1GH1K6GGQX9DU"//WC
+M`(/17P<8C/X^P&#T_@"#T0<##$;_&F`P^GB`P>CL`(/1A0$&(]U'#$9I'S$8
+M3?@H%49V@E'^E-0+OV/U'R:RRU&,K2G-GA%$;E$J'48I?$>O9?\0FK1]%?F;
+MEXB/Y"=V'./O9SR?CM^`CG>%'.56*S-Y=6M8DXM4MI-/)Q?*%]$U`E.%,@TW
+MF[KI+F%H!Z*OIT(1@2D)\?F0FGF)NCD+KWJ0"5!=UP0"V_;K5VU[*K5<"Y6;
+M=[:5-<2.#G>7F[9.DG7=7%9,%[6@CR]@$7-JLI0_J5`8&../XQ,SBEBT0]=Y
+M*S'XKZ=QR5?7[%OJT)=%PR(.'4&-/O\UDSXB$(%/`.:52KF%^6WSFS@ADX%4
+M\IK(&`CIXIHZZDW\M`KEZ6P\!!9O8E_ET%=6W5GA+[%5IJUF.0-[D!&=@.=2
+MT/J<*8F#>6C4M4N6+',YBUWEBQ=?"ZW#NW"+2(D>UW^A@84WXG',>NXFNV]3
+MU;W8^/OK.7M5%7#IZS@[,$7V^BJ.]JP;*-\<N[,V'@)&0PNN7[^19P5!9J]K
+MS=KEJ\K6T#YO)B3SV^JJF8.L.?9UFZKBN]R0V5FVIM)5SK+:G=ZURU:5+U][
+MF[W<=<NJ\F(MNKAX.1;H7)D4GP4)<^?.3=KM5F,V5VWR;:G?7+T^<=\\V2[:
+M-1/H*G?2/8%)RNZIZH[QA^CQM]0DE0ZA/U@S,W)=.IR*4%,8*IE@Y$I-9YT&
+M"W^G7#KD0P5+]6K<:KP')XMX@2LV/QQTZCL5`_H/ASB>Q87$3C:FRR:2K),R
+MGI/4\5S)Y@JD;3/))29'278+Y;DIGN<F91;+D]K"B:R%>A!:4?@6/V1UG3:S
+MO*5#K=OTG-\*\CQ+^$T\`80\(P\)PRSAZ>0$/29P@Y3PS>0$'2886<+6I#H,
+M5(>))=QE'J>AF=JL;"0(.K73'<!Y,_ML%LX<2DM/I$UC:>9XFBF1=B5+&YB`
+MU>6RY*Q$\AR6_,8$YJYCO-9,X"_!X<B,3R\<B\Y)6K^2FBFY!O'.D&VT"(T#
+M@`$K8!0-P$)6Z^U0JVJ0$$1U%E="+3$YA&'+CMOA&_5DJD)Y!(D"N\-I:5\.
+M+Y1EX9BZ,M6Z^*LJE(\O4LFB1XE.I/Y^E=7R3A83J;OU5,K'W)>5\DRB%.]%
+M5$HE*^6[\5+&Q=?')S)\+1VT2'@+A:K:20"HI@)J[.@Z8[\SW:.=M>P]SXS!
+MYG2<Y3=`_L;;0V(]RUO(\IKB>3<FY5V,>:\+B1+EW=#*D=$8R)X5S[XH*?O$
+M:#:N(^(/('LT'?@0UI__R42"J8SG*]V003[2-N"6+I;V_&<I-E;:^E&))(FL
+MO)E.F_6R8&-7Y`ZAW(P^>Z0>@PN-:+\ZF>ZGT<DAGKFB;M62<+B5,G+"C%@9
+MSG*WR>'.;LF2T[NYN;'TJ"U<43-7*08\1V-%%97*KRQT9&V@@D(_&HB?J":W
+MO20=VVY5VT[`6*Z9B!FO[=/2:6D?U7"H)HW67512TXUJ/>J)5VEMMV#;':SM
+MS071A=#.3`LZC$F^>8BF,@^FC4`)<_DKDCN;J776A'V]=<+X'<Q$CX>9L(+`
+MDWD3\QE'M\'JT+T<+#R9=/<2UX!KKKG&7EE57XMGK!A>M>9:6H`V;VQH@#C.
+M/BN+R\S$`J&@ANKZC56;DB+JJWVPFF^PSYK9D)<2S==O&QU9O;5N8WUU2JP]
+M#^(W;ZS=N%G83`G0L/5V+O,J^*4.D/Z%G<N"[%SFTIGKE^(*5U>%Y[/VAHT/
+M5*O^V6;YM@BUZZF'ZS=5U]J;JAK8Q3=M34N^.U1A3+DT27??7K6,<_>MH+.O
+M(%.]Q\O<-:.XCBY\T%'6.PR_5-+6R\[_+8D3\?56W*@]+D:,E4H@D?$T)$K^
+MDRH].6(=14Z-_,4QX7A(#%\@M0VKXDT?G_;>39DOJ5!Z)Q'1V:M]D$L?0'M[
+ME8LS4Y,R69+L[5TA7JBV[#R?H;+B1X?9/L03.CV7#<_*SW3T8'@KQ^*RD]+6
+M#K.T?DA;^;F.RX_IN*=&="EA3,-P^'-=O#Q\AD=2W__O,_[3"3!N51\TUY\F
+MCAB%1E1K/@/$>$D:H87H/VT4`&/.*#>;]-I8]QG3R$;-Z0Q+Q]QTI&IGE"M,
+M='H1,:(?BZ,EE<JGR&%$]&SELNQS'<4;T8]IF/(W`]U!Z_N0G=49_*?[SB`'
+M7VI%(Q4FU4B%%=Y1,,B,Z?HN-9+_4&M-9E^&D?F1.JT[+Y7V6/8M*(%%96HE
+ME/\KK?P6*%]W#D^V_#V-,]4LEZ=DN4/+TE=#C1#]O1,M'5]'R[GB?BW3`FJG
+MJ:\D3?4IG=(^<Z)]T8G4-N4KZ6S552?T91?B$]K2;D8'/*DE3%)+L)/H0_VS
+M*^^FI93Q]OFD,HY^1J>V(?'/V$3ENDST8'R;604^].]O6M.WZS%I23Q)N0QY
+M$,@QH.7XFA[KR:]4+DED.FMFF3(^4S/=0,6<FQ#/<5+-D:/EN$@KYD0BTR_5
+M3/.T3/_2T2E>WPB=P54J;V5I7$U(7*%E.J;3,_T>UO&_#K&.Y_3-1;43Y8?C
+M?;,W]9NGM6\06-^]H`'<(N&>$0.ZY2'<,^H[J"-GUB%Q%1:E_",#V=>3AM+3
+M@%/(`O[>(N+!69@ACZ7]5[BO()RR//04DPL!LRP[<+^U=6D6G]:Z]"IA^:C!
+MG:@.[ATPN)-H;.]0THTTMEBHFGNNFOLFZ:/6\UG"].B\<#@IV:(FYU`R?S&6
+M.5GZ*'`TH,<<A#98=H7R,X/*\)T2_:<XR\.W(],'C=RY*#8&[Z:H3;L*9M9]
+M>FT-JKFJ[R9Z"9:>#I0JK>=MC<9NEV*#Z:N@@=*0JP](PPP=WM3Y9Z8^A?9/
+M!'(,TQA'ZU+FX^/?SI4+^A0\__!L$I[W#OUG<V5?:AD_2RJCXULXS-\>PG.O
+M?]N6VG@YE<J?TM2NF/I6J>?<0`8M'47(J"G]C!"6:PAH@S4(+6(`(;E2Q^BB
+MT?+05`AJM/1CEL.R+\.C%/T3C\*!8/Y3SQ0U0V*%5M)KL'*5%)PM."$>L?>U
+M,=RS2*6G2L*M,*!^7\<)81IA[-V$L==#,U]*HX-S;'>%Y#VB_/U].C;U*%/3
+M5`D).RY[CXSI.T+Q(H(A?K=%Q[)[CZQXH_J4^UPW&1P/R*Z3!M=I1\3R8/U8
+M'-+&(P]*NH:-1Y[R%590]!)X[P5)(S[_894FF)I9*2"OJ#L^5A7WLI0/./I6
+M&IKM.NEPG49.Y33`YSZMC*>AC(*8-*3=-W9R96NX6\J<I2YNS2HG5UK$E99P
+MI>5<F7?E2J[RJVLXS]IR;MGR,O<JKI3]O95;>^M:KMS#.=UKBHNX6^?=P"U?
+M4US&E:^%HIP>^G,7?K5F>0GW5==MG.=6KL2S:@WGA'_<RE6W<,Y;W>5<J7/Y
+MRB+ZZ^2<9;=Q7BK=N[R8*UE>/.9\QGU!I^Y/MET8H?.9C6DJ7]2;-D)\4>Y9
+MX'?@.3+('C.:?(5G\%,=I\!S&IX>>([`<P">9^!Y`IX]\`3@V0Y/'3SKX;D5
+MGI7P%,(S'YXY\.3"DP./#1XS/,9/$W7]WR?U.0W/27B._W^@+?_W^?_?,PS/
+M(#S]\)R!)R1.!2J@G3]E8U@]?[H,P^KYTY485L^?9F)8/7^:A6'U_&DVAM7S
+MI[D85L^?KL>P>OZT`,/J^=--&%;/GYP85L^?2C"LGC^MP+!Z_E2&8?7\:36&
+MU?.G2@RKYT^W8U@]?[H;P^KYTSH,J^=/&R",YT_WXV]C2!3PMS8D;L-?7TC<
+MCK]?#XEM^`M,Y`[\+0N)0?QUA\2'\7<)\![X>V-(_"[^S@V)W\??KX3$'^'O
+M%2'QI_B;=+8RG\Y63@[I$F<KR\NX96M&V_^%0:&;DT9^.K.198U^)1PF#R3\
+MQ72'.R3>-H'5=<<$5A>U8:HG7M<RJFM#<ET;:S?RW/KJ>X1[N:JJ+;6;MLT2
+M:C=NKMN4QPD-U8WK\)!_<WTB<N.]M?PZU/H6ZAO@,U]MU6:N@=^VI:Z66U_;
+M4+]N`[>QM@%3JPOBH7G<TORM,S=M73IZ#3K\B=HGNZ7]88AJRL/NU35-P>[=
+MAI?Z[NC[)>-KQ2$3?Y<X9.7OZ?L>QM`])EYHND@<*N2_?C-N[O%WD7=J@`E>
+M>N$W-DVX&7>W^%NCM1AG@N"=T74$I]].8&/[V@0VMCT3V-C^;0(;VW],8&,[
+M.(&-[84);&QU9C:V)C,;6XN9P7NJF<';;E;A?0T$`-YW$+R'SB;!.]\.0&G@
+MN`9NYGK[^JIM,RFP88M0ST*;-]:R`&2#P)B[)@]]K%,=_,X/B>UX=6OW#1-'
+M8M)N#/ODW0YX\4F[`_`6W'T3O`1V!R',+,6%PR^BNPIIX-P[J`/H'9:]PW&/
+M4'A[):];$H:EM^(9T.?9F`Q#TEOH8^[I<^]);W=]:)308'U7KP%2I7-Y$?0*
+M\1PVIN,$?YUX02>80KL70SNBZ:'=-\-O>4P8#(E+(>2I4/X"2S[PJ.&P&WWD
+M7.B(\0O)`INQ.]WN%F,Z88+Z,=EA9]]7AL1E[.OOLZ_9M^1?8PE^+:"O:5:"
+M?VB\^H>`468EW)E:/YGRME(9KHZ8@#;B..$F>L]"*VI4AUKRL$[(4DLVQ=N&
+M+L/$VUG9ND^1C"(D$M=V4OZ-&=M?#^@XU9B?:MA'%FS2QP9O-@V5U;(O2WJ[
+M#]5RP]+1F9UT<GDS_=S1]TU5_A-L_$3:5,<IT9T^UQTR%CA<PXV\#..R=K(.
+MAF?YUON!AY\F>0=*Q`MSA8FAX@(]9EG=G7Z'.^@:"*2['7YS8]'R;7^,EI"<
+M,<3Y,Y$!MA9*KB'IJ-B[M*L7I,5IF3VRWZ2+./RF)AM^8A%=@WKRM&)RN`:W
+MJW>&[D>]\GV6DHYCS$)5=SKV*^H\YQK`:_'"`KETH..8/QVJCGNHY">M5IZE
+MP4'[8E%+PJ980+4I)OS0;7EE*G0"!)`7J(GIL_U6R3]$UI3.)-_1MR?!N.Q#
+MFC^2T(O^L<X;2JU2Z4"JX231;^/X1=!$^49)Z!==-C0,4R"7VJ328=$!,$>8
+MN(:-LC`L`M8,RJ7#4NE0U+*J[U*:9)JI2*'7LF^J&VI"0W0QE8ZAN:4-I,1H
+MBZ&7Q-YE'LFK*.A+1W*=H7U*I:-S^XQ0I<[A';#LP!6O:\AD[@QDA![0!5UG
+M`OJ^-[6RLM&CK@O-+L#X-4S&ACC$+B.T,X([IISD'V1#G&A+=&%8O'"'`&(2
+MQ$QV2J70.C[7X1]H7!+H"624I,2;\>,>]1T18#"T+":5GNDX!A0(.I6%5[,[
+M1\2A)8U3J&?YLC"D7H"="?+Z&5D8#$R"G.3;#RIIFD;9,N72(=9"AB%981#M
+M2K`"<ZCZ9,I=;';5%DTE-,PF/+(60L/LTAMM[Q#F9[6=I]_TJ$W7$S461M/"
+MCH'Z4XZ!)F/>D.:KH'HH[J<@81.I^)\D`9WK(B2LEU[3G*1JANZFE0,@E6L^
+M4;'0@E;N2H>C4U+MVV60?3M^WMCO)Y0K$S]AKO_B-O'D]O!\HVJ;0CK*C"^-
+MH0-/]R..6H$4TV0G^P3#B(Q#EGU+I(_[VMGX2T.,!BS7:,!N%M_JF,M_H]5Q
+MAZ!S6O;I/$Z8\H#CRN<CY%+<.VC9I_<40:0291Y:(`IFH*-;<*_:]AO+/H<3
+M;9.W+N+X:\787'Y:]#JJ2YOT4V#2>\VZPY9]BXIP/P/]C*#)PDR8=S!^T:GJ
+MW+`A%7HPR:_!F60;$%Y34.^#\GR6?>4Z7V8/[:#%?>($=5V]V99]JW5=[UHS
+M`?]6Z[O>-5'`D-D3+Z/4[$,[2CV^+L44T`56ZY)]ZDA'NY3L@!Y_K($B'?Z:
+M`D7ZP`I#G`Z/L?TZ+ZK#>YPA\1DDVEMUH647XU1BT[G@;,W%'H1:&^*-=S`<
+M#NJ-/8LSF\R65_1B9P]01IA;$/?]Q6EJW$\Q+A?C7HW''<,X:QC`*V2(KQL1
+M$<37347B2'K3*I2^G[L#[RST/OB!CN/A"<!S-SPWP;-2?8*N?IBHI`D"\T@J
+M[8\6A%]AUX305:T!2+2K/WIYN.`LRZEV@'1`6$PTT^$?MNQ$*X&LLX'#(X>E
+M\[/>",C4==6R*3>.CL\D:`#,R1+)/QR2CYPE*[!^4^M2CE\I^X>#&9V*D:X:
+MAW;?<16P($9]0.<,PARQ4!`_<Y[KQJ8+DT,5.C1QOB_#<=AO[-;-=;K5U^[M
+MSW?CVGGD;(K-DYGKYVK_4_G(!_ITG&6?:P+NZ&?AGTS\8P(^K&XJ+,4U4T+/
+M<>>0$_OKOY(XL=0R;NPC:J#.T_RV[L5F^*TPBN=CPE1&I:ZA.6LH,LW61Z\@
+M&QJ.].:+8,W-:IGH6&'T_[U0/&QUI+=\F'#MG?*O[U[`'+)?5L6-;_],2[]\
+M_/2KM?1[QDUGOI;C/5JO$#9'7`KB!EZ+QGMC)^0[S["^J\9`4L^TKX./U//@
+MF9RJO)3B_R.1[ATO_</W=:K9%G0Y,%$N,JXNEPN-L9[H56%Q$?!S+(:#B,GB
+M(CV?D6S+:IS[U]]/*D^GE8=?7PWS9A'JQ2=J0-L>7U)FBKV<DO?9<`MF64=V
+M/.HS4=ZX/KH(UIA7@=0.RZO)ELYJJ`#*GHDT7(O1QWK0S:-/=@W[I/0DVS`I
+M-G12ZGO[O2^I;___^_7=B_4)9N*0AE5KA<I%=`&9MP1=PX'T,3:2QBUG^GCE
+M1#__#\M)HAMO_2,5`-?4FQ``SNCR,#!1EKV=4D1\7P?D(14.UXZ%0S9Y#-(^
+M6)):_\`X=Q=N_T<<9U=_GM!Q2&J<XQ]$U(#%!MYBN_26^)Z!SWP1;T?D?22]
+M+B[5";/E$F,Y;N;+A:98#_.SN1+8PE5R)9YOV8"\>"KE(DB+.M&:2E)^LY8?
+MM4RFL_S;KV+YS30/EH["64U!;^OZ^KONV<:C7MUH8X:I[=]V1D<*:UZS/*^2
+M=#GB?KK:=^`D6.KPVQI,Z)-ID5YH(EL%.`B9]24X"&71];#DFQ@D;P_CG:Y*
+MY4\P\L@NF*5YS%EJ3DBLNFQDU-V29R`7[D.@R5>3\F,T=G(I^IVN4.Y!S/&:
+M5:,L_SW6%E>\]2__';<!F*T*C]AI9'>C$@Z+4OL:^CL;*^2?S96$T\S^S'3L
+MOEYL-J)Q=4<Z;Q.[3?@F?(*,LG`Q6:FJP7/*2MF-N(4Z2>J[-SMV(AGJ#7S]
+MQMI[Q[<AF8K7(^\B7IOE`D1N9`0G`D2%'#R;PZV+,2YCT0^1.HV>O!`?I!"M
+MY59'*:S*>,8"<GD1%8BC-*%^&8[2VF@-^C3C;\?Q*5<6_8/&I]0L%<3'Y^V<
+MT>-CAEQX=@>D`UWV@GQ*`_4YX`?9=*U07CI#'5#9\63:,MY<LD!W$68TFSXD
+M>B*,1V_Q7W[!O.OGWW#C@H4.%6YSDN#6_0X-HS0BBW6HN+:PT2R+V_$XU'@@
+MNB$<*CW5$?.G22/G_AH^\+OCQX^?>Z_K`T/(^"WTZGX2=R%.!MNOL%\Q$@/^
+M0GH+NO]'R`]<Q+7.T.Y=,+N6!W6!(@LLR"'AE..CQHG0/HS2%SD^:CK;C<K3
+MF"M4?31),M?I#<:T]`Q39M8$\\1)%NOD*1?9+IXZ+?N22R_+N?R*Z?8KKYJ1
+M._,K5\_*NV;VG&OG7I?HWZ*;%M^\9&EAU3WKUE?[[MVPL>:^39MKM]3=7]_`
+M"XU-6[<]</L==W[]KKN_./T;V_W-+:UM#XKM'3MV!J2@O"OTT,/A;WYK]YZ]
+MCWS[T<>^\]W'O_=?WW_B!S_\[R=_]..?//73IW_VS,]_\<MG?_7KYYY_8=_^
+M`R^^]/+!0Z^\VMEU^#='?ML=.7KLM?\Y_KO7?]_SQHDW3_[AK;=/_?%/?S[]
+ME[_^K?>==_]^YA_OO:_T?1#M_^>_/ASXZ.-/!C\]>V[H_(7/AD$Z2)UG,WN!
+M!7NY!R#,R';4'-0YVSN%-!CM*T$.TZ%`&30N7&A<Q/^#7HT++?LJ8I9]MD5Y
+M/=ID&J-;^_K?=.A@B.-7L<*1XJ,X#B((^<[T@WBR%*1X%#I!Z@D:%RPTSN.M
+M4/H"8/^Q]'EYL-1#OF`&<).#[9U\6JS4*G0CQBHIVRRI_?'^3:?9;7)G2V[T
+M/63BT\GAS\0*Y6!4IQIG=$OG48@;DJ?.KK`Z*FPME@IER3M:ZJR"$[$RDYP.
+MF4RQ]")(YR=`23I^JAC+$B97*!=!5K1'R5A&/9X+IM@+O#7>H"-_I=U/7\3U
+MO$DOH<?#`Q$7^FEKB;@.XD_(925K-JZG/(H-9ZGWJ6ZTV_-DPEY>*FSK_ZIC
+M9A2M>FB/WZIK2L>]#-5V2]]:7=Q@=*4R^PQUB9R\7!HJ*724J-YGGNZE!-45
+M3J0DF_V0,2W+JTUFZ:/V8W[(:55:6<ZV]^[X!-TM0*7WX)5*)&^52@/("9G=
+MI*QC`PA'7&BCBZ.M$AN9E;P+[<L(4(3D,C/8@J`R2*:32VU`"'D+R[Q:\:B9
+M\*L9/O%UO8]<O2*5XT(EMT@94HDU4F(CTE6'_GQ?;Z6JJ)3TMM=QZQ>A(1C$
+MUW7X+1)-B[3*BELZJVSGNK$D_DHFEO"3U9)E2/FCM"H[:J%LIFB&EK"[G11L
+M6W'+1B^[!I/\3P/_79FP_WU:QRPW]*._,=,87V4#M!;T2ZY!U9<R&I-&3<HM
+M[V*'%=FEH"06Q^AD.KP3RE;Q`RGQITA-1QMT2LY?"?G)"FS2?5>EY6\I7UWW
+M%3Q,=JY4;T76<]=5\^NNJZ]NV+*I<>ZZ+;4^[;:B/1.MME3A;C]=/B0#+ES#
+MEGI^T\8&GE-O.7#TB6K<!H\99N7-G3O7#A2P2MC$V]EQ@1V_8)<`F+9_YMRY
+MKK+BN7.SN'+7FKM6>>B6`%==VZCJU.:G^H)H^;..BW0,?*:93^F/AY1XZ,QG
+MR39:Q(6<D![ATA(16X%'R(@4&HWQ*-*/A"A39]R\B$_<6@CBAO+5+.WBLT\J
+M*F1ID4);HOSNPLEZEN'`#1Q:BX=\4[1\9ET\7^L3Z$=BH#6`/SHU`RDX$EZ+
+M;\Z`M5Q9B[C/;%-;VO%DBQPF5*@M[[S;HZSXJT[M=Z+L4-W=4EUQ:.NR2$>/
+MVGF8B:U;[^;XS?$[-9UW."(-:UN79/&K6I?8^;36)9F"M3N=8]_0;)H1%@]1
+M`?PET@(Q8DP4Q^"+F6CG_!G<7`BF&\\MUC5.P!@LSB[\$XO+8/WY&_8G)+Y#
+MW?K17Z!;'8,)3QR_2$NX/#J-VF0O#&J^-V(O8(12\Q>=YH!C*61F[C=NXM]B
+M@1G\[VK20^+'6+KZP6-_TSX@UZRMA](AGYV?R`*9E@ZD$N(APACAX=`+&*ME
+M,JN9!.01W0B>"P`>_E/HF:7];MSQ6I)E::^$@#H>=-5?[+X;^"F<F>+Y&70&
+M\+W3;/ALP!,;"+8:6O9=2GX;L-&?)S7ZS%_CC;Y8-UZC8XE&6SK>0@7HE(9/
+MT!H^<6R[GQI1V_W]D7':K4<*D56A?.LOJ4W^0HPB=+H]G(I/SC@J34Y%);1W
+MK.*2910N$0:]%$W'EB8AST`<>1+(UH>&*FJR0J(Q-P&S9^.8T?$"#726!K,L
+M!K/O$\R02.@M#W\+L?&%+()9E@:SK"^"&?^Y"K/[R$(&.B2!87WH79WJD*]]
+M3=RTE+P7:T#_S)1-*IYL4RE"L15(@IQ"$HHG3XD1V>J;0G:;:DPAT9+4I].G
+MXWW2Z;%/)JU/)M:G*`[*"_@B'D("EVEY^"AJ<H;P);08'39R4?V8_CPYK/;G
+MNQ2XR=+^+9QS+_1^AJ\<7X5[[*^DPT3MH8G:_F>UIT()Y.:+(,_VFRVO3!WM
+M%,92KNA.QX]KK./X@!'2:9Q_:'EEDA3"H8?A#76@TQCH,U:O+'PG#M4!+F$!
+M"[-([8LVH&;D"_BAUC;E3_'\Z`\O2`@52'>SWD0=XS336JY\[<_Q9DX>SU>-
+M0.>)?!9V%_"0\Q_XXA;OZ%5;P$\;U=I-\!+-U>9&[/F%V'SEL$'KEIH%.;"(
+M*49+5)#J"$S2QO,A)TS3OD\ND-^RFHR0F)V$'P?_%,>/-RX@*F=H^)'!\.-E
+M]*LDVO&34`?&>103,Q?>]P3*G30==,T6U?!,"%^E9:K&?7`O-J'S72-;I"RF
+M\'J"/M)D)?,4`5#S_74WT@'A1J(GS&]2A5)[2L.:*VKF5BA+_\A("CJUF!AR
+MZX`]['^;<HB'%$;)CB?6KF5W2\N(TA0N0R0N.!&G0$1Q)H9;E\P5=$6$38/Q
+MM.B<L'A!UWPMU"?M/87M/`:-"-7IB-C(%+4B<;FLT^.(U+_.R$N2>91E(7%F
+M+N$]?)SP;@:CM+68XR\+AV,+0N)*RG$/ZR-S.R:\'Q+74/17&71"XEWTNN=4
+M?/V&KHOWY=*RT)S@`I:9=&CW\,AGHXT!\BH;->NJF0U7S;'C7^2?LKC:]5OX
+MAD7(*E&(O!4R!8Y_\RVQ5Y0S:Y1LY#A!AZ()0%C:#:2(;*X(B=YKL2,--&#F
+MOBA'9TQ)=`67L*9KJ5]?.:5BI7!7R)WN47[\!QUSQ25>L+1DJSU^UZ*R/@RK
+MHA/5>&*$+$F#L2WNRP[(43.UXI]O$="C7Z])"XDRJ_17;VN5+I-?IH]+3'HA
+M5_/3]$WZ\/FWM/&46TSB[_725A-\$Q)_3:F/4+'&:$8XL09-HC4(B6:'E<ZO
+M1MDP5^V#=W1NMZ";O)CZ?NPW8=PX[T0[+:V\]0"2G412^``:2XF_:SZ#X@/Q
+M;(^.4_T%??RFCE/^`7]\LG?(=[UWV%=PV++_L'SG8)(\D'R>R??H-+\TRL4<
+M.=+(9%)H&NW_T&'C&-_*2WIHZ$/H%5T)APMB$5<_;G2U+LFW=&3I:'7>BH3P
+M5L$"26BIJ>]CA@/P:J(U&;/[>[GM;LLKWMY1)%>X6!9Q'HN=\X'&ZKH4/=!8
+MM`\-1'.J[.VW_/)MRRNNWM!V:T_?=SCMC-S*3/5AJ99=J-HP7LD7)9=,Q:(=
+M>RAW'96X+$LJ/=WUOE$Z/'H5F%2NK/V#N@J8DW4+<`TP0D$\B(BG0]L=WX]F
+MT?T*#+_J#DX*E/:V'[-T6(@!G"M<`^!VN!2+^`I\WT;,C&7GKTGV5-2#>,7=
+M]U,T+(H8=9-EUU[JRIAE:6*Y\IN3.NX+UR3^[I!K``K-ZY*.2H>[+NC%"X:F
+M#:2LNZN`E'6S7]=QZ^%9"\]B>-IPX+FF6;)KH*LW.[H(WSFN*9N]R][!KG>M
+MZ-N%M;H1[^H5)*?A(>\0';IF1E#PYB=)0RK:HO2L4_>I>Y(W7%+M'_Q.)2G4
+M%VO;X?EXGE9D%$=BPJ1HOO3Q;*M<:):-X>A7"HXYLIJO"(<=^2W9CCKC]@GB
+M5I#T_R(7FJ)93K'3ZLAJ.1-W#)\JWR;[:^)_ITOUUX1H/*Z_I@C`^C_PU[2\
+MMJJNKGY+7?W&*C2ING%3-;NEOJ7>CK?'JWC.+=2N0T)+IDY10:YZ<W4M7[V>
+M*]MBW[1EW7T-]JK&JHV;JN[95,T55:W'*XGKJM<+]=58`+[=6U^UF?.P7SL(
+MT0U8&-E(Y<H]MU".N50XE4-Q8W,U\/7".JB_P7Y/U7IN[98M]LU5M=OLFZH;
+MJS<UX/9U??7F+="#C;5VLO2SAJ^"KI2YU[`^;:BJ70_M*][8L,Y^O["%K[)7
+M;UU77;V^.JDL`63\AL0K]:.AH;H!OJJO7L=O06NNT,KJS77\-NQ\_18!*N2W
+MV-%`$;<,_F#SUF]IJN7<6"=N&T`R0@DZ,4Z3&[9MOF?+IHWK[&CUJ(&[A5FD
+MQ7[75_N@->NY5775]544@W:5UN-6?:(@R%1=7UV[#H].UE757LW;&^J@M&KN
+M%O:"/H"K?'QUO9V9O;4W;!!X:MX:]@ZMQ0ZIEG"AND1\U2:TF;LM*0TZ?(_@
+M\V%I=57KJI,&/:7=L"[;[P'@55?70W$^OJD*$&%=%?9&*PPS5MVSI9[GRJKY
+MIBWU]]G7`P+6I6;0"HOG@48)M="H=1NHTJ1HZA+K<U5#P\9[\<O[A>H&,JG+
+MK`ES3M6JL-8O0!-H4CS:5[5YXR8VO`U"'5ZEA6_OV<:NUZ[;LDG-@%B<_)[Z
+M0=)HI<:K8*5YE9H2+^]+HA.`CD<S`\-4'LXQ-KQ<*?2DZMXDE"L&&&RL92W2
+MS"HC:`"=XXW:$F\S-;OV6K6P1%^20$:3&<&9W-.FE)3RZH8M0CW@!P_S9$M]
+M53V"2:A-=`(RX,X8-1)MB7%EPN;J^HWKJC;9X55`VJ*=2*D[<47U6^ZKABHV
+MUE4GS2*:,N70LFM1H9?-<K1<5KV96[YI4_6]4%Y#=?5]B+<,83=5^WCLY/KJ
+M1IPD-$43K5A;O95GA=PC-&P;118W;EG';R)0JQ_'FP'@JZ7/&L:+0\AH;:IM
+MK-JT<7V\C]QR0$;[>HVR0#/YE/<OP"5$2K4-M]1O:6BXEKT0.%B7JK=N;."!
+M9K%XZDP1DFGULP0"(*W6IH>GNIYNA1-X:C="*LPG0KY-\"V"@)T.)H9W/4">
+MBJUJW+)Q/:,/ZS9LW+0^B6YB#032]=4-Z^HWUD''.-?6ZG7JRL)N>'-.;=1Q
+MES09>:FY*H'R;;Q7P$8OKZT3^.L`/^!'_7XY+$;U]4(=0H<!&^C-IDTT\,*Z
+M#5I[XN_4(AS*+X!U'<*"QVGHK5U?[=M86ZVZ4E]DS^<X3^KRR?4UO:;JJZ!)
+MPW'T62JU='[<=.VL%9AM=#$5EKUFRRM911W'^,M#6_'@"/5=/T(K!,-D3YXE
+M"OV65_(+.\X*/73>G,J?,'U".N;/E<[+@CF8'M"Y\5AKR@I^"I31K>.<*X3S
+M:#(XO$)X!X]OAK0BXOX@ZK9]B?^*!6/]5ZQD_BM6H_[5_PD?$&H'X^W;4/\E
+M[9LWIGUKY.)<4W!E+IZ_!;,7_I'/*&S_L_!I0>?M8_R1QIFMC".X6\@\:M_]
+M/^,</HS*__9O4#@ALZ<)$TG*DF/)7XXY6__A;S2)QJS(D!7O4)HZ8OPLY7N_
+M1[$:;T]OV$>"ZC`VY"='54G0;_9%W,!O`G_G"H=]DGN23VHV2XTYLHBN*25W
+MKBSR%)@CBW44F"6+FRA@/^L:-O'F&CT9PE6>^[TNR=S3Z/ZEZFU^?!C/W_`N
+M84=,N+:@L^]I#@6:0JE[MC"0=[]1TE7$A`%HK/*[HWB<-]QMG,JQ2PNHR.@=
+M7L77([[<C\?YN:NETD%E^#C;;"D=!+EF$N1R>(>%4NA7.>63)TO>`<=(HUX:
+MJ:C)@L+QFQ[ZQDS?"`]"O;H"M5Y,+6=`T@G#>><@B_!-;`<9U!BMICY&=WH*
+M]<^DJDF'@Y82R[XW)&^O_!PQ^3?*KMY@\0Y59D'K$""^"7]L/7^M8%9/N$A/
+MH/7\;,$`'],Q<#K\M0HYK>?SA6FM2U'27'JK,#&X2B=&]!&7%>5-S"=<!"\D
+MET+&#`B;B,='+]TMI)6?P72X6X$8%)PX)Z!]>P!-Q-7+<?%33\N^+LFE/-5J
+MZ3#I".:*Y#T#LMB$H$LAI47)=>:<ZPP)EU?(SY%PV3U?=IV!7JF2*^0@F3#B
+M0JD7FG8&JF[MZHE6H6XR`.-,`ACXV0WL&\QG:?\6M>$8*5#[LP)'M3KEW?3)
+M%/KD056G6/V*3Q.[CD4-8M=/U>(%J^-C_U?Q3L)V],+I</4V90I661AP?-R<
+MJ9Z@1B]1I2`8$<LO75:J5-$=A3'1!DTY>[C5TGX>M6>@*/\,@%0R+'L)EJJ1
+MV:MPY++H'@!O.'=G+PF$D^52$]W5,(16Q5!%>Q)4EJ2]/6K^O\KT^,1=N/E9
+M!+,M0($Y3$"4K++8275AJPLZQ^@5?EO]WF6E8V`;S`8]?J1J51?F1R>&(2XM
+MM$(GF2S[],D^GT@?6';9"-^F`.G7![(@[Y0BR1I%O1`(IS-KU'&5R`3^)Y^O
+M3WE5QWPPYJ#:`#\5R%^C-7:C\FT@@!&WE1""#KRS+#N_S=$1-#FXRG>2C+[U
+M%1WW)#S+U&<//%N3WC>HOQAW=@>J!.GX-7)S3M2'>Q!F62<O!+IRVZM,O+7A
+M"6;TJ^&D-'YF]*:4]XL=K[1"KOH"ZEC?%>P.D#:LZ,^8:0:D40++;!'10!^K
+M/U>PP(KI7H\:;":4F'MDNE=2Z(A8=CP:SV;BY\?VH5*Z\J-.W/"3O&BL'P#]
+M`WE'.Z'XL,>R;T<`@IYRY9W?$`&*3E+IB'KY(EYRX]P0:C4/AG%U&8SMP^@*
+MY3X"KA4WO)>AN*[E;OJCUH8),6%(Z7^5Z*7JJJ($]P<+M"^%*W%H!(/4G-/V
+M$#JSY0I5T_.52.G/PPH35R$9LT\V]1#1/LO^DF6HJ.4T-A:34F*E\N(QZ@\9
+MAWL.,H?\@Y*_/^(:,-$$'$9W0*56V6F47$-`-FCCQ-\O^:UXJ4FE([1JF!PO
+MTFA-0%SM'!:'=$VJ3EYZ^`"JT6FG_4N/J>L<[Y;S?7*AT8<6=OPV(U\(?]/X
+M)<G%->8SZQ05JY784:VEZ#\._1[&"I0_023#@K]RZ*?>=1HU"4N,8J<I%]JN
+M6/:[IUCVEUFETMZ\HT`RQ<-Z1T_#=9;]KM/0'B4FG$'H8;,>/8JJ+^RT%4`5
+MVXG5]P5H#03:(';VOZ'X'*[3#9=;]O?@]WF'=2?*0\5NFT?LU'L44Q<USR>Z
+MK7K+?N]IG^R>XIOM4F#]GN*3BBMLV!3=``)SM5%";Z3!TC,!4R&T-]9DC"WP
+M*-V=I&0::\.:6R4<8U,-++H%RF!$1S[!DS>LZCE5IP#S)0WU[)=QZRH;+2_R
+MTQ/:$LL1MSNVDS="\J=PC0%(58QN"]T*4_V<#F]N63K^B*;GV;J#[?2>B;@4
+MAN?L6M!J$RU,JN/V(1:'_H`KT'_Y!E0KJ=''[L\F&QH5-9P:4\,I6R*,![*A
+M+8IF5$UHRJ'J\7+269V.OTS%:_1=LMHJ/8*3#^_IN/5$C(*K;8%'<#RB&=TT
+M&[-:*7\K&9DTJQ_G0GJF',*.2F6;5,_3F,/2?AONG^\FZD%JG:IGX1<PKU)P
+M!.'#XV=[MQ*4K.(A?(T)@GAH*P4VL:_%19<+54"FSG89+!T_A4+5JEOQWD!G
+M,5ZD8V7>`--9<F]03_GD1$Y]@O:8Y-TX2Z+I\N[G<4VI6-_W*X9S7K/XK@$O
+M,>GYR7U%1..2*O*V:K6\_:IVD-A!AT/^9SEABNA_/@$3O+)SE^Q]5JK8GN@Q
+MC(D._<T_T45$KX)'__478&@6(@PJZN0RWE#ZK%2V56MIEKS[61UC@N3=S["V
+MJA58$;!/852E4=[])`6@8T]0P"[O?IP"9GGWHQ2PRKOW4,`F[PY3(!L=V<!:
+M=,MO-=IPM^R!_D^'W@N3(=CZ;F_K:U;)8Z[!??(:("8W*G\]HE-7+(Z_DG#(
+MR%^BD7YK3:Q"KE@?.Z'2?JLT%%VLC3ZN'2PLSX.%)K-2.7R$*93AK)F@`M;W
+MDD[-)<W#4ZX-L21;=(D)]]+^E'7U(FU=77HDOJZR1MF%#-F]B7Q4JVN87EO#
+MQKEQD:+_A%5XT;!K^6HD^=G)BE`PQWZ+J]>K+Z<(,F/DD2E0B/AR[CEX$R8H
+M&V$=DT1\TV24]P\F9)0;8#P,2#9^?4BG>739;I<^!HQ$?+P,%@:QU^`X#'Q4
+MTG(,C+TWK+QZ&!$*UL\!G_2`F>2124Q+34CWM:TP<SH?4#F?M&*25*Z)-$6:
+M2%.DB31%FDA39)=ZQA-@QO`W\_:-S]_L/YS,W\A>VPKQ@LFR$QD`.H.PKB#^
+MYO@+.FX]/,^HO_@$X#FHAI]\@:E*,][DSF@#T#>-S\D`/J<$F&AB;J*WQ>,O
+M@OA5PG+&O[Q#TSJ<@J!)S,DTF1@8YL]\#(_S)'TL4A:.-S%FIV%NO#"5T<'C
+M2E/'"6&KEK-=98L>W$I3GO$4AW#*NP;91/N^.H=Q'C;GJ$9_@'6I4'[<Q<X_
+M;6=W/$3=@5D*,E>L('8C^GJ^JXND0!0H(%;626XKCI22K"^:C'_?>IZ-#ZSN
+MHX?(UC6*!>5`T,X@AM$V!A;1[2JOUV!7N\]G,$9CW2@HK%E5HZ^L4%[O9(AM
+MAN+4,T4'LX^##NHKE%<Z1_73!NU:P#KY0"?K9'I8SE`[.)#$8V4GWW]^CMT1
+M<2YTM.'2U3@[]BO\C=T_7RKM5YY]$9/[)>=\=3U`>4JFG))SH>R<CRX7VU2&
+M4_X5=A#UB@6S0QBTB(^P->%%3)>A0$&1G1MBRXS;LF/W;\#B,U\D`B8=ACI(
+M+H!T&42G*3$.J#J?ODJ$!6PV.YV%T5T-JSA^]BXM'E;9"XQ)/V##Q0P^-X?#
+M@1Y94`+I[NANP#LHP1)S::UY$-=%%J['LS=+FZ2M,^K)VNDD&.4DW___->-#
+M]SV,"[A4.B`_3!TM105J1RET]"_84;EIOKQJ(4B:V(\2ZB<P21N4W`-J)Z,3
+M,#ZI?VD.[X"P6"Y!*$H#L_%W&.(%=")_?[S7E9*W7_GP%;7+V%\OZZ\?SVW/
+M<,("W^RF^<C5(JM0LC"-9D7)0D^L:3Y^V@\D5"J93[=.\>O#EOW=4K>A:7Z@
+M!R`5*SW35T9Z<7%XL4X].(?T@C&LPNOA4?`ZE02OY#V9K_^*J7V7+'3L))Q:
+M'MM/.-4T7[DKWA@0#F8R,K&?T1CX9%05S.X$%D7E0)^H6$*ZG1K2-=7)+5LE
+M_R`FO4KCXA^(5M*]_,'&GV'LMPG_5LW'_47LY`2V`PGI31^6T\#N)#EIM?+B
+M/DT7("8,5"H/'$*@YR"34HXM=0T`'7#X!^J?Q&L4377(W9Y)UD-.P.!KSS+A
+MN;Y.7K%5*E4L^X(!%6=>PD;BU?T[L8U*TT5MP91>1U>$PY(PA#IA#M<@G^[&
+M3!]+'\U&$6V8-:^R'*:"\J>#VCQ`W]@,*2:&W250>-./I'IJW^DOT<]_X9<J
+M<;..(6X+#B83-V0WQ)B.SZ4],+SS(Z/&O<M!(F']]&5`GZNPZ25)Z\O5*CG7
+M_(\Z<(S=.9@75?)@_*^.E>5$QZ&5EC!Z+64DWE28["P\M?V?_D(7]V.F?.]E
+M32=%M8&P!.O+M^PO-'I(5IJ/\%<IZD4@HL#PQ.8I92^CE((Z`"B>4=1-$)5T
+MB6#,G>7F7]">HT\6K#Y)&(;I9-E?7&(+V1:"%'ZVR`AP"A6EX;XK3K^;J5TX
+M]U`(5.\%/(X8*0S)Z:K(-PA"[A3=4-[A<H\!C\OKGD,E%&'0IVL"2=`U[)/Y
+M$AM4-A!:90-"<C&D#?@<!0T9+%.!V*67>GPK?-#[,U`4"&K]N2.AX@Q;WE'I
+M\!L?H"IHV"<[]>R[@0:C#ZKQ23KXSK="^(>OK<0Z`L31%'L(APSQIE?#ZZ2.
+M=_Q<1>I1R)+U4C*RL!WJ(+V8$GV.;L'[:#&&'58^)]:X/=;(*Z^_H`D">YG#
+M9"ER[F\:ZSF+!?3`W39N4`Q`5T"`CS5N4EI_J=X.X=->C9&88U*>?Y%4#`06
+MDQC`^!VR_*2NO/0,HU%-H[JR],741=T\0;#`>JOLA/B^Z23/R(\@7K:]R_7"
+MWPNXH<&;"CK[])C(VFL4;*F,O*7];QPY"41TA>9OVX>\3(_D/8D2F[^'LW2@
+M/HOH/ZGZ``SMGK]F)`;H%'$-TZ9B68Y4>@JD6IPJ(5B02\_4&**S8"Z>!D(@
+M>WLE+WJI]`Z48_&'<<'R]A9!#QP]PKTU&2'OZ?*0]TQYI5QIBYU`M@&/8V#5
+M/265H?S$WZ**E?#Q7UY(;1O98#D9X^TQX61,Z,$L]0=PUT&8U/9CA$3L5;1@
+M'+?[<"29X/2]_TOUO&D;-^YY5$1+7SYN>LKYQ\^P5U98DI@\@3+$,4A2OO%+
+M7=*=XZ3[KT^3/DR%<LT+=$$H2Z.0P$>5&>5TRSXNEIXJQ*3L?SZM(TSFGTV(
+M*"GE-SZMZMMLY]@=AS3%\RRB#UW<.>LVVX5L^&L4EL-?JS!-(W29&J%C-K3H
+M5M3T"L7\K';CZ=U6G_E<Q$U77R)NN@W46F8V1F\(B\WY'#\WY"YTN/'N4&.^
+M4OL,NSODIKM#LGNQY,9ID26[%TKI9'N)[EME5BAG:*89H3H#;PF)=WM1#6__
+M/G;8`5QB>JS1YHDUYLCN7.!&W49?F\\<^QM>YVS)$;*@`?8^-S(*:O\@HK#O
+MAAB.?8I_DN3[7S]E`/*;@^GNQ?7\Y):,Q57\;&#4%C?QUNB-X?`!+*K@1,$Q
+M6!T.8']?0FQ_D4N']>)JO-^8B$-56A1#PZ.$MRM:E\SF)[0NN4>PMC;K9@.U
+MP=G[$DJIF:])TY*4",>N?T]1^WQBLYD3LL<.#[FP9N,SJ4+9]`O&QT50YRTF
+M-MLYWD;@LJ,X!$#W,\K3"J7Y86RLRHFGF7S>3!>^D@;MQ:>3!TUL+N:`\VHL
+M5G[P-*(/68YDIVEQ)""0)]]L&Z\___@)(VJE9KQ^:VE')7Q99]F_V@@+E,<&
+M3%_!63<L3P4AX`Y#)?,]9,C&Z`FYTSR5RO//8Z-LR.V@FTG@LV1OMJ2/WH%K
+M^DXF9-PBIQ<Z2A8V7(+,I?*MGVNZV%[@Z>2I15+EPMB-6!JF/H,D-AW+*#(B
+MTX8.87"#38L3N].D>;0/LDQLR3<TS:PQQIKF*#=KA6KKQART`5$R)U*"]Y#(
+MEJK5@QE78OE>6Z2(W2(JF2/IDZ\[:_!)Y<L._YCDG8@SE^#*J*MVNA:F_>]A
+MQ@5L?BZ^B6!I/\4FM)6_`OV0W&_R`1/DF^T=\DFKS=)16,3[ODIK@X\V'BW[
+MW;@"2Y$W/F3^?16`O]NF&Y!<_;Z82_$Y_`IODX&++>TWZ!PN<WT&FBAY"_/Z
+M%11WU=/5O.<2^]S8`V`BY'(CB'AXMXZ_M-Y,5P"_TN?">0EU-$^)F?-K=-&I
+M+&S,U]@<E'?CV\^W_YKI%5N([0_'W>R"<(W%-3%?-^(#N1P_+;8B5UZ1&S+2
+MY08I8GC`SN[]QX`E+$.)DP&K\-=Q8/$+Z.+?9&!#C-1M:!+MJR8B6+NH+;__
+M%3N9>"C>#N^@9!W+N":/9XK_HR=I/'UR@66_SB=O=QII9!XPQNJ-L7F6_1'=
+M48]R%4PKGQOX--K"6>Q$G_6CLL1^FIK%)Q6$;"XTJP30EB[`6`_[I+7`0$E0
+M1<H][539YYXGR7B#W&RU[+>@CQK@$<7M37I#D[:GO1=ZW(<[T32&67*IU2<7
+MKQJ)9B`EDMUXE.V;7;P*:@+\<`TO<W0Q@P*6_1G(9AKQ$F,75&$H@RJ\0[K7
+MH`I(:-+/=@UX5I<K-T!/I(_QR,`[O-T3,E>"P!J&-E3JD<8!^R>G^Z3B2F`I
+MBROU&!J)7@&\(3"CI0,^0X%/XC&M=,AG6(GI*RM'1->`D97GWP^M4!-+T!B7
+M3S(WD=-E`S3`![0$"FP:\6&*V#WBDQ;@*"]?",UM+;/I1LE+Q<G^?_Y;'<?E
+M9I]4>AJ>4S4)WM[Q+-W.I",E_A*68,4$.R7TL[.F18QJHU%OF',G/>IY23\=
+MF5`Y/T`)V:^TWFL[!U.OM<IVKJ^#\700N<J6B9'+X:?)*@D]\C:KY#\#,_HD
+M4HB#C%#TZF@H0#([:`E9\:Y"F5XJ/2Z5'H4R#@*8F_6&QC:Y]+AE_V2#%[BH
+M(9C2IR1_)Z!G7D0:PG.Y<FQ*,W&P9IC\0B-`\+1OMNL4OU8N/0B@+,/!/VW9
+MO[9,+[LZ\WH\4%(Y]L;@ZO$H:W^"L@&>&1WW&3+PB]GPA5QZ%/AY&!N([X5A
+M:];(+;5+AG;Y)/]IT774*+IZ]=&%N/]U$/"F3`^%HJ=S/S1Y&D7D'4:#@H!-
+M3!`^H^P8CL5\HNNDGE0<H+25V,+24Z+K.)1V4*_"8]>%$?3XZS_IRUL"4>K\
+MP2;Y\MZ`)KDQ(Z3#Z&YW&^52!0=`]O?C<"!J/)LD;ZU-MG_T`\0-*Z"%?#\,
+MS"FYU"8OA]>3,$@1UW%:+64A&\2C3N!H?7*F;SFT[J@LG/(Y)EEV/*%'EKE7
+M*CT8$A1).(!YQ&U&0U,S_G!\$W85$$063L<:S17:+K5)^?O/X^+_9#K-&91*
+MK1W'+.T&?!.L<B.A":KQVS"Z7T?6`RGZ))F).HW1!93[-$5#VT\#NM#&!@PH
+MM5'<[M8#VQ^D;AC=,/3/PO#FP&S2^_+2+?NGAHQ>%9"=OKPN`&0%`R2\`E"-
+M.!D`65S/TC6$23_7D?,/.K=EIT>)NK7YU1EQJ4=,QSE^4DPXCE]ZS"2Q079)
+M.)[(>P1FP%'$N`1$RVC.`&*K[0><M^S(HVEG;D;77,_CCL=^X0B`VK+?N`UM
+M1_0#:FW3DSZ$9;]M&[TAHIT!W-R&N'D$(/\\MF/],_&9<;<L]`!W9C0T7B&[
+MSAA@HG>:`"`P,RKTCIZFS)AP,"8<J(C.5$=LFQ[WA*R,)[D;3RT13WI8MM7*
+M*^?I(!&&#JE1M!KGP$G"A93R8>E:NSJI_-71.804)N42*M_&V!/5WD!E?,C5
+MUBB5:C6E-B`F.I@X1_5)T-MYA&9)XGT3>A3'@9B@#D0DBXG@3R3-A^0S@Y'O
+M,9VG55;U'-\G.CAFSI5U)@O70G&Q4T5Q@Y`..?3\_0SM89)/AM35'#\1)%L8
+MB-4CGNCU.)X%DC`(?;\?J(Y-+C0".0=0&=Q&QV'+S@O(>W&5,FY5K'2.2*5#
+MJ[&MWW^:;5-;\7ST/5R_5UFI.1WWQY!H8'.^@A!RJV6E0ABZ;*N(-5FCR_%<
+MGI@Q,J9#OAO9L0[K&!6+A5W[Q85-P<)6*Z?.$?C)!B";S%1D&O'<N$X4`:G7
+MX6:'>R%9'YTFNV>AE4VY8J'4\]@Y_Y#4Y2B;[Y]!8P&K:?0RM9S5RM8L4LMA
+M]Q?H[LNHLP-3LO^?QS5#6D"WVAZ8C\<5PN6X_KZA2%UM[\1:H),KYHOG#2T9
+MD:+YQ/V4FA%GRG$7_V0:@P%P-,,^8+<NJ=$!E0)^Q5.NS/HIG>M(3D1$O%-Q
+M2SC<N@R039YDV?\&48=B-R[&%2;U1>]+&XYA!*S^VROTODAQA1'QI0OFWB1L
+MHM,4JNY/L4%7F-27X'=5<T<F^5MH]D%"`X8FH!#`7=!6/1G\F26[S+X(<7%`
+M/LK-OK;#%Z!2CSY.3I89^S[6J?8^OR*-H$^INL70N<H2R=];J2Q[BLE80!F]
+M)@/_8&%T25@:Z?K7!-I"E#YZLQ=6^V5H(\EDJ%_<]GXL`\OJUZ&+@'XE*_%U
+M*7S=5J@;J>&D@<<DUQG)JZ`!Q')KP'L4IKKL58*E1WN.67YT^,U>^M/9ET&_
+M+"_3LH@)@\KK3R)G*[V-FR$C,2%-C,7X:TFUSXS)OW^<\!\B@;?"?=++'?X!
+M_G+MS'957)8<X9A\D(X-SN&$`A\:,IV-W&J$%A<&H+8N!-@*/5HID0L!8$7&
+MOBY.\S_9]H#IA!%]P?^"8\7PY?(#YJZ87M5I<?C/6$)T1".8P_(DX#^#KE@@
+M/>@=D4O/P-@$U@9T0>_G\*,/`F_J/1-8&3:(W<8BH,.."]M_%[V-]@FG^B3O
+MA:#WL\#4H/="H$*':]`#>E61!NIHF4=<SU'4,3GJDSED58/>\T#3`I.#,(^@
+MW.(*W%N$/*SHYK=PICR?X/V2_63-?8SAEH9/:)_Z@(UT3"=[%'\ZQ[9%+!V_
+MUA%F)6-@VS85(C\EB&2C7LC]YJX1O:KZX8"%)T2FGEQFR75<]AZ7I\#D"I;&
+M9-?Q@(D@TS\.9/H),L#?0/O['1]O[XY^%2:)97\F>J!,*KQE/BN8QN>X3YY"
+MH"O]3"W]@E;Z,AT4IG=*I?V.CYK_0.A_-:`_H3%@S:T,_9?_2$7@XRH"1Y>&
+MQ^#_\3'X?YSP_[B2-?KS<?'_N(;_Q_\C_/_!E^)_Y#$2_$8`_QW"`-FE0IN`
+M8_!?<]7!C4,GYWZ;J1#=;U9.87&N8;:UVX@T>L<!XMFMJ[IB:24AVR&20[U#
+MY36<1\G"A=!MG@UL*MV%!I[+4#J\6OD8"2^P`;W37Z&MX*XWWT/#-OR+PZV9
+M0"(%/$\G.>_YU4=HL@Q+SW\373A"Z],U>W#)M!`RO\2T)%%W\0W>I#M1*`Y-
+M;QP\]IMESC7+%ME7L2LB6QJKZWV;MC39ZZKNK6Z8:[<OKUU77UW54$T1Y$@N
+MB_5_5G+_'V'K1+D=K7_#+%CYS>+E$DQ8W)^VBMT&V7\&ACXF^?LIFSED_`-^
+MNFP&C!5>4C3)VW)9AE-X$`8(^[;E850I!/[F%):RZV'L'9"#CF/H.>94I8*R
+M-@&:3G67(P7R]SO\IX1,V3L`"!"=$F;S417]EZ%Q'/\@YIB=V@@TB&::<7^N
+M-+#-$')/[QI*0S7:]WJCJ-M><%:C3(*R_4KH!ZQE(>-+87%AS-(QFVZ%&V.0
+MO=L.&?Q],1<PJ?T.X!H?*L+31_\0UE7\4K%4E!N#'YE_J1@-C<_F7RIL&T'D
+M;UX<<PV)_J'IS=DU!2'Q6QO1^*A>R0>4ZFM0=2]+A_"X;I4]9'Q8]A1*:Q\N
+MCBTK5&VY)G?1X1H0?#%@`OW]TUM^!0M*C0Y$VZ[>";H!8JUO^9PTK)`291-2
+M8NNP66ZU+>4PBX?$V'3+PW5T=CI>O05G\6(%'B6Z!CHZ_0:QDT#6U?5.FNP?
+MR/N]=)[T,=Y\'R"5N?A!%*[['N.8'R7`B.'8_(>5&FB(KCL)X(>[WDV3/LI[
+M(^73E,Y9?NDZ%>+3T?JKHRFW)3U4$9,J<R,NW-C">0,P]U^"LN(I5'@',/LG
+M0&=.8<KOM_>A'RD^BR4RV(]`?ULNAM:=\@&`?+H!TGB,VX0\_D4\4=%N]>RL
+MQ"P=]G5],($8(2C,UW&"GXR7K0638>6.0NEHR`,,5FAU#%M<F=ML@.;B7G*9
+M5>PR2&\#LI^7&Z%WG]+078D*L(CI!QFF^X<[8H*%.-3'=!JF`RB3((XP@^[E
+MO?$2\..Q-Z'BX2MM.]2-@@/?U\5)P!C^N_E;JD[^,%$V[Q`L1>6HD%2C4V*`
+M>*'G=N6C_JSA42!F.VTZYGYQ"$ADA?(^I-?H:O2Q_1BOF!XCII34;FL,2A>D
+MBJ_2TF?9PX[#SIU*L765?`YY]IOJGDDFB&E#`!QB]=8"JP<KG&7_,5AL?#)?
+M-N)#E0QDR+87:;MCN-<D;2\;B6^!#7B482)#M#,&D]`G+2Y+3OWK(^JU>/$P
+ME#_51Q:L(=?:,N0ERW`-WC\)=[N`.<>-(*S(4&3T(?.:=YCJ@ZS80A3^QS]?
+MG/E-[;S`\0I2X>:5()`K1W:3KM^>5Q8RZQV`*/,!A+H:J+&]&0FXI[Q"6?$I
+M3LYL8(<GR.V4%1U*Q9ZGH+)L-]-%'1RUJ3C&1N(/P[1TX!J!^K<#LA76?Y"%
+M4-.`6:=7</'`3=BAOJM4.3CB<`W[#60J%K=M8(DI=AI]LUVG?72R*YP&T;:?
+M)HC!->"12GN5\%X=ER<,ZX1^-/Z^WU&"\/1)MFTE/LEAV7\N9/23R)]W&,!V
+MOY[*Q`QKH=R(<5O<N*KG>ZHQ-UC/>I&2>TD*=Y!<LPU$<Y"(^1H2MAVN(6SC
+M$+81T&*;T9?7C9CAD^:#-([G?>6PZEOV=VMM[-^#HW%2)RAYN#G8"\.\;=C`
+ML;:<]N6M=;)V81&\TX@B5P;E82YW5R#X6E?8=.K&K-[7%AF*D2'9CF-H9N5W
+MM`<226X7>Q4L@&=HS;S"*!A]L=(O`JF2`M*;]R!(AZ"Y_VN0TDGO$,<7(&SU
+M&FP'OZO"-NDLX@9<3S3<B&:$\0,#=G><C@Y!1W/4\[&C7[1?/.\AVB^6A.&(
+M:X!H<9E5/8Y`C]:^M!$0HH=T31GJ;1XFST\@`1^JXH12%3@CN*51PU4PS7-L
+MO_&[;$_>*OH':)=G`&._\ETZ7I&$@8ZS_$(DI]CSW:S<70`WX""@O&W`FP[#
+M&(HQ??.E/@DZ%7$:\7S1)!69HE,8-!IAO1A63?2)KL$1!E"BXO[!T&*"-S$D
+M3!B<S<"-H`?RZ9-;S+Y5M)\.52'\H$%FTM1X\#LZYGQ[`/=$J-E;OD,T-[9J
+M86(3F1L'GN_N8OOO.$##LC\;G5,(-B2`6&.)&3A)WVPC(KS#.[3]?MS%\P_3
+M#KU.6&?9;VS2'06$!NA(;P!CXQ\8?HK[Y,="K<X[F.<=HOUH]@GNN#.KN=][
+M3$43W)M>)2^SDOUZ*[$7;$??-QO[#!5F^Q]F%0N7H[R#JB/&9J@0;R]0A50;
+M/^4`KDAD*_?`YQ@R@IQEC?<ZE69^)&LT4\Z`RFEO!X?2ABJOL]@^SY70P=6`
+M*Y<`T\SV>RJ4]QY5MT/X"=%(6,K`':(FU/,RHB?P%%NBR>=G#\H,OD`BRZR$
+M@CKA>CI;@E&%LITC!)3`H[J$E_2?Z0BM#S#\Q4_XW].O7KAE](>KDC^L9Q\"
+MS?7)S2`+(V8NQYWG(1_M?/7]$QFCQ%QP^F2;$Q:_(9^\3>_+>QN^&*:/*^!C
+M[R#5I57TWK<3%76@]\X^(Y%.HU-R]4N'=:_)?ILT#6"AGPWO)49VHOI[MMNF
+M%ZY"!F"G7<>6D=C.7`A%=J(J.RFN_81VRU*[QG^;V'SI0?P*:37ZCJ!BM,]D
+M*E`N!,`NY(`554O5:HFN#<>$;,M^+UZS*Z>9<C<58</VP3QO,<9XIV6_"V:<
+MXB@R"WDP>>!UR%!D]>#DV8]LJV)[&-JQDSA8KPW/3)'7'ZV#E73^-I;_D1C*
+ME9KE;8!P)7JYS)S7A2P(NH>@36.84BU&@Z7C*>(NK0:Z722^@I4B*=I'#7E.
+M5B\.#2J]$)1V9.LT49_T95!*MK3C5GEDAP8BG[A4+UP<V1&'_`Z$4?0;ZMFM
+M63TE0PPW/H)EVG7:):9VF4L`=P7[,%%0=.'H[X_L91JVJ"JS!G5Z758#2)K`
+M:WR`;CU0%1F*;5Z(^EFH)^DT"_:8,(0`,3@!X)"=>N11?AA"IF)P?#@G^[E/
+M`O(E`=5VKI5ISK-+4\K52%+=1N0F+?+.'.1MTS5;T+$Q-I-2>>_NG4P97!TT
+MDN)P"WY8'32@E%;=6T`E$\O.&CP(?BE'';9?8T`9EFC8*I390>(_I;:<Q+CA
+M7JW:8)W&2W^FNJ?G;R+]\U0X8XZO[=%HT1KV;05%HZ\,U2QB\R+$8UAG$:VO
+MBB'E!"@7$91QKX.:X%$<N_#F\/AP3MW;3-;O_<4.Q&<;:E:R,R^:6IM'U&8+
+MM]%I_!!&'MVMGDWDQ-757/TAEXW:NPZ]#'OM/JD(F08?=&<.67^U["^B6]A*
+M/0H_I7;):6(;T=/8UN`Y3MW?LT>*F+E;M+S;S_'`%EEQ5U>J,\EU5N+N5^*N
+M;ND9MJ,+,KE/7N(K`;8)EMYL8';<["5B=*.QU"48QB,B=ERD^-JZ<`]XI1L]
+M!D-U4A;N(:\PXG9_'=7D$Y?H&\N!VB;+$HJZF>PZXVM+'XEABG@8WM>J!WK0
+M'*Q$/2,Y]"VZDM9NQ_U_J=E$]_KI*BCT*`-KU4?3"0I&7,I/?8D^R\4=JH\`
+M6G2AD:79YPX?^R@V75B'1MJ_POP9W!3UAJ4>M`#6ZUE=`:$;T5%]I?(\2!/1
+M9>%QT\+`=J%BR7AI9N@`R@ZI>D8I.J@T;J/MM-_;KKJR:?_&2`RX)+P$4F26
+MBJQ2D4TJRB85LIFY#;4;[]U4S7_]*PP/UR=U]ROM)!NCWQ\#]$^8DMR"ON^A
+M,^4-I_%BFDZ9M3-NWL_2+N+MMQTD->*,>05YCXCK<>+*\&K05\Y%4+E8N"+D
+M>H+P\->RIK<S@U4A+M1K^D\85*_F0ADZK8P%VC'*O@!252;4TK5&JZJWL;#O
+MGVR_!<5;CS(WJ-YS>ISC+V>H4:%LQ/,S5:>F`Q=OM!5`FZ&3Y%*;N,W*\6FR
+MTQHUR2*>M\M0$YKOW8!+<T5L'XG,=W;@CGN%\MAD)E?'8L+$>!-NQ>MJ,<PN
+M7-.VI.KB=`Y6:K=Q&=*R2VK,(;'S&VBNGTJE2RP.=R&?]2IN4_8A"9'=V0;W
+MK,?.-6='=AC5E0&6@F].XK3;:E,IEQV6O)"-=E8,:W<4KY!1X<<@=;UY07H$
+M^9RN=_7E0$]V+"2R=$\@<>=K,G74S/&XWTET>P.N;!7*/Q]F>L*ECTL/Y=->
+M)+O7%=R!X_F&@O?3=\RG-2M7'>J:7.4G[:JYOXX3&K[("RN4;`/`U@?X79\3
+M$I]J1GPT0N?;"3%#HD(Q=@B(&`"XS*<D:TB\-8`!6TB\^T$,9$?TM//<$[T*
+MV/-)ZACHVM4E8$!$&W]TVXP8\_"X>MJE;32/.V+\M%A3CO(-PH)*Y3F1J/47
+MK%T)_P=MI*4.V'JE7)BCG@SPF7(K!I)H??Q>6K+_F>3YU=VJLLI6%;,C[H6$
+MYVXZ0T"%.RO^6,T<T[M$8+MSR.R!V\;>Z!!O%':V$K,7<A=[E*VPE-04XLC3
+MOH2R80<"*IMN[^>QZ6=6K@_$[SX^2=2^5W*;/<K*$%Z\M.)8QOAOB$M!'HTM
+M4&[$V"ZIS$H;T&^^*U6@Z?:V"]B.9FLRA8A^#>92BY'CTV$%E]SSQ18KNGTK
+ML;)FBBTF3*HT2=['Q1;`Q.RV%ML[T&$^$P((`.%7<HE-<IMBPN,5"I:(9XLP
+M0*IOBO'']OX6!E27>1E,F_F%0)']:>SJM/(`+L==ZJ9DR*F3BA\JAF>95&:/
+MN'/U!#:/=+2K=T(A3+(SNU3]0UZ][_35<#A4&9,J\J6*62"]$W%SST%)`@T3
+MOZD42N[%>&#;G%WH4291721CO-D+$'*X;7Z#Y+9!P6]F)5\A&*M#]HMF;3^/
+M.,K]\XG&5BI?W:7=ZYR0T)$;%E\]1>R06]Z)@5A^=%HX''L8J87\;?K+XN>'
+ME1.MC,%]&&U?B*^:Z$CK9&P_IBLOL,1*!85]=N`QF;9MDBLK..O83SMAN3"V
+M!_<OI)HML><II-2S(MPL3\M?U:U#F*9L=_%K6A7+,8!EX_E,0H<6#T5,ZM0;
+MT.2])/^W?N8K%I%WZMA;&HN8'8>/\>[(*_.I93-Q5ZY"F2)K5S'^4*%<PA#I
+M?R([\E6"FJ0P3'?!D;XE#<=T/W.I\"J5:6E_!^O-0%H>*3$2TIA#NY&.E\O?
+M)CI^0BHIE!^F,\'0$)GG'H:_%95*,#.N=/\")B@Z7#8[!I!]WSM(_)U=/(2O
+M,2%3/(0Q,=ZAKC;LB_>;&7TUXR'W%6T7,"WU>#>R<P[$Q0^ZH@L*SB:-U95L
+MGW)/$]*#<G7@*A5%4G%=>,TMCDQO_CU>U3TSHEW53:5_V]DM'0]=/$=Y`%4)
+M:[AR!7U?1B]+'IG(@]B8^!B-L>GQFV^PLDIM4%S',7Z&>-[$7_$E)<`"??9!
+M'""#,%W+IHMGT\6S74%W$Z%=-`.A5$$E`N4*7I%-TI^/MV7!-Q+]LNH:L\=O
+M172N6C]O(<&AQE"ND'&4R[ZD.5J_4VWI=#_`2%6SF32#T%0H\I4W2L(9Q)'5
+MQ/;7TW$SX]</([JXAABSGLV8=3RLQ[,8]#_:5XT<CRP,2<)@:YD-#R=(B6:`
+MCKY[(R[4"&-'T#=I9U&]/G&;WM!89-D_61K*ZW&X%.%RV75&>AN*,32C*U*I
+M6WJ#-H(L[:N1G.!NYC8]F3;M%5W]^KZ_<ZPL`<IJUG-"$0(&Y,YT:O3$I$9;
+MVC_$$I:-URPZ-C3WJ7<T65D&RTY4-=5.?_M5J6?>3E7+$I7#'SZ(`SPT8NGX
+M;YWJ#3'N7@GG%Q-]+.U_!&PF=>K$CF3]CN2FH:%A$FLFH0Y)MUX2XDUC@R0,
+M(.AV'26#.69#4RU**VC<Q;P3+S_OV:KCSJ@/AC7%/6KRO3N888P/J:>#I.J9
+MI5-MW9JAGZ]3`BOO#BJO%<J8HY;%;454&6SUV<ZQFX@]7/PL$57*>F6AWR=N
+MOU]O:"+)W%:AUGL.N-/HO6$\]A=Z29L2#Z6=Y/=$![&6_;8R5<D2]R4KC-&Z
+M!)R?[M#HYE=3.O.=#KJ_XH[.3^1M9G'SV/3#NXW*5[?K&%ZP=E/"973/&;O/
+MWB?$TY$*G_S"?=3O-+')Z;7)RW(Z3O#7B!<,_$SQ0@9O3YFG;2G4HD_!A>Y%
+MY$^Y[6GPB7!%I"U7)?N1-FT3)]*F[;H4Q*`];6Q#3*B1OXEY':MGU1?2/@'0
+M.';E=TA9T)ZX\CL$_0Y+])6\U>I#6^#6HD3I\'W#;R2M*/\TU@)L'AO*8O:=
+M_$WF8X04HXNH/H]EO['2LQKKBR!C"[C=EK1_=`E2EJW61$TOL1TI+('O8NU(
+M="U&U:+^VF6D";<4EK+)&))_Q5R9X";&63R`8?KA.;AA@A34LUIY3&0R-%HT
+MZOLA(*?\3>HMJN<9FPQ%>#XEI=.KK<F'CK$;,W%'>H3L3CO->3V8`>5^%U2R
+MMD0O_PJ_-U18T<?M5/BJ!'=?4`&SPN@37<-Z4MEV+&BX8G0'$KW%`WW+?F%8
+MHO:/TN5.WA_\ND!T-N:>)9?-PFVELEDSRO)Q/]Z=(Z-VW9L?.E[!A;3E;D>S
+MK66V[+:%;&BOD".7YH.>\M".4R0X21RG<F!VU+XML]488XW9RC4X.Q_!+)+Q
+MI93S&0_J_.T@1HOD-]3L\R@?MZE"DJ/"[I^$TEOQ#F!$'RF6*NQXPETVIV&"
+M[)XCN?,S@=.>0S-LN$*9\&"2=:(Q_O]X$M9AR)0930F#\W,JZ4)$A?*+;720
+MF#?D`6G`N,"CW/D`;0_$YBDO-[*-X'EHY&YP+-]U!<_@1]B@R:HSW',<[EE^
+MPPQWOLH]C>%CWVL@Q@FOT=B4=&P4<:),TK^DQBBOR@$V_<U>C]+7&-\^$-3Y
+M+.=7*N\.`J8Q:2Z?P=-)=M>8L2B\"C[LOS8LE^2@#_LND$5Z0L8=L!3*WV9C
+M$73"(,=V$N"]9L<;VT^.\FE7P;:-@VY#0!=TZP-.^*L+./7!](#3$'1G!)S&
+MH!O":4%W6L"9'G0;`\Z,H'M"P&D*NK,"SLR@.S/@S`JZ30'GA*#;$G!"69,"
+MSHE!]\2`<U+0;0XX+4'W10&G->B>$G!.#KHG!YQ3@FYKP'E1T#TMX+0%W5,#
+MSHN#[HL#SJE!MRW@G!9T7Q9P9@?=EP:<EP3=EP2<EP;=V0'G94'W](`S)^B^
+M(N"\/.B^/."\(NC."3BG!]TS`DY[T'U5P'EET'UEP'E5T&T/.&<$W5<'G+E!
+M]U<"SIE!]\R`\RM!=V[`>770/3O@G!5T7Q-PY@7=>0'G-4'WK(!S=M!]7<`Y
+M)^B>&W!>&W1?&W#.#;KG!)S7!=W7!YSY0?>\@+,@Z"X(..<%W?D!Y_5!]X*`
+M<W[0?6/`>4/0?4/`>6/0/3_@7!!TWQ1P+@RZ%P6<CJ#;$7`N"KH7!IPW!=U+
+M`\[%0?>2@//FH/OF@'-)T+TXX%P:=-\2<!8&W44!IS/H=@:<14%W8<!Y2\&)
+M<#A8_$A)H/B;Q?#KAE\7_+K@UPV_Q?!;$FRO0+,M@792G(*W(^P-(XO$"].;
+M7P$ZHNDLKR1WBB#%H!*B+N@:P?%V?8[C[1J&`6?VN8*NSW#871=PV%WG<=A=
+M0S#LLM,$M"#H.H>#[SJ+@^_Z%`??-0B##T1.<@T$79\@"K@^1A1P?80HX!H`
+M%)"=5N!7@JX/$1%<_T)$</T3$<'5#X@@.VV22PFZHH@.K@\0'5Q]B`XN!=!!
+M=F9+KC-!U_N(%*[W$"E<_T"D<)T!I)"=.6C1S_5W1`W7NX@:KG<0-5R]@!JR
+MTRZY3@==?T,$<?T5$<3U%T00UVE`$-F9*[E.!5U_1C1Q_0G1Q/5'1!/7*4`3
+MV3E+<IT,NMY&9'&]A<CB^@,BB^LD((OLG".Y>H*N-Q%E7"<095QO(,JX>@!E
+M9&>^Y#H>=/T>$<?U.B*.ZW>(.*[C@#ADIN-HT/4_B#ZNUQ!]7,<0?5Q'`7UD
+MYT+)=23HBB`2N;H1B5R_121R'0$DDIV+)5=GT/4;1"77840E5Q>BDJL34$EV
+M%DJN@T'7JXA0KE<0H5R'$*%<!QE"R8!+DNM`T/4R897K)4(JUXN$4ZX#B%(^
+MF2&33W+M"[KV:ZCEVI>,5OL3]@W;^D]S*?+BA[7HC6MQC'DV4KYG`E)$!NO8
+M^1$:I@H=6H]KM\LF=0^_B/LYG_SH7`=&H<1GZ?`AST]VLSA^ADSVM-(X2+J9
+M&T'W`B60?)9B=9:.192WCO).9@&=Y:'<=+8^1CHP`@4?9GZ+$ZZ4162*I`ZR
+MSW5H.T6:9?$,19)I,W\K)U3*U&3)U1I=2?J3]!$9]8IT;(AI'L#6JR'Y!<HM
+MM"8J3"XR0JW%C&W^5MKCF0@!4I3MV);&<1O""*G[ZE`:1L"IAS<'M214KOPY
+MKB9[,3521+[6(D6+2;826J7ZE9$B,CTL4[>DHCODO5BO_`)FD2KNCK@WJ1N4
+MZ5A)1&HVJG<$IJ;A#N8NQF)PK-<.]TH^BT7BW5W510S5+57FR,_AI2NIR2B+
+MN/LME9CDW;3>5-KEYTY2$L"SAY*L\N[C.F:DZ[FCE,1LRMV%=V+?,8CG=9;V
+MK0"&EBP0?J?T;89@6#ROYVU]]QA)#B)PM`:P*84).W1=]R.DBK&'K%5%BU6#
+M=.BD$;AO/+'!37N]I>,2B%%XU-UG'S"0N!?3)<YL2&0&X/2X3<ZJB]4M5F+U
+M6@W:?<]_&M!@VA/EK(!8XV+EOY/RT.[A:P;<G>_AA"RR'-!^`C>N<D*N=@]K
+M9JQ^L3*W%O?%L+7'++L>PP_.YU@ZV@V(&NWW%*1QPD6L!I$N\W](V^`I<`"F
+MNUW:BQ[8@AWKX&_`U1[<>P\&O!W!CBJ*V1&D#`'O3ED(2"_<09GOHJ1`<._7
+M*4D*=MQ),<'@WCLH1I:%7=(+MU+FVREI5W#OUR@I%.RXC6(>"NZ]E6(>EH6P
+M],):REQ)2>'@W@I*^F:PPTLQWPKN74LQNV5AC_2"AS*OH:0]P;WEE+0WV+&:
+M8AX)[O50S+=EX5'IA964>14E/1K<6T9)CP4[2BGF.\&]*RGFNRK8+!V%Z-O)
+M'S!8.FY$]5G7KF2:,0.MY;EV`<'`.T/G7(_>193&3'?!H--DC,C[*(-S9G@7
+M2;UAJ:Y0=NU1<>S!5F2Z:\,J91+R<:.8)O;-N/_9E*7.<BBRC64!-KU1BX7P
+M62(7Z,*=!ICAG9U5&2DLI#G=VJK.1#;61GDOGS2/B\5#1'OX67((XY=WA/"=
+MOT3>B[]%,I&F<SU7'M4=EBB*4<^0N=5!.1O2)?J5U40LUN`IEMY8+AUEE12<
+M.-=8+'448G)9L=C5+QV%J!>0JC%<]\GL)^WCF$]R+_.)S<LN;TKW1=S+KN!B
+M+Q3&YV2LOACPO893#B)SVZ5V81*2G6/L*OQ9HC!Z86I%[+DCR%0_UPE_5RMB
+M(\F6,?I"^2W'?(0-Q?C-LBL;[Q78>2NK0[74PY&QRG/=2"0@B7K5%F!)>KJ%
+MX!_U@9&3AJ+WI)XIHH*/]KZ*5@Q:PWB'.A_1J_:$6*-1D6N8C09&JK<NCD$T
+MD(SM+%IMMJ^&-!Q_E!U+LO>7*A]TW\L<DC(I),3'#8SQIAJNLF\G+2+L#'"J
+MI0-EKQ"(02QWI9"PLU>OQMTB)'R,?1V%4.'62#H[5TFV6@!#9;6Q&T%%Q6A8
+M-.+&:<#!@*%E%==FU(AE8I/2V8`O:OG/-9!IGJ3S(29*K"WU%"\OYZ[C-]=Q
+M,QNNNX>?>RO]T_@#<ZJ_TM_[T#MDVF-H[F+K)K)<DAX2S8^1;\S)^$,^+S5'
+M:M=N0G8"W0E2G7O)N]Q>=,-6KCHCK-$IV9L0]O8*9?HF!A<CWHO(K%`R*`'O
+M9)+GMAJ#\L_[R)K0CQ3-W1@;%Y"JC`:]SK+/A59G^2QQR,A/I+WY`[A@'_M-
+M^`"NU_!;T#E*/ARI'M]VHUB?9+N1H7J&[%[\9;8;&9^>K/^JENVUGFTEXF]I
+M?X;HG)D3)I4KC\*ZUO==V@(-2][G9;W*W>N1NR\B[KZ(N/LB@URD<?=%Q-T7
+M$7=?1-Q]489<I''W1<3=%Q%W7T3<?=$$N4CC[HN(NR\B[KZ(N/LB"^"1%;C%
+M?R%_7T3\?=%DB)OB(Y[_GX$BXO.++K+L+]+,,$"!8N]T`+2E`^=WP5F?8\0B
+MGM`Q_=VWY-+G?7+Q:AN4\`'*!1!$P:!X]<6H+F>37M,=QJZ25*!'H0"[^@_J
+MZAGHJGC8B,DD%NA1*L#D=RBYER6?U>OYQ468B:0#/0H'F.DOE.ETH@P2#_0H
+M'6#R'RGY%"3[W-CB!W'!ZKM,W<=$;L.BB_>&Z:\E]^4ME":H+V^-Z0O)$GH4
+M);"B-ZBBGD0[2)C0HRR!R;^CY.,L.9@5*#V`9F3;D6(4G>W2\S?A)R1AZ%'`
+MP$^.T2='$R62B*%'"0.3?TO)1R`YB(7I^"5J-I(U]"AJ8+8NRM:9*(6$#3W*
+M&IA\B)(/)N"#!S^AZJ<2\\R33/_N&8/;G4FX?1#"?;_4</M9%7O>4`"0!Y+P
+MYYB*/\(!"_JB1/W#$;GT6=2QC@/WB^:$V@F:%7J:%#J:%'J:%*F(0I-#3W-#
+M1W-#3W-#*X-FAYXFAXXFAYXFAP&:@NJ[-FV"0!!G2/&VBQ%$T.B=R,?T?24)
+MAR[5)7HTB<63(0SLDS/>)Q*8]3@ML,(^JE!)M.=+Y@8BS//C(,R7S)<OFRE!
+M+"R!,%\T8]1DDJCU.`,P^0^4?!*2::8\J\V4$S@;:*:<P)FB@>I3W'HM?18W
+M,6A"Z$BXI@GAI`FA;F(PX=I(PG4:"=?I)%RS30PF7)M(N,XDX3J+A&NVB<&$
+M:S,)UQ-)N)Y$PC60.2>2N5=(O+:2>`UDSHED[B")V5-(S+XH5/UDDJXN(K@5
+M;SAZ8P%KT#L2\-"]1H\^Z!T.>`RR!V\NX-U.CQ$O=WK2@M[S`4]ZT#L4\&3(
+M'I/D'0QZSP4\IJ#W;,"3&?1^&O!D!;V#`<\$V6.6O`-![R<!CSGH_3C@F1CT
+M?A3P3`IZ!P(>B^S!JQ)![X<!#]3[KX!G<M#[SX!G2M#;'_!<)'MLDE<)>J,!
+MCRWH_2#@N3CH[0MXI@:]2L`S+=5?3$+_ZRYV,>Z!'-)E0"-M3=;8`N4[L*1&
+M2C0C;6=WXF36\9-#)39/I?*739K]H"N9);I63K-$QUO@XQ?8"HVJ2ZJ>P:VH
+M-V%'9JO)KEQ1Q9);YE#$'&6B%C&?(N8KPW<S=JQI<:4R<#>S$:;<C2H\']Q-
+MV_9[$S=W!K_H'M2BKX]O]_?5FE'VYSA^VIBC=^815*8U7NQ=(0Z9^*R"SCZ\
+MCT?V%XF31Y-5OTOPLMTL6L=7HJ&INKO5DSA4._@95FZ#RA^H2;"$CT"V2C3O
+M_P^@FI;][FR@I,K]]ZG7,[.QR)G`ML%79N)#S1!:H26C$;,,)E">T^I=H-5B
+M2]1B:9]#LFTQ5%2I?.,>!.:0\MV[B".$K+_:B%`:3BAOCM'=_/@.MN>-9_P+
+ME!<W)LP0K8RXSJ"@%G$I!N1L2XJ!/9!+"O'&))G)1R<!WV:F_)[@Z%(IRLYG
+M/!7*QU7$A4*!^1N)!=5LVYT:=7V(Z\NH4NW7H97!<>S;O7^WFG['N.GD/VAS
+M]>:&:OZ+_0?ESQ_C/ZARC;P]UVS95YQKE5?FVBJ'Q?.6YMS`$>EP5Z\ULT>Z
+M<.Y/XKL&Z7_RWI3>^.1IZ8]=??I/?B;]47S'\,G3M]Y^URA_3W%H/GE[PI\I
+M^KI(^"]-T?^^G?1^.X[QVV2QGV.V[ZZ,;B*]$GR?O5`:ZAK2RUZS!'\&0\7S
+M=%%/6#K:ZN!X<[AUX<U\>F$K?/-IWE$<!/I&7AB=B3H$@ZLK\/QM597J4&<(
+M?:I"(:V+Y]W,/X%^A1=TG!7>3C:\D/0OE7[\X6MT6<'R2]0]]-^I<NJ`W!D5
+ME<JU=^K&&E2COMX:+V#/UYAU9)>YH[-Y=LAK\T5<SYOT4NE34NF!99+K62#%
+MY>CUPO641SE#U.JI;CVGXHM\YY.C#5B-@O?\KR7@C0807\+/8$8:\("EAZ`_
+MRN:@GKID0BT;M`N83&VN[,;S)*980_5L2@+%:[?1/%$RL->N/=((>D?-#Y-'
+MYPO1JP_\[OCQX^>J]W1]8`B9OQ4REN)G<ND>5.M_-.AZU)@?2)>\>\I:E]S*
+MOQDJTTFECSM&&F\.MRZY3K@.?72[G@#2^[6JN&(;ZC3[9-=3OIG<@.]FKM#2
+M\4>(Z4Z_+FHJ<XPT1=@Y/,<7D:N%#?HLU(KYVM>Q<8^2MU/:7]M^$3NR_1E2
+MMN[TJNC_Q'67Q(63^;P^W*QD=?_U;DVG]:*X(JMVAS):*PN/R[O)N=#A^=CS
+MVUN7/""D0XGNZ(#EE72`2$<G^B3:H^IT[SGGVD,^B:8`$()K@[JN#_3BNSIV
+MO_5$QPE+1RVDCJ3W+8@EV5"+<+A1BJ@92-"KQ-UQQVL-Z,=(=Z+0\5K]^11=
+M-!B:@F.`JBBKA6S'0K9O6O9EB)V]TAL%725E>/&^[X`N'(N=>Z?K`YO4T]4[
+M6==#AZ7#>3WHH5;SND9G;*4FZ76#8"XXX?B(GQ$.!W7H;,WH^*AIZL83?US<
+MO8[Z&-JCO_DWCL<='PE_`TP3AD??Q7RL$K'9C*TRH3\+U,(*%65(D:X/#>*[
+M&>*%#,M.7%[(&OT33Y$U^G"X$+YZN4+'O0[/._`,PI,!<9?"<RT\EGU34=\O
+M2P=_TO..ALQ6]_\GHE99:".3`#G^>:]40;2DX`12OK.6]I\C/-PJ/-[+$$<`
+M'H^I\'CNV9^J\,B'K_[@U7'OPO,A/,/P9$+<5'AFP(-#F:;KL>R;K#OL_#_X
+MLDK8BU;@1U]_':OW\4-HH'H343WW)1=.,U!CZG[<Z*';N<UF7E]PEM31[H#<
+MN*L0Q:LB<E'VLAEH#V-(+LI!5?:N-S^4'\3->MEX`$F]=TB>'Q;?&Y;-8?$=
+M/=V4H[HZC@EFTODC'4'T-C:``:#TMR5VX5%ZT%;W7.3M!K!MVB0G3SV-9`;J
+MW7M(-P8OQI0BG;%RPBVR?SCS'-9?.B@M_B;:.T(K0E/1-F6Z7&:4=&1F'+<%
+M);>Q+8([@](2/*7_]1'2(S!*^4A>SR3MK27S<S5K=1R[E(;KQ8N=I`=#-N.$
+M]+,E-A._NB9;N5"16((N4RU>O(=Q)5;&,UDKE?^J0(ZC;[^F+V92B[&TWXE;
+MEA*^])73'OTTU/.%]E<:Y0Q)+[:`&)L%=1DM[?.PR956G[@(%ES+?CV(.44C
+M(#<,0[*.SZGA@B4VL=?HB369R1C=;56:.F([%L"7D$N`[&52]XPFL^S,D2MQ
+M*#_`V#8VFF'Q11HJ_F(L$OIH?%;/9T;@+^)"!@00,-((:AU;VG^(]%MVF]2-
+M0:G[K!N:V8$7LBS[297.46866N2*\9KLAB9?QFS^#5%K?W9WW%#I"9AG9"@5
+MUA:WC9.GXD`!2"I@5"4]M1>'`B]PPVA36$I7?^N,-*IB,[20SBIPW5EEUNZS
+M(MJCHJ"TS=1=8N.B1OAKI!()24J,;5U4C`7I[8N$)#`<"Y&EB-L-P(W,T*^I
+M!2ZSH<B\3%YA?7-('$KWIQV@R[$/XG`R%)-8/F%XK([UQ')5([:3$&I*'QJT
+M87NB?6C;'O!D/R9%:\F2;3I"EY]%/;B*P(<C[F8CWHB3I%*Y]RYMQ`_0.CR/
+MQ!"R6INSELDWJ;"L4(P0S^J!U*@A+-\8VHEOCN[_A[U_`8^JR-J&X3X!#31T
+M`Q&B1HT:%`0Q(`I!U'!(.$@@(`%TT!"2-`GD1-*=@)(0;*+9-*U149D9G&$<
+M5,9!145!14T8AH.B!D0)"A@0M4.B1HP0,-+?O6JMW>D$G)EGKO?[KO^_WF=#
+MY>ZU:^^J6E6K5JVJ70=W>;OU,3-X1OC.6!X'CN4"BD4!6:D#.M7B'6]!+[6'
+M]TG%\S2+EFCAWYI#$!'C29/D1QM]-3[4_D_D?M2B=EW$HGM"NXC05$97U_S!
+M0*MK`!K94P_Q'O6=]<[C^?.;Z^:AV\#>L2Y[Z&33^B\K=L;M8@L)M<-""QQ'
+M6>R;B\;'--H?Y.VO;#'YEL*)-'ZNENU9[]$W<G4]XXMK0D]$#BN;;YF1Z'\`
+M2G>^A;XATF:\<<V)_CS<*4W895);?=O0WU(KZBW>)(=YHH4.1(NI*DRAT*?-
+M]&^8W;I)+.V:XJ-=80[MC*L-AG^5A._@\/V)?@>';_31_N$."A^<3+"8::XI
+M!6Y_:%1`?4`WNOM1EH8A2V?/)NML"W_X7%ZC=K&;&>[4DJKYH!?/TD3:YCBN
+M)E'.8_$/4MOE[>?YLY>R#V[?J6S0_1+0(VJ,9;^W,TQJ;])^)Z2!PJ2B<L>J
+MC4?R]4*ZV#LN+,;H[NF,F1GNMGF>I[OGZJ^3-85;D,92=$W89/R;4J#J_2'\
+M?J2KOWUS7#72L&6F__E@IKE[Z2^/P<MU]`V/]*Y#%:P-!>NIM-$6_7N\25OL
+MFT?WM&_.=_1O]";L\5298G85])4P]P3<NYAO%(GQ=SQ_STS*FG:-]\7S06S5
+M!=>KZ;#H-]![WJ2M_;?Y;$DD2U,1OF_L:#F8+?=.Z?]L<7I&J;/9JK6D[6KX
+M9T#<'J=&PT!CIX;9-R_L:?R(Q5#KZ-E!$D(#[_1S1<*N\N[Q$!RUC<<,?\2=
+M:OFG>2$])/>L=_+Z%!2=.P&1>19;#>ZK[)M'\=#G^)BX[>Z;=HY+-"ES/JG:
+MJ<V<57\%Y<\6VCO3?;%3?7_NB4?47,B=XV;1EM/:N.DTFY$R]?N[:.E!6!=8
+MTDG[Z=P(;5R8$TET:N/"2]5Q'U92'AM^8Z_#G@G2WPD43@_<[*^YJ_40('?W
+MG?%J$D+=0=:!Q4U:B=7IG3Q++4#6)MOX5#W8(>9Q7(IH_.V;IZ((:6O7YOYG
+MD=4QV^P/T)QG3TFBR1V+-LJS"%E09-\\@Q;B<29L<\_SQ5M)>&?X'[Y;%@24
+M[5LRU65Q!N)M:HV_%C^K_OH*];Z%CF11RRVB@Z_-;'UMZ27.G?&SU"EQJRIA
+M#GQKI,G!,7BT_B+AB(]AO-G_RBS>MB38TZU[*E'&$V@6]@7&&XIT_PX7]-?/
+M*\Y)S<Z3`8<;SQ]P&#*X_8"#.J_8.RG*YIT>Y2C;I]9TQHZ:Z%JZ(GSY%Z[L
+MX1>[,XG,4^2](.\F,D614T#>0>0T1<:"'$GD&$4.!GD]D4,5>17(RXGLJ\A>
+M(.U$]E:D9?C%KG+[&^A&=.Z_ZW?_H'5);0],5OS-O2\]/_>WAE.&C[BIW7',
+M/)8"YAPM@RMI'.72?SE\$C)ZTJYO[IRHN@AD4+@N48L)+DXTMOL86M]%WS\_
+MN`I&?;.<U?:;Y:43@]LAEQ[]%?*\B;^?=J=94K"MM;CMWM$#H41]9>OI^V3<
+M>FCFG7$;Z4/FSKBM#)44&.LD7_'ZF?[3K:LOE]AG^@_=H:SD#FJ/M%-QFV)=
+MG1!EZ01;+`S=9]?\\IO?D4LF\*@(;0=)NQYZ`EU<5RUU>`)6^W+:.;[N554?
+M/0$'[W%0]PS39SH7=9U<6A5=WKV.SC%;=@;Q+BV\<C(//AREL0?+8\9*ZM16
+MJ:T+6]2PP][WYCF=SHJ*R=JNTS]4G36A[]9\!=3F!9]%1^)`_:T5D\MW176R
+MX4Y5G=E]4BV\[#<RVA4U>4?':%JK@K`\M?85%@<]87$WTIZ>_JX)JNZ$'CU]
+M_OX7XX/;;<1%J$V)F\K0/";RNO6I,_P?T=8VDZCQ(:VG\@4MF7WY/LJ(_G(?
+M&4/[J=9=3#3>'^CNX#G7N:AO(*$)AFZ7F3/\G1+4D@LUWMY0NBT:FJN\1]V/
+ME)'+`BK?1K8^_/DD-8'AO.?%^Q^AWEYW@[>XL?7=;Y+^Y;O?3CGO773**LL"
+M[JVTOA3A:">U,Z7'.I6^S^_9-YPSHTN,A[["0U^J+1EO+8V)=@V?@+S:88RN
+MOZ%"WO,<LZ^PT0!A>1>\9:GZ@<[@_AIO':5E"A7^^^_@]0QQ3?IN%!-RG(;)
+M*9,-T8.'W#CTIIN'#8])F9N:ENXT],MQ9V7U#[D_:O28L7'QAFA#]"##()D7
+ML,34IHYMCN>M3!*LIT;9K*Z.M/S8?0E5VZONU$^7Z<JFX+U]^+QPM8V-Y]@E
+M3L_9+F[JP3D]B[L;EO1`)9LQU7]C"QZ]D1ZMT%X?25\BDS9H3T33:K.DAN#I
+MH]RW+NMWCB?HD87G:_H51H?WB9%J8=I0_+6_VT7S#<>/LMVNOC16]@X1?5T7
+M!\KH(7[4_FY/[0GUT#[W$:^*<<#K]+9KLE>%XO6IR'MH"RU&=Y.GRJJI&X$X
+M=)P;.Y5<%7B=(E9G(_T2G%1V;V]*U`9^U/@ZI9-C1S^N+_PX!3O+!I[3)R5:
+M@K^B@K\BS_'\B1UE8^A>NP0+%V7TVU-9ZVF>97^H;Q=HI\\'K/(TT(9LQRHJ
+M-HXQ&EI&L%L5\KN]*X??;/'/`";*[PVCC8:U_X'[K7#;NS`\&S>*?\\:=;[_
+MG)"P%MUVX3#ZW=KZ>\W(_SSN:(3=3>(G1_%/EWOZ,^/EM^5VHV$AXF]`7"/E
+MWGJ)]\J0^%<B_M)W5/'8RWYW3B^KR+HIR@2N*/51$1OK8JF0XAP6M6BN1?-%
+M*;&T^T@R3A]DFI^UU(4%@QE09SU?4+G</6>O<U^GA[BP17N=A,5S+F#W??HK
+M298N.W4[J%I4##[E52][ME5[SG8NBO8-?4-[O>%7"IQN^USYU5X?1].9*XU$
+M4U6-)J>P.B3\%6W#OU^%SVDOK9L%BM9N_L_#IQRH&T2!<5C6.MNO>I[$UAF"
+MOQUU32WZ[\@Z?PM-+TH,UGG)D1436NJ&=X(2D7>\3Q"<VA;I&H$GK.HHYF;M
+M"96[4UNT)VRJ@M)?0W')Z:?IOD?=-)Q^FH"FG55X55BGJARNBU0TZ"5,P[L.
+M\K\QQ#\VZ&]_+_A`3^B?D/)WJ`@=*L)NIY]V!(O\^BWT$:SN\0XTEXTRV>#N
+MPKE-?0.^%=!OT?"'SIK5U0L1T&#+%YE-AY\.ITA[5"ANDQR'1S?SK<#K$>HO
+M_?9?.T4?[A]X\/M#RO_+VM+C<>Y.DA;?XX$MYR1GWZ,/@'4_(UUMPOABLAY&
+MN,]K?A-/^UJ?WME!G5VL\H5Z_;XGQN+7M,#K2B:>&$^$[XDI?&^@"C2R?2*'
+M]*!9P*IL::$QO3G/U9E_C'/?ZGF'0FDIZ>Y]@EZ-48&61&R)4[FEGG9WV))N
+MH$"(0JNX4_V8%WP@?6E"P#=>Q:@$\_7QJMEIGN9_2<5-]5';:7YG[#F>6*Q^
+M&.V/J//"I<R-]N5T-&'=`\%0G>Y;.&V&DFN\ZH=>GEWU(C.Z9GI]=,^W),98
+M?X=7^7MVFNIC*[QE]$9,&46UM*>VL_65J/HKU9KQI6%>E9N>;2;MP``50;VU
+MPJL2-Z[TG2G<V,3!B)7"K(NQM*8WTG6E+L.C6[Q/D!K2]E:=N4)ST.[B;S2K
+M_GM0WB]NE7>O4EE:E[K'^!E)5ZP\H\3;R0$ZM1YU6<VA>D\BZE&7U!RLYX[6
+M)%TNTNJ=V*SY5-V<B*JBZM^=%:UQZ?4OI"IQ_0NF1?>W;PX^H->_D$JKSL6J
+MNTI-5FH?H#K_RO=X)Q+H)YI)C[&"._IEZ6Z3IGZS&-$AQG5'C,$P)'R25U@4
+M-I\W/%@GI/R7W,)23M,;Z;:_9IR^14*8MG/`.W0O1CUJ]RVEJ<[J=YU+I3.Z
+MTJL>:'F3E._)E[3W3^_SW1>HFP'?\W3=Y;^IZS@__^?Z;/._TF>LN?:I?HKO
+M\2N"64=S='U>E94^E97!!%[VVPF<]O]"^APAZM+H&D@IZ.-YQZHJ91]1_^[N
+M:OZHZ&97)\Y4DVZ"J>JJ^<A:*]N]I,NR9\EW:4#,5+87=7&>HH?=4P\;:DO9
+M>:Z%@==;<\)SS#@MD64A\+I-_:7W_-M/TO1MUGSA];?I:6H-9<!OAD(/^LM_
+M;'T_3#LQ0"7/=]\&RKR@-?I45U++K0WH"M4XE_OHCMIT1#C7WJ%!/3%U7%;?
+M3",=]QDL`Y.KLV^F27O"H'+`HC*I1:6-[L3L+>ZH/4'T*67R+K>7;:&R4(W^
+M@-?)H^R4_6$:`?6<<Y3,)'G9$$V%I6SO+CM'6ZCL/'%-#L\V*W<'+F"`O_9#
+MT``_W"7$`/?L:$2P2__N>UP%^A\;]*FMX?DH/+TGHN?"#-\38\ZU]A!VCE*[
+M'07BS@O4_O#+Y!$,N$MKP$-#$UI';4A0CYE<2W:4D>$8K1<*&53E[SNKCEF=
+M]C=\L4K',G1^@L"GB)!<,W&NF?Y5KA5_'TS,\YU#N.1D+#M&'T>6G2TUT+JG
+M-RY0:L](J27YO%O_YV46^"X8>__.%RRSK?^C,GNY-;R#UE!N7K>H5),XGB=K
+M_T6ZQ[7&L]#Z?R#=IQN"X5W9)MU<P?YI=$=Y52NBIU.[SV(L;@HFL4Y3:Z_$
+MHH'`@3SX_>$RLJ$^KR.S;FQI4ZR][!>E`Y5QH<R'I1<'-:*[N\\;#2U=-\&L
+MOIOZ'A\"*D2Z@]+T+_BXH96/NSJUR7^*;3)E_;4=.>MG5?R7>?]!?3".GSO^
+MAWE?-\?,^:-,,OLCM&^^SZL8_)]5E\FMD2\*C=RKS,;31XC#OXIPS:AHFQ3D
+M89"_?Y&']2>"45S4,20/@_RUR30M7\G6OTCR'UO#^V>'T"2W$2@V)R6I4RU,
+MUHVQ\#?T$'O4_LA$^N#X[U\V)OU+D;>T)FM0A_-R<H`2&,K-9PTA\O+?Y.<?
+MZUKYM_P?R,\[6L-S6T(3KM<D^_(QM/#0>U-;\=);AV"=/<G[X+2MUZ,M7#\I
+M]\KHGO4"2=CE#R;AI+E-$M2KW-3_N_@O$&Y>:[A_,/\;41F@X@J6^05*V_[P
+M+:;0=J]G:^@CS2$%41=&&2$=JZ7VD$Z5VM^&#9.>Y:J-"RB+9D?9*/P=Y%.W
+M_H<J:N6WP52\80KAL:VZC"MMB74-;<>WCU(X@7;[3&J::%:YH`6+J4XS<%UI
+M574_!MO&_T9NO_HFF-!NIO]6;A>VAO=X:WCO&$,8KT]H)X/_F:R,;0TNQQB2
+M/'2==4:]3X3]IG"$!G7FZV!05QLO4*,L]N5_N8#IX6O5L_^-O>AIC57-1/M/
+M[$4]F(M:@QFI!^.>[U6CMS%EE,"2CEZ%1C5,[2EN,KA"7NH4?.DF&<YNK0W#
+MZM38H7K%X4MJ4!-V/CM.LUK5K"YZFB?'JF'W6#=BHCA\SR[Z-71]7.@Y%]UO
+M,!H.TZ9EX9[B2*>[TULT0%,?!B*=SAV+C'.;`W$.=>+SP>]K#O(X4.>#M3N,
+MU].$S1TTQ[8YD>?91@3<CFF>!NOAL*@OBAO\U2-IK>@7V0T(9IX*;)R[J]<=
+M=GJ'FMPT'1TSX_LJUKZE,='N2U'/6FM8-W6&S`#:#SY"&X8_YCX'OV\U6-QV
+M+:FYODN%-ZYYAR$Z$-<<D]2<?[+>=+C&6]S<_V.O.TJ[C28<UK9^:UK60)L3
+MS9SA==M6Q"%8:WFGLE/%/4\?V3'.>+UGITE[I_*<&AOSQEEWQ!H'>"I-6AG=
+MTNH\YSJ7W%4Q80M]*SO]/7TF.UT5N*+_69_E,=](&E$R]#^GO4Y[::THH[^6
+MZ'*C]AG>6OK!!*V1J)BZ@EM6&+TJBO).H\9Q9#%U^2?JK_:J6,!&K,2'-_0G
+MY4%^9$"<U??L)OSXC>]GHZ_G;X=)-L]]-#-L,ZV3;OW\TF>JEM#@?R:&9R`E
+M-)!\KS&I"35T;E>S.KR+9O'=9Z':D=2,=TVN=-J"L<)[`>^R@,NO-2\+T`?1
+MP@Y;"-39R@LC:$.-A(9`M?H@2C&A3M)\%:.[I?]IBFZTM7^C-MKJWEK7B]>$
+M(2JCO>R(DKW?BLN[$%+=S>2Z.N9T@4D[-X/B&DPL31DB\SD:^B^T&@=KY^KO
+M]QIC1CD*!L><+KR>GDNDQ_H%'S,.GNH?,2@T'RJ,O%^N=V%8S.G\*V?\-A].
+M>O+2T.BK![>)OCV3]K+;:3S\.C46U/9+545%6<`=*?=^,X^IOKN'S)S?!3%2
+M?)4WT4(,E1Q75SK%F(X`;:SOB+ZWEM2(T-2(\':;UAQ3W%A@]L8U(N?,"\.\
+M/;0D?\Q41\&@F,:2ZRC]TRBX'H-#L^7JZUNSQ5U<3WMW49XT+KGL-_.D9`;R
+M8T=K?E1&M\F/_NY&]R5*]'8.#`G[2F'[_.SRGZ-S/>H[T]?R]OOEAUX\3S0H
+M_6.1PS0ZJ\X?<TR;2F$F6*=-]6<,IVELS73FQCU-(:&$[I?8Z3JC6KS=[M7K
+MZ5797M%PGN[<US]X!B7IJ;"RW<5]3G_NV6LX?5#MK-8D6^[5=Z\(TO1J6:"X
+MZ^DCG@.&TU^6NAN,E.B9,VA2BKO1__8P"K/9F]#">WKKX55K[[=J,[[4?(S,
+M@LP<YZ#4"\_'&#8B.KKM?`SP,'B?TQO7W=FW<:GSUL:E4,=Q-MCN!G='M9E'
+M!S6?7JOFN0F#]WGC;'WID_BM!@,>[D+/V%=5VM^H5H^<7QZA9P^^VH\^`D<@
+MNDBG%G?*6VSSW&YTA\_PQ9U*U%L-M>]U1_1LZ]O>U\_@43M&AFMQVSW%VZ'2
+M;NQ(LUJ33GD3>+Y6_\:0Z5JC>FH?&7=`LY>^IW8&*.Y+>W&.TF=LA=.,K>*P
+M0)$E,&R&?_[U?#CZ[3(?C6=X%8?11-/0YQWR_`@\;RZ"\(8%%EH"@V?X^ZL`
+MPH4K6AE0^B9'>QUO<C9SJO\HNKJT%7H%S=C:3L=$#//'#.43XG^E'A0_*<S>
+M;]5/L[(OC^H0G*.\6)T5/R'*NSC*9_F58M!VF!?*6?&G:+[\JQ;>;Y8.I&O6
+MBO?/-P1NYB/@+4-IJL-VF0[X,9U*ZBVT...=FON4=QRMN_4E!CQG[?:'>AIE
+MO8&#-I>D^?4;KS$:*N`:^I[OFB]PK[V_MWB_??.X,&.S%E?K3:CU&F6R7W7=
+M2P:>4Q;T/T1':P?]:3KNTCD&U_Q3HZPF=QK*6LV'Z^3T%)\R%D[W%M?@/9I$
+M%W7.OGGZ\)[&LVK1KF=;9SI/BD*B\\RK.FL)QVG-F2^N@4[H\(Z;`ZT5MT?%
+M0KN3QU476A%;_=5J'S9UU+5JZW;&5=,7`)XG<>=U/$\B83M/;EOHZ'_2&U>M
+M)K<5W$7S1V.,[LL"[NI0X55GHPU&"=9?IL[)K;Z`9!>:=<FFD@DS4Z.P2VF+
+M6ZD_*W,:3Q5$VC=7VS?'G>J_S;AOFK=XNV_L.)G&N/XZT;/;U31&?=IL\?ZV
+M!7NE20K6_SD7;$V4T;`:SG+U^<[P&_=U5WJUL4W]&Q!7'5(!:0D\:B`8#KAK
+M9_A)J5)R.M&A&I#X/^OKG__-^^K`YL[>XCW:;?6=*>^I1+EZ4F#J5\*A%1.L
+MI4=-5$?C]J`]Z>`M/N3ME.B-.^2I[)PXP[^BO^3.(9(B^W(Z3RRPL#-E_=5=
+M]$6K]N5_I%FD'57"2+Q@BU-F(Y]I#\>>VCGCCOI+U#R9%OOF1/0:&DJ/0>C&
+MFGJB#E+%K?%?UD7->T?=,ZI=(9/H;:=WG#`WCIB;2<S-#*/@`N[]_A.=^97]
+MZA4D1<TT_R_B5V>`RWQ2!/@?)0#1MG^GWNI?<*V1]V_=!2T[^1<Z'U+IM6$A
+M>JUG4*]UIBWPPY1LA^BOM\W!T_C&D<*K884W_@9:\4F;<P_SC[Q!*<VZ*-J_
+M`_=:6$WUE4>:^8W>-ZB5H9-9;];P,T8]&'[FI++?PM4NN/Q`[2`C+V3@!_:"
+MA.[V+X8YTN:8U//FP7:YJG6EX)CHX%XL;EKW.U?6BL2U:)V<.\>%;K8RKB<?
+M[4R;9AFU<1;O5)OGV!7:3)N:Z'LKNE3VS9UA2@0W.XBI<E\+^1UMI8!Z0V.'
+M.W<:U1D^Z!$GA6DCM.:ZDP9=[P<6CO7WC6I=2NSN0T>$J\U;3EVOUK'LT)^U
+M>8VP&323"IS:LM$6Y\[1E%::YC@*:1W=4TURMWF.7D%/3K1))\%U"W(LW\H9
+M>.#ZX`I?=W=:+)QSM2J'%,1!=7B^03:/*>2V4_7XPF<J&5`"<$Y-@N2T\UV_
+M^1IZ-"K&W>PV>^FI9G_XU7Q43I)#Z\)L-P9GX9ZW]B<GLK5LGA_4ND_.1:1.
+MZ>9C@UJWV^R`Q#JYK&#P:1VI9"CA^C31<2%[YK0KS/B>JD#)#B7EJ<7;M''"
+MX(R9JJ-]I>HJ.;01E.8A[<^\"9W#^=85?(9\DD//_P[-`:Z(XU`/Q_7T#1U^
+M:K3-X>H6%`WZ:*8.)O^X@UH"0FM4.Z)5B[>HBMSZ?F]Y'W8(^DP.5_=@759G
+MF@7<8?Z5'`0IF#!5O8G5<(-GGJVV=(K-2OL!J>+>.(`G0#?^UCKZDY>WY\-3
+MV=2.#SIS&]'MH/T@.NZ(MQBX\:%M=Y:J#3#>HC8I@:PSV>U"6OEFT5#-[1DS
+ML8)GC;^CHR$^,,0W&AJ=<N?UJUFI)[6<&FTUN3(#^4JA3[/H"MT]@[<=4.NE
+M*=:I8<;W_VV<M/AIAG^6DLLPT<DV:?^O4GJQ318:@UF8?1UG85M9B`X]_^`R
+M6O-7JUIF=[C3>S,LKP:>[3C6N6Q;0T`=J;;W!)VAYE3G^3I5YU"M6+5OC@]N
+MDT+60*/=LY+UD=.;U.B,26IP]X2!K;FK=\;1QHV&.HHV*,2^10%/`!;`!P:V
+M`-[V'R,+H";":-@.-^L";LUOW-?=D@AJ_ZM4VL;&AVFGC3N]G>HOJFA_;YS%
+MW$DWYU;,M'J.F;2D0_4)[9\34TM27W^]\B>-.79TF':`PO946E4@^B,TE_B]
+M2"X3KQMYX&XHNAA-YG%S',RDI.:8:KN'5C23A^M&YRC<:^234Z4YI(H^=D88
+M;)29R-Z>1CK@LL8_^TJQ%FK42@QCTG%U]F:,^WB^W5-\"`:XI[C6[.H1B*MU
+M!N(0;8+?_E`1??38'-?HL\2I32*3'$XC;1]M]<:'T2HED_L6A-;@C)D1GD^+
+M&<+IS,*8R>$%%U&50N4.4VV[,Y#06+^9]@X/\W:D59&CPYS])X8'V;,[5;^1
+M=$]22WVW"G7F8@N=2=6_"PN+2LZ#5QK5KP9W%Y5$?LEM\\:'RL)KNBPTT8D(
+MM7LN,1HVP:5=P*W^C?NZ*[V$9:%=>=GJ)U;\ECRH^<GMWM'-[:CSY$HO>QB!
+M_@\NYS*7`@W[=P7JO4(5*.4$%:HJKR_/T;(J9(VQ$CJ<R@IY[*<\=G=P>D8[
+M3&H[C.TA=3ED_^>+];4R;MJ-8\,U^MR<BTK'VR+G&Q-Q,_F:]GNJZ6L0>!'Z
+MJ<'[I..B5>VM<\:\7X`.Q38R],+,0X<[1^-._O=JGP&5`GW_BM2,?%EP<=,%
+M%EP,/W__"N^2**MW+"^[*#O><O(EM]4W+I#\#W5^=)O]*4(458>+U3I(WVO1
+MIR$V8>^6[7-U@8Q:WE7SRM1HK';FDV]\EM=I'7ZB?\6EZN3@^RQ:OA6VAFI?
+M1ZNUB*&+H4/'6/X:KF]M09URW^,J(LL#FI$L%ML#K>=*A*Z9S@GG8\J*')J[
+MV0<+ED:XU-IIU(-&;T?[YEWVEQ-LY@1'E=]A?SG.IKU?=<)AK-9V5'V/5QQ5
+MM0[[YMV==]')ZR;/-@O>#]!QP\TQ[I8E[ZAEG!-BBJQ+;X:(QB;Z:>P)74FM
+MRE-E\\VT(5HPK%JX2FOBM*G^XY>I<I_IOYJ&V8M)M9`]Y7HJ;+0VTT'K4T/V
+M;0^U"9[K(VL;PM12070\6]Z*>?BKX:=/[#T+L5.K+@;O!FMJ\.ZLL:1+Q=[T
+MEE$Q22U+3D_U3Z5D(;/#D-/TP'N=#;SY3+&M<\G5GAV=[>]V]%16)\;/[S+-
+MOT4]C%2.BRFV+?TZOCX2=OV.+O474]T+>:XBY#G'TJ^IV!I#9!^::'#EZ6VT
+MN[_;JN9(51US$(TJ@$"L5<>LBFHDRE)US**H2J),5<=,9?N6](Q5MV+=G;=$
+M&M1V>Q6M^S9X>YS:ULEU+<VXZDB[\%54T,R6KGM/:#W4(L/=_Z@Z8<)OD_H]
+MN-)9MD]/Q@G'\GV<A!/64]OL'/\)RZEM9H[\A(EF+=AB]YYP=Y*8M1[M]OGK
+MW9OKL]'_<PNR(2]L9ZS*V="]^X:'[O]^47!M2KPC9IRCQ`H=K)WS%K?04G<Z
+M$;?9"P%(:C+NU1(:8R9;BXT0I]]3V#!'(4YA6L)Q"*$O[%$MJ39F;T$?.G-^
+MISH.0!T_`D_<SC_AV0'M7NM-:/;9'M82#GEVAM%1\4E-OK"GM*3]-"Y(057'
+M'+![>DK?)`F=P)Y:DA]5=J$WH9;"*JZ6L4;E?]R^V82ZX;=OMAMWF>,:M+@]
+MVC9DHQHN.>XU<M7Q>_NHJN-U-Z`/KM*D_5A5YZ"CSK4B$YJR/4ZM#^T2DW`H
+M)N%X_O-HV[0^U/'MK)[RN_+`@Y84$KMWF++#CM-9K:T12`JJ)&P5[DR34QNF
+MPFY-CWUSGPNFQIMT*"8)\>.%N!J+)ZX:;^V/05?X@1_I6PD=8]'B6_)H6-F^
+MDBC/SA8Z.R)B(BH^Z#`8$&ANZ=3F$BO[N7[@-[2I#J7_MUYXCXJO>ZD].SS'
+MS*Z+YQM\GEW1ZAPJ->='K1*SHB95%=M,K@7>M_-.TRBO^[*,A1!?O^=7^'OH
+MGK:3]U]&U57]-MIK[6(U!.JE9W;0K]UG:?-I"FUOL<UUN;<3NGX]9\[T9](3
+MG?CT0#ID>F?]N]0OM0:5[7GCTT-ZJ44X5><ZD`9=:M&*&[1&.M%SE".6SEP?
+M98V):RGI$HAK,%;BU])3`7>#_YLSQ$PS^EDD>8V#*^EHA\;BWI3>QA!Y;8R-
+M:5Q"EJQG6Y@*'IKR'?*%[HUK\J3;KG#=]B95O@$)-I39X%,57A,X_J2V<R/T
+MIM8)98W@O4.\"0V??`_%')/45'18&U9VRA4!!4T#<7A>/;C-PL_2$_6H<%/H
+M[)#%:C.*I\_0SN/-;;[SS9RAUL_94!V]HQS]J]TQOH5A/LL3E#9?6+1O[/`P
+MZ,-M+9[*%F^7&*LK3(UXQU@+.Z@=@K1J:L!C3A8=4HL(0^WZJ)"\_:P'GYE-
+M:ZX?HM>JJ`NZVWWY?(/_K\VJUHM&V1FK=OBNZZS6H^TN1JZVJ%Y5BY9D>U.-
+M^)DK!N\.%"%3#_GG\;NH8MIX&[=Z*`A?V&:U1,RFM$,#6?C3',*3L1&=`]8+
+MTM%0-E8G5!S[YIO[-YKC:E$@J.]G4=]KO9U0N6BMV<UH'_LW&JL]<0TJ?\5?
+M'4>NCIT?C&*FLXZ3&O)?B2EN++P%84I8.ZK..4A)45C&QM]\&V\5O5]O#B0T
+M>ZI:/#$&U\_J[/D6;0;7M.K0/C]]:*!O#+YR-"(M9;M+;&H'$W5:>_T4;=?I
+M&BB,,V&>,[V6]D:?TFKXY"S,8?V!0:UG:7BJ&CQG+E]ZT5M7@.C_OK97/]PO
+MJ;E>/^G]<%SS!<[?-CG4?@>^\5"P3=Y8V`XFWQ)KB[</'0GMKZ.2V?$6B73_
+MD[2=10_/N2Y+1[S9E6[\"+/R$W\W,'`[2B^FN*F@@W=<2[T),C09UG[C)\?D
+MN4_\G;?Q%A,5]%17Z""O'?4#0B<ZT[/C9]<<,E=^I#3[50/6OY%T;=4G)[1J
+M%4?7.+]$T\6[M`5U@\9)]4/N\62[5QOY5?56,WIKJBXOVZU2F]!"+R0U'Z9J
+MU/9<ZM"\^:8[C;[Y=_VL3F<6[8#6P[;L*'T]0O.W+-U&'XH@VE4_D.:0W<"6
+M)333SO/(5Z08]G(*C>;XFT_S\<-TK,O5>CK5\37?:LU=2?Z;M%%AX".[F;;^
+MIS$=6H(^+HP^Y"4T:*,LJE1IB:V:FT">U/SZZ_M7J$T>GE(1J*<II)VCN"[&
+M^95]M2-2&4^-!NC7XD;?\F$?THAG@D,SOGD3%R>JJ;V^7\6R'1^IL5"'-LR;
+MX/<6-P1<C[3XCYRB9L9?=:Q#_VVTOKQ'R#+*"^3="]WDN&F;^N*EVH/#]S2J
+MTY#]A8KP0QT,0.48YQ@0[U!["Y55EG2IJ@TSQC61/L*O_G$-A^,:#[G][3Z'
+MQC(TOL=8>_L3-ZU=%0A\>?M-7[]\4RO]\>UJ#@1MZA62-'LWHUK3K/)F"\,F
+MAF8&/I^FV*H5;U3G7VU<T;OT[`#7)4MMR_?9E_=%YM.:W]*SU[O[X%6>'K31
+M6[RQ%*UNW[H.-&A6O-'^AMW[^%@*J.>*Z2MNJCK1T7,,=A^>K'^1PBR]+=I]
+M+1)`K\=K3'?5PXF&WJ!;=$1\%Q6<5KRA]12&G7'K&"H5J#,;Z)?]W4Z>YAM*
+MIE9XFF.6WL&G25B7]O2ZU_G"WO"-340SM8ZV6ZA@+_O27EZUT[LO[#WEJR((
+MJ.`H)>Z-9#LWW[!THU<]KQ5O]S0/LI>=$8Z5?UG`7D;C%)[F:'>/0-Q69D&E
+M)-KU@R_Q8\]9J_TA&K?%\YI[@[=XJ[&X4@H`S\,VMR]_3'EO-;HK5>L0\V/Q
+MJ`KO$WG!U"",I79O,=AXS[A/2UI7'Z'SX%C:P_LZ\_`&O-1V\Z-B$K8NK?R-
+M]WUAB1R`_G[/X/ODI0((IDY8\2724D'[@PG*KUJIK.9T5V=/<YR][)@A>(*'
+MNX^G>*O!W<-3O(76-KEA,&^LZ]Y9"M`J7]S&:9(_`UQ63_/UZ%S'[0EFIT2E
+MSLVC++57M,G0DYRA1??ZQE>K_%Q/LL/%5'*I*O>+?&&:;U)B=<A[-RS]QINT
+M<4#2>LH'Z[(S5TPV&$JZ@A/Z01]585VK+U`7G[ZGFCYR").D8BN8#9W#*XE#
+M>UD,?;<%E_:R&ZQZ7:F+LO+9?Y7]W=7TP;!XN\'=.2@Z7MZ$W[V+IJFA5=JE
+MUJ"XUPT.T)+OJ=.^'!@%>^)P4K.G>%?GDOZ^QRMHQEGQKD.VLUQ";1\\4G7X
+MGF8Z2_9PC2[-Q;1YB'WYT[`W2Z;B=^^E?7R/UT2KM@\&.@+"*W4E\'[33E::
+MCU[S3>T=DU2]=%3_A.K@PX=L[Q^F9ANOG*17[NBDUME7GUARB3>A^O3!U@>'
+MOD_^`SJIM0H4W("D7:3([`_3OLZPD([:7?8VX=[3'-5(GS\U"/JM="1IR57Z
+M\9]T#J7W<9H_X>U"NZ[`YHMKJ?NH(_I_S1;[\IFTK_)N3[.QY-+U1@JU8G!(
+MJ*/V-L-KZ=?+2'UM;&GG"QMRV;=D:VBJPB^#NEB[I.A!PHHEA;"BT&O[82DT
+MH%K(2D=I5ZB`$LUUM:K1L?MJ#+0KY'DL#6UEB99$(*5MTKCE0FG$C<-)_C:>
+M2<T'OS]\5)_K=OB@.^-@U9%M!W?#@[U#)L+=VDY3AV1?W5HUB8`FOB0T3YOJ
+M?QS-UB'$=D\S?7+\'7G*6V(6U5L.UQRN";C7!91X!MS;`^X-_N@?J,U?32<$
+MNE?3F0G_^(YNK/%4VK0?/54V;XG#%Z9,?\\VZ[2IB?[W;&J0Q`>KR9?4-"T8
+M__/4)L>MA1FQL)%^K5*G-U<;EEP\N+)5GT/2-/<AS5U#`T^0U--?<C'QZ1<[
+MXVHXP6HXF*9&+8%N:3*J2E'?$79`_^)#7$4T]W[TF\WH<T\,+#MC0J'"ZDYH
+M6E9UHT75YC=O)KE/:#2JXS>,"8?X'(Z8A$/%9M7%W4^XGTS1_LJG?\*A_J`K
+M2_HF!MRK_(=^5$P$W&L3_7M^X.[;6G\7RASW6L_V,#E;I"0LH))#GG>=5#E`
+MWRJ*:PPE/0)NY/8:_V,_<H;2[4/J]B&Z/>!DZ^W]ZO9^BC?LI&0>'29-H2;_
+M1#<JO(MLFJK\LB<8GDWTUY_DOHD#/8_1U#REJ7-MFJ&L[C;3X2DM9+[9RQ+,
+M!O5UM<+_NDI,A7K[Q9,T&]515KGTGKH!9M5_X25:^BE-PU"XRXY1$,O.JEE$
+M=R/L@'NZNDU5;-DVLOY:+?6ZXVK"G\3K'D!)<?<-/NY;@;^!9;O9IFS1ZZ#:
+M.?X4A-2^?)TI&+N][$I:2J:+UR9DPZ'L9E*:VZWZ9%&:3&I?7D.[1\PWJ3PA
+M'N\ZI6;9^E[;>/)<X'!'GM?:P9VILV4]7'/0?["R/E<EK[.DUG4EU&MQLY&F
+M0;5`MSZ`NP?]OK>W4""=U%RY@WY]CFRWPS6^URI5\/5=*WQOJY^=CNQ&J.C;
+MZEY$ZZV)Z6!MJV8J7D?JJ':IO8P.;SRXF^>$P<!%7T&TFL[X%\7+OU`'8OE?
+M17%]\2+]/+*;*WHP8\'M%]G+J9#^O*2P_^&:93!EH>2(%7_`OOS!LU2UVNB]
+M7L96O5=?`MZ6%</0BC47Q8/)SQ63Y_8@=PMN;N6TINI@\7%OPO'7T7FK/9A=
+MZVFP?!$1=??![./3OK!$D<W=RBOQU)Z!'W]LSP"GNYW&CBE>YW933$G'W["A
+MVRDQA47=A9BF?AX5&I.];1%>YWMM5TB9Q[F2?&]7<]$<%'DQNL:HL5+?:S5<
+M1O+D]>BGDW9<Z[^FCJKS&O_E"E?Y>RNL\'<'UNU'5LISY_S\W"D_/_>]PM7^
+M;_S\_!&_.GT7\@;SA;;T'(8&P%.\R>!"_OB>I1.&0OL4H>,/,XS\;7:I@X83
+MXJPQBQS%-%_!SO-I:?8&]=#\`?3OXEK0D]7B:HT[->19L97[;FHN2-QQKR&6
+MYF?UUJH'[SOM1O=>M5Y[0[L`/#T58?J]?=10C)\^6[Q,7U::C%4TCGC`_G)Q
+M(X^\HU=^2*NN\CMH2]+B!OOFV^V;]_8_@((VGJ'=A1RT@2EZCK=7_>"P;TXZ
+MU/^`=M:X#6_H/CP6:%<1-2"!,7'^PN6>VPSNV&#2/3M:8LX57DLWKP*#3(83
+MV4OM?Z/NN!L*.N"6JU'U':W:.'VKTYKO:,:\?>519=4VMF63SF2O#*/=S/4<
+M1-_3[Z7=_30:D3Q+/)\AGG?1X,<VXO8`6-&*F[QQX-9`W%83MU7:QU4!V@H-
+M][T&&M(D;JNU;<BB`T$?IY8(;JTJ>,1Y/*;87_AP2"):?$.W$&/#B*4=PO,4
+ME#G3?8CN^2]X]L8UZ@,M$W*<F3F9KL6\RX_T'@W-MZ>,R4U]_J%]M[^V:XZW
+MWXH=M_^R^,^)O<9^<CO[1TG_,D(P+%;O9ZK^9'G;_N1[YZ@!C_"\W8\VJ7;=
+M[GV<?GB]`VGP<Z)%2`^1:A6QZO#?9PV\1O?]'WT-+>11KQKT[QN&8CL??"3C
+M"_4=><J!-\DF+<Q9-34UR9L0OM-HOY9:-ZO!W5N?UMK-]W:M@6SNE?1!W^>M
+M(R)AI:<XTN":YBU>6;K4C/JGG87M4M\)MM)*SS:T^I%:#W7N\^$XJ[XL05E;
+M`VB!0?C.3NI3@?>[D+`ZCO(61VIV;]S*NO[=>)UD4C/LGQ:U(B(BRO^W[U5K
+MCG17G0A#F]F)ML6OIM9UGVL@3R/F6<++TIM4@YK01`,TR^*JC2VDG->J3DBV
+MFHMO3FKQK1@",X;Z*F<B2_IMH5+IOXNW!?Y6*RY=MJVGA?LB>S_Y03O;-:FT
+MWH$TR8AL->+[Y-C@W<&.QCV-RTC^'><0'8V%(#IFL1$L'C8>RF[TO=U,/]&"
+M^;P&(]T\4N5[VTJ_.GV>4'T$FK_!F]1`^MA_,-O_15+EP>R&UB4CO;^(JPQ9
+M0-4YD%#)_17I]7N**WL71>F6-#*C\E#$^[I"=ELF:`F5,D`!]@<D5?OR`V6G
+MEMC$#D17NMYV^@CLQIUQ&]@PK#0LZ2G&HK>X4BM>;RS>4-\3X<**.WU02T#$
+MZ_E)1^="],#X"Z8ZX9'3X^A0TMT3YVCA>ZPB-NE>]H<>5@$[:%>EMV,M>.+8
+M^E\,!G+E<&EPR^#N^85>VQY0ENL>ANJ>*BPU*DS?RF7$A3926XJ$A%$<-*J4
+M4*TE;-<2]M1?$WS&FQ1F3JKTW6?4BJNUXCU:TO:R`+U#!S0:WE66OZI;'%YU
+M>*'2A^J6\91O1A@Z=T6-@=>(]O]ZE+Y*4&73XLJUN)6JNNWI;G]H"%F(?)BF
+M?7E?-3&UFB.WTB!T$DJX"?FH)6RE*9K%NSB#:!0.IO)\^*!3)`5I>1\=X*IS
+MEM,[*'M=(SW?V%&XAU[;2'V=>ZS\IEIQ!%M?U@7U#*B[W&=##Q,]GKWG`G'5
+M9:?<A_'RD1_QHCJ+VAM7>;K&%:\Z84'!47TK*XU06UP#@F&&AX9)XB4=8*L>
+M\@'JO[MB#OH/W6-E@;V>Q@!*KE73SA\VTC"6*@S(K>]MAY+Z0PFH-U8.&6%^
+M[E-1>,.E<AR^IW89S>>I;*&0W'$[XU:Q$-$0G,'W=J0*A#@Z>CC)>BBI5L5K
+M7_YB!TIB[<%:L3OLRWUT,%B)[+FZ"85">P#Z'J^.I@K:3T6'DC@T].RA]%K$
+M*L4%R]2K$FH4/=:F?K)E=B_J*+QFL,E$&?=C:54TM&*Y?1PT)N7G/;5Z+;0O
+M[VY%L%6'TMO>I3XZ<M&;L"<FH=KN(],!Z:_9C:0@`$)K'>=^M2JC6DHLY7ZM
+M"*[.Q'^=3H[:/9JBK:(X]ZK4'3YH7S[%2-8S,D9RTQV#QG-EZ>TTOIBPTJM^
+MNGX.0&O?1.,6X$//-2[>NOD!6G1'_6)O<3G%!1T-99W4I-$BD:W02][B7:B+
+MJDNPDL8PH'NZVQ^A]3XLE:@1J`A4O8M'DB@LO;FM*-`]^\KGS*U"`>.7Q;"#
+M?7F%F4Z%,ZN^NLHMRJ.:'W\KEPY6SOC<1IET*-OZ6_DTGT*HA-!)/KFN#]T)
+MX'HTKUQM[,NOI*-W>ZGO!>4Q"2M=4;0YJ1HCD+R+<7WM35AYSC@*S6#=3[QF
+M(1"'+"G?T2FZ_GA%:&8FM>N4;>N@Y*9NH)I*<4@KWNA-J-%4+=H9MYHS:!5G
+M$`G]`ZQZC4M1)]<:7#VH3["3NO+0A;0MC-Z?;X;BY'5+[CV38]PU2^S>XIK^
+MIS6ET>CCQP!WC=&]WNBN:=7LR!B\A2YRE_X)&W5U5UQM+#Z$5F.^T5_UI72Y
+MH2(W&DJN\A1O,)1$>!,VXBUO\8:8,R5FI`+*2@T1;.R?L$'U[^]6MOP84:8E
+MUP5>7Q+@GL#:HS)VL";17_$ECQVL\7]TB,8.T.$/\[IK!JB'7;UGT)BD#!1D
+M'M5'!)"H@2I1%2I1ZPTE]H![?:)_W%&Y:55Y-4@90U?JQE`X?I"UY+('X@X%
+MXC;LC%NGQGTZR2`Z!>2ZUEM<09]S>4S'FU`1<'5Q^$\<5D<9>Y,V>+9%]M^&
+M1.'G:)KP3/M)5QM<7=]3M@4U3'3#4M++$U>-#EZU,>&0,6&C,6$#.K[P,"]U
+MP"-"S]Z-R.$VHQXW'6T=]=B@;F^@OM+E(8Q!5<?A'CW=]9BLERV^$:J9-M:D
+MNZ]_(6'85`GTY/NK_$]_(>5H8VVNJN.=R"E320+]7M(73W:@Z`K4DQ6)%-KS
+M1]56.6652WNSS>(M#CM]0"NNK/L'];9`)ZS<81Q,=0"R7_>221?9;Y0VV*B8
+MV$CQWU6K#]UXBU=IQ:L]Z%*[;J%9ZKF?LT^E33M#8VI+VXVI+3BCUO31$,TJ
+M?T\]&)NN$R0W/OV1]GR,UN+VHYM)-QIJ6;;4J,>PHVK"SWTV@_O2:?#E([#]
+MNVI5%GH5A0JN[+%I6MQR_VV?DT^$-VYY6:5;[7GOONI4G-4(`[]X?XS+57:J
+MQ!R(V[^"YJ6L+.]1]X!JHV"7=7=/5D^/5T^/+JLLB::4K_'/4C*[!JE)]"?6
+MZH-+7=P]O`G[:3)$9P2'L$>XPBE0Z*T^=;>I[^:5)?TH3CHS!GD=H_2-F>>_
+MK$C8?ZY*Z;@Z-2-&3PX]@Z8FIKC:OIRD6Q>.U0=UX?`FK(I)6.WN33Y3_:7J
+M_BHUU&FKOZJ"GU_MSU#W5^LR=-=!?>R2E)?GG%J3W:X<$AKU<M#9(/5+F:PT
+M<'&XGA9;,"T(K+ZJ@G-IR)'67+KN2_Y2ZB@[M?0B]RV23S?6=]9U<GBK+OXN
+MJ(MIT9FNAP=3W/675M!S"2MIJ;6MHFW;1\(QK4;5;T_Q*H,+ML]J@ZL79X^K
+M*V7"C>Q-&="/?Z*W)&T!4AQ60SJ\/*9XI;L[-#_%*!_D5'E1&XC^43BZ]=17
+M0C:LE-Y2N>_9K-9ACC87SZ%K[5NF-O*AN?[-Z&3.[SC#_SRA8<9\L__KG^F.
+M_\&?:&;B^F:J*I'SZ<[Q)OV1;?Q(JGJDK)E&._T=?R(!"HFO-;)3/QC4?"_/
+M$@.?P=7!7XT03L7;K)#J>)O#;>69Y@LK0%E<T9Z2:-JA/SXV)CZ:SGJ(]D>?
+M5'W8G?&JKUWJM'TANU-[XQU:Q]+)-BN="^$&(\_]HD(VNL)DI8)W1MCIS[49
+MX6HOK<&5\#.YS=[X,"W>&MS:^OSY^J,YS>KIOOIRLQG^+.H@[0RX6_R?_:@^
+MP]!@L/LB),#DBQ^C==3B'3OC5:^C?H37LYR^N#Q>JHZ+6/9Q*;W;79M,$S:T
+M^#`:2W/UL+\7WSW1'_.K^OYN]GQL='8NL;4[1VY.Z/?O[PTR=\[I*>F.?AF=
+M*L6!#/R9`J%Q>0?/+:J/K`@YVBJ2=G&'?6]4BT4\Q;7HS^_L1"O-MQAHS:@Z
+MMKL3_8F?I+_V'OG@W5*WP^O)0Y`Q\?W<'=ZCEVA^YJJ@J)V7?Z;O52?'9YE6
+M56OJ7^VS_).^C"5J2<W^-8W43:*EV73"\>#*^F%J3H*GTDX;W[=PVK6I%FV4
+MM;XW[7.]T_>:"UVKEC?IS(N?GO54SIJX^$2;X_;:RMN#W]&X2*NPJ?V87FLR
+M\MDNWAF6^BY.SR*;P=57!?43C?LXYG?QTQE96D?>4+FC]^;Z?20O]5.=.V-M
+M1@-/%@N>%&)AX)XNSTK:&4LGG1GP>'?Z;A#-]X8RC&48K_HKP7F1(>N?&]"-
+M'')&3^B`>"2"OKO>1JOW;E;DTI.X94WDN:8==<EM.R_8VT#'A=.91'[ZFJ[/
+M`P[Z+Z!Y[&WDDC.*#PP)+L]N$^:P!C64A\+J)D%?=X9ZF:=B;>&N+HG^"`,;
+MMOK1(S2?5LZ5:PG*<.C\W6_JE6S8WQMM6V]UW>F]SU$6<$WR#NE_3ANQWNSN
+MXQT=IHVVUM],>_M.E'7K]8,J=HY6>4]3)"IFS`SD1]#.\DDM@6I>Q8+,V=M_
+MAW$G=/O1T*4X.C]@@<M0SJE6-`6MTVK8:()JL3^I[6RBVX:0^[2_R2>55_[&
+M_3*3?L!=R)R?5I9_.L'5ELZ<:FK_E9&&77R3`Q)SF8DV(&FA,0`Z`L47UP2]
+M4WN2ZO82!.`/G1-?*R+`\0T,1K?\!+V\7RWJ\I'J;`[HR?/>0XO-ZTY_S^-J
+M'089+G@^PP'=O^^%_3?K_F$7]G]*][_K@OY\OD/FO+S\W-3LE((%^BD(@X;R
+MRON;;XC&_YLBHX>,&#ILQ-"AD?,79,BL_+J1I%HF15D]9VC?WK%1:A^=^H[>
+MSAIN;HD.B6\_G02!QUPFS3BXLMUY8B$"F51'M2*#<F<X1/%BR'*1A><HC-UL
+M#51/7GS:>WM9P%W'50=:Q67Q&@+5E+W??$>,LOYK#=%<I\J;#S6POS>C^S1_
+M0KTJPA[:-K4+K'%&8H_)TZDPG<N<ML`/2F#/UV5O^:4=ZF9T]9IOHN.E6-L?
+M42VB@U_6XR&/PR>"&J9=6#E^25286H9FFS:54_8X@M+VPIH]&W!W]YP)N#MS
+MJ/7=D+;)-H-#FY&H39[.^R8$V\M@L'W\2C_8WXM%[(^<"%4CH?G==IWHL6];
+M/Q,\3AJO;)_K!N3W?59OOJ4^PDFGA+EZSJ0M/!*L@;V=Z2P56LGGV3EK\N*C
+MWIYE^]R?J)EB?GV-0##HA[ZE;Y.VC%ZN@;%40@TA2>)Z$I*.N[]59UXA0]8[
+M7&&^XOW:9RUJ>N%/SY:BK^5+VA_U`RW`NV0I[;]LHT-\/,TF5Z_Z*RNF982Y
+M!I;6=Y^6<1%AQVD9O8$4XWV(L;['>2<U^=)WM5WG&$S%_F]4*M`JDIF14>BR
+MJ'"&G)"C3<\[__0;@UK)F5'DLB@>K2=T_=#2JA]:S^6DDZ=B^XG>HM]1K3H,
+MT8[N%Z(#B8YJ1_>36_+^LD@C;-12J]$SQW)NV1Q;RMGWDI?-L08:`H%EXZT&
+M,YVA%6G<$7NEH74M9&N6?_NU$L-6+5AZ24>(=<;]+D/D#/]M=0;]!*KKR.XB
+MB:=__HO\9'YFW*>>"J]32LW5J>T:H49I5X-QW?^U>NE>O$39=-3?VB:&YN?T
+MKU7^4\E>MK03E7>7^H&>9K/KTOJ^%;*01*VW$L4L^QRTJ.'6/B'G:@;+NKYG
+MA2H@AQ3E/+]>E.>O:_SLN&[3^68&/&?-18O5'@.3+@VH/0;6P7LU7+DX\),+
+M?FCY'OI5&3DJ0SHAL/II%:3T9_B_;U&]4,J@$9Z`V=W!%_=CO=D7U[C"4![W
+MR<B`J\=\HR_N$SRY\1O.QU[(Q[`+\1&RABOT\G4PMNI9>-8][Q=]?\^%VX.'
+M=/^;+^P_3_?O>$'_\^S+9[Y22H?6`+4_FCJJT1!R-+7*4FN1D\__C.`LK8C$
+MZU8X'?7?(^4WX:D'^>RU7C-Y=NEXLX'/@ZZ_OF(FG56C[MYGX+N.WY"#.VE?
+MHDERNHUZ8S;U'';2=%H#N@$PM5N<6GPX0CCUX,,JPNYJY3TXN?L'U;#%-:-;
+ML>QAM7&`D2WO-OV#4+VZXICZ4J6?1-:+/L:%39OI_T+M)T!&W`QO0M@$SQFK
+M_:$%)C[)PKOI,OKFT@^O-GQI,.0=922WM;:5IM]>MX-,THZ>$HO!W5N?(-5Z
+M%MTE:@^]EFF*7ZL_4YGZS;RZ[["WN-F^>8K%VTFV7]A[(F:O>XI61?DVU3K?
+M,)4:IYNUI"9_RO<&7IO<1$>Z/FLDH9^&#%GV/7>Z;&6[70_;-T_E4%Q5"-FI
+M5J2C&TP'=#9[^WBG6+3>VF1+71G9_6J&LZHOTU0D_F&M(=F7QR+IIT;9>KHC
+M:9&S=WH7"Q+#*3GPG9Z2^G^HM0`2IWMR!6U-X!HN*:=M$NCYY[\SJ,V/FJ8%
+MAOGW?<>1A%,D7Z@5KGJ2MP5_VI>K?9J+;9J=>:C[A--Z7IH]WX6D>>4Y27,_
+M"4EM9C&]2\\VR0]O3?Z6UK2G5-`F,)1V2VC:ZQM"TMX[-.U7_$;::1\%+C7_
+M2WA96;!JOH=B)_B8<Z)3FVD)/2#L/+G=]Z626]\46B^@2Z_-.S/,.R4<G48M
+MH44_WJ^XP6"0/7AH@P>GMRC<4^SHY++1UT?7C+I'*=><\?;-'X6*60G2E(>2
+M2D0(9@GAE'TY?;:<;Z`3U*]I#?:/!MH82=YU[1I\JCY6.^F<3*OFU!JL/`N'
+M\W:]A.-*XS".R8U*U^]:WZ_6/G-.5D=%.[6%%IVUT7(J()_T&M/#W=T)Z\89
+M,]52:'$&)EC41E9^,KYI7:Q:/\^YVY7;.EKGTC8_0S*3-G^C>I!D]3RC8J%-
+MC`)#_*/K#?J)]JXK[9OC+;QEU)@&VFJ"%N*K'2F.PY;0&H-GR9]W%N\%[;F>
+M1U@?MU?&3YT(5<;J@*L^YQ]A25M#5OAHUZ6FJ>H8NIJ0E!Y21]1=A!"'(<#X
+M$[J<W4][W3W(V7D[*KPI)C[,?;/3.\[BC(D/=P]DE='[A$$=4D>A3A9='8Y0
+M'U2A=N*@HJ&OYAMFSO!7UHO""BKC;A+O1W4THYFVP'"H55+^UK6IH>L3NAS6
+MCS*CG.W1RH;;.KBRSDQCW-X$AR?&8%_>I/8KL9Y:QBR$>2>HM3+J-+5PIY;0
+M6-]=W^..EZ:S4E.5P3LL9$TBY*>[NXO3F]#HC)EB<8V@IL7N=<3T<$5"4'EW
+M!3MU2/K0SH0S$42+OB>#$Z13S2A4NZO![(9>+X2-"_UN7T[3Y;P)S=[>",I!
+M.Y:HH+;[>?@<)6SA.R?\P0/;W'TI]HLH:3$.>YDU0(<P2!J\>*SNE!KDU8;9
+M-\\0Y0#5@*KE6ND,3+',E(RKK@O61FJ;SD_$[7X1J`:#O4R=$N)N5C5H-+%C
+MW_Q^,'Q4_H0*[PRK_JJ6Y/<;_:(6:9WG%%*P*M"K6OFP+T]0.B^82`2-9S?3
+MRNDD.MY7);-_G:J?%[<.N5VESN04XB*:7Z+UH>5I,RWJMIJGTWS^)GQMZ^\_
+M/Q?CQG%>?1KW;6A]8O&/A>R$'/O*^F$.[`Z7U1,PNNSU-U4H\;_3H';$TNV:
+M*Z3RN+O[XL-@ETSR\^`*5XG("]@RM@K:';5462+MUDJ&]JDZ?JX;`2J3;"'2
+M(>>45:J]B*D"7M.ZOUK6-U*SZ_ZB)MX%W,=GUFW09=RJJD=C:_5H\':GZC*9
+MIK.KS3Z09[?MC%.)H(5*"8>4C5ZK:@GJ1HS=?3WJ2(,S9K+%?75KQ7-W+]74
+M#UG0Y`S$6^HS55L_PS)-*4BR:EBOWX`ZF'`(DM@CX*Z5C4LV?6W@'7R.!]R'
+M^-9?<*NN!PDN/^[NBA2J;%5KRVI#UD_9-T^VV#?/U&6UH/\,R;8/OPE6@=MH
+M%4+;Y_(75'BG6#6:4NV:<X%$7?&U7DG=^_E.W-=!761?/D6%**&Y7M=N<ZKQ
+M=#WNJ:UQTR%GR$YOG[;AOW><:Q`RNCNM(9ULJ7"2TJ"31B=;O+<Q4:0':`@&
+M6/:**A\JCJN"Q1$>4ARW2G'`R@XM@R<->K_0OOS8K\$TT5C9\9#LI-C=&NE)
+ME37C2(@XQ=V.TT-*3D)RY0;<T+9IO:E1@*EYSZ^4+]/T2C_#4G>-FK/0&LP.
+MU?'P#S4&>_/GM84=#Y!94NQP:L701#MA"ZE]*6ASOB:ON^E4O-7DZJTUTMYJ
+MQ-GVK_0==UR7P\_HNLK;$7[&1N7[7-#7W84KS^\I`^,MYH[T@7,''5)/$8SK
+M:6R&Z=9_V[1$O.D_\`728"SJ:=^,[H47L3MI(3)U!I#I+<X)ZMQ75[B3+.>8
+M$05FIW$(G7*T"SZHXWX.4C8VJW(.2&BI[^WTCC;Q\\WT?*.3-H$P.2>XOZ&O
+M$<O&.<X%VIP!>YZ]$+J>^MBGRM[;.2Z*;J@M,3P[K<@PLG=E:ZS'CX78NS<;
+M>0K>%"OOQB)[-6D[]G[OA`663.=A.O?ZG6::!QK72-L"::-MO*':-"@*?_%7
+MNL32(<^T'Z]]^7/*\G;P'$1TQ-3).F65)3:U)Q`U)0VP^_9^[_ZKVK\WD[:@
+M02+09-G4:TK7)%E//:#.;7;?[J3V2&WC99NJ(IUC5*-T'"EZ%TD-P3VF8K:Y
+M[6PIJ"T.YQIDPJR:D.54DW>+&YU0XA;:U,:^V=TX(S`83U*P;Q[5>5%2`_%:
+M&.9U694UK[(NDA^HVZCV?VVSIKMM/_KN_0:U@=AB*ZD%=3XV;8VF1+W7T:#B
+M=I4$FT)W'V^))=@.;Z[EBAUP[T)2YZ%Y;&TS)U*KR:VEZ@W^<E24@/MVM?<+
+MA^"N-?!.R\W:5"LUE5/A$<9-)3=%O?C<;'F>-/KY^T2%\O3@)\*3Y7R>;J_]
+M]SQ]]>5_SM.U%^3I+U_^SWA:^.7Y/(4P]/H^)?N\_YW%VP7E/2I,VV$>HM3%
+MC;YQPQ-]XX8F>N/"Z.!T77O,]*]0C(21UOV8Q&O<4*2B?@'9S0^Q=3L%BB0V
+M9MSP@LL3`T5#_9DU,DI@7_XGLE3PPF3+*&W*<#+U=*6$YQ8?4"J(9E:.LB!8
+MS4@&91C:Z>!-?AH>Q0Y8DF1Q*+UWG6]<-!([,%$_Y3V^,Q)Z]`A5._?UWG$#
+MU<IA6"^M:1SG[1@S+KH@$C$/].\\H(]CR#?CX14:7NJHC8L.W$R!T4.??X;D
+M=:20*'4#$1[-U]7O>'9TU@93;H?:+Z'R$[]7/M8XO`ZG.B8[S',?_G8_-=IF
+M0KRJ`(LJ!N\FVA5FWQQK43LP&:M/Q5I-[C#T@-O=<W7RC>]<WZVBPK>H,\U5
+MI^^?:)VN]<6CY.*'\D:G,_R?'Y;R<G62041O_%#H;=Z?S^:-GQVH;C/VH_9"
+M@@D/!1PSTU)@5C^M,/Z+;=YA]>$5%2N,PSNZNJL//_8W>O>OI@^JH^(GTDC_
+M<;6/*[TZ8)Q%WYU!_U8G8YX7#'T8A6ZO[[JBXW"C^_+X48&X%A7@#\$`8\99
+MBKK1\6#T75>-4[)7+/+\0OW53S]6&4YMIC<^BKXQ7^N-[^>I'*+%]ZNJ-2<&
+M"B/]'Z'!T.(C4?!=/?']/N+\B?#.B/+&1U+OVE;-OYW:DFI+(#XJI(`-%^BO
+MSE51TD[3\RT!7DSN_RMTX7P+C0.38-+*]T=).]+NA[0Y<4*XUQ@3UUQX-0W.
+M#?/?2@GJU$86BRK4WMCAFDG9JV,]50UDHMZN%=LJN+ZWL'I^\XO6[NUVM8%2
+M$[+7W33#-XZ.:+;YPRDINLZZ\PN5BOZ-JF<:3M\AC)"&<;0+0/W?VH\#M.V/
+MWO<1?]\(2<_@?=[A)(2Q%K23-.;*6T*BK?,_>HBU(U1-`ZSU;FQP_,$0W+>S
+MHTR["!X6;B,2QF-/W@M2F78:K>YOBCE3:*9%,V[\;Z8>!D40^XETO!K0F;H$
+MU7:T=;Y1>E]9GRL_EI>.-!^\DS?!WS^AT=4-P1F+F[63=8G4GS2*GK[E<]::
+MAWZC'I=\:)"]`N9;9J@2KMI')>S9022*]]5];`NVT/C/YP9U\'U4V3YW9RY.
+MM,.HX9$T'DLC8GL.TJP.^C8XUK.C`3B:"F#:3/_C7RB=%.-N+KQ4#^[`00[.
+M!CY?Z>]NKM];$:K@0[]1'-@CC85MYVB>TS(JEO8>-6FC8I$Y8'3:0?T+5MMZ
+M\_0>_<.!IR36X**^5&$LC1N'1-[#&Q^+C$1:@=64N3/Q1#1UT=K7CXS0^2][
+MJ`^WEOIP_D_VZ3HW`@;0>N>R8X9&Y[*SAE+T.V4$^#*#(;B+:@;-D?"_\1&-
+MI*SAV13'O>XUWN(U6I%-*U'K0QS:C`AM1KC,3?7&K5%]O-551Z$^UOBFVR.U
+MQ(%:8C\M,4J;'A/IJ70$XE9[BE<O+?E\YT.15K8I:>^^S;0T'/58VSR0?^AK
+MN;TT<:UZVE3_1V0,(.J'^JD';-KF:/S8^=!("67G0\.#OX;J(<>M\:6O#)U;
+M0KUQFJ/LH$@KZ#FMG-[3-HY4P9Y?-L8/5-G,\+]#H^Q5T/9W>A^D-&BCPFAT
+MM%-`43M'A:L]-T:%C??4+JVJM?C&=HST.K0>U'0YM(D6S>J-#]=&67TE#FVQ
+MC7Z/MVF3P[VC'#1_,E3+G:?C2MY7'T+)3%E%WR[H&RI]Q1SA'6_S)EK)-!EO
+M]2;:R#HA11^N)5H].QW:(AL)U8QPV,]:?'CI^'"3-]91UT_-GZ'1=6O,9DIZ
+M49OQ?Y0^;_VLMG&BW;=5?%+Z-MI4I"ALYSC%K782@=A??HK*3/L,1>9NAN7/
+M58>W'%:%Y#_[B7R8WNZ(26IVKXE):'$_1</-;ZC2+FX*%#D";ZA'?_A`1#[F
+M2?)S78+>W,H,ZH%+&J?@;]U,ZLPA`,^[JJA=?22,HK#`&ZH@GZ3[@7U0Q=X9
+M81,]QY96':,VSS>]3Z2WB]8='4+`0HLVA')KALJM$LDMXO`^R'>X=YPC=`]>
+M:D_FM/SJ37)XCAD[)[;HWU%#V[]=K`%&16COHV[$5+LNT@Y4>/-LB?YA'_`&
+MM(TQS>[O*6>O^8"57I,^_A@2CF\7*[RB"%H#<BH^W.CJ/6.F_TM#L`LI=L65
+MWD*;;YPC9H?[<\GJ`Y^IQ?@R2>1T38AR:!M'?XE#5<.8AZC^%4VA&,<@/I-[
+MA(K5AE@S#?QI<987F=8136)O&(=T\M8,2+&5%-P,B+:-A*RQ_B:J_WJ:WO`^
+M1&7HJ8Q(].>^3RT2C/4>OLD1VF1'0,7+^_6WE_U0W?_`3I5,SWNJ=J.I03TH
+M=`0*PP*;54$_-5P5-+5%8.8IEB>;_>698?]*(#/WMA'(P220`T,$TM8JD#-V
+M(WL>I-ON+IYYX><&5](D3QE3#[7S8;SX1@6X\GLJ(V$@T,Z^D`':@SAF?)C+
+MZC7$5+M_5G*C7W4D%^I[*4GW!;ZG]M']S1?V/_V^^"=?V/^`[O_.!?W;S/_8
+M06HF.*>$<LTZWY!!DZW\Y>]?<#K(^>6U[Y\H\+<CSH%RY_DS/Z12UUZ+4+-2
+M_2,^5#,&??&!JVF>H*4_[W94W-&LGH!T])SAO^A#7N9(`T34JLC\@K>H_#ED
+M:V$WXSXZW^AQHHI^HG$K;R2MLE3!J$6?UJ(P]8:\_6Z+,C,KO.H5KWI:2VA6
+M-HIQG^M&A.:S](Z)LQ;]Z'MMW:\D`\W>D>]">-![O(1VZ!YAX#'TH0]K[A;9
+M5SNRPN?AAUMHZ*Y9"RO?T>F'%0G-Y5.,6C,8#$K(>?GTPG8UXN#99N8UGWL_
+M^;8L4#(]1C%8XO!Z"&$G_OYT0-M1[]#.F+T1G&8UQD(I:F!5>3;@NDR2D6!%
+M"A1//DL?S:1MFUQV:FF3GHAV]7^[:M=H;SE?24MI2<L/[E[V-R;_ZGM<!659
+MH<6W:"-7_*;^(!D:'%!+*;J3<7'R5UB87QE4VV)%$=`>^8L1:#?%G_V-J;_2
+MQ`O8?/Y=!E;QUK)]Q1%>#^VR$8B>X7\EY':'MRX'Y9MH5LQ^\DV,*MC"#@BW
+MOJL/"=LA$A-PC85M%.6;:)(=S5@F2CIYMK6H?MKH%FV;6=V+<=N*;#%)ML).
+M,`+J1W+[1GN;JBG<-O]@VDMPI]JARVU!X5X24VQU]8+6CVDL-&F-_(EM[0X>
+M]V^ZX/>Z3[?IANK@W=!K^Z18+.5T7G5%S$F7'=K?HNVJ[SG:2_WD[T9YSEQ6
+M<N!??*`[SQ;(WV;X[?-UFM7V$.JL(W6^CM#T:EF@N!=95/)LJ;O)2.N6Z-9\
+MP]1IK"#]4ZM%+])Q:FW/V0GY3N8(IN9XE3JWJ:.J:$V=N+Z1)J.9/OILZ_DF
+M7UQCHO^FW=R.M)_;U!#*<]VU.T1?[;B@ON+YAG/S_]U$PR$A$PV]DZ):9P@-
+MJ:*):B.I,IM^9QP;9?%UZ!$2T\7!!SN'/&CL\KM_U/G^J<<_-S4W;_&_3L"-
+MH3,=U3Q7KRO*YET2Y4!JPF).%_1LJ:HS_?0L49ZCYI_6)=_[#^/'QH]^!3%E
+M\D_KZ#X>\'QO]OQ@_NG9Y'M;@O-YE1Y16R=#HDN&OTG?D`8D.%#4U!E,:+9O
+M[@'[]I-C]LUCB]!_;?FDV=F9%M\[-:.GR@0%$H_WEGYFWVPIHN=JG9JER)?>
+M&'(F7*FAS?KUP'MZ%QMJ;P1JQ\U>[\@;21>M5$,H@_>=_E&+VZ_%U7B*PPWV
+MY0O5R3OAM#2V!ZV,G6JINY?.]8DIMN5W<O>';BZ(HB==W=L^I58ROZ6D8*A%
+M?4=NTA*J?4E^+6F/+^&0EK!+K;;=KU;;UCB58'L3:M3^IRO1H5GIU))..6EG
+M:]IX-FF_VLP5'O#4$L[B@?TTYJ>Y]]/FL>W>.R'O-;1_[WMYKW%GW!;51?84
+MGY##G0,)6SS%6XSVLJ=4T[#'OGFAQ9M4;=\\VH0L.:4=<&IQ&ZJ^=6C%Y>C"
+MV#=/L&C-G7<%O=:'>G4,>NVL.N;@>U:M6NY]IK*K]^#=6E*IEK!<95LI9=MR
+M9!L2NJ'J*.VDL+[S7BVA1CNCJ&JUJXPG;@]D8(_3L]B$DIF("O<6<3$@:8N6
+MM!71*`]WSXI`PE9/7+6)]GGWW&<RN'YXC^R-`<5;%X5Y$W;Y+(O5?O_4`E>>
+MF[+X9PED*_G9IJ)D@FNQD0OYIF7G`DO1,-MIO<TFXRDF"W^B!6`EUP3<F[Q)
+M6\U)6Z!TJOT#U!F/N+-E(OIZ>SS;3-/\?7ZEU8X;#9RM3N\$$PIBNWWS7BUI
+MG<IGY&3"6F_2+BUIE9=6A-/Z_PHG[9NZD3CPCIUH<GJ73+0X8]S;W3:UZ(:V
+M96^L'ZC]B,SI2PL<5=:ZUVEQE=IGWKBU]I?C*I'S]LT?=]X;LZOP&K5G1J79
+MO0Z)Q]-%%WF3\$Q2I0K`OGEGYZJ8]XL.#S[E+=Z"=GL\DNX+NT]+6JW&5S8:
+MFU41VD9YDU;;-_>D%_OO[?^C]A%EN39TE-J'>^5;E*S^)^V;3WKB5I^;4A98
+MNMU+QP%T5D^"(VT(/^A*1%KTN&Y#%OALB[4$U==.VDB[BZSDZ*9ZD];8-YN,
+MN[2X<CK49B7EAC9T(D+QQ*U1,2`%%4[C8`A-I3=IE5/K0E^+DE9YXBI,M!]<
+MTM:8I(WVAU]4IW!29:9#>-1ZP43M@+EX2\R!DMO>51H'98;*28)AWPR!W41;
+MCY8K\9]^WSG>;),K5]>D<J?F(+F)*=ZZ9!_EP$[+8OJREG1*Y7A"<^?WJ4)[
+MD\XRW4(TJGFX-V&_UH46P$XD*3_"4EZKI!ST,::/$[W?&X<7:GS/NMHNG+K!
+M79!_P]S,G!'\AZ@"]4O];=]^7_2V/@Y#1G!<&)T`>IO5U3/@CIB:.&WF##_M
+M#UHW@68Y[V[[K;[N!NXS>P(F>UD?^EA48C&Z^\(VZ>`9?GEAWYT&VGD59/3\
+M*WR>RK&!0.(T_R]0K/575."NPS/<7-1U"VU157>";*B=M#0'SZOS=FC#!BKK
+MR19/U3G/F9[VAVC[=9H(Z5T?QQ,A;9"EAC<-!D(+W'[\;GZ3[VV%JWV3[_TK
+MMTN>W6E*)0/BP9TF/ZVSOI_ZVCM-D92V7/Y-JXGJ4OGWP"YFZ8_O-"G=?0?_
+MIO4$=;?S;^J*UMVH^NSGSTMM8_;47?NNM/_O_W;[GYJ>GY^K[_]_XV\TP,-#
+M&N!@`0]]DXQ_2H)F_)V*7^UOW&J`Z.<+9.<6IO^;%OZFT!9^!ATP8$,;K[?O
+MO=NU[W3VP+]NX_F)EK8&H'-:!\/5)L/`'.`4LV%@(3`,6`*,`#X('`-\&%@-
+M?!)XQ&`8^"?@*+SW''`>\"7@5;C_!K"+T3#P76`:[N\`SL1[:8D=#,O-AHB/
+M0-^`^Y\!9P./`*^!_S?`;<#O@;N!IX`C$,XYX"R$V_'.#@883`.[`U?@O=[`
+M*<`,A/NVR1!Q.>C[06>!WHEXK@'MQ_N#@.6X?S/P3="W`2]#./%`]&@'3@8>
+MP_T9P/5X[E[@:XC?"32"SD-X'R`\%[`3XLG!_2-XOA"82OD$_!+A/`@\`%R$
+MYUXU&B(>!OT0Y1<PG_(+^#>$MP3^TQ#><Z![4KX!KZ5\`PX`O@N$C3QP!_`/
+M>/\CX"6([S-@#O`(L!?E%W`"GOL>>#7HTD1%1RP'SD7XIW`_F_(/:$$\Y;AO
+M1OH[3N]@F`ZZ.S`-_KV!4Q#.Y<#W<?\:8![E&_`-A'LS\"'*-R!4QL!XX.>X
+M/QDXF_(-^`O>OQ>8BO>=P";XYP!/4SX!3\*_!/A7T`\"HX$KD9Z.2,_#H"V@
+M*T#W1+X]"=J.>/X$W$3R!1Q*^00<3?D$O!/TN\!K*)\H'<"/@%`:`S\#K@0>
+M`:)5'O@-L#O"_QZX@N0*V)GR!1@!7(5XOT"^K08^AOC7`+\&=DSJ8'B9\@D8
+M@W#6XO[=2&]OT+MQ_W+@2WC_&N`5H`<!:TC.@(?Q_&U`%^*+!SZ"^Y.!F7A^
+M'<*)0CCK@6N!,W#_%,D=<`[)'7`#Y1\0G=V!A<`%E'_`8U0?@3>!?A@8`7P2
+MZ$2X?P)V!?T<\$?0+P%'X_DW*'U4'X%UP!W`6.`&Q'\<<K(1V!_\;P)"9T9L
+M`?:Q&"*V`N]`/E0">X#^".^AJSEP.^B'\-QGQ#_H7:"KP<<1T*\@W&^`?Z%Z
+M#'P"?)T"G@.>`^['_8XSD$X\UQWHI'H,O`[TY<!E".\:8"7E)_!9RD_@1\#;
+M@.\`]R"^SHBO&O@E<#_P#:2S!K@/=#R>ZPCYF0P<A.=G`!]$O(?@_Q<\=R_H
+MPXC/"?R8\AGX&)XK!(ZB?`8^`/I!X`^4S\#%E,_`(7C^3\"7\?YSP#+<?PEX
+M.>@W@.LHGX'[*9^!Z+P,_`@XDO0=L#?2=03X(]5?X-TDE\"S".<4\`622^!-
+M\*]%>M&B1W2<B?A`=P?N`O8&?@T\#O]=I/=`]Z=Z"[R,ZBUP'>4;<#_E&]!/
+M<@A\'K0?[WV(<!N`'R$_)N,^^D4#&TEO01Z:@!,1;C-P"\DG_!O@WP+Z[Z#O
+M!;V-\@\X&FB8VL'P,\+)`3T?M`7T,81?"+H+Z4?@/Q&O%??OQ',V8!;P0=R?
+M1/D+]%#^`MUX[D_`8J`#S]V$Y\*`D<#G<+\#PGL)^"(P'/?S<?\-T`]3OA/_
+M>"\"]V<B_AV@KP(="=J$='\$>@WBB0*-YCFB'_`,<""P/\+Y#/Y7(MPCP!22
+M8^`8*A]@$>Y'4[H1SE`@^NP1PX$^TK/P'TSR#1R)YSO.0GZ3W@">(/D&FDF^
+M@;^0O@!.(_D&_DCE!/10.0$_A'\\T$?Z`CB+Y!<XC/0#\`SI5^#SX",'>`FU
+MU\`.D*L2X&O4#@$OQ7,/`UT([TG@,\"12&\OI/]/H%>3_`(/D5X%W@%\`YA/
+M>A5X-^E5X'W4_@!74OL#_(SR!_@'TJO`O90_P`+2J\!!H&,13R;RY1SH.ZF^
+MW]7!L)GD%_@*R2_P=6IO@"U4WX$K<7\0<"*U-\!HTI_`7Y&>>"#ZF0/'3E5\
+M1TP&#;-ZX`S@&L1W+[`7:"?P+LH7X+64+\`:JL]`+^4+\.]DQP"_0'A/`O](
+M\@:,I_P`/D#R!70#QR.^/<BO-T"_1>TR<!'9,\!GJ+T!_D3Y`GR#VAM@!OR_
+M`:XG_0>\'#@)X823G%#\>.X<\'ZR9^Z&'D2Y=0<N`MT;6$CY`GR+Y`38E^HS
+M,!EX,_!UDA/@[TE.@,]3.PS\F-IAX(/4#@.7DIP`W:`3$7\WZ.\<T(^`GCY5
+M840AZ#P\5P)LIG8%^"+H6?"?0O8+Z%LHGX`C2.]1.BF?@/\$/9OJ#_B:`SP+
+M3`.B=Q&1`;P4F`6\&N'D`2]&/KJ`CP-?POO74[L$G$_R!CQ!\@9$1V?@HJFJ
+MGD8L`9;B_8]P?S/I3^!P/%>*^QJU-W<K'/@-L)+D$'@<N!S^6^%_"G0QZ5-@
+M#ZJ7OX,^H7H)'$YR"-Q#]1+X!>AK@#]0?@/K*;^!;^'^;<`>)(?`>RF_@5&4
+MW\`QE-_`"+*O$.\2Q.L$O1;^.4`_M=_`?B2'P`=(#H$WDAP"3U']!`XA^Q"X
+MFNP=X%/4?@.]E$_`STB_`=^A=@683?42>);D#SB+[$+@$]2N`&\A^0..Q_U3
+MP.4D=\"-E`^S88]1/@`O)[D#CL/SEP,UR@?@:JJ/P`3@2O`U`.50`0R@G%<!
+MGP+>#/]#>'\UR3?*:PVP`??7`N\"K@,6XKWUP+'(EPVD9\G>`":2O0$L`MZ&
+M<,*1KBV@OP.]E?0WWHO'_5ZX7PFZ+]Z;#/HPZ4/@K62'X/ZON'_O;%7>`YW`
+M)7A^%^Y_@??W`(=0NX3[3^+Y:M#?@RXDODGN@5^1/0K,H'8(^#F5![`SR3OP
+M.Y)WX'W4S@,?H78>N)W*`_@IGML!?!7A?01,)#D%OD/Z@-ZC=H32B_O[$7\?
+MI+<&V(C\.`2<C/1\#__?P;\6]!C</PX<AWPXA?OOD_S.5G;.0#_NKZ5V&[B8
+M[--[.ABFDAT%G$CE"$PANQ3X9](?P&54CL`<TJO`=))GX#CX-R*<EQ!?$S`7
+MZ6H&/@IL`:X#&M#OF@I_"S`/\5J!+M`V8'?X.X`O`,.`MR,]X<!PLK\0_@]4
+M3X!EP!F43JHGP+?);@#>0GH:.)?Z!\`=9"<`!U+]`!JI/(`NL@N`^Z@\@+E4
+M/X`74?T`OD;E`?P)_N\"5Y)^!I90>0`?I?X`\&%JMX"O4_T`6N'_/7`CM5O`
+MU50_@,^17KX7_0YJKX![J?T&WDOY"CQ(=A;P+L0;`7Y'@]]!H#^E=AS8C_I)
+MP'\BG$CXST&^10&O)'G&_3[P[S=-\1\Q$/@B,)KZN\"AU(\FNP+8#!Q)_6:$
+M'SM-E5O$6&`\Z/%``W`RPMM->@CX#=)[+_!5:@>!JTC_`(^070O,)?T#?)/R
+M%]B!\A<XF?(7&$_Z!_@NY2\PF^P"X,/4WP+VH'8,\58AWG=!)Y(>`J:3?0OL
+M2>W,-&5O1TP'3D)Z/\/]#,IWX`MD+P`K2"\!TX"S:+P`^7(*]&GXAR<KNVQL
+MF*!#T"9H%;0(&@1;[F4<+_389-4/M,4*CA0<+OY#!:,%!PKV$XP2C!2,$,P3
+MS!+,$$P3G",X6W"CX`;!]8+K!-<*KA'<([A+<+M@I>!6'>>@?T/A"JX77"=X
+M:([PD<*X?"YCJ>`B09=@EF"&X!S!V8+3!1,%QPN.%1PI.%PP6G"@8)1@I&"X
+M8)B@3=`J:!!LD?0W"38*^@6/"QX2K!&L%MPCN%VP4C#<*?(E:!4T"#:G2WR"
+M?L%:P1K!:L%=@I6"6P0W"JX77"NX6K!"L%RP5'"18)Y@AN`<P5F"B8+C!6,%
+MAPM&"_83C!0,%W0(6@4-@LUIPK^@7[!6L$:P6G"78*7@%L&-@NL%UPJN%JP0
+M+!<L%5PDF">8(3A'<)9@HN!XP5C!X8+1@OT$(P7#!1V"5D&#8'.J\"_H%ZP5
+MK!&L%MPE6"FX17"CX'K!M8*K!2L$RP5+!1<)Y@EF",X1G"68*#A>,%9PN&"T
+M8#_!*,%PP3!!AZ!-T"IH$30(MDB];!9L$FP4;!#T"QX7K!4\)%@CN%^P6G"/
+MX"[![8*5@EL%MPAN$MPHN$%PO>`ZP;6":P17"ZX2K!!<J>M#T0,9@FF"<P1G
+M"U8(KA0L%UPN6"JX1']^'NOGY8*E@DL$%PFZ!/,$LP0S!-,$Y\P3_C+$?[ZD
+M4W"VX'3!1,'Q@F,%1PH.%XP6'"@8)1@I&"X8)F@3M`H:!%LR14X$&P4KQ'^E
+MX%K!-8+;%TAY"VX1W"2X47"#X'K!=8)K!=<(KA9<)5@AN%*P7+!4<(G@(D&7
+M8)Y@EF"&8)K@','9@K,$IPL:LB1?A&X6;!)L%&P0W"7/;Q>L%-PJN$5PD^!&
+MP0V"ZP77":X57".X6G"58(7@2L%RP>6"I8)+!!<)N@3S!+,$,P33!.<(SA:<
+M)3A=,%%PDN!XP;&"L8(C!8<+#A6,%APHV$\P2C!2,$+/GQS)'\&U@FL$5PNN
+M$JP07"E8+KA<L%1PB>`B09=@GF"68(9@FN`<P=F"LP2G"R8*3A(<+SA6,%9P
+MI.!PP:&"T8(#!?L)1@E&"D8(A@N&"3H$;8)608N@0;`E6^1;L$FP4;!!T"]X
+M7+!6\)!@C>!^P6K!/8*[!+<+5@IN%=PBN$EPH^`&_3[26V0RV#8"36:#;0/P
+M2=!C<R4?!8<*#A2,$HP0#!.T"5H$6R0_-@F]07"=X!K!58(K!9<++A%T"6;I
+M\>9)>@03!2<)CA<<*Q@K.%(P3S!+,$,P37".X&P]O(42CN!PP6C!?H*1@N&"
+M#D&KH$&P6<)M%/0+U@K6"%8+[A*L%-PBN%%PO>!:P=6"%8+E@J4Z7Y*.68+3
+M!1,%)PE6+.1V=:5@C=S?+U@MN$=PE^!VP4K!K3K?@DV"C8(-@G[!XX*U@H?T
+M?,SO8/@:\FD`5AL-MBWY(E^"&P4W"*X77">X5G"-X&K!58(5@BL%RP67"Y8*
+M+A%<).@2S!/,$LP03!.<(SA;<);@=,%$P4F"XP7'"L8*CM3?=\G[@HF"DP3'
+M"XX5C!4<*3A<<*A@M.!`P7Z"48*1@A&"X8)A@@Y!FZ!5T")H$&PI$'D0;!)L
+M%&P0]`L>%ZP5/"18([A?L%IPC^`NP>V"E8);!;<(;A+<*+A!<+W@.L&U@FL$
+M5PNN$JP07"E8+KA<L%1PB>`B09=@GF"68(9@FN`<P=F"LP2G"R8*3A(<+SA6
+M,%9PI.!PP:&"T8(#!?L)1@E&"D;H^57*>J'<I<9E;<M=:ES6UE(JZ?>H>2FV
+M.1Y^;JA'?:>V17O4>*YMH$=]K[;U\ZCOV;8H>?[0`_Q<S0/\W/X'^+GJ!_BY
+M/0_P<\OEN5)Y;HD\MTB><\ESTQ]0XU]C*Q#^]VCG5@IZC`;##).!ODVK:PY<
+M.=VCJ4MT9I\<TC#`R/[U<*GX?37<!CC:X^Y%N+4RCX@VH)J$^_%PF^&ZPQ4B
+MG-7`SGAN._!D2+COPKV(>[?`W0M_VEN8C@W93_'@.=K:[''09^"^`WT;Z.'X
+MW1_N>SC:>9,.=R\"YL,_#;]/&5O#I^ER#\/15C9O`Z.`=#K(*>`R8"+<5XAW
+M&^C%>/]GX#]QCXX)HAWU^P.O`MX*-P+^@T'3;BQUP`.@PVCZ*@HZG?(.]Y^&
+M&TO\@?X)OW.!N10NW'UXE@[VNACWLVG.*7">@1?X'P>.QS/?`.\%3;OLA@/I
+M/*'#N'\-<+21'>U;<C'H+L!,^.V'*X;+I7+`/3LP3<KS;W`?XMY9*;^_PUT&
+M/UH;48%[;P(OPO-+Q9_./TZ$?W<@'?PX%OA'^"V5\J4SAA\!?1'\+L=[5X+N
+M"CI?WK\$;BW\K@>]#VXZZ"-`.MD;\D9S6`R?P)]6ZD\$TNZ/5QI5%M)W&@,=
+M8),"[`WW.SR_`O3-(?*R#*[8R#*P'O<C*4XJ#XF?3@]IPOUIQ"?NO6#@S4+Z
+M`&.`0PPLDY3GI^%HAZ^^)'_"W[.4[X@W!7@I[M/6["_0-$O0]P&O!=HIWX&1
+M0-HJ_$7$][V\?[7(7"GEM9%EH`#^I7#_A/L,]VD;1=I';@;\:$.1AX#_-//[
+M<?C]-R/[76JA28E<U^BHD&2SVLY1U2TZA>@>X(=49D!:6_`DR2C0;:)C/PV&
+M&X%1N+<$CG:.3B`YQ.]T$]?=KK3W(N[32=<T(]0&I!F9=-CHM?!KA.M!=0MN
+MDZ2/9DI.I[H'/XN%Z]ZYD/*AI5#1H&_'_==-G(:%<+3)7B[N?0W\"O11N%YX
+M_Q$#R\IPX`_`Q<"1P&(J=^`BX&1@%N*G6:)Z/)?"O8K[+B`=4D&S0$<`:=N*
+MV4#:'24!^!#P+I)%X&O`@\!"XA?Q5YGH$PK2#)KVJB==0.N2:<DI[3I*97\1
+MG`^NH\@7'7)!\]WOI'M(_WC<NYSDE^(R<5A_ANN`^]<":0>/2C@Z+N,HTD][
+MGW?#[YEXMH^%\W(/7#<#Z[1/2?>8N8P>@*/=X,?2N\"[@5V`ATF/27G08J9L
+MT+2+-1T:6@A$^V-(([G!^[1+6R1P*N@K*'\H3_%N'&@'?CLD'#U?[Q)=H=/D
+M3;S/1AB/PVW#[\N!OP#I#%M:?T=UOQ&(_A/-L3#$`3OBF2%PM+KF`/S7X%X5
+MW/6@:4ML.N-HH(GSEG;+^H#*E&2.ZAB>&P;Z(_RN`O[5Q+IZ#_`ET`^2'@0.
+MI'P$1@!I%B_IWG+@&&`L\!I**Y!6;-%A`C=1.H`3@;M$/]+&<[29S^-4+XVT
+MG@AZ!TB[1T63O%#=0GI&&;@N;97\&HS?J^`2J)X!>P&3S+RL)`OT#4!:`/TR
+M,-;(,A)'[2#H/^$WK9)\#O@7()U;]3N*%_ZTPJE'2/X7X/>/1FX+Z*)=5O93
+M>0#O!SX*YT2\[U&^`@>!?@WA/"_II'5%I$MK#5QV-!^:YI7?*&$G`FOQ_``@
+M32>GNO0'T+=2/<7OJPS<-EL1WF"XSAPL?>M7=8%FFU,=Z4?YC_>N`](IP0,I
+M'X`QQ`]P#-"%Y^*!R<!QDH<3J/[!?R)P-^@[@+1]ZR0#UU%:A3T2\28!I^'^
+M+.`*(.T23S;)W<"7@/<"Z8!`6ITZC/+$P'F1`9Q%^H/X0W@YP"]`+S1P'<X'
+M+@06`.F4-[>!=1?MTCL*>#^0-H0M`>8`'Z!T(CW+@>-`TXZ'SR/<!X&WTL)]
+MX#S<I_V=_@JD`TZJ2%8,K,.?,+`M\93D(^W-13J9MA!]"O@T\!&$\V<#VS+/
+M`#.!?P72&OEUP'\`GS?P(9ZTW=T30-H0DV1AHX3[&AQM<T:K9>X`TD3^]4!:
+M3_0FPM\,)-N/UD*1CGC;P&W/5@/;@I7`CX`T2YSJP';@>""M3:,#XVF)#M55
+M.ES^$ZJ;0#IQZ2.@#^]]"IP+^@"0CHNGI05?(]\^!TX%_86DDXXRH',E#@,_
+MAO\1DBN\3TO08;_2W%=#$OR_!7X*FB;8SP=-BQ?B2;\!5X*F@^)/`'^@_$`X
+M/P+30=..K]WPW$_`^X"T1M&)^[18EVR>,\`,TGG`.?#_%1A&NH'*D-H'8!X<
+M;5^]R,BZ@G0TV5X3S&S[T$5MYZ]&UNTI9K81W$;6L<\;63>3;49U;+J);<`O
+MC6R[T$6VQB$CZ[)C1K9=IIM99V\UL:WQOI%MI5>,;)/>86+;A70IZ;HU1FYS
+MGC&R[KG:S+;N#C/KRJ4FUFD5)K:U?F]DW?6=D770*!/KR#M-W/:6F+@N336Q
+M[?2!D=M8:C2IC5YF9MWV!R/7E2XFUKWO&+G-HD-0J8Z0S4^R\[J1=<\",^M@
+M.BZ99+/,Q'V&X29NLZ\Q<9M/?0;J"[QA9)EYU,0Z@,X2)YFH,[%L76_B.DZV
+M.+61?S&R#K_2Q+;`(A/;2B\;V;:F`R5)!]UD8IO]:R/;G.EFEEFZJ(^SU\@R
+M--7,,A-AXKIM$)FALTJI;GYA8IFD4ZBH#;G;Q&W`.2.WS;U-K#MHDT^R@3:*
+M3%E,K'O(]G-)N"0SSYC81EEC8MMKJ\C>GTS<MM.Z6[)%^YJX#:`V?8F\3[9Q
+M!Q/K,K*)J6[=9N*^S%5F;GM_;V:=1GT&:DNI+2<;=(6)^WZ_FKF.WVYB7?N(
+MF?LJV2:N:[0I+?6ISIBX+S#:Q'V)7B:V1>N-W&<;9.(V<K.)==0D$]NHGQM9
+MU\6;60;7F5F&AIFXK_&<B67Y,R.WE1-,;%,9S5RV-2+CG4RL8Z-,W&9\:^0V
+ME?I:5.>.&EGG76%BFYIVWR=;OI^);7.R8:GO66[B-L1D8AG9:.(R^KN)ZUJL
+MF6W-:2:V(:DO2FT-[3I*,DVV$<FHT\1]7KK(ICYI9-NCNXG[GD--7)8#3%Q'
+M8DS<-Z&%Z:3+>YG95J2^%;498TRLZ[>9N$]*-B/)T,4F;@N6F;C-?-+$NF&Y
+MB>LHV5YD4]*.7-3W>\/$MM2#)I;1)!/+=I&)^VB_-[$.?]_,M@5=GPF2[?:4
+MB?,\P\1EEV+B-G2OB756J9EMTG$F[NOU-K-NH\-EJ:_L,'%9'#*Q;J.^!=D6
+MW<S<1E6:N0YN,7$;DF#FLJ33-ZFO.]C$NOT&$\O6C6;6618SCP%07Y?Z#A^:
+MV%:ZV,QY_YV9ZTJAF<<$Z"0&ZO-=9>(\[V_B/+K.Q+I[B8GK[,<FKMOJPF^/
+MB77&O2:6D2DFK@-_-G$=7FGF.I=C8IF<96:;)L_$;5B$A77C9!/WN0S2)M%%
+MLC'/Q+KPK(GS:K6);2;:]);:PB=,7+=>,7';1&<<DDXY9F*;AB[JL]QB8MF@
+MOA79U+$FMJEGF41WF;GO_X.);?B[3%PW.IFYCW#0Q#KS!1/GT6PS]R%6F;B.
+MT<9$I'/N,;&.OM_,=8GZ9I27_<V<ET^96<8SS6SCOVUB'3W7Q#IANXG+DOH>
+MU%><8>8R_MS$?0:ZJ*YT,;..IHO&``K,K"/HHK:"QCZH#ITT\]C,HV;.@],F
+MML623:S[:+T@Z3*7Y`E=HP1)=]G,7-?^:.*Q&^JKDZW^KEEL#!/+=C<+C]'<
+M;V*=1`=03I1P[A`D'=?/S'WMQZ3,.YI99JC/06,K7<W<IMYA9IU29N8V]UL3
+MVP9OF;F.;C+QV!Q=5(97FKG,-IBXC:&+^@S#S5PF^O6EB67U,\D#@]@V=%'=
+MO=7,93'6S&-L7A/KKH=%%E7[!JPV<5M;;^(Q"[K(IA]HYK9@G)EE_@$SCW'1
+M*;HD\Q^9N<]_RL1C<F8SCX$,,W,9/&OB,0JZ:&RPQL2ZZ"T3M]6WF'DL[F\F
+MMMG>E3R?8^8Z2A?9)A^8V*;9;6)=V-W,?>8<,]?9<C/K1+K(QD@SLPX\8>*^
+M.EVD^Q\W\UCGLV9N`^FB//G&Q#8@7633>LR<1]>;V49_V<RV5**9;9,;S%SF
+M/YFXKSS(S'6'+JK#KYI85U-?F'3J8V:NZXO-K(/I&&_J>^T36?2:V0:@B_I6
+MOYC8!OC:Q+J'KK6"U!:]9V+;8;29^\P3S=P7\YDYS[/-W+8>,7&?Y7T3CZ%1
+M)Y_R>H>)Z_[E%F[[Z")9FVGF,:X^9M8]=-'8X%UF;BNGF5DWT?6J(/5!(\TL
+MPWO,/!9$%[5%\\UL$]!%.C_&S'V2'A:6`;I(9UQF9MOW1Q/KGHLM+`MT$:]#
+MS:PC_28>RZ&MBZBMI+XJU<U19M8U]68>>[O.S#Q.,;-.H(MDYTXSYP5=)%._
+MFGBL03-SFU)BYKX07=0V7&KFNG'$S&W@&#.7&5TTMMELXC'9)6;NL]!%==%D
+MX3%CNDCF5YA9Y])%NH_&=,B6I+$V:BL[6WCLERXJLRO,7+?-%NZSTU@$M0$'
+MS#RF]F<SCTUEF%E&[C&S#.\RLVZARR](MO,6,]<%NJB.OV1F7;?=S&/M=%%;
+M,=G,8X%T_2AX4I!DG0[(;A*:ZKS1PCJ8+LJ+"#/;BO2M@-JX2\PLRW2U"/XJ
+M2&.)0\Q<%]2%WUTM;/O=9.8Q)G6;=(V9;0#:JX[*_C8SZ]HF,[=I='46I+8D
+MVLRZ=X29=?X?S&R#_&1FW4$7C9V_8^8QGX?,/!;7U\RVV35F'BNGBVR<5\Q<
+M)SXS\YCQ91:V/>@B'O/-+"MT10B23*\V\]BYP\)E^K:9Z\I&,^MXMYEM=;JH
+M#W>SI(&N:P1IC.R<F=L:NJCMK36SC-,U0)!T]20SZZS;S:R3-IM95WT@>5)M
+MYK$=NBCOB\QL8]$U5)#R?H.DY4$SZW*ZA@O&"%+>?F)F'4X7C=TL-'.;0]=M
+M@I26I6:VK>FBNDI;@Y+N>LW,=8K&L*B-*C;SF*++S'V&A\W<]M!%??!4,^LZ
+MNNX0G"28(#A9D.K^7#/K[-?-W+>C:YK@G8+4]_[6S&-Z=,T0G"E(-AYMI7:7
+MT#06^JF9OUE\:&;;Z2]FKH-TT;>M9\P\AD\7M65OFGFL@*ZY@L3+,3.W5711
+MG_1G,X_QU9G9AGO:S'5\OYEM++I(IYXP<]^:KFS!',%<P3S!A8+Y@F1;/2EY
+M_(7((%UD.Z\5F:!KD>!B0?JF]5<SVX)TD<Z[PL)E]H*9=><_I*Q_,'-?X:"9
+MQPZ.F]EVH(O:UF_,/(9)%]E$KXJLT?608+F@)KA"T"M(MOB?S-SF_4UDA2[J
+MPVXS<Y]BIYEMQ<-F;H/I>ER0=,D^,X\AT?6D(-FTZ\U<=^FB/O0;9M8A=@OK
+M0+JH;/XN::#KSX)K!?\B^(S@7P77"3XK^)S@>L&_"5*>[I4XK!:NDW2]*/B2
+MX,N"&P5)5[TG>4H7U;$P"]<!NHB74V;6#;TMW#8<$AG]W,PV*5VDJ\Z864<V
+MF-E&INL]0>K+?6GFL?XN%L[S7T0&?C1SVT(7C4F=E;*XQ,)M%%V[!:DO6F-F
+M'=5L9AN"K@\%R<8,M_"8(5W5@GL%]PE^(KA?\%/!SP0/"-8('A3\7/`+P4."
+M)#.-9F[[Z?I2L%;PJ.`QP:\$2=8[67@,E"Z2]=-FUC%T^07K!$\(DNURD87S
+M.M+"?5JZOA?\0;!1\$?!DX*J;;-PFTC7SX*G!$\+-@N>$3PK^(M@B^"O@N<$
+M`X+J`ZZ!VWZZ3()F08M@!\&.@IT$K8*=!;L(=A6T"783["YH%W0(]A#L*=A+
+M,$SP(L'>@GT$55KH3V('CM_`?7J+,'BQT+H=%"5TQE$>*.@O=%X?IH<+73&5
+M(X@5VEK+_N.$/GZ$PYNLAY_,SR<)O4LZ@'?KX>7Q\W.$+I>,I>\=1CWA!OY>
+M3_[];F!ZN=#KAG-X/CV^2$[/:MU?TO-GH8=&,/VBT-7I'-_K0F^5B05O"YUV
+M-=-50CO&<GST?8[&SB-Y_8WZ'JORJY+]#PL]YY],-^KY_P^FS3*N.?Y+#I_&
+MV^E7=2=.WS7BWT\ZQM<+O>42+K\;A5XM#>MM\KY>_`GBGR?YFR3T.NDHI`D]
+M_0I^OTCH-5E,>X0N%WGP"EV[C^G'A(XV,OV,SH^34_""T&O%0'B]7?K>$?_$
+MY?S^#J'72P.X7^C24G[C2Z%;Q"#Z5G]>\IO&Q:@\ULSKH+Y1_ZKGW^<</HU?
+M$;U'.EQA0J_Y"]-10L<>YO0-TNE,IF.$+O^"PQLC=.,U[#]=Z$-BJ,X3NJ6(
+MP\\7>N@@ILOU\(YP>!5"AXNBH_XR\?-,MIIGI?JSJKRE_#<*?3R:PWM/Z/$6
+M]M\E=,8A#O]CH?/$0#DD=.0Q?O\[H:-*F&X6>H.)WZ?^B2HO^=#57>B\:[E\
+MJ!\16KZ1^O,B+P.$WI+!\0\3>JV\/T9HR_?\?)+0+9TX/9E"^P^S?Z'08^7]
+M8J'7/\+T<J%G2WU;+?3^!]C_>:&WBW[9)/1P,;PKA4Y[C-_?(_3*&*8_%3KL
+M`*>'VDTJKPI>OZ+:/Y7_Q]B_4>@:*;]FH6M]G!YJ7Y1^D?RV"3VG@..+%+J?
+MZ(O^0KM$/F_2WS_*SX\1>J,TO).%WO0ZOW^7S,69(^U#GA[^-GY_B=!+GA=Y
+MU?V%GT>%3AS&\?]1Z-A\YN=9/3TI3+\B]$BIK^\)O:N&P]LM=)@,:.[5W^_.
+MX=<*79W+M%]H]2$.UX]"VY9R?+\(O58,U<X=)#\^Y?=["5TJ!L2E0CNV<'A1
+M.BV&Q$"AQ^OR*_3`.$YOK-"'A+\I0F^5]F*6T'FYHG_UYT5_YPD])XG]%PO=
+MLHCI,J&7M'#Z*X2.3&?Z#T*'5W'Z_R;TK&^9?D?G7PRG?PI=*1VU_;K_0(ZO
+M7NCM/45>A:X(9W]C1TG??/;OVK%M_;](_&=G</R7"[U?ZL^U0L>.9/^;A"Y]
+MA/UO%7J]R/MXH=-2./Q$H;=X.,:[A5XBZ4D3>H[(>Z[0CG?8OU3H71)^N="6
+MZT0?"QTE[_]!Z`PST\\*?4@ZJ!N%CI[,Z=LB]'3IH%3IZ9&)>;N%7OD$A_>)
+MT`W2`3ZLYX]T^+X6.B^2W_]>SX\'.+_."#W\+BF?3L+/H_Q^#Z&C/^'X(H3V
+M"__7"AUY(X=_@]`;Y0/:K4)7B[S%Z;1T@.[4PY?V;K;025?R^TZA#XE\N(1>
+M6\SE5R+T>)&/AX1>?X*??TQ/3Q8_OT;HV#%,K]/3<Y:??UGG1]KS-X6>(_QL
+M%[KT(7Y_K_Y^!M.'A$Z4B<+']?PZ*/I&]U_%]"]"K^G!^6&S2GV4#G"8T'GW
+M<?A7"AW[%?/;7^CC;S`]6.@Y8M^.$+I?'(<W3NA=GTI[*738L\SOO4*/%_M\
+MGM"-)Z3]%#IZ(#]?*G3S#HZO0@]?Z#\+/;",T_^BGOXL?O\-G;Z*Z1U"1^K?
+M775^I/]Q5.@,T:?U0J\5`3FEI_\@TQT[<_M*ZU1I;F2/SA)^-/M?+'34?$Y?
+MW\[Z^YR`P4*7WR+Y*;1?[,/10H?_CL.;(O2L04S/%'KH1)%GH=>+?94G])H?
+MF%XJ=*/(AR9T7CS33PEM$'E?V[FM_MRHOS^/\^>MSGI^\Q-50@^,9/]/A9Y^
+M7.15Z.IQ3/\@=,1L#O]<N_CL7=A_47\.KX_0Y3(Q\QJAUXN]<X/0&\7^'R5T
+M]0P.[PZA8[OQ^S.$CI3V=X[0T7G,?Z;0VT4_%0A=VH_]EPJ]5>R31X3>]30_
+M_WNALU8R1\_H\4M]?U'HY2]Q_&_H[\N`\[M"+Q'YV"GTI`_X_6H]/)EH>5SH
+M+5(_OQ.ZYDF._[30L_2!CZX2?F\.SRYT[5+VOT3HX:]Q>%%"6T4_#Q:ZWTI^
+M/D;H.8])?T3HO%N9GJ2'+_IGIM"[I+XDZ^_+Q(@,H<NE?/-T6@8B%PD=)O6K
+M3.A*B?]1H2/*F?Z3T!NO8?IYH6L>YO=?U=^7_N>[.BW]QP^$7MF-T[M?YU_T
+M7:U.BWZKT_D5_Y^%3MO"^1D0.E+:RVXVEG\'!V^(L+'__B_9_P:A9S=P>+<+
+MO5$&!A.$=DCYS]#IY9S^N4)'RP>4A4(W2OTO%;KT5X[_$:%KT]C_::*!USPE
+M[9OX'W)R>"\+'7LQQ_^.T'..,_U/6]OZO4_\5\J`VQ$;Z],E'NZO_&AK.][2
+MK9O(O_0'PX5>+_KT*J%CL_GY`4)GB7P,%WJZM!=CNG%\&S+4/GB&*>(?*0-W
+MLX2VBOV<(72YQ%<@=(;T%^X7>KE,-'M(Z$H9[WA4Z`KY,/`'W7\_^Z\3>I/T
+M#S?IX25Q>)5"ATM__A-)/^U[0'.%:\6_.9/Y^TY_7SY(G-7Y*>;PK=VE_#_B
+M\'L+G54O]I?00WLP/4QHARQDBM7?'\SIGR#TIK_R\W<*O?UICG^.T*6B+S+T
+M\&2\JT#H:%V_"AW[!/L_)/1PX?\/0F_X)S__HM")SS#]NM#[I;PKA0XKY?<_
+M$'JU].\/"6W9R.]_W5WD3ZX?Q;]:[+=?A!XOY6^V<WG0NC6:L^D0FM:UTIJ-
+M<+OH!^'W:J$SQ-X;)'2YC"<,D_=7.=7^NH9)XI_E9/^90N<]S_0<_?T_,YUM
+M;UO?[A/_V=*?>5#HJ#<Y/YX0VBH3GI[6PX^0_IO0S9O8_U6AETO[_:[0X3*Q
+MX7VA=TE]V2_T?K%7CNO^,G[5H,<G]FZ3T)%B?P6$3EPL^M(A]HKDY\5"E_\B
+M^D#HZ1.8OT%"KY?QK1%"MX@^'"MTTW4<_E2A70&.?[:#\[-2\C-;_/OMX>>+
+MA8X5_:D)O7$XTX\)72GCB7\4.FT,T\])^+LD_'?%OWH^TSN%]DOZ]^GAG>'X
+MOQ#:NIWI'W3^I?_8+/0<^7!O["'O5TA_3.A-TO^_5.A::2^CA$[<S>$/UM_7
+M1!_HM(R_C!<Z]GJFIPO=*.-']PB](5KZ`T)7B'YR"SU2[)^E0J^7\<5'A9XN
+M]?=/0E<?$?D4VB'VPMMZ?.DROB/T'ND0'!"ZW^><WN-"-TE]^E[W+^3PFW7^
+M1/XZ]!1YO(B?=PC=I.>GT+4B']<*/5[:UR$]>?R+UHW2%2/^Q^_AY^.$KE[(
+M\=TIM.U2]D\5NE+ZRUE"5SPJ^2>T7_350T(/E`]_JX3>(Q.P_RKT)">']W<]
+M?)OH5Z&E^AO^(?1JZ1]5Z_'+A]4C0D?9F3[1LZU^.B7^5K&WC+VDO$4?=Q4Z
+M]A*F+Q8Z4>S'JX1N$/OZ!J$KHT2?"KV_@^2GT*LGL'^BT,-7R'BDT,U5'%^.
+MT'-NE/ZJT%NEO2_5_44>RH6ND>]'C^KI^1WSOT;H:OF>LKX7YT>DY,=K>GKD
+MPVBET+7"[VZAHZ5^[A-ZS3P9+Q#:(O9/G=#KKN#X?A)ZO#[1,4S:(]'75J$3
+MQ5[O)70_D9\(H6>+?-T@=&P]!S=<:*N$%ROT=)DX,4GHB#'\_`RA=TG[/U=H
+MA^B3!4);9$*'2_>7_L]#0N>)0#VIQR_Z<IW0XQO8_R4]/FE_WQ)ZO8P/[]##
+ME_[+1T*/+>7X:H7V2WOC#^/V.H_WH3(TBO^64^Q_5N@-TG_M?I'HAR?9_U*A
+MU4(57%<);8GG]`X2>O6E'/]PH9>(?(X3.DHF1-XE=,/['%Z*T+.N8CI3]Q=[
+ML5#H1NEOEPA=^T\.SR=T8B\9+]#3*POA_B+T'K$?7];3MX##WZP_+_V[2J'7
+MWL3\[=;YD_&%O4)7S^7W:X3>)>-YWU[$^K)"].7WXE\AXYUGA%XG_=G.O:4\
+M.DI[)W2Y]&<N$7KUK]+>"=VPE..[6>A*&1^^K;>N[SF\.XBF\D?[3B$FB7^T
+M3)!U"ITGXY4+A6[LPOZ+A>XG]M`RH1.E_[M2Z*WR/6UU;Y:W*-YGQ_"B^$?*
+M]Z&M>GS"[W8]OF;V_UAHA_27:O3\>9S]3PA=(?;12:''R_C46:'7[A;[MX^$
+M-Y1IF]"58G^$";U=OH=<*;3E._:/[L/\;.)]'0RWB;]!ZL\DH:,/B7P+G7$W
+MIW]>G[;M25X[VB7/CY2),!ZA8\7>]`E=:^?G_RCTAG<XOK\)72W?MUX1.ES*
+MXTVAU[W)SV\7>JV,=^T1>LW%_/[G0F_Q\//U0I>+??A3N_3_*O[6S_GYKN%,
+MKQ1[)USH/<]P?%<+/5[D:8#0:]=P^,.%;I0%`>.%SI#^QU2A=XG^G"UT[`CI
+MOPF]<3"_[]+#Z\#^Q7IZ1'XTH:>/8GY6Z>%/YO?_K*<WB^GGA?:+_&\,9_G8
+M*/*Q7?S7R/L?"SWP!::/"ET:R_&=T/,K@<,[J=,R@:]%CU_RL\O%TIX/X^=[
+M"KWJ8J8O$3I*YG]$"IV5QB5VG="S9'QTB-"Q,?S^+4)72'\Z7FB_E%>BT'DB
+M/[.$SI#QW#2A5XO]7:#[R_C3$J$WRO>7!W5^I%?[A$Z/Y?0_+?02Z2^]('3+
+M*7[_%:&/B_VP5>BQ,OZS0\^?.SC\CX4VB/U8(_1ZL1^^%GJM3+S]Z6(N7]G7
+MQ6"^1.0GE?.OVR5MZ\,EXK]+^OM7"QTN\S.BA=XH\R'BA=8W6DD0>DX<^\^Z
+MA./O)_HT1P]?]%VAT-4R'K)4Z(I4?K]<:)N,SU?HSQ<P?[\7.D/LV_5"KY$)
+MCZ\*/5"^QV\5VB(3DG<+[9")\`>%#GN#T_.5T.O3./X&/7UNCN^,T,UY_+SE
+M4I$?^=[2[5+F?Y+P?[7XSYDCXQ-"-U[+Z;E=Z/'R/7Z"T%&;V3])Z,ATII.%
+M5AN<4/X*O5\F;-XO]"P9WWE8Z*SW./S?"[U+X_2L%5J?W[Q!Z.:?^,8FH3?^
+MR/Q6"5TC]M8'0B^9Q>'OT],C_;OC0@\7^_D'R9_UR!]ZHD7\$RO8OU.$\#>'
+MT]-3Z":9Z'B5T+72?[Y)Z(J3_/QM0D?*PK4XH1.E_S)9Z&J9V/H[H9?;V7^^
+MT!MD/IE;Z.G2WRX3>HY\+_<)O3:+WU\M]$89KWQ&Z-(5,G\J@NN?3$<P;-3C
+MZR;VG-`MKW'ZJH6.D._1AX0.$WO4K^='$X?WH]`9,A_@C!Z>I,]RF>A#F:_7
+M4^CE8L]>*O1:&6_H*W2CF<.+%GJ]M&_#A>XGW_M&">V0!06)0L>*?I@I=.0V
+M]D\7NE+LG1RAM\N$]$5"]Y;^P=++6'YH'UG*T7+QMXH^_[W0NCWZ%SW]TKZ^
+M(G3TQ_S\NT)/E_'J'7K\TI_[5.@TF;]3*W2U]-=^T/F3_LTIH6NSV=]\N>B?
+M!V4\0VB;S`>X5&B_V#_7"FV5]FN0T(WZ?(K+Y7NIJX-AN@WZ0OQK+N/\G2YT
+MK+3GR4(?NDSD6^C*/O+]0FC'U3+?2NA2Z<^4"[WF'(=?(?0FL3?_+/06Z6_\
+M3>BU,C_LE<O;MC=5XK]HC_0']?2(?'TF]&J9<'Y,Z+$W,#]-.C^B3W[5\T_:
+MZTY7B'Z3^8X]A=XD[>>E0H\7_7N=T%9IGVX4>KW4CU%"]QO&\4VX@O-_H.CW
+M>\5_3BV'GRUTV@A^OU">GT7[F@&7B/\2*7]-Z%(9'WA,IZ^1^1!"-PZ4\22A
+M:^7[QP8)/\O#X^-;Q'^6?$^H%-HO\[OV"=TDZ?M"Z'4R7NN_0F\?^?D?=?XF
+MR_BGSK_TS[M%2GV2[R,7"QWV,(?73^@,^7YW8V1;>1@E_FOGL_\4H?6%'[.$
+MCI"-JYSMWL\3_[Q_R/P?H1-E_$83ND;FJSRATR*O?Q+:)A/%7Q!Z?0H_OTE/
+MGWRO>$</_U;F;X?0X^7]?7I^2/Y](?2&AT1?"[U+[/$?A%XD]LHIW5\VLC)=
+M*>4G_'05>F-?Z0\*W2+V].5"1\EX7W^A2^5[]Q"A$Q^7\22AAXK].%WH2AFO
+M3Q6ZHHR?7RBT5?3C(J%CQ;Y>*G2>?`]>*72YU,^GA'8,9_I/0J\7?;=>:+5!
+M"*Z7]?B^Y/2\?:5\K\OO8(@%_:'X3UK(S]?HX<M"J&-"-XK^_D[H2!E?/2WT
+M!JD/M)&0>E_J7U>A#?*]I:?0$?+\I4)GR/CDE4*7BKQ<)_022?_-0J^7_L`H
+MH<.D?S%>Z$J9OSA-Z+7R?6..3DO_>9[0ZZ3_E"WTJH4<WA*A^\E\EN5"-^YE
+MVJ>G5[Y?_%ZGQ1[^J]#5,K[[DM!SQ'Y_0^CC@V1\5>B1`SC^#X4NOYF?/R!T
+MXF"FCP@=W9?37R]TLRQ(.BWTKID<WCFA8R?Q^QVN%GX^X.<=0L^1^2A7"+U(
+M^H_7"%TJW^>N)QIX_`X>_QHJ_N.EOW[[U2QO(T7>$JYN^SUSACR_23;4N$?H
+M1)G_XA2ZG]B?>4)OE/E5B_3TROS74OUYF9]?+G2D]$<JKM;;6Z9_+_0LT1_K
+MA!XH^F"#'I^,[[XM]`89[_Q8?U_FW]3J_,@"F&^%'OJ4M`=Z_DG^_G)U6WW<
+M.4K2NX!IN]#ETSG\BX7.D/DOUP@=)OEUO=!KMXJ](W2CZ+O;A*X<*/5#:*OT
+MAV?I\8M^3Q/ZN*P'<`G=3\IWJ=!KI+UZ6(]/^G._%SI6UE>\('3U,J:W"#U>
+M[*]_"+U?[.^/].==3-<(/><Y?O^HT%OD^_,/>OQ2OW\6>H_8JZ:^3(^5[YE6
+MH<N%_S"AC\O\PTN%CA5[]"JA^XG]?IW0:V7^RC"AF\3^N55H@Z1_C-!Y7W'\
+M$X0^]#:_/U7H6=(?G"FT+8S]4_MR?:)]9FDOQRP]/+%'\X7VB_S?+W2C?&]]
+M0.CE,I[QL-"U4G^>TOGIP?3S0L^6]3\O"KU+].$FH:MEX[JW=7Z.\_M5>GJD
+MO[Q3Z"7"[\="E\I\RJ-"KYK-Z?U.:(O8-[\(O4;LD8[72'L@WTM["-THXU%7
+M".V0_E-?H1.E?8H6VB_\#!-ZJTR`FB#TRM/LGR2T5?JCLX6.E05Y&4)/DO8A
+M7^CI81S>`T*/+Y#\OT;LP9P.AE+0?Q3_<K&GUPF=]RC3&_7T2GNX5>B13XL^
+MTI^7!:6?"QWY!Z:_%KIRNK3G0D>+O?"3GCX9CS1?*_JL@/V["1TAY1<F=)Z,
+M+UTJM$/6BUPK=)2L/[E>Z*&BGX8*/4?BCQ&Z4C8.&2VTVB",RD/H73*^E2AT
+MN>C#WPD]7NKG7*$KA-_Y0ENE/2D0NF89IV^IT,TR'K_B6IF?E<WE\]2U;?7U
+MG^3YD;*P^`6A&Z1^O2;T1EGHOTWG1[Y'?:"GSR;VK]"ULA[I2Z%GR48@)W5^
+M15[/2OK6R'HH:S_);UG8'"9TA<P?O53H4ED?<(W0L3(??K#0N_3Y/[J_U+\X
+MH:,E/^\0>JC,YYDIM%7>O[>?K`?,D_%,W5\V@G`+W23C)_<+7=Z/\W>5GAZ9
+M?_&TT/WD>^[?A5XG]LTK0D\2>=DJM$':_VU"1T[AY_<(O5H6I'XF])*[^/FO
+M]/R3_ENCT)6R$/P7H=>*_=RAOY2?K`>S"SU'[/W+A1Z8P_0U0A?*_(_!0C?)
+MPO);A2Z]B)\?([15]/L=0N^YD?U_)_2NV]@_3>A^HJ\6"-WX=PZ_4&BUT!W7
+MDOYMY;M,]Y?^DU?H-%G?\+0>OBQ,_[O0B3*_[A6AATO__$T]?OD^L4/H2ID?
+MO4?H*-'?1_3G1=Z^T?-#GF\0>I7,/VH2.E*^#]-&I<H^D/DY=J'72W^JC]`-
+MLB'-U4(/E/G2_84>WI.?OT'H-!F_N4WH6,G?.*$;9?Q_ZG6<GS;)SWO$/T/T
+MNU/HU6)?9PN]4<:/%@D=(>.##PB]Y`I^_V$]/+''GA0Z3^R]/^OI[\W\O2!T
+MI.3_JWI^R'K>M_3X96'X/X4>*NN']NK\BKP<U..3^>)?"]U/OB_4"QVVGOG_
+M64^O]-_/Z>F1^:4=!TC\(C_=A-XN&SE=(72%M*_7#.#O[QOD^_OUXK]+ZL=0
+MH=?)_(T8H1/E>\EM0J?)>N@XH:TRWC-)Z+753-\YH&W]N%?\]\O&Z!E"3UK,
+M3[B$]G>2_HC0X6+?/B+T>-'GJX6>(_;_GX16&X7C6B?T4.E_O"YTK(R7;QW`
+M>_<NG]Q1T55Z>+)AP1X]/GT\2P]/YD?7Z/Q*_$?T_),-&^IU?YEO\9/0ZR6_
+MS^K^-?Q^AX&B#V5^L4/HC<W\_!4#I3]HE?(9V':]]W1Y?I%LH'JOT/ME?"YU
+MH,P_D/9EH?A;)3]+A(X6^_(QH>?XI+\N]"897ULG=,LNZ?\)W23SJ]X0>JO,
+M?ZT2.E;ZS[N%'B_Y\;'0I=)?_53H7:)_#@N=(>,WWPB]7O3##T+73.7T-^OA
+MW\;AF:Z7^G<?^]N$CI3\[R-TK,SWZ2?T(OG^,?1ZF2\LZ_5'ZN\+_W%"1TG]
+MF"3TG$N8GB6T2_HG<X6NE@W"%E_?MKXD)X^]:_*HA`EC\"LY/STU*R4S.WFN
+MVVE(7I26G^S,RDUQ&9+3W'GPCDL:DUR0YW;ENW/2Z>DT5VZ*(7E>NLN984C.
+M<.7F9!F24^;FYN.%]/Q\0[(S/1?!Y.:EY]#3J;E962FN].34C)3\[)2\9%?*
+MW"P$,S=_@2$YLR"E(#4SDQYS9BY*<Q9D<H`%*OC\O-2YBW-2LM/5@R[78@2=
+M2Z\Y4^;BB50\4I#NHIA<F3EIG/"T%)<[FW\NSLM/+\A+SDXI<*7GZ[?FXLED
+MO)66FZWBR)N7GQ>:2HHN.2\_4T]F5H&+,F*NBH!>*,A0C"+/4K/3B-\"EV(Y
+M/S\WOS7>A<F+G$PB:Y,+%F3B7FINOB0R)]V5.W<^.,C(S\UUJ704I7%R\G/A
+M)4P3G8G[:3G)Z8OR4B@%8!7_V2NE@+/)E9F-#$]+64RIFNM*SG,79-#/O.1\
+M21&RG4,$GZ[%>?B!')B7G^O.0PB+\RA2+CFZGY%;X$K+*4C/45RFI*6E9=ZH
+M7H!P."DC\]-3TK(R<U`.*6Y7ACLG<U%R*NZYTEF2"E0>9N8L=*?G+^;X4_+S
+M.75Z+A>XYQ:X,EUN%W/I)BY5V@L6YZ3B9SZ8'3H\.=N=A41`%E,7A+ZMDLI<
+M0\ZRY1V\!?ED]BAA.;DYZ<&$(?GP$YY<8#R/.!&I2\LD`<O,<:I(LM)3<DCL
+M)2LRI<S<R5FY.?/T9.9E92*H@L)4I`6)AH1E<P:J=.'1E#3\24U1(N0L0&#S
+MBE+HE<R"G!14B[FIN7F+VXCI@O3%R84I611$;J$S*SDM/2N=4IZ?/B^3!!B5
+M@0O5N3`H'90^Q5-FP;S\E#RJC6GID,=<E=E9J;DYA<B+U-1T$AE"DAC4W\Q"
+M5:;)>(_S2Q627IAYJ*<L67E*_)`1*.YTI1NH'B"YA7E2"4C<YF7FL#8H<&82
+MO\GC)DT9/6I2\I3X^#OCIB=/'S5Z4ERRSBM7)PHR=QYJ)@E1VGS*,XAYIM/)
+MOU2X\])5#`79*0O2@WHI+ST]G]DOR'"C$A=QU*E4?5`:^2E%P2*GQ.3DXG8J
+MA"DS7T)-S<X3A1?,X622,Y4A*"\4&E[-R4YQI:I*A&0.T04@D[*:M([*\]:J
+MCJ+C^ZDI*O!0`8/:%(U!#^3HNJDP/=5%^H+J47*.TJ>%!5`[.2ZG8B@MLV"!
+MK@;`ESLM+SD]AS12:DIJ!A=^.A5N,BD'4B_!^BUU1$F@TF&JR$E24K(R4PJ4
+M0#GSTZ70TU6*H%)0J)3?A<X">I,D*BNWB%@HR$3YDORY28@@7`7I>2I^77_@
+MIU))*GMSTHLXX+FYN5DB%05YZ4IT*58EVWDI\YB%>4J\7/F%F07RK,I9)1U<
+M=U10BUW$!')26(9.2L]2+[IR%TI:YNGUE)H9\<OB$E4U9UZK`B@L2LG/682`
+ME(9H;=CFM59X3C>+*H4$,4V;FPV1@K97I5U(4J7TQ=S,><A2ESL_AS6CB!KJ
+M6`&)5.:-PV^FX)*STO0\RD]7-38-&8L?^>VJ4T'Z0HDT3<0#8:H@(<9*2E5*
+MTI5\9N<AFZ&R<@N0?A=)&)I)/.PNR$I/9QT&H<K-SZ2V4^63R@%2TDH]HQ5,
+MH=I;A"?2"X,I2,FGP*FL*;#%><G(1=4&9^5EI*BBS$O6]3NEAG1FOM)_$*[T
+M1>F<W^E<)GGYKJ`20R*1UZFJ?H;H/KVM!(V?G._,&BJQ>HTJERK8U*P<5V@M
+MQUMHKC)S0YH@U01*!=5U=DI!1I;H/&7:N'.0_VDHP`QJ3;*0..8W#YF1"C%T
+M06C36?<5H/51`@Z!XBJ1KS(5[R+48&ZA"J6DIE/6I\-\RL_-3E:M6C8UKJCL
+MJAHKHR9]H:IIJC10:PTJC?.S\\2"R"Q(!8?4#D#U*&L$K8(NW%QQ80UDNH+&
+M17I.6JY3MRY$5[0V>]EH!)R9\R2Q2&-A>CX)2[*R-,!SRF(VU,!]:HKD&AJ1
+MY+G<ZKISLG/=.:XVQHD[>RYE0T9Z2EZ!$MR@/"F%[9XK%D/Z`E492$(X#B05
+MN5/81GVB^%6SA_#G%F3>IUH\4<,L6DJV(4"IN:2Z*9F$4)EL.:;GI.8OS@L&
+M2,9/JTQE%LS-2LE1Q@,:Z517ELB',TTW:ZE$5.U'"^>2J@:!5S5=F-;K#T6=
+MP;*(HI%&+SLW30E=07XZ9)6U4A;QFJ$+AIO:M`)^G=I\)5Z9(E\JK)2TE,)Y
+M*G=R@E5T/IM`>LI5!=0+G*QKJ&441RHWH21:X()S3&_6J`8J$50W,_.=U!B"
+M-<B):IHXN@S6B="1(C2J&E,M2\X+WB"YI#C<.:T5F35?)@S%?!?K!M64<+7E
+MXIZGS&PH&&G'VI(JPZEQYTS'PVA\I,U+U2L#/</-H[+54&T+E+F&S.2^26**
+M*V.2-!9BCN2ZV3YG,4+)I&9DM>V*M)J?NIG/F:&W/OF<<:A5S(@K%0U3VER$
+MN$#G4#5TR?.R<W-@+E$MSEY`1F">5*"V;$/!9"M[$9K-6<!J&=:[BBXEV.P'
+M?R0G+T(A41T*J22L@G,R@^TN53I*%H6V,".7VJADTJSS(*XD;ZG.>:URAOR"
+MVBU(5W6'VT+=O&`%H5<TI:Y#RYF$-4>I(*XGZ;I@(DC4,7#N=!6HED^WJPKS
+M,LFF#+*5.0\EK'0>:5.]_NOU,92-?&:#N4:GA?1RLFJ#\#3JG)[YRC3D"HO.
+M8M`.+T+YD!6KQ%QZ;*3GY@FCL.F8R8*BE#SUWN*"5O7OND_**W,>JI!*+\>F
+M&I/LE#18*21DJ>Y\JJ)M\KI`":_BBW)#5_`P@EQB$W//DV,"MT'+/5F5*5+K
+MRB;CL4#L"L@5A"7?13(.9G+2%[E$A>>Y\^=Q@)`R9E))K&ILE6QPZZ-H,(_X
+M\;2S*"5K@32$+%J4OTJ_*0T.IDE]<2FY\EG1J79>]/J\D(80#TOK`$Y4HZ!8
+MR<"+4F^I>K051BB4T(:)*S8L1Z<8.VZV>O+4L`!U<_3V1,]NM@CIF4QJTE$H
+M;!#,:ZU>N7K_H6VU"9I4*$"8?4YWC@Q-L/T7;`%8&5/@:;J,JRY'KK)_@QI3
+M[QMSKX\U,7Q4JI@5;@7<.;I9JRH;:SFD0.R^$&TDNDRDF"58:>""=BJ8*G'>
+MXE9=R9TW73/R\(D8.&S=D#`*L\'FF`SZ@NQT;L-5(T@2*'T5YE^53E9.2JY3
+MCXLXSL[,4:7#9@]468'>I\HOR%<6>7#,1BP$)%C:1[&MX8660N5$008Z[MPW
+MH?`XE8@I4W5`6"N[LO.4A03FI+^CS.F"5G-:>"UPZLI';W59K?!O,(_L8"Y)
+M&Z6Z,JGV+Z:Q(>GFZ3DH;4N.,H6HX:2:IRQ^Y!^KO<)49UI0CI5%S$80]#VU
+MWFT&FD@$N9#<*5DII"Q)]1>Q_&1"+V5)=-PK1?W(2N$^>@&R@E4!-;Q.UI_)
+MJC^C,HSM"66O4C]_GI@*RI`7&R-7=#]51*J^P4H<;)<*5"O7:I(7+,[F@9TV
+MY<6/YY-A2]JY0,9KB$V]-E)8KA2Q.H(J'D*6JN05?52VWEIM-"5`[@+%GBNU
+M53'(8(D:A4&>!F-E5:P/]1049:2XU*``Q(C-NF"CI@L84I:6OH@L_!QETRB%
+MI[)1C7:H49%T*J*\K,6M`V)*T%/9Y"W(3TG+7,2E2YG(,LH\H+BE7Q;,J@R7
+M2':Z+C&N^<2T:HAS6SL4P<&,8!N'0FC50LD%SJR4>05BU;5VG%(AZ[`Y,H*V
+M/<H_5UF<*%(9*W'FR>@!J4RE>:$^5:7-3D>S4:`/7:)RD(K+S5:-A*@7%%=V
+M;B&'K`_$A.2J/NR2K5I?"B)[@2AI:D<YDX,OZ)E16)`3-`2D#N>G%^8N".I;
+M94A3;$/R<@LR%ZGQ$Q$BME"03:Q[*9=U<S6]2+5\JE'@I)+$(X2V!1)LT0NI
+M3UH@(PZIR%#%N<M%9@4-"4B/0ZFSM'2GJH^4_V29B(0D)V?/I=8(2F.1M`S!
+MXF-[6?)1Z;/@.!P48EJ*"P9L7I9N-$,Z^!9*3"P2)9SYV2XV]!?GJ6%%J5SY
+MZ5PLQ.>\;-%;NG'&TJ\WYH""-H6@5_6<-%<N-0)J,"<_V+Q(BH/)IRX"M1G!
+M7I<^K$2JU<EV77+2]/@A(<,F:!;0]^2JC^JJQG:4>$@@_#QK7_39N+20D`)*
+M+O5>R$NTAQI$X]?<.?1;R99H\3%L"4Q#K+K%3\]+5XTU;FB^%;"((W=TLR]H
+MG[2R3QS#]$,WP)!<E.K*S08FBQ&"BJB&T@O0HTH5DS57C?JDY>H60A[Z'WP3
+M9:%J1FL_G\?30TP&I]X!4`E2K7$;43<DZTE6;4&:]"!<]['V;S5@,PMRI5N4
+MIS<CA:'V=A9E:*J8TDI^LPO4.`AD.\6=Y9(FI'6P6ZPE%LM"W=K6JT.><Y&J
+M/:J;"/%7FI(EW\WE&:HI0^HO#S(L5B-1W-QGS\UGL9G;VE+/51]!G*'#GSQR
+MJ88#1/C2V-)*<1>(@4=5)2--"C.T"2D(#B06%K0.T[F"'6/XH^('.R&JQK4;
+M.-7-6#0TU-R1`B+60Y.E2D)R"74AF0<UJ6!8\4$)I>>K<5?519$A9^2W4]?`
+M>-:=KQK+?+;G4S/2J<RD#>=^I%L90NX<;I=UOE5I%@0'"]2(IJ'U,YXK/2M+
+M25>JDSK8^2G45Y5O*D@=)6!A6F9A?CI_`T-W6$9P^3.3WBG6C78T6'K>YA2(
+MW"WDPBYH':8@_O2*QHV9/HA;H,Q"[NZ@=I"!FRR#XKJ1,T^5B3+V6@<3LW6M
+MG*\&L:4GD!7L[8.5D/%DRIO<O!0T208U@*4WPT@REPC:-[UCII>_4A>0:^ZD
+MR4"<_GE";YA4A#062UTVCB<SIW7\+2AV^2G<XR05K\L:,Y7.%9JK2B%_P^0O
+M<<E!LY_ZJ30VQV8364VB:(.6@734N2^8O8!'&X(9FN-F.<XLD$]\^@<L:3+1
+M<*>PD9`U5_^:R-I)A$C9<UPJJB4>(C4[FWL-&=G*XA[+"B14"<]K+=Y4U0:Q
+M39W=^B6-!Z-)H1:*<-.(BGQ[S6@=8*)\2$M/55T&9&TA=60-R0O0,<V;IQC*
+M+PP9L93\8`+YD=G:5.EV8FNESEU`*7&EHFM'Y>I,S1`K2WW:R5$=`G0WI+=.
+MIDI^?HAMF*<,!UU<>/R5RHF[R2$*#_FG]!U7?]05*@+2"WDPLCG_X_7O2<%/
+MR07Y\K$+O275.9>^(PTK*&N11@F<U$XNYFC%/&E7.3,+Y+-3@8S5!L>S>#"`
+M=6<RZYGD?$I9@8B^&OUM'1X2VU])+O6""ERJA:?![>3<G*S%HM)=9)T79*2S
+MY!44Z6E5PT7DIVJIB[.+.EG0+7-)B?,WD@(>-8):#]8\E&E..N<3`A.K`=YS
+M>>0[V).ACZEY\M48S[%O4*3FA<JUFZT,BDM]X:"/,:PQD`+J%2-+=2V6/1><
+M%J6JK^(H!!Y>(3E3@U#Z1R]N^;AIG8_4MO8BVL@!?QH#DUEIJG@HS4-52YB;
+M)U_PYTECXFPU(V2T>*$[%RTXV7;TVHVZ0-&'6#&OX%`1J;(4J($87:<I32,#
+M`\%/%B@4&5+,+"C(4Q\J4)JZN*%.L%6AFF`>IS2T]G@X:AYJ4[9(D6HSY3-:
+MJX&OQHN0+/EP)MW7(C*M@FJ*OC!#)SL+<$,:"E6,:BR&BQN\2/O-9K[2/[`;
+ME!+4APM;/TBH)RG7[LO-44TE#_:1A1<Z+2$UN5"-L$''YB\B%2?34]+F0A=F
+M*FVA)@QDYZ'I'(+,R%6Y[W0IZ88^(*U+O=.Y"*90RB`W+YC_A9GYE#^0Q$5Y
+M//F%OP0&1=LIJL\I(WCTG8S,>KU^D#Y7#2"-N!(_BFL21UW6G.F0Z-3T-B,,
+M]$=9N^U&'6!@W8>>L\I-J0@T*C=/\=8Z-N;,X:$T5MUN7<Q;/[-GI2E^5&*!
+M6:'M/7_T02]35'YP(D:KV$FW33>`*?^R4_(7%(9H&>DT9\[3OZ(&N\;Z3`1I
+MIZ0AHQZ9;DTHE2*=R@(1'\IZ99>ICDQ&9A8Z<,QE4;#-H"_FZE:!WGUFG21#
+M!DY63-D+G)G.7(/>D'*&%"K3A$60VBC.FZP\K@]J>#&T+S\ORRU=-YKN(VV.
+MD]6.$XV^_JW+.4^ZKZJHN2.HS![N=,E'N.RYZDL&33TRR)B[BKWMF*?^A0>*
+M@*9&Y?*GF!!=S;VO^3SHY(3ASE-@9$RV2-DGNC7CUF>+9/.0;TCZDE/RB1M5
+M5&J(CC@3&:!A0>G_)=.GCGR]ESPW'P8VVAK]>[=TWV@(@1H"_A*K?SPF<R+'
+MA;8O-Z1%30GMXT.R0ONH^>FNUI'`A30Y:%X^E1%/OJ&T%^6CCRP]1,KS(J5_
+M5"ZJNLFCFJKWQ7UGU1E4\H_"IU8Y:%WGR'#^(M5BS0NIMCS2BL@+5":V9K::
+MVJ,^*"@+B+_6"^\<G]XG53QDYO&WK`(6;:0?K7]0K=&0D.J@.KD*SPN5TS99
+M)`8PTJ.&7*4K4,##@RHF,:DH9+U@^%NS\E7)X"X(!#]$DJ`YTX,5A`?]%N30
+MS`7(8E;F7)ZE12]+OQ\MCO.\>6-ZK]30.G&FH,VT-E;9$-4TR?(4]>%`S:A1
+M>KDPV'E4@R_!WHHK3Y\@IW,R3WH`,@B;3`I?Z425*-S+Y*%0JH]9.7H%*."I
+M`ZHCJEJ1%#6[!%8D*_EIJ(K)9!,GI,S+5*GG<6\G-X74[\YB#9.M7L_0B[F-
+M:92%6M%JFM`4,Z$0&T+-=N?P-Z+,>6@J7(M5A<M24R&#(S[!ZH"R5JQ"4DG9
+M9G,><-^)YX6)O9V32ST/Q8N:3:5&E_11224"V7-I4"3T\52:%ZE4F$@TFZ_4
+M!9'/%P7ZQ^?0N2ELG*GI3[EJ;D1N#I+BRJ>L7"#3)W+T!J:P]<.H4\1<J<H4
+MW88+#J.Z9<Z/,TUF,D"[N0ORE(9>H+[)TZP4[F04ZI_QD#_<OHL=$)*!7%ED
+MO#Z=AT12,[))JE5FJQPERY[F%[$`I+)NY(XTM**(F&K.>>Q!.O[R42]TBI,S
+M-8<2@M+E0&@R*-N\H7/,<G)59];)@V+I.?J$24Y^2BIIH+FZ^5Z@=T-EGJ)3
+M2D&*&$9)ZW08MUX!*$^S56LLTP1#)^Z&3HEMXY.9$^H%TYF&T*B)HV$N40(R
+M9XUJ8W"R7YL)NB&#X`7<X9#B2DN!L<P31Z3"XI?^I35M+C.?YL[CY*<J*58%
+M12VS#)+DI*D?:K:PBZ>O9I&YW3J&*SG2^LF=AQ%$E&DL(34S+X/4$DI7-?]I
+MZ85<S4@,@I.5V>AW!D=&%ROM$QQSTR=;B8C\[_6_U_]>_WO]QD7+<!R)'0S]
+MY/RS_^2BL])F3^M@J'W*8JAYVV*H/<2K/3K2.O7+.QB6TUY8>&:MS1`\=_-_
+MK__[KHJZLX%``.@_*7@":`0>`YJ`GP/-P'U`"_!]8`?@-F!'X%O`3L!7@5;@
+M"\#.P&>`78!_`'8%/@:T`5<`NP,?`-J!]P$=P'Q@#^!\8$_@7&`OX-W`,.`T
+MX$7`B<#>P-'`/L`1P(N!0X"7`J\#1@"O`EX&O`1X.;`G\`I@%V`DT`2\$GCV
+M7"!P%?$/O)KX!UY#_`.O)?Z!_8A_8'_B'SB`^`<.)/Z!UQ/_P!N(?V`T\0\<
+M3/P#AQ#_P!N)?^!0XA]X$_$/O)GX!PXC_H'#B7_@+<0_<"3Q#[R-^`?>3OP#
+M8XE_X"CB'SB:^`>.(?Z!8XE_8!SQ#XPG_H'CB'_@>.+_UT!@`O$/G$C\`^\@
+M_H&3B']@`O$/G$S\`Q.)?^`TXA]X)_$/G$[\`Y.(?^`,XA\XD_@'SB+^@7<1
+M_\"[B7_@[XA_X&SB'W@/\0^\E_@')A/_P%3B'YA&_`.=Q#]P'O$/S"#^@9G$
+M/W`^\0]<0/P#LXA_8#;Q#\PC_EL"@87$/S"?^`<6$/]`%_$/=!/_P$+B'UA$
+M_`,7$?_`Q<0_\#[B'W@_\0]<0OP#BXE_8`GQ#RPC_H$/$?]`C?@'KB#^@5[B
+M'[B2^`?ZB'_@P\0_\!'B'UA!_`,?)?Z!CQ'_P,>)?^`JXA_X!/$/_`/Q#_PC
+M\0]<0_S_$@C\B?@'_IGX!ZXE_H%_(?Z!SQ#_P+\2_\!UQ#_P6>(?^!SQ#WR>
+M^`>N)_Z!?R/^@2\0_\"_$__`#<0_\$7B'_@2\0]\F?@';B3^@:\0_\!7B7_@
+M)N(?^#KQ#WR#^`=N(?Z!;Q+_P+>(?^#;Q#]P*_$/?(?X!U82_\#MQ#\4X`[B
+M'[B3^`?N)OZ!'Q#_P#W$/_!CXA]83?P#]Q+_P'W$/_!3XA_X&?$/K"'^@0>)
+M?^`7Q#_P,/$//$K\`X\1_\"OB'_@<>(?Z"?^@77$/_`$\0^L)_Z!#<0_\#OB
+M'_@]\0_\@?@'-A+_P!^)?^!)XA_X$_$/;"+^SP0"/Q/_P%/$/_`T\0]L)OZ!
+M9XA_X%GB'_@+\0]L(?Z!YXC_,]2`@'^@P0C^@4;@'X`FX&-`,W`%T`)\`-@!
+M>!^P(S`?V`DX'V@%S@5V!MX-[`J<!K0!)P*[`4<#NP-'`.W`(4`'\#I@#^!5
+MP)[`2X"]@#V!8<`NP-Y`$[`/\&QS(!`./`F\&'@">`GP&/!2X.?`".`^X&7`
+M]X&7`[<!KP"^!8P$O@J\$O@"\"KB'QA%_`/[$O_`:XA_X+7$/[`?\0_L3_P#
+MKR/^@0.(?^#UQ#]P$/$/O('X!T83_\#!Q#]P"/$/O)'X!PXE_H$W$?_`FXE_
+MX##B'SB<^`?&$/^G`X$1Q#_P%N(?>"OQ#[R=^`?&$O_`4<0_<`SQ#QQ+_`/C
+MB']@//$/G$S\`Z<0_\!$XA\XE?@'3B?^@4G$/W`F\0^<1?P#[R+^@;\C_H&S
+MB7_@/<0_\%[B'YA,_`/G$/_`%.(?.)?X!Z82_\`TXA^83OP#G<0_<![Q?PKM
+M!O$/G$_\`Q<0_\`LXA^83?P#<XA_8"[Q#\PC_H$+B7]@/O$/+"#^@2[B'^@F
+M_H&%Q#^PB/@'+B+^@8N)?^!]Q#_P?N(?N(3X!Q83_\`2XA^XE/@'EA+_P&7$
+M/_`!XA_H(?Z!#Q'_P`KB'_@X\0]\@O@'/DG\_QP(K";^@;\G_H%KB'_@GXA_
+MX)^)?^!:XA_X%^(?^`SQ#_PK\0]<1_P#GR7^@<\1_\#GB7_@>N(?^#?B'_@"
+M\0_\._$/W$#\`S<2_\#7B'_@)N(?N)GX!VXA_H%O$O_`MXA_X-O$/W`K\0]\
+MA_@'ODO\`]\G_H$?$/_`/<1_4R#P(?$/_(CX!WY,_`.KB7_@7N(?N(_X!WY"
+M_`/W$__`3XE_X&?$/_``\0^L(?Z!!XE_X.?$/_`+XA]XB/@''B;^@4>(?^"7
+MQ#^PEO@''B7^@<>(?^!7Q#_P./$/_)KX!WY#_`/]Q#^PCO@'GB#^@=\1_\#3
+MQ#^PF?C_"?J=^`>>)?Z!OQ#_P!;B'_@K\0\\1_S_1!T$\`\TF,`_T`A\%6@"
+MO@`T`Y\!6H!_`'8$/@;L!%P!M`(?`'8%W@>T`?.!W8#S@=V!<X$.TQ+T5[<;
+MZ:QQ=%--?/8\;0-*1SW,QOU)G0T&6V<^D[09;A=<:2>#H:DCG]L;>M']J]OU
+M?]9T1YAP:7:\#UP-K+&W^ILOT&>Z(=V5>@,M)<4U\&K>GZXZBO?!B\+OB+ZM
+MSP[M;S",A,N#B[Z.SNAK&U9LOZO[ZZN=!Z5V'C9HZ/GQ$1N4I"O@;@])E[$=
+MQE0,_D-4Y<$A#PQV_G'T3W^YIW;9+4=>S^WRI6FK^<=?8G\:O^#K":Z-7[SR
+M;OA=L__^Z_3T5?:,02O_O/C6^LVUE[_RX((QUU\W:-[GY>^77W1/0>97IV^:
+M4O'9(Q<=F-KX7.Z3"W)2#OVP:L/CMX^Z>?6VJW9LN6[=S_<?*%_1_>D7?^YZ
+MU>^U-\?]<NW0.1T,_<29):V$Z^:T'5LP&MI>D7>=GQ_!>6C(D.&#!D?V&YV>
+MOR`]*WUQ_\B;;QAZ0\R-[<(C%YG"-'UYS<R9-R+2E9%9$$G?,_)3LB/=!>D%
+MD11LO_X#(XLR,E,S(N'KSBE(<:8/ZM8E)+RH"6DC(O7O#8-2!Q9&#D8*!L?$
+MW'Q#]$TW#!D6.3AZQ-"8$4.'1.;1Q*#(N$5YD5'G%UF;])U[WF`X#D>[;QP$
+MOOL\Y\TKP*>>YWTX5@)=<)1;&<"I<+1;3!RPW_,L`Y<!C<_S>-"IYPR&P\_Q
+MOC+[@.\^Q\=A;@*N?DX=X6KP`=W/\3Y'\X&SX>B(TJG`Z^'HN/JKZ=YS+%^F
+MY^@,5CYG]%/@:W(^\ZO`"OGM_3OJ'-P=<'%P#OG=!:Z3_#;"U;[`OS\'?BR_
+M=P/GR^\TX`3Y/0;XU=_X]V'@5OG]!O!E^?TWX,/R^R%@GOS6+_I=(N?EWO<2
+MYWOA2YSG^2]Q?N>\Q'D]_R7.9^=+G,=S7^+\G2UXUTN<QU,$)[W$^3Q>,.XE
+MSNM;!4>\Q/E]O>!U+W&>1PI>]A+G>S?!+B]QWG=ZB?/=_!+G.;I#!MKB\1=@
+M3^!I8"_@3R^J([@,/P`O`M8#>P._!?8!?@54YWP"Z0B90T#:"J8&2$?`[0?2
+MUO][!3\$TM:>[PON`%X._(?@>R]R_=TJ2.40"?P[Z"N!:UY46PH;*EYD?;H<
+M2'6@"$BJ+QM(1VO,!5Y+\@:DK>-N!T(-&FY^46T!9A@()'5X#9"V)KT"2,.2
+M/06[`FE+0:/@+QN@>RD_!+\'TI%G)X"T]=`WP"&4#T#2$5\`29U^!J2CI/8!
+M;P;N`=+64SN`=`1C%3`&^#9P!-5+X"W`9X`C@4\";R4^@;3%3^$&UL,9P%C@
+M="`=Q3UQ`Y]Y-T*P+Y".Z+L$>"_0*O@K9#49V"3X[=_Y:(A#P/N!NP7?!BX!
+MO@PL!OY1\`F2=>"CP*6&ME=[_1H]>,B-0V^Z>=CPF)2YJ6GISG;>AOO/H5[`
+M)<'%PD6>X[JA7W_M9C2LAGL$S@.W""X/;DS[@-I=_[_N'WK%]C(:9L_K\&_=
+M4KGFS`O)H4C]ZD=7Y'E7N:/M90E><F.4NHP7N-A_M+I,%[C(-_)_P.?_6]>:
+MD/RXD+WTKZX;TM(+;_@_FYS_O[ZVP[B>,LQH&`=7CM]C@+?`-<)O&/!&.#HV
+MX0;@`+@,_+X6>#7<.OR^`G@I'&UEU@?82\ZHL@,[P:W_-1"@=\GMP&]ZEUSD
+M.5CM\FQ`?0FX\&6:9S2<<;9JF3.92%MF>ZWSWU]B_ZG]'_X#\^^"[]...5DI
+M<].S_D4`MU<B7^%NAAL$UQ\N"NYRN'"XGG!=X2QPADKF[UG@6K@GX5;">>"6
+MP&7#.>'FP-T%1V%/AYL$-T[>W2"HY)WV+_N-J_PXPH2S?(/POD99`V=_TYJ_
+M>DT;*?CPKT;#"K@'X1Z`*X&[#ZX0+A\N!VX^G!-N+MS=<%/A[H"+D^=CX6Z!
+M&PIW'=Q5<!?#.>!L<%8X"YU]"-?28C0TPS7!?0?W#=P1N/UP'\!MAWL;[E6X
+MO\']`>XIN%5P#[2<WVXH>[NPG<%]HQC<PVX8,CQR\,TCZ/_@_]#@_C=7>TDU
+M_AO7_C*)T_5<]QL__/O0GMG?-!SIH&R_L-M,!@><#:X3G!GNW*TFPQFXG^%^
+MA&N`\\-]!?<EW.=PG\)5P^V!VPFW#>X=N"UPK\&]!/=WN.?@_@+W![@GX!Z!
+M6P%7!E<*1_&;8Q'?[29#$UPMW%ZX'7#OP*V#>QKN<;A2N#RX-+A9<`EPP^'Z
+MPET*UP/.`M>(,+^`^PAN,]R?X32XA7#WP$V`NQ'NLMM,Y^57%^0B4@2[F_9"
+M[@1[NC/N=85=W`TVL-W@:/=\>_FVWV]2^6T1/'L?XT^"WP.IG$X(?B58>Y])
+ME=%^P6K!?W?95TI\@F>]$I_@]UZ)3_`KP5JOQ"=8[?W/XOMW5Z@NIKY(>\6\
+M\7F3ZH-TD&>KWVM;!G/VF`S'JTV&57";X-;LA?Q5MSXS=K_)T/R9R;`>;A?<
+MH@/P.]`VC"N.,(_F(YP')PXS;Y\!J3_U'I#BWPBD_M3#0.I'N8"4YM\!J=]T
+MZV%.ZU5`JBN!0R;5/_H&2/VB_4#J_[P+I/[1LT#J'VE`DI-,.=_SW5I.S[I:
+M3H]6R^E96,OIF57+Z;FUEM/3MY;3TP48\17RXYC)$`6,AAO^55M>J?T(+B7F
+M`9FAAID3)HT=-7KT-/@O6]A!N=#G92FK>OJF]@48838L@JN%2[O,;&B$FWZY
+MV5`#U^\*T%>9#5%7FPVSX=;"'8=K@HN,,AO\5[5*D*Z+VK?-_ZJMINO'$6;#
+M";AC<)_#?0*W%^YCN`_A/H#[!]S;<*_"O0#W%[C5<!5P(VXQ&X;`]8>+A+L8
+MKL<M;=^W@[;!=8;K"&>&,\"=AM^_ZW^TOY)R%N3D%N5$JEE_(R+_W>.&V2O,
+MAK%PU\%=`F>"^T$S&P[";8/;"+<&3H/+A9L%%P\W`BX*+AS.!G>V'&4"MPON
+M3;CU<"O@"N%FPHV'BX&[$BX,[MQ#B`?N*[AM<*_`5<`5PLV"BX&+@.L*U_"@
+MV?`IW+MPZ^!6PN7`W09W+9P5KKG,;#@*]P[<&C@/7"9<`MQ-<&%P)Y>;#4?@
+M/H#[&]R3<!K<(K@TN*EPH^$&P87#G?)`GN#VP;T+MQ[N8;C[X>;"Q<+I,Y5I
+MT<V_S6Q<OY*TF?X#-QI_1AO:NO_DO?_$Q:)6][/\]\[6P6"$,\&9X2QP'>`Z
+MPG6"L\)UAOM78731T-[#V>"ZP76'L\,9Z$R-_Y/NM^*_&/'#V>"ZP76'L\,9
+M+K;\GW7MXSZ_B?_?Z__"B]HCW0ZF-I=:1&IKJ9VE-I_:>VKKJ9VG-I[:=VK3
+MJ3VGMIS:>1KCI/%-&MND<4T:TZ3Q3!K+I'%,&L.D\4L:LZ1Q2AJ;I/'(2`./
+M0](8)(T_4G>`QAUIS)'&&VFLD<89:8R1QA=I;)'&$VD,D<8::,R0Q@MIK)#Z
+M@C1&2.TVC0W2N""-"=)X((T%TC@@V:(T_D=C?S3N%PM'GQOFPM%'(#K&@I0G
+M-6XTF3L#CHXZHN.,:,MVVF:<CE+/@:,C?6A;^(5P^7`%<"XX-UPA7!'<(CCJ
+M(-YGX'%%&DND<40:.Z3QPCG_'\9/XY`T!DGCCC3F2..-I7#+X!Z`\\`MARN#
+M>Q#N(;AR.`UN!9P7;B6<#^YAN$?@*N`>A7L,[G&X57!/P#T)]Q3<:KC?P_T!
+M[H]P:^">AOL3W)_AUL+]!>X9N+_"K8.CSQ//P3T/1\<:_`WN!3CZ1+`![D4X
+M^CSP,MQ&N%?@7H5[#6X3W.MP;\!MAML"]R;<6W!OPVV%>P?N7;CWX"KAJN"V
+MP?T#;CO</^%VP.V$VP6W&^Y]N`_@]L!]"/<1W,=PU7![X?;!?0)'V_#3T6.?
+MP1V`HVWBZ2@_.CZ)CBPY!$='[]%V[W3$4"W<40,?ETQ'5M&Q3E_#?0/W+9P?
+MK@[N!%P]7`/<=W!TW.0/<#26]",<'2_\$QP=L_LSW"FXTW#-<&?@SL+]`M<"
+M]RL<'9>J&YO_M]?_408V:6@\8RP<'645#S<.;CS<!+B)<'?`38)+@)L,-P4N
+M$6XJ'/4G[H2;#I<$1\>GS(2;!4>?1>\V_';]__\J_O^M__];_R]4___51><X
+MZ_U5ZA_+$EPU&CLD=#0VYH9A[8=SU:K-6>I2])XS;4=1VG]>B6YWD1XBW5$<
+M?*-1IDQ$Q3+>Q1C["&/Y/QCG-RLL73Z(JI:ANF>JPN4'GE*8_N&'A)'):TU4
+M[?R%XX<1/K/JDFQ@[-=KHI\932=);]_Z&7#H-3\OL(TQE-8.6_R/46,,:VO*
+M9@XM'&/8-7E>=M7?QQAN?73.\5E'Q\2N?'W192]?-#;QAV.?';_DCK&/?9K0
+M\>/&TK'Z>WUR.KS^^I;'XW\^<WN=><KPA"&719\97_3`W2/?*UAZ>,I%[JU:
+MS5.O[ELS\L;GUW]Z]:D),;<^WS3V_V'O_N.['O<^@+^NZ_HLTUE:-5HUFEH9
+M#8M01YW[VUTTA#G"5%BLK%I\8TZ=<^:T,@S#*,EMF$2+<8_26><D0S'):8>A
+M&$8[QR0LBC"Z7]_/]W7=<WO<_]WG_J_OX^'A^;@>U_?Z7)_KY_OZ;.WS8\]'
+M3WC@WHJMB7^9,F3<U;4%F=T:?_[K#>$GMO9FY73['VG!+S/]BSZ)OWB*FO<O
+M*K?[+PXB=?^'LB8N2OC%L[J.__ZQZO]7NQSX'/@<^!SX'/@<^!SX'/@<^!SX
+M'/@<^/QOG]@9)#RMY2:$S]!B[W(,]KOPF5CX7EL;?^85OK/R(Q,^ZPK?/]G7
+MA,^NPG>SGA>$SXG"]W"VFO"Y4,QM'\2?`X7E7!:$SWW"=V%>:,/G3>%WH_%G
+MS.$[H(,@?*X<GNJZQY__A.^6/3[^W"=\+^E(&S[?"<M,-^'SFS#]@_CSFO#=
+MIFGQ9S#A>RFG!^'SEO`=GM^;\!E+^/[7P29\KA)S\G@;/C\)WUL]+2%\5A+>
+M8X,-GX6$[[_<9,-G&6'[O&3#O.%[.3\T2#9=[S`]1NF9DRV&R_7]'4Z1EQ4X
+M_+OI>D?F>4J/LATNEE>\8L/?O8MYTD"'/\I510XWR^7LBSOEUC<,ELK9QN`Q
+M7[<9`9Z2JR]S6/>SZ[Z@]-PR@\URS:T.V^32T@`[Y,ZS'#[S>=@FL5>YAN\@
+MOS(!QNI^WS5(DK=LL$B5JQZVR)0C[P,G>,\$QLCE[QE,D#N&\APOMPQSF"UW
+MSK/XG3SB.(L*_]T/#);(J5\YQ%Z;'JO;\CD)>%+IR]C^:^2V;(N7Y)S`88M<
+MV&+PIAQ=Y-`JIW]LL5O.^)-%IUQK#0YR:L/W@-YR]*@`_5Q7.V?X/.RCX^7Z
+M0A?[%89XOS#_!#GXPN!BN?,@BSER^_L&?Y#',_]"N>;.`.7R5-Y4E=R\*,`3
+M\D;.HWIYY)D.&^6"NRV:Y(I1%MOEE'<,=KAX&U:R?W<IO?!C@SWR-K9GI]QZ
+M>X!N@>81VR19SK_6(D/.Y!PY5BYFOX_R^3^RF"#7[73XK;SF68-+@OCS_MC?
+M&BGVY;QH42J7K.08\.FLVSUR[BG`0W+DF@"K_+6F!7A6'LTQ_)+<R`'_NIP2
+ML7C+Y^=BV"8W70WLDI%CL%=.6A!@OUQ=[=`C0??R%M!7+MWK,%!.KC?(]-[G
+MD"WGQ,:#G'6:Q7BYA?4\7U[/-6JJ'+V:ZX//P_6D6,Z_P.)ZN7.^Q2UR22>P
+M1$Z?#CPHIW(1>%+.^\3@!5]_=O2K<L/E7!-\>I;%E_)&#OA.N9*3/:&;KCO+
+MH6>WKO'?3^E3N:`-DILYWH;)D=$&H^32.RW&RC4<,Q/E@FE<!^7Z&P)<*I?P
+M6H5R/L?,M7+R<PYE<B/+J9`#+LY+Y`SF?U`N=`:KY);97"OD['/8[O*D9QPV
+M^6N="KPN5]QC\(Z\:Z;#1_Z^[G#X5(ZF`U_Y>UED\:,\\F*VVT&JVUT.A\K9
+M;QJDR^VL_S`Y_43@1+FNV6"LW,0^/<.;$_PB7P[7S'SY@B,-9LFQ9_[SY>KK
+M`RR2<]@OM\DU.X&E_EI%`:KER+@`-?Y:WP.K?=VXMC\GY[-NC7+IS0'>\OD+
+M`[3*N<,,VOT];N><\NE+#/;+5;T<DA,U5A]U2)6C?P@P1([LL#A6;EMK<9*<
+MSSCA-W+F:0YGR8UO<8V54QX%+I=S&+?,ECMV<KV5L[.`,GG?RQ9+?#GT(W+6
+MC0&>]O4I`O[B/0C8+#-4P7N^;HRO_B$7<NY_*5>S8[[W]=G.$.C@^#H\=48"
+M#CU8Y60#A\L9LP(<?;#/;W"27'XJ[UUNY[Y\NIPZ!3A?SCL.F"*/.)-C0Z[A
+M/E@L5WUI<(/<P7ZY78Z>;G"_#(Z9%0=WS?<U/O^5#AL.]FT28).<E>ZP79[4
+MQC$@-TTP^%I.FPK8[EUE]ND>3Y]_M,,`N9P;ZS%R#?>L$^4ZQC^GR4T7`N?*
+MD1X.D^5TKL\%<G:4^ZR\D?-NGES*H.4&>3WWG<5RXP,&#\A%W(`>\^5SS#\M
+MESW%,>#S9SJ\*)>P7UZ3)[YFT.R_VVC1+M=SW.Z6MRT-\(.<Q_TQ^)7*.<R@
+MC]RZP.$(>>1JQEIR(M>-D^3,"H<Q<O[=C+7DZ!B#7%\.Y]<4N9%C[`J?_VV#
+M(KF<[5SL?9M#B9S"<7B+W,#R[Y'3R@V6RW5##9Z0M]T18*W/S_CV16_&JUOE
+MBA[,Y^O/.=OFS7GZN:\ST[^3"^HM7)+ZEVMLKZ3X^(G]/D"ZTIL_M#A1GKK+
+M8)Q<][S#>7(RVW^R=UF`&7(V@[KKY`Z._S*Y]$=@L=Q:8/!PS+SFT'NY3BJ]
+M98;#:CG2S^(%.;_-XM6DKG'^MM(K/G?X."D^]TMN2,#>I*XS4:\>&C^,1=/D
+M&L[]H7)D#G"\7,1^&2U/XAHUH4>\S%H&#^<K/?T;AZER(N.-(KF<9<Z3"QDC
+M+9#+B@UNDQMX9KE'KISK\*!/;V:=Y#6,2^O]=R\PV"BG,K9_1_4IX?K6IO1]
+M,P/L]OFC#C_YNEUOD72(VO]O!OWE(AY,ALDC>AF<*B>/9ASE\P\'SI;7/&)P
+MD;SQ`8<"N91SI,A_EV?&>7)V;!V0(PPR;Y-'LOX/RK6;+)Z6<Y=;K).;V>8;
+MY912AZWR,L;YK7)09_&IW,0]]&LYAVW^PR'Q]DF[-@&)/>.NF)N`Y)Z:"ZSG
+M`+F0^^Q0N9SGA>.5?PG;=KS2BV88G"M'5QKD^?P/&4SOV34.KU'Z5,9C?Y(S
+MUCG<+B?VM;C'EY/&,2_OXR'K<;F,:_A:.?4)BQ?E1HZK+7(S]YT6G\XS8)LO
+MDW'"+CF=>^*W<N[O&2\E:]_AO?>2RW_@>)`GG>$P5*[AV?`$N9/S=[2\YQB+
+M,^3B_?Q.<OS>&V+%*CV3!\/KY`CG^$*Y;B1PJ]S`\_)BN6`<QX/*B?V.QEJE
+M-\T"GI?;69_-_KO?6;PI)VZT^,37GS%JAYS/`^9W/G^EP\&]-(89\_>16[FN
+MILFYKUH<+3?<8C'2FV>BB!PYEFN'W,$SV@5R;;;!97(EY]H<>33WK'ER#<_.
+MM\B3.(:7RDT?L-_E9.X+JWV9TWFFD+<P`-HJ9[[+-5'>P['W3Y_.`WZ'KR?[
+M]T<9AQHD]E;^V+W+K>R7@7(.U]YC>L?/C!5<,X<KO>T28(S<-#?`67+2`,8_
+M<@/CZ@*Y\B[>K]P>6_?DK"T.%?*6*QG_R!-G`(_X<I(LGI1COU?U5WD98[E&
+M7_XJA[?EC)Y<YWMWS;LOE)[(??`[N8;K@^NC-NG/?4W.Y1[=7][%V.,HN2&#
+M<U]NYD8T1EYVAD&.//)6@_/D?2]8S)#S3S2X2E[/=7Z^3V=?E,K;`N[U_EI3
+M');(39,MJOOH[V7POR?\M5H<ZN56UOD%.9OC=K-<=66`9CG@GO61O&*@Q6=R
+M#LO?)Q=R#8G]8E_8#HQ;?B5GLK]2Y*GLQZ/DR&>\GIS([XZ4)\UQ&"^GC0/.
+MD1NYYD^6DSEWKI"#:=PC?#ICM@5RE)UWAR^?<[Q*SMD%/.;+Y/K\C%PS+<`&
+M7PYCL)?E\:46V^1VKFFM*?$U/,HUO%WI]=\8?"77,@;N=JCFQ5+&A#(&<#V4
+M@],9B\C+!EADRR7L]W^3,Y98G"?OVLSSD9PWR&":3^>^?)7<P3C\=W+K)HL;
+MY=P^!G?Z.JQTN$_>PCUZI;_N[`#_Z?,PMJR7JT_BV/#UY-GA5;GI\@!-<B//
+MLQ\>&I_CE9SC_U1Z)<_IN^45C(?-86JK;EPSY7+&8[WE93]RS91W+;`X3FX8
+M;7#R87[-<1@7<ZS]N<Z?K?3L,HM+Y2C/W3/ECNX6<^5,[F6_EW,9,Y?)ZP.'
+MRL/B?9HQ)P&/*CW];HLUODS6>;TO<Y_%*W(RX[HF?U^++3Z6*[FO[91S>-;[
+M2JY^E?&#_^X(@Z"O[I'[2Y*\<4&`?G+PN4%FWWC=UI0FX&2E@^-MO)S=PG$B
+M%TX&+NO;M785_LQ%RC.ZT>&/<H1[^HUR*_?SQ7+M<Q8/RTTS@55R*MOJ:7G%
+M.HOU<C7/B1OEJG[`&W+]#18[Y'+VUV<_J\]>I2>^R[4T->X*[EG)\I;E!@/D
+M'/;=8+FZRB%;[CC!(B(7,KXZ0V[D?)\D1W[MD"_7#6<L[;^;P+.#OQ;[:Z$\
+M:2SKX<LYQ^)>7X<BBX?D=HZ?FM1XO]2Q7]8KO8KY7Y&S'K?8+I=&@(_]/9YM
+ML-/[*H<]OOS8O[7LI[7]%(/N\I)^!KWEC./9!W)108!!<A[/\L?(D5$\=\N5
+MC+=_([>S#7/D*/LK5R[\TF"JO(SQR6R?SC-=L5QW,6-.7S?VX.W>XWG6D$L8
+MXRV7.[^Q6"6W<;]8(X_GF6N#OZ^S#%Z18_^0H4FNX7[QOEP]A&.F7[R=.]G.
+M/RA]RQ4!$OIWC:7>_=5?C/,'R*FE`3+ENJ'`;V0,,SA-SC^-:T'_>/F9G/LS
+M?#F<LU?)33R_S),KKV!?RDG'<4S[/-<ZW"47,DZHEJN6.3PN9\5^WB$'0QU>
+MD)/?L/B[G++6X#VYIH!MYZ]['<]?\KZH0:>\+(O_'Q"O_T36?\``W5<^SQUR
+MQU$.I\@Y*RW&RAE_YOHIIT]WN$B._9+Q#+GY88=KY3R>K6Z2BYZWN$MNO"7@
+M'J:QY[@NR/N^=JB5ZW8;K).W<4]\22[)L]CLK\4XLT4>R7CC$]U7#>]KC])S
+M*P/L]_7,Y]$[+>X][SKTEUL9;Q\K5WX%G"RG][`8(^<R'CM=;EKN<+Y<UM/@
+M<KF6_Y\C3V),?KV<G\J]5:XN,JB4ZWCN_@^Y]-8`R]/BX[,^=@^^S![<6^7.
+MU0Z-<MILAV8YA7M]J[^7/<"G<N$>A]W^N[QNIQR]T*+[X:H_8X,^<C7/%(?+
+M'<XA4Z[A.IDM9Q8ZC)*3!SCDR!'.BW/E]!<=+I$;N&?-D#=>XA"5#V-<-._P
+M>']5%R:@5.F)7%ONDF-[_7V^/ER'5\G96PW6RI.^X?K@RV=L^;I<8`VVR4V,
+M(3_Q]62<]H7<.L?B!SFXB6>3(S1/9_)L(K=S_QHH)W(]'"IW,,8X]@@]URU.
+MP%BEQZXY48YP;;](;CF<XT1NZ.LP4TX>'.`ZN92Q6:E<]1/O7U[#/?U>N9XQ
+MU<-R]1L&JX[H6M/6*7W^%L:B_EKLQ[_)RQYQ>%<>?[S%+E\WSIV]_GZYAN^7
+M&XL<N@]4';C>]I%SN#X,DA.Y[@V3:SBN1LF9IP08.S#>/EF<CQ<J/;^59W.Y
+MX-<65RE/WJ($%"N]A.V_4"[EN>!6[Z$!EL@=63R[R:US'<\8\7**&$_6*3UO
+M.-M+;O^8YQ1Y#Z_[IKSB&(O6@7Y=-?C4U_,<GM]]_1FW)Z1K[$4=>LDI=UBD
+MRX5OL1W2N_IBE-*K9QE,D,%ZYLII7P"7_BQ_H=*C+SG,EW-YGEHH;SN2>Z@W
+MQ\!2.>DG[J%RS32#6G_=]X%G?3EC+#;(.<R_V=\+[_=-N?9FKB%R(V.53^3Y
+MW(.^\.EK'+Z7VUDW=Z36L2&,1>5.QAZ'R1D\\QXIE[[&<[V<NYAG-WD$]^N)
+M<L-^GN7ERAL-9LJ)G-=1.<(X9)X<O2-`F5S.<7NGG#S28*E<PSE;+>,HGE]\
+MF1\"JX_4<\MK$K!)Z1/G&C3Y<B[D?)$[N)[\0T[?#GPIUW(L[?/Y.3[=(%WK
+M3,9C<AKS])$+>>[N)Y>RCP;)):S/<7(-8Z%1<@KCJ(C<L-?A3+EZG..Y3F:\
+M?9F\@O'>='G)7(MB.;/%H$3N^+O!C;X.E8Q#O!E+W"\WG6'PF)S/>.8IN>TX
+MAWIY]#"+37+YR09;Y=SA!F_+V4.`'?*^AQR^E!LOLOA&CDPT^-'7[36'Q,&Z
+M;NSG[_)\QJM'R*5]+8;$S&9N.RLA_/NJX=AF#'_*X'B?CF:?GJ;T-7\VF"CG
+M1BTND#.YIU\FUQ4!5_KK7@U<[?-\Q/$FIS.^6C#8K\.\9SF/<V2QG,7Q?[\O
+ML]'B<;F6Y_0-/O^+%EM]W1("O"V/N)=ST-\C[WWGX*[U89^OPVS@)[E\DD5B
+MAL;5AP:'RBF\QS2Y>KU!AMS!>7JLW)#E,%9.9/P\04[GVG*^W/:PQ15R)MOV
+M*KF*Z][UOLRLV,_PU(^O6-PG-RVT6"G'8H1GY&;&),_Y/,4.K\CYC]GP[^.&
+M;;O2X`-?/L=VF[R%^_YN>?PLX%NYG/5W0U3G'8QMY`CW]UYR)F.8?G+UZ=S'
+MY3W<L[)DL#XGR-$=C"GEEK\:1.0\QI^GRTDI!K\=$A]O^=QWIOCO<G^?)K=S
+M_,R2.PYRF"N7\3QRO=S*\7:3KULO8*D\]7N#*KF1\_<1N2G5X'%?M[;8^JMK
+M,:Y>*Y>PSAODTI?9MO*2J0XM<L"]::=<Q?UEKUP3^T>%0U5GGN\.D9,9XZ7(
+MN5SK!LKMK-M0>7TRVTVN^-9@O)S(^/:_Z#H/.*FJZX_?F=E%5#388L-D5114
+M6+<#8EFJ2!%01%1PF)VVPT[;>3-;L"T!%1451"S$@L:"2A056T!=VU]4C&@P
+M045!(?:"$4N,FO_OW/N[,V\&\_DH^WUG[COOEG///;?,FW'DQJ\Q=R"/AR\*
+MD*?LBR&2/,9!_1S)\3=9KBZG?#[BC<7D]"*/NM7F`?[S/O+Q-Z.OV33+?>HE
+M<L52Q,SD[BD>M8E<A7'A`_M<S*__15[E(&8F]T%]^OI1)^9NNY%[C_6IWY+[
+M7EVF^I#KT.\.)\^$_O[D[IQ759/51(R#Y+68&YY$GH^^/)8\!G8[F;P0>3Z+
+MW!.^JXF\<4Z92I)_:"Y3G?VX/XBXZY)^!1]R)=,<O]BG;B1_#CN\G;SR,)]Z
+MT.:MI4S]Q3ZW%^:>Y"U_0#Q)GG:K5[UO\PP;^(3/O0G/_=[6R1*?\O6GGK]A
+M3"1WS2U3^Y$;%_E4!7DMRGNDE<,^Z\A5*/MQY+JKT0?)/9%^0G^>^4R7JQE6
+M_K-7A<@[,,>919Z/OW/MLX9ZU0)R_[<\:BGY#HQ-R\CCT4;WD>6`ZX/DBHE>
+MM9I\PZYEZ@7R^6<I]88M+V+(S>3N/_K4I^1EB#%VD+>\`W].GHDX9X^C.(XD
+MO6H_<EN%1U60=]SB4P/(7?MY50VY)_S,<>1UM5XUEKSV1(\ZG=P???!L\O;[
+M?"I,5C?Z5,M1!3O)6CEBO-GDT/,^M<#J^;-/+25/6N!3R\B#$:LOM_I#9>H1
+M<O=4I5:3^\*?O&K3H$W?M&5!FG?(U_[;J[:2*_;QJ*_(CW_I4;^0ER/>ZW$T
+M;?@O7K4W><"",G4`>?#>'O4[<@ASJ('D1M1#'7E[5YEJ/-J47=Y!,)[R9OB9
+M,\@W(/:83EZ).5J4W`=SX5;R^;_WJ`OLO1@K+R:G,>9>9?/S6XR/Y`K4SVWD
+MY8=C'F?U_^A3J\AULWRJV^89;;36ZNP//T;N'RE3;Y/W78[QS^8!,?P7]EEG
+MP+=;_6BOG\C/7PK??@QM%7YXOV/,FOP*C&5]*%\+NSJ<?,<@/(\\*:C40'+H
+M/>25W!/SK*'D9>L]:O@Q!;N:0/F&C$>=21[?6::"Y(_1B=O)!R!.N)`\!K[E
+M4O),Q#]7DM54C`7D.L17=Y`;TQ@+CC'OEYAW:@^UTM[[OD^MMCJ1SV?LO=N\
+MZD6;9^A_U9;W)<3_5GZW3WU`7HXZ^<3*-Z)/DK=L4.J_Y)4_>-2>`WC>HR?J
+M;4#A;/F(`29-QT'P7>0-F*N>-H!["O!C,RGOB;(GR%48Q^>09U[I4_/)JS#W
+M7$S^:2WB3_*.K$?=25X3\:B5Y$;$V(^3QZ`L3Y&[$`,_3UZ+_K6.W(PYU)OD
+MY>@7[Y$W3O:JCZR>$Y7ZFIR>[57_(5>@?GH,Y'/[^M3^Y(Z785<#>2XB4*Z.
+MH;P"^:\C]X5=#27//$BID\E9Q%V3R>L?\JKF@04;2P\LO/^CB[Q,]IFL'`EO
+M'FA^X_"G<\O5XY3+]R->((NB]4S3QU^N/B37@7>IY/>]\<]OR?+*JR/(D\OD
+M7+OA[S%!&2$,W2MZFK-ZPMM@`_%*HW,\=%Y<:9[;N)M2BWFO\)UD.>/V&%G.
+MLKU$EC-K[U2:=ZFL1)_]FOH/@"/;[5@CE[Y\Z+$F_5N[*U5+?@\\BOP?\)G'
+MFCRD]U"JB7+A5LKE'/7YQYH\3T>>%U/_*NB_GVED/ZC;Q>N8_GRD?Y\Z>^P-
+M.R'7RYYYE>$']E%J+_+?P8>2?P)7DP]$?#B,7`.>7&6>U76@4@'*A7.4B\W,
+M)7>#%U:9_"Q`?NXA+P0_R7O_C31_M<\%;R;?W0?V06Z`,D\UUWC`>U>SWF!P
+MAU:;.GD<=3*,\MZ'P>]5FV?=A&>%>:_(<TR_!NFO87J9+]].ECV(!WCO&MS[
+M"GD]^"OJ^:N\T*;&<!M\SUXUU(/^=PA9?$E_LOB`>K)\"6B$30.>2!;;/XM<
+M`9L*DA>"X^3M8(><1GN>9].CGBXFR]F&A?9>\%*RG!^XTZ9'.1X@+P,_:O6#
+MG[%I:I5ZI<;453?JZEW*Y;S'Q_;>>J6^(<M>_R\V#^#=:IE/\%[DE>"#:TV]
+M"1]%?A@\B/PH>)1-/QBZR')N_&QR(_Q>A.F%V\C#P9>01X*O8_JN1N2UEOX'
+M[?@PN??,<O4<67X/Y6_DY>"MY!7@'>25X%WK#*\"'T)^'%Q-7@,>6<?OKPS#
+M^$+^:CC*4,>ZPIRNF>G7(7T;Y;+/-;?.U/GSJ/,;+5]:KE:0UX*?(:\#;[1\
+M1;GZG+P>[*VG39Z*&(LL>_W[D27V.X0LL>(19#GW6TV6WX`YOM[D_Y?I2HTC
+M]YZ!MB`?`HZ1#P5WD/N#+R4?#;Z.?`SX3O)`\"KRR>#GR`GPW\CW@K>2GP=_
+M0]X$]C6P3\U$GLCR>S,'-9@TPOT;3#WWQ7@WE/)#(3^%/!1\)N^5^.I<LNPA
+MQJQ^S$%:K7[P>0VFGC>@GJ^A?!GD-S>8L4#X09L^K-239#GS\#)9OG>PP>J/
+MP.^1J\"?4/_T!>7JO^298.EC94SS._)QX`&#F(>(O(O>R(5'D^\"GT%^$!QB
+M^JZH4BG*A2\D7PR^DKP`?!/Y2O!]Y*O!?R'?!'[)/@N\T3X+_!&?)=]9VV'S
+M"?Z9+.<6=AE,_P/^#;EQEE+[#V8?!Q].N9P)K"3+NEP#66+4$\D23XX>S'I;
+M6*ZF#38V,``V$+;Z$7>ER1*#=9!E3?(/9#DW<J5-#[[!/BN%\<+F![R"+&M*
+MC]GTB(>[R?+]Q)?)\IW--^RSP)O(<A[X8UL/X&]L^CL1WS+_:Y#_O8>8.MD-
+M\X[#R=^`Z\C?@D<-X7/O@4T/X?C;A+*3^P?+50?3CWP(_93\[),H(_DE\#WD
+MOFN5>F*(J<\0ZO-EZI>SRAO($H=O)LMW!#XARWKR-V197_V9+-_SVN4XID>\
+MNC=98OM#K/PMI?J1&\&#CJ,]@,=1OA`\C7+AF+WW;8P+E`M?:O6#KZ%<^#;R
+M'>"5]EGO8.YLGP5^F3P&_!;3R!K"5ONL34I]:?6#_VWE[\)'#:5.\!YDV8,X
+M@"Q[1H>3Y0SSL>3MX,'D*L3DP\AI\%CR2O#I-CTX,-3D4]@9:MHKC?:ZA/)9
+MF]&^E'=`?A_EP[;`1Y%'@%\C3P2_3_[J?;2CS<-6Q*\V_V#?\:Q/\&_(W>"#
+MR6^`^Y$_!=>2?P"?1):7I8TC>\!GDLO`0?)1X!3Y)/!YY#!X/GDA>`GY=O#M
+MY+^"'R"O_`Q]B?P0^"7R<^"_D]>!MY+?_TSVG@W_"/Z9_)O/T0]/X)@"WO\$
+MMN^_E#KL!%//"U#/]4PC\I'D>>#3R9>"F\A7@%O)Z[[!/=0I9PRNH,Y5T'D3
+MN1O\$--[OT/\1MX+O)Y\.'@SN1[\)?E$\,_DX>!>)QH>#3Z8O.U[C-\GTCY_
+MA+^E?.5_D.Y$XT^.CY2K<TYD'(+\I)A>SGY?0);O>EQ%EK/'-Y'E=XWNHL[K
+MP:O(2\'/DD?\%\\FGP-^C_?*WN579#GO)"^!U/W%XU&]R?*=ICYD^8YM?W*C
+MSZ/J3V(?!X\FCP>?23X7W$P.@CO)DU'HRZFG&Y/I6RD7?IR\#OPZ^3WPI^2M
+M8%^CX6=V0][(O^N%_)`KP*>2CP9'R0/`$LOJ/KB'1UU+^;W@%90W_L:C5E$N
+MW$T>#EY''@/>2)X"WD:.@+>3F\$_D3/@GL,,9\'[DCO!%>0+P0.&L2WV\J@&
+MLJPECB3+[SE-(,MYUZED.:,^@WKVW1]U3KGLN;2ZN-.F/]BCYEH]?3SJ"MXK
+M?#TY#O[3,&.3O1:5JU64WW,(ZH3\+'@=^17P1IO/"H_:2EX(_IHL[TSXR9;K
+M4(_J,9SE!>]#KCC,HPXA=X./(%<=[E$#R6GP(/)Z\'"RG'>:8.\%GSG<Y+\W
+M\C_+WGN$1^7(<@:@BRS[C%?89QWI4=?9-.#;R/)]AQ5DV9=_Q*8'/VG+`GY^
+M.&.#_A[UFLW/T1[UEKWW&(_ZP.89_/EP$_>N'>!192-,G@]`G@\8P;Q!?N@(
+MHW/:0(^J)*\$#R7+"Q_&,+WL94\FR[GZ<\AR%C="7@EN'6'\SZ;F<C7'ZH1\
+M(7E]/?HFTW<U>-1]E`NO9C[[()]_I9[/8YCW,<WI@SQJAWWN8(_ZF2SG-GN.
+M9%\`[S^2\N,]JA]9SD)7D^7,TG%D.:\^TJ8'3R#+=PFG4>>41O1W\IAA'M7.
+M-#/E>W.4"R^A7/95[[#/`C]B]9_L44]9_>"U-CWX#;)\;W0S6;Z;_ZF5G^)1
+MWUOY6(]^B:VV$_#NHUAOUY2KWUN^KES5D2O`)X_B/`7IIU)>!?DLRTO+51>Y
+M#GPM]7>-0WOQ7N'[R5>#GR1?`UYG\S/>H]ZTSP)_0*X%?T5N`/_$9XW$L_8<
+MS?H\%6U'ECVC(\FR/W@L6?:_!MDTX&%DV<<<1Y;]E#/(LN;O)T\")T;3+X$O
+M(G>"%]EG3?6H&RF?=Y9'W3G:]*,%TSWJ4<IW:_*H9YD^'41_',WUO5GEZD-R
+M%UA>,"P\#]R'/!]<?[+1(_>./MG4PYA;RM4,IEF`-.U6COJYBNEWB:(MR'N"
+M5Y*[P<^0]V^&+9%_!]Y*[@_>0:X$EX]ANX#W)P\&'T4>"AY*/A$\@3P,[">/
+M!+>2QX/GCF']QSQJ\1BN]:$L?Q[#^!9E?)%\/G@SN0O\`_5TS_*H7J=P+`!7
+MG,(^$H>O/L6DGX?TP\DW@:<Q_3^1)D;^!#R;_#GX"O(WX)MX;]FMR!M9@9]C
+MFL_2'K6!_`7XGS8/K1AW3N$:%,I5-I;K3N"#R(^#&\;RMU#_5*[&DN>#H^0*
+M\$7D:>`EY`7@>\B3P,^,-7EX(8.XA?)YD']*^6V.1_U(O@.\VSB39@K2]"7W
+M1+F&CF/\D$,?(6?!YY#G@%N8?N'=F)N0%X!O(?>"GH?(O<$OCN/\%^5]E]P-
+MWLXT^R+-+N.-_OW.AXV1?[P`/IGLOQ!]F=P$/GD\QRGD_QQR'W!F//WG/(^Z
+M@/)KD;>K>:_(;R&/`/^9/!Z\AO?*.;IUY.W@=\9SK0]YWD%>#^XUP?`&\)'D
+M3>"A$XQ.N?=4\B_@`%E=XE'9"<SS\G)U';D"_!#3G'J91[U`G@3>2)X*_HQ\
+M#O@7\DSP7J>R?<%]R;^]'/5&/A(\]E36&Y[50OE!"^#?R'W`B\F_`]]-/A2\
+MFOS%E?!CY._`6T^E?UL$FZ?^OM"_ZT3#_<&'D0>`ATZD#Y?OXU->!?FYE,OW
+MZ.-D.?=X/KGQ6H^:/Y'M"+Z!]XY96:Y6D&>"7R*/!V\AA\`_D:>#?SO)Z+E@
+M"<8.<A>X@7SX=?"WY"/`4\FMUR.&F<1^^G"YZB`W0^>53'/V4H^ZF?)&E.LQ
+MF_ZQ<O6&E:^`_R>/!/],'@/>?S+KYV:/.GPR^Q?N'3*9;0WY*>0`^"QR"SA&
+M3H`[R2GP9>16\(WD2\'WD)>!GR`_`7Z)>>BZ%;;'/"Q#'K8SC<A]I[&/@'<[
+MC38/WH_\-;B"?/^?/.H8IE^VTJ/J3N->84NY&G4:]:\N5U.97M($R7\"I\EW
+M@2\@WP.^G+P"?#UY)?@.\B/@!\E/@)\BKP:_0GX*O)'\#/A#FY^GR]7WY#O`
+MNY]NTO1XU*,.)/<$]R,_#*XGKP:/(#\)GDQ^%NP_G77[&.9*9'D_DD->^!>/
+M.H_I`VL\ZE)R!+R8G`7?2FX#WT?N`#]&G@-^CGP-^#7R$O`[Y`5/>=1'?*[\
+M'N>.TTV[3$&[[#F%<0BX_Q2N5Z`>3IC".D?ZB5/,._2>1YH`Y4]`[I#7@"\F
+M/PV^GOPL^![R.O!J\M_!KY+?`F\F;P)_3=X,]IUA^`/P?N1_@ON1/P8/(7\&
+M'D?^$CR#_#4X1=X!GD/^'KR8_"/X3O+/X,?(\A*YE\@^\#OD'N`OR+N"_TON
+M!=YKJN'?@`\G[PVN)^\'/ID\]47T:_),<`LY"+Y@*MMK+?SA5.YE=)>K&\D;
+MP0\PO:1YBMP;_"JY#W@3]6P'?TBY\`[RO\#>,]EG7_*H/<[D.(BV_CWE6R#O
+M?Z9)+UQ/'O$RYL7DU>")Y(-?\:CIO%?.MT?),]<A/F0:X8O(8?"5Y!;P'\D9
+M\#UGFO)N0GF?)&\!K[-Y7H_Y!;GB==@2[Q7^@G(YP_,=6<YX>Z:Q/[Z!V)(L
+M9_[W)\N[[/J2Y;LDE61Y#^$@F_YOF">2Y?S>!'(W^(QI)@_"`<KEN\#Q:8P?
+M4+?G3S-EV8:R7&V?^P^4W<7+R3/!#Y.[P$_:O('7VN>"7[?Y!&^RS]WH4=O(
+M%>"OR(W@?UO]<D[X+.H'[T5>!JX@=X,'D+>`&\CJ+8]J)%>`)Y$;P>>29X*;
+MK7YPSNH'S['ZP5=:_>";K/ZW$9]8_>!55C_X*:L?_)+5#]Y@]8,W6_W@3ZQ^
+M\#=6_SN8>UK]X!YG4S^X-WDF^&!R%[@?>1FXEMP-/H&\!7P*66WRJ&GD"G"3
+MU2_GEZQ^<)O5#^ZR^L$+K'[P$JL??(O5_R[JQ^H'/VCU@_]B]8-?L/K!ZZU^
+M\-M6/_@#JQ_\M=7_'OK+.=0/WI/<"#Z8/!-\!+D+?"QY&?@$<C=X+'D+^$RR
+MVHQ8R^H'MUK]X/.M?O`55C_X!JL??*?5#W[`Z@>OL?JWH.Q6/WB]U0]^Q^H'
+M?VCU@[^Q^L$_6_W@7:93/W@?LGK?HPXA5X#[D1O!QY)G@AO(7>!&\C+P*>1N
+M\&E6/WB&U?\!ZL?J![=:_>!.JQ\\U^H'7S6=:V7P,W=,9RP'^</DN\'/DE\&
+MOTY^Y$./VD+>"/Z*O`G\"]G[$<:(&88'@ON0JS_VZ',#PA/`QY'CX+$SZ'L_
+M18PTP_B]S^'W9I*W@UN91K[?VD66[^9?15X&_N,,4ZY>\7+U('E?\,M\EJ1Y
+MA^DG_>!1GU,N[#F7\17XM^0;P<><R[K]$7V9W`4>2MX"'D6>]!_X-_)*\-GD
+MWC^AC<YEK(O\S*%^^1WO:\CR>]Y_(E_S,_P8^4/P"^2/P7\G?P'^B/PU^`?R
+M=^!=_89_`!]$_@5\#'FW7SSJ>'(O\`3R;\#GD@\`I\A9<)??M,7R9\K54O(/
+M:)<'F6;&+E[UK##*^#[X;:;9@33?^ADSH.Q[SS3I/T&:P\F?@>O(7X-'S:0]
+M[.95$V?R/!Z>&Z)<OE^<(,M9[AQY)?@/HL=K>"GE:G^ONH-RX<?LO>!NLGS7
+M^&6RO,_S3?NL`[UJ*_,F_"VY/WB7@.$J\('DP>!C`KSW(*\:0KGP.')_\`Q[
+M+SAE[P7/L?<>[%57V'O!-Y*/`-]-[@=^A'PL^#GR^15>]3IY,7@S^2[P%^0'
+MP/\AOP'>M<GP1^#]FU@_?;WJB";:;0)S-'(%^&QR%=CAO9+^8O(EX.O)UX'O
+M(=\%7DWV'>E5KU)/'?1\T,0SF6CK'YGF]_V]JE?0\*'@WY&?!E>1GP4/)[\`
+MGA+D'BOT-),??P$Q%7DM^(8@V_IHU&>0>Z#(PU/4(_+7R=>`MY%KC_&J[\D-
+MX-U"7$/[/\3#Y&DOEZMZ<@A\>HCU.<"KSJ5\.^0=(=8;Y)>2%X"O(]\"OI.\
+M#+R*O`+\'/F02J]Z@_P[\/ODZZJ\:COY7?!_R5O`>X;97ZJ]ZK=AGDU%V8^F
+MO+O6JX:&&:.")U$N[P8\Q_+Q7A4AR[LO6LGRG=GSR5W@2VWZ1J]:1)W"MUKY
+M2-A&F/X$=;*:O`.\GOP3^)^\=_HHK_J&W`3V1+@>^TJYZDWN"?X]N0PL9ZWT
+MO&.B5YU(+CO=JR9$3![D>_U3F+X7TH?)O<%M3/\QTLPA?P%>0-X.OI[\_)E>
+M=3MURGL\[B>KL^%SR!7@;G(C^#6R?(?EG0C7BI/EZE^4RWNE?J9\#>3[1LVS
+M/C\'_I/<,^!5M>0I(:\:0=X1]:K3HVRC%O@<LGR_+T*6[_*GR?)>Y?.L'#R/
+M+.\(O9HLWP-=:M.W>M5]?)9P-^7R[NO7R?*.M4UD^0[71U&N]Z)N?R8?`-ZK
+MF<]J]ZH^Y&[P0/(6\''-M&'P.,KEG7CG-#.>0?UDR3O`"YE&SM7?3%X/_C/3
+M_(0TZ\A34N7J4^J/GX?^0DZ"]XT9O@!\5,SD^0;D>0SE8R[PJNGD]>!TC,^]
+MT*LN8OKE2'\C>07X_AC['9Z[EO(UD+]//7+O#BM_#?4SR\C?OLBK^I)[=WG5
+M(/(^X+'D`\$SR(>!T^1*\%QR-?@Z\DW@>V:QSN?`5BD7?HG\+/B=65R?7%^N
+MOB)_OJ%<]6IA#/`'^&?R3'!5"]=@D7XD>1+2GTF>"<ZTT#[GH7]1OAWR6\CJ
+M3<SKR0O`_Z#^R9=ZU:?D*/AG\H7@WG'Z0/#AY`?`#>0^\[WJE#CM\S*O.HN\
+M_@JOFA4W[1)'NUQ.?AY\#^^-+_"JI\E)\)OD"\"?Q;DG\E:YVCW!_BCO.B!O
+M`M<GZ!NO]JJ3R%O`$Q-<;\2]X03C)3RWB_)5D"^E'DE_/^6A]Q#?DAO!VVSZ
+M=\N5-VG2G[H(?I[<!3XZR;8&#TERS0'/FDC>`FYF>DES'OE9\%7DZ==XU6UD
+MO[R_*TG_N1E]BERWM5Q]1(XC;S^1>T.^7XI[>9#7I%@GUV(<3YD84MB?,OJ_
+M`3ODJB484\A)\!_)<\`/D)>"GZ/^=7C66^3X-OA5\A;(>Z<-'P\>F&:,<;-7
+M#:,\7M9#3:?\R%N]^@RH\$G@>6F.7[>C3M+T)ZBWV\@J7:Y6D<O`_T?N"7Z7
+MW`LLYT0E+A4]Y:V,M\'[D)>"#R7?"CZ6?!?X!/(]X''D^\%GD1\$1\FKP#GR
+MH^"YY.?`BUI->=,H[UV43[T+L27E6<A?:>6X=K=7;:"\;X\>:BMY'M)\PWN?
+MNL>K?P!;^/_`>Y`W@0\B?P'N1^Y]+^)_\B3PL`S/N*)^3J/\9LC]Y#^#X^1'
+MP9WD%\"7D'\`7TO>Y3Z,R^1K5WK5R@SS7]Y#O4#YH0][U=_(VU8ACB*O>]2K
+MOK)Y>QQ^AGSU$UZUNV/XS;\@_G>X!HMZ.)KR#:N]:C#Y4_!H\G?@*>2^:[RJ
+MB3P"G"9/!5](CH`7D.>#EY*7@Y>37P8_2OX8_#RYQY.(#\D5X"WDP>`OR1GP
+M3^2YX-VRK"OP`>0-X".S])-/PP[)"]=Z52/3")]!>?=+7A7(,JY&.[8QC<@O
+M(?=Y'6,0TV\'W\[TTY'^,:81^8M9TT<^WNA5[Y+7_<.K_L5[)[V%.##'?4;8
+MY'XY<^\\R/N3+P,/)5\'/I7\%#A`?A&<);\,OI3\)7@IV?<VX@?R2G!WCF<Y
+MD.=-E`]X#[$W^5EP61O[`OB`-O;]5LP1VNA#WL><MXU[H\C_C#:[GH/QB.G'
+M(_WY3%.%-']D&GG__YWDE>#[R6H;[($L[]GNMFG`KU+G'.C<UF;\K<B_H_XZ
+MZ-^]W>1Y]3\1CY%?!@\DOP<^L=W<N_%3KYI&'OP9?#73S/H:?K*=<<+('NIF
+MRK_[#OFT\A$]U(OM]($_>-5[E.]`^J\H[_MOU&$'8P/(#R'W/J*'JNF@'9;[
+MU`D=)@_"4\EW@I-,7S&JAYK78?+P$N2+R:^";Z<>>?_D"O)*\*-,(_P\^6'P
+M&TPC[RA^ERSOJ?C0YJ>73WU%7@_^B?<*[]%)GP#^';GG'CYU+/DP<"-YQ9X^
+M-9D<W<NGFL@)L$->!)[7R7@`95Q*^:J]?>H^<C=X32?CC7U]ZA7*A=^C7-Z_
+M\2%9WK7U5:>I_YX'^E2/V=0_NH<Z<#9C=<B/)LM[.`>1)QWD4R/):?`$FP8\
+ME;P2?"YY/;B9O!WLS.9\!_9Y^6SZ`<AOM/<>YE-W,,TFI%E-N7Q/]D7*?X)\
+M"^]=>:1/;;?Z^_F4]SSNUZ,L?<YC6?JC+.2%X#IRXU$^=2)9WOLZQJ8_VJ>F
+MG,>UD4RY"I(KP+/)?<&7G\>X!>F7DA\&W\LT_9'F2?(`\'JF63[0I[:0'P-O
+M)V\&RX_&:_L!]R9_"ZX@>RM]JHJ\)[B1?`1X$KD2'"`/`6?(H\!SR6/!UY(G
+M@^\D3P,_2@Z!7R0GP!O)%X`_(2\"_TB^&[S[!8:?!O<A;P`/),^K0E\F3QGB
+M4Z=>P'8YSJ?.N8"Q&=HNS33#A_K4'\BCP=>2QX'O(I\.?IQ\-OAE<A-X$WD6
+M^$MR2GZ@ZD+#[>"]R5W@ON1YX`;R%>`QY(7@L\E+P''RC>`+R;>`%Y+O`-].
+MO@^\BKP2_'_D1\`;R6O`GY*?`_]$7@O>\R+#KX$KR!O`->1WP"/)6\%3R5^`
+MF\G?@6>3_P->0"X[WJ=N(>\!7DG>!_PL^2#P!O+OP1^2^X)_(%>"=^LR7`ON
+M0QX,KB0?#VXDCP2?1AX/#I$G@]O(4\'SR3/!2\FSP"O(R\!/=G'>`?MY@_(A
+MPWQJ&_E$\'?D$>"><PR?##Z(/!8\@'PJ^$3R:>!)Y*G@)O+9X"PY`+Z$'`;?
+M0&X!WTN^";R:?,4(GWJ5_$?P9G+%2)_ZFCP1[/L#^R9X/_)T<#_R3/`0<@@\
+MCMP,GD&.@U/D=O`<\ASP8O("\)WD&\"/D^\&OT*^#_P>^3'))_D%<-E<PV^`
+M]R=_`CZ:[!F%OD_>!SR)O'VL3P7)WX+;R/\&7T;>:YQ/W43>'_P`>2CX6?))
+MX#?)D\`?DZ/@_Y#/!^\YS_`UX$/)]X+KR`^`3R8_!#Z;_"@X0>X&=Y%?`"\F
+MOP*^B]Q_`NIP'L\HPB;_2GG;&3[U/KD#O(-\'GB7B]DNX(/(%X,'DN>#&\E7
+M@$\G7P6.D!>#.\G7@Q>0_PB^E7P;^"'RW>`7R/>"-Y+O!W]&?A#\"_DQ\%Z7
+M&%X-[DON!@\B/P<>2UX+GD%^'9PFOPF>2WX+?!UY$_@>\OO@->0/P:^1/P5_
+M0/X*_"WY6W#/2^G?P`>3_PNN))=/]:EAY%W!4\B-X,BE7--#>YU/^1/G^-35
+MY#7@VYEF#=(\3OD1T]%'R$>#WR-7@;\FGP0NFV]X%'A_\A3PT>2SP2>0`^!)
+MY&9PD)P"MY';P)>1N\`WD2\'/S"?YTR0SQ<H7S(#[4N^"?P9^6;P+^1;P7M=
+M9G@YN"_Y(?`@\FKPV,NX/^O'6$.6=R`W7<;UHI-[J-E,OP;RRR]C[(=8Z%:F
+MZ8LTC_#>]1'T9<IG0KZ!]XK\GU9_%/$2>2'X1_)*<(_+J0>\%UE^J^N`RQE/
+MXKE'7<YU#^@?<KG1_TP+QDWRH(1/3>2]74G$)+SW<]R;8AJ17\0T52F?NE+D
+M'L-W4"[O-5U!EM\/>HPL[V5]EBSO3'O%YAG\=WMO%O9C]8,_M?K!GBLXMH+W
+M(I\$/I0\#%Q-/@T\C'P6>#)Y!CA`#H%;R2GP''('>!&Y"WP;^6+P0^05X.?(
+M#X,WD)\&_Y/\"O@[\B,7P+\M,/P/\`'D]\!'D3\#'T?^&CR.O/>%/C5]`>OP
+M(I^*4?[Y',0SE,MOFUYBTX"7D!OGPN^1NRZ';R$O`S]!EM^[>9XLO_/R&GD2
+M^"WR=O!6*U^`OF-U@K\ER[ND?B'+^XAVN9)YN`KM19;WBQ[DXL-LFD7P\U>:
+M<BT$'T]YQ1+$GY0+3Z-<WE$VT]X+GG4EU^M@VQ?:>Y?"/_#>-/@&RN7=:W\B
+MR^][/DB6]W@_Q?37_@GU0'GO.U$/Y"KP5K+\1LEV6Q;P#U8_V'N5TG-,X7VO
+M8I[O]JE#R/+^J'YD>2=A'5E^1V8X>>9]Z(]7F?S\ZPF4]RKVQZYRU<DT\AMG
+M\\GR'J>K^-QMX)LIKUB'V(9ZA!]DFIZO8>PC5[SI4V^3QT#^F>4-/O4S^5KP
+M;ZXV_/A&]#MR]QO(_]5&?_P?Z'?D->!3KV99WO>ILR@/?X*8W*8'MY-;P9<P
+MO?QN["*RO!_R9O+V;WSJ;G+O'8C5R57@O]A[P<^3Y7=:_TJ6]^6^39;?1]MF
+M]?R`<<KJ`?_"_*A_H[P+#??^$?..A=0/'D"6WWQLL%Q6IDXD=X%'DY>!)UMY
+M>9DZF[P='%G(=;,YY>H"<A_PM7RN?]<R=0<Y"%Y%CH*?)W>`-Y`O`F\C+P3O
+M(%\#+EO$<1"\+WG\[F7JB$6LA\/+5)7E(\O44+*\VW,T6=ZY/<FFZ5>FSB++
+M[QV'J3-]5)G*D<<<4Z8NMEQ;IJXC3ZDO4W?SWNT-9>I!^ZQ!96KU(NXWH2^_
+MMHAK"*B3]RE?#_EVR@=#KJXQO!V\#_F`/Y2K?M>P[4:4J7KR`>`1Y`KP9')_
+ML)]<!4Z0!X//NX;?<<!S%Y(7@.]FFL;)9>H1\BG@Y\@3P*^3)X$WDZ>!OR3/
+M!/],;@;W6LPZ!!],[@`?3>X"#R'/!X\A+YM2ILY<S/KTEZF99/D=AUED^:WD
+M''E24YFZ:#'7]E&6:RB7]Q#>9/6`E[OX$:LS7*:>)LOOL+]$5I$R]7>K!_P>
+MN1'\L;U7?@.+W`7N>2WOC9:IWF1YS_F!9/G-N,/(\CNS`Z_E^-M2IHZG7'Z'
+M=)2]%SS1W@N>1EX(#I#E=V];J$<ERE0G>=]DF;K4ZLR4J47VWER9NL7JG%VF
+M[B/+;^P^1I;?57^.+.^0?,/*YY:I=\GRNY,?DKLO*U-?D;>`O[?U<#ERLH1U
+M"-Z5+.^HW'N)'<?+5)\EINW./[6'JB1W@4>2R\!G,+W\EK>?+.](3Y+7@\\C
+M;P?/M6FN+E,+K!Q\_1)^AW%NN;K7YFT)?-$2.RZ7J6?)/:\K4^NM?O`FJP?\
+M(7G2]67J:[#?/_*L4X=-.&4$R)\)!^.!6,+?E(LH?T<HXX_$4X&L\H=R:7P\
+MZHP1?B>=RV9RR;"D#F53`>6/AK.19N5OSJ:2<>4/-*4RN"&<R2A_))R"FE0Z
+MG)34P50\'LB&_<'F0"812/NS@:8XU#1E6I0_Y@2<8"PFR2*QCE#$B1F%CE:?
+M20>;.I.!1%@GS&8[H3HEMT4"34@11!(GG)4G96/)D,EX*)#-)0QVIC-A)^U/
+M!)QL.&-%34CIQUVA5$(_(QW-I-VYE,?YTYF8S6;<R4I%-.D'R`U.LRXHZBR8
+M"$EYG:PN<B:3RA2>V^KOB)A+5*W?:8E!%DQEF,ED.)MJFH42-&=2J:S.1WO(
+M9">3PD<LM%S'(`\E_>&.=$!R@*+B/_-1P#'5E(TE4.&A0*?DJBGK3^><9L&T
+M/\,<H=J-1I0SVYD&H`:BF50N#0V=:7FH:3F1-Z><;"CIA).ZE(%0*!2KU3?`
+M.")2D9EP(!2/)=$.@5RV.9>,=?B#D&7#QI(<78>Q9&LNG.DTSP]D,B9WMI:=
+M7).3C65S65/*G)12Y]WI3`:!&12V;K`_D8LC$[#%8(O[;IU54VK868+WX"[8
+MIRF>9"R92H;S&4/V\1G+E$7!TU(26ETH)@862T;T0^+A0%+,GE418YOE_/%4
+M,FJSF8['H,II"R(OR#0L+&$J4.<+20,A_!,,:!.*.%`6;0_(+3$G&4"W:`JF
+MTIU%9MH2[O2W!>*B(M46B?M#X7A8<IX)1V-BP.@,IE$CK7GKD/SI,L6<:":0
+MEMX8"L,>4[JRX\%4L@UU$0R&Q63DKU@,^F^L3;>I'_>9^M*-9!LSC7YJ+"NM
+MS0\5@>8.:]\@_0#9;4NS$XBY16-)XPV<2$S*ZS]Y_,3AP\;[)XX>??JH*?XI
+MPX:/'^6W937=252FHNB98D2A65)G,/-8)&)(ZXV&]1.<1*`EG/=+Z7`X8XKO
+M-.?0B=O-HX/2?=`:F4![OLDE,\D4Q$$84RQ#K<%$F@XO7\-^L3-=(6@O-!IN
+M328"V:#N1,AFC36`F%2U>!U=YX6NCJ8S\F!`*W<;&-PF/88D2%K?U!8.9L5?
+M2#_R)[4_;7/@=I+9B"Y0*.:T6#>`<N5":7\X*1XI&`@VF\8/2^/ZQ3F(>\GW
+M;_81;8':A^DF%TL)Q&,!1QM4)!-FHX=UCN!2T*A2WVT11^X4BXJGVJ4(3@SM
+M*_:7$R."<3GAM'Z^]1]`[9)T]2;#[49Q4RH5IU4XZ;`V77FJMNUT(&J*$-7F
+ME<VTQ1RFU36KK</T':VJ,RN%0$VRR/!)X;B^,9MJ95ZBMI_*,,//XJ9%=<^)
+M%AQ`6WL@D^R`(NTA"@-;M-#A3;Z-J8HFF&FH*0&3@K?7K=TF5J7]15,LBBK-
+MYC))XQEI:NACCIA4K'9P@ZCSQT.VCC)AW6-#J%A`IJ0[.>%6/C1$\X!.K1)F
+MK*U4YR2L[3.11C7#9:4<Y#\K%H9A$HES3CP<-CX,1I7*Q&3LU/6D:T"<M';/
+M&`4#TGO;D2+<EL]!("/*I:U%66?:CUK48W`\W1S039GV6_\NN1&?F='^#\85
+M[@B;^@Z;-DEGLGDGADRBKH.Z?[I\GQTK<0TT]6Z*ADZL;Y/.I1LV&$]FW;T<
+M=V&XBJ5<0Y`>`ME!K<\..,UQ^CP=VN22J/\0&K!91I,X,F?*FT9E!&&&61AM
+MV/@^!Z./-G`8E.D2&5VIN!=:\[6%+A0(AJ7JPPB?,JF$7X]J"1E<T=EU-]9!
+M3;A5]S3=&NBU2N=Q5B+-""+F!%%"&0?@>G0T@E'!&K?IN(@&8ME\<!%.AE(1
+M&UW05Q2&O00&@4@LRLPBCVWAC!B+7T<:*'.@TP1J*'TPP%K#(.)O,J-N+IE(
+MY9+9HN`DEVB2:F@.!]*.-MR\/6F'G6MBQ!!NT9U!+,0\`UE%[;05N4\TOQ[V
+MH+_)B<W6(Q[=L#$M;=LPH&!*7+=D4_["99K(,9P,9CK3>842_!1L*N8TQ0-)
+M'3Q@D`YFX[2/2,B&M=(BNO=CA,NRJ\'@=4]GH6W_D4<W&UM$TW#02Z1"VNB<
+M3!BV:KQ27,K:;`TC)V.:8VZ7,5^;5XSVI74%0H&VJ*Z=9+Z+SC(AD,VY[H"V
+MP26ZAEM&<P3-$"JFA5*8&K/#FO1`;8):&,M$9#!$T6`G>F@RCVLV/A$^DD:C
+MN['T,G\Z+Q"[E&?DDH6.;#Q?#(%B)FM\@QY*3+<US1W5838<#,>QXDM=X3*X
+MFTI'8@P^'/."MC-(&C,\ZE@-W=;1X1HJT\Q-)@6RS>,Y6#`<2>5,?&[,""T3
+M;(X73T4*X:<-\TUEV-$G8RH.O<H4)!O$P!1J@L866T(]T/FCB502X9+TXD2+
+M!(%I=J#B8L/!)'2\",\6<8Q;1O2N'Q?(#_MY\/L[T$C2AUR=Q+C@9"P_[DJG
+MDVR)MM;FE(Q1?O&L49BKV%LP$BW8&>H+;M<)Z[YCQD(;7A@'83N:=M?N=A9C
+M36H79/I)V!HF5**/H>21K*-'/AM7M:5C$E/FBQ6+HH6USQ-O:ON_[8_N8F1,
+M,4RI,6D1O^S78Q!2H\_9RM>AH>FPF"SFX_!VM(]$L=K,S8P-%<*".>V!M$[;
+MZ11<?G8VVR@61;?1>31/T`-((A!"9"*&%<QEI%L6U:^C#5:716K`.G4$/EG&
+MP6:V:9Z$$N:C=;]N1^0PFY"`T6$L`5N"@62R8M<H0#+<D:7;3N<R4:,0EF4*
+MIJU4#[#:'LR(HZ_A%O!\I(ZT!^(M'/R,.4F=:I^FO38*+2[+M$PV8YR;'MOI
+MRZ.NP0^).2*@)'H@T$5IQHWLJ](EB@T03L0]&)G.C&@QP@`G9R*=M%X*D*F-
+M'4-L=9LH4-+$9!A'HY@@(%KH4BD[9RCN*ODP"@V(4"^22W(YPL1\>:]O'+`H
+M#UF[UM.,E(YY\U[2SH?-3,]X7WRB<V6*8CQ_+FE#6=W!C&=##ACKN3P0_1<M
+MUUBM]KI.B=N5CION+/A',V&SWM`LF3"H,1&-&",+FQ^")8AW$F$S;NN!3RR0
+M\Q-3?MTZ\60@%;'/DA(G8DG=.B;4@?MR[#PJXV1T%)Y?IV%4@`QS3&0\C8\P
+M.NB:<)HQ63?S$=%G<HDGQ?2DPWCB;"*MHR(4CG,<'4([A1":974BUN'8D=:X
+M$L,H/*K#E%(\4#`;D][?*>M!G-K9&N1XDM3ACPR6TO-TE(_Z,ZZN+1@)Y>U8
+M1\$F\(&/EQ&[:'%)3-`T4BX0#XB#%'??;NPGAI`NSL>9F2CZ1SQ@YN4.JL*X
+M`AEL(\9G^O4<1E>8B2%TC"IS^RC#`QV\,ZY(T=]+1Y3NF^_$^;'(T2-;(0QW
+M.A-F,:>HO4SRC`2SXI$=KM%(,6UO%%W9`".-O%N'D06UO6)>:B*V0ERF#2CG
+MZ.)E@P7'P`42O?*".LT_U;ABN[SCM#<'LGHA`&9D0KG\0&8-##D+A3LDJD_J
+M.$8[/%V->H5#KX2$I8G2\<["(I@V]*`)<YU,(!3K,*TKE6ALU)0!S<VY6+ZJ
+MFK.T[+"UF.PL*;0>?%.%241^`2,_KJ$1"E[([T3B@:C#2*XP60K"UA%G-.?C
+M>;1_2D>9:%*NCT327#$0EZD]+]RG[K2),(8-QRY7HG.(BTLE]"!!]X+F2J3:
+MC&:[^.*J5;O4DM`CKJA(M-!)RSAJ*CE_@ZV,-B>9'_S9AS/AME1+WM_JX%F>
+M5I-..;$.O69"(S)1":K)^%ZI91NBAMOUR*<'!9-5L7AH*&Z0_(C>)O-0AZL,
+M052H+GDV*Z&$+`-PEJ'=62@<T?U1ZE^B$5J(WY]HDM$(3J.#(T.^^4R,S'K4
+M_BR_]@:'&`ID$;2FXS90AG48$5J,$8DVSDPB:X+[SK1>2F3GRH1-LT@YHPGZ
+M+1N0&>NW@SG^.$6-8+MZ,I1-R2"@%W`R^>&%.<YG7Z8%,F;D9UIV*4E<:\3$
+M<OXSIHRN<2V58%C`?--T?717O9ZCS8-*3'KC?3%/,ZV%C#B279FQR$?T'GKA
+MS-R62PIKVZ(7'V$B@=/P5!OE2WI.SXS'==>;8TP<M6/#OGQ\4BB^E!BA'T)_
+MY6\/9E,)_/4S"$%'U,OG#F9108:I*;W2$TK9""&-.8<1HBUTSRC,[<T:NBMD
+MB-B@7V=(C\9%IJ[\-LMZ+`AQUI"=;;Q_(8"-.2E.A=)V&&ESQ]AQJ=`@PV=M
+MOPE'KWW`M@.Y>)9#2&&!F]&2,<LV&V';[I".=.C>HZ>&,'_M*8WEYTQ[NCVE
+MJ_^:A85.O?IDAOM$4\:835-AI&[2&Q\1]Y*G6:W42P`TOI")M`(YAP&>=)7F
+M$!O3/80X^<7#-J>P-)?-3X;Q.3I^?N*A>US)8JD-8S'0R'`G#DB*[LZ6;@G6
+M$OJ"WRQD2L,8QP<G%,[HM58]+>$R,^H[8CTPTN8R>K#,F'@^V!R6-N,8;N:.
+M.1T(Y9)F7+;EUJWIY!<(]"JF*FS=9</QN+:N8$0FU9F`S$^YCX+<209:0[&V
+M3-CL>V$*S%5;L[5D)\(V:,>`9>LVZ=#N6DUC.X6E"2F?[6AF,+,+MXX."\UT
+M![U#`EP_%\)MD!/5;:*#O<("8L)ZY8Q>N.9,()Z?X:,HKC5DJ9M4.H`A2>E%
+M*SL,(\NF13"^V8F9;7_M+F#79I+&Q3>[)6$')OU`67^5*9MY3BQ96'/+FUU&
+M[\H9%V]MS10J;#JTZ2IM9M_2[+[Y\V$_NDI4UN-,V"11$QUM/C+@Y-S,!1,M
+M9H4A7Z')G+'CF,-M/;MIQ2$3`W?`!`GQ)KN#:+P3C4C'<Z95]$A<PYZ=,+.&
+MYH2.N$<:!^)VPM%"\P;U&&1BZD1A]\PL0(M#;:-QRRH*]UN;"XM*4@^A<%!/
+M&5"U;3*15?X63$S345V@3)MKE9+U82Y0'['"4&7CQ$*G3K5(3K)!3.VD72/!
+M9D99>CLGJ2<$F&YPMBZA2B;CB@W3.G"PYF+67*6=S#39Y?!0?]K?F>Z/OB)-
+M('XAC2#;U/]HNX>4WSYV,MS@PFQ)3\XY=Y1E!1TMRBI!1,;)3O-8AB<EG3/F
+M<*O)X?IL?@W++`88W^DW?L:?D9PY-'V]XEM8$F+LKRU79D%.5H_PLJ#M3R7C
+MG73I68G.G>:PL3RGW>95+Q')9[J79DUUR20+OJ5)G+C9%W',2A'<>K[GH4V3
+M85-/4,:H`1\WF=7N_$Q&-E#3W"E&.O-IWJ2B;KO.F2A#GJ5W-60#QG@,Y$!F
+MQ:A2Z\4232AI>U#OA*,1N&X$.],+3W:CRXQ\9FB=A=P69A%%=F"VPU#(>$@W
+MC^2Y3H^$J31W[:,<3"*%,((KQ*VY%$9PB>WDMEIK4++YRO`*_Z,C2F=Q]$*,
+M]6G:TW!A(+]-@4;A,F+,<=)Z<P*M:<T-?<)$%7H(-FN3JC#C,8\VRVLZ%FG7
+M8R:WS@H!OEXO0K:X6<;I:[N$5GDW);O*\,D1!P(.%+H9]5J,:6Z4A>.W"?.U
+M_T'<H)V@72(L;$+HE%)KLU-)/52:E4R)\-Q'$8+^-KW"!A^;Z1`7QR,IH2;X
+MPICV%OJ00"*-H;,&E9'2M1_):NN&/Q"O*[/3)JAI8QNDTJQ_&&!'VIQS,9M^
+M>8N.T.-%N'`G6V(2S=MN(6Y<CWNRN"K%T(45*[0F%@G#D(/AHH4%^4<'N26+
+M#8BK9F/"K"N1]B^+<5%=I,*26"1I5M",Q\Y9ZR[LJ,=#NCPZL_@;=P_S9G\'
+MDTMZ^OR9BX*U<;9FXUZIMD0@T]+F<BZ<*\>B=L,T/R.VAPXX/''\DHF8#2*T
+M)^%<TJ'52-7K<$S/7YIC<<S;3"G;\T.%;(YKD6-GS<85<:4@8OQ1HB42BZ24
+M'3]-A;3IB,18G@Q-IF[B:=,-]*JB>PH?C><X8Y.3/1QJ(L;;1##6VVVM2)2S
+M5MW49OZGHQTSU^)^6Z));UK(*2/%Y77]].*E3KN9@_XOIZ!29M?%Y:+-I&N6
+M66N*(%XWIUVX%-NNPQ(;Q.3LP9"$6>EUY<\?R$AI=%/IE3DI&6U`5@,Y[?/+
+MKD;&3HZ;,HBK,<38K6W.VF3E0/R_V72U^\02122S&/)2KH$TX)[:P[+<4]-,
+M.%M8`&R5<T#1C+21.6<C>6_/8&K,B:'4>;MV.[H6==\TBYEZTF6FS'H.J.T?
+MC2^#<3ZH3G(5OT,/5%%7MS4+K'BXHRNQ4-GZ%(_>1]"!C]F89]G-\^Q45)<A
+MEC;;5HXQ;>0?@W[>F\E*D)Z71DP7CKKMM*B*&/<B/WJEE3,`QZP*ZB<QDA+-
+MMF',MK+^5&?#S#Q@^"Y+@L,,YSN(6>MK2<HA!=AB/-9D#F3)S9SN8Z")['1$
+MS$Y&5>&,C%-T@LUX:IAJB%4>T/L%^O",=L=M^3FC7G/)3U*R:7L6SI8DRL"?
+M:Z]^\?/:)^I,018S*Z#2'^-)VP$<<TI`SS_UX!'0!TD0/!HG?QJZHE]"X0F!
+M:$SGWBQW1\P(*-/MN/$P"7U[LVWFHH@HCEY1B$CD-!FO\#1H3>229FLH%L50
+MD>W4'2ZN3SWF%WKRW0%MK8L*2Q5GFS!U8*9,Y@@8P^QD2B8<NBSZX)1>5+*+
+MD=H$$DVR%N).'I0CD-J%T:)-U"HS#^Y:.':?V7T,Q<1D^J132A^#2"61E6Q&
+MJK*%)R62=H!I*^R!1FCFVE4&;.B67SW-\7A/),1#"_!N.2>M/72+WGZ7`RAF
+M;M%F=^]0/V98Y_#OJD#36;A,'S8K(<'FA%BUKFQ=HQ+0RU$B8P!!XQO-_!E>
+MD2:FAW.SY,#Y/O?RW*>9(L&D9`2M:Y3(N4\3ZKJ/DR53>@X;,6MAX:0]&VFR
+M'PB*!VJR4;MC9Y\\DAAA*[")$9043K[D;`>0.DWHT9@G`MUG=-VG7XL^B27=
+M'R%BEI4S&>)D=8M.@,?3I#?FS_45G<5UK7T[9I[!Y@H%$".;,R+LL""[P1IJ
+M,H4/Y=(F^T%MQ;JA9&3FVD@RI$$?#,Z:DZIQB;(+2[>LD<+NNED]H"G+$D(P
+MEFX6MX36U<-_*-QFNIF80?Y<LHGU(_D%T4[M??)+;?9<%4W$O8-5Z:24^U"8
+M7)MME5`L57I163C?E$H[*G\R6]+)FF,VF"[&2KNW@NG&KT@1'H7"L]M2.:<D
+MP?@15<67U<67-<67M47*=;2+BR*AA"RE,AF:9<W9G\UTZ@^<&$+OL"U"_BJ?
+M';>D>B=)S4Z2VA*)''A*.NE2*08D678)Q$L_$/\8AWV6ZJW;25*_DZ1!\1B.
+M+8[!?%DR@?;\)QHK_68A4#=MD=@<9$5G:Y,!2I_-2270.\1!B0Z[<U#"E?DQ
+MV"V4YQ=?5Y=<UY1<UY9<UY5<UY=<-RCW7D0^4X5KG8="QY$4^06DTHM*OUX7
+M3::DMQ9_<-JD$2.'%\L*BO."ZE)!3:F@ME10I\SF0-X:BR\K[3'2?)/HS]F@
+M+D;">$P.+DB+NN62S9)TYAACD<)H.(DY5E"4YN?-I1>5_OR5?LK.G^F/BA;L
+MB])(5DH$U<IN!VL#->OC&NU,C1<\\Z"ON%PJ;%;S=;OKH5U(1\H"B*EU^O9`
+MD_ZK#UF2Y)E$3'9(07YNUKR$,,#P,SEP1,RF6HJH4L=4E36*!Q"LMI0I"O>E
+M!>TY<UVU30[+C#EY$9E^Z[JJ+KJJ43S"DL]$JZD*,^*4L%96?%U=<EVCS#Z0
+MOM-2)484-`$FARZ1$TX774=0Z^[K3,FUV6=S)]#K_;)<5"K$TW:2R7EOETR.
+M:A4_0)?-=56MKVPY]$TZ=,_O%YF/"A?H#C+GK6PHD2:#E8-*1$T)F-S@7[V[
+MNGKGVZMK?NW^:C@X?9C<&$8FJDU!PF?]ES9AC[>R@66V48S&)MR7-<67M<67
+M=<67]<67#<67@XHO!Q=?#BG)1E7)=4F^JDLR5JT]H`EAZ7]+R7I67OG3<>G8
+M=44)JHNN:A0KD+M\NGMA\F;^RNRGB"KSR\15Z+3<M9,4!:R4HZYZZ<-^-\)\
+MGG1?Y&\K",T1HB*JE(5^8R=U;BEF%I7U+H&4VGU5K;A!0&U$FZYP65U\6:.X
+MQJ?O"Q?K#Q<_P'U94WQ96WQ95WQ97WS94'PY2.6_LZ7MUE:4.5J@O74NV\Z_
+MCNNOB1C,63N*@[2-=OYU7'\K]6I8.&2,@Q)4*H_L,Z768-9%-9F3&QK-*5N-
+M>KU4D_[RCJ9H(65>CYXS&#(&%HS+]J$V,)>I\-L(%NU-+I8X-9-QBD2H]KI2
+M07VIH$'Q2#H5$N&,]'&NL%,LE"E$D6C\D.JB2_39(26"FJHB0=V@P44Z,07'
+MC$"O\$L>.+G33:U/X`LE4UG*S'JP=GCZRT[:TYF)$-%*8WF5[F]*_,JUMI/\
+M8;Q\`EZX/PVY/W7=:Y8C37M;+/E$=Q%^2X\)0\4)0ZZ$A3H(%,H6*)3-?(5&
+M4\@2MSR(UKCMN0M==S+SLZ"C"?T=50M:POT23*EWNM(9+9;X4QCL2A-5ER8*
+M5`[9*5'-3I+:G21U.TG$?(/:.<MZLNNO&;SS7.WB&A?7NKC.Q?4N;G#Q(!</
+M=O$0][.*'NQ^<K7[T=7N9U>['U[M?GJU^_'5[N=7NS-0[<Y!C3L'-=6*!QUT
+M2^<1;26#1)U;))56=%E=?%E3?%E;=%FO+ZVE%+#2'%EP"V1;9R<I'^ZVFZ++
+MFN++VN++NN++^N++AJ++^CHE"\$VJRZN'%\SJ.C:WQSNT'.-(B%KKG#P6_L7
+M]_<^\@)]\ECWJ+R;;G;YV_JBJX:BJT%%5X-5T8:L':CRYZTHT-N(I=?&928"
+MP8P9</)+=Z479G)0+*@N%=24"FI+!1(1EBP2ZB?]BM`\\=<_J/Y?']3\KP]J
+M_]<'OYXC1JN_^D'#__I@T/_Z8+`RJQG%A?X5F7$JN:3^G'^-P\ISM8MK7%SK
+MXCH7U[NXP<6#7#S8Q4.4V836]I]?4==7%B+V\W`N6/A3.;ZA0>E3.6;<<?3H
+M94X9:Y-#85U_3;B=Y^H\^QW95(^'71_6N+C6Q76*^Q<<)_GU@$H[:AHL),EO
+M#=*Z2;)OH^_A/,@LQ0OY7<G-VKVY,UQ*E?J010AQ?;*0+E'`N`O-07;!605I
+MJ(#Z*(0%^=L6<PI_$!95*7.25X0Y.Z\W7X`MHDIS)JD9FN/AC%LN.X1ZEU`?
+MP=$W):WZAEK71=T@U\5@^80.Q)ST%^+Q8J+]O(!ZRN&^UC,"]R5F!#S8H.\L
+ML$GJNO8']?&'(I&`'&PMO@]CH#YCHEO)G&@MQLKQ@^J5^ZO>^F-][IL4LA#,
+MQDE<O#$[8,4(?75%E]75U;0QQNGN"^M.[98F/R]\B\X($BF::CY;X7QN[!==
+M*SG5"<48ZO,TB;Z0(R\"Z7:]3U&,J$[YRB[&*[<LW:Z#P_HB85+&M0:W2$^9
+MBE1%H6I(D2R:T:JJJW;6A<KAH5Z=ISP:O>[+ZN++&I6VP:L%<T_AHMI]44B/
+MHL7,=]/T&;%*'=[F]U#UI7RJ(6;6],PF-RECXDFS^4AB8Q2^I;C3E<Y<J03>
+M+I[2JX/\:[PA67^-))`)NS[4"P]F;ZC2#-_YBTJ_?H>!E.O7Q7*J8N=/_"UP
+M!O_C+AX5*?J`JR,E*?5IKF*QW!]OD?.43LDG:=WR@QM*%=>6"NI*!?6E@IUT
+M#"H5#"X5#"D55%?M)*G>25*SDV2GW%;OE-WJG?);K3.</UO`-G1?(W9LT>SL
+M_$DPQR,).WWRO^XPAT!V_H![`R4R721SLHXYRU]4RN'>2E-$EU!.Z%6:8A:D
+M-!&WH+I44%,JJ"U]7*1$,#N0UEO@)??5E0IT9O1&*LM@N=*O3Q04B_R=:;-S
+M6RKUASN"\9P3DU<R%7^6;O>'FG:6.=EP.HW*EM.B.WTH7WIN#^TLUR_#*7VT
+M[*COE+(E+%\T+)*SGDNRK5^6$BI)6%UR7?-K^>=1XZ)/N,)E[-:EH+;DNJ[D
+MNG[G!^CO\.K=X>*/_K^O*UER'#>B^B*$$MRDX\1$V)>V'?;,R1>%5%JJHE6+
+M)57/M+_>S,26F8_E2U6^!PI\V`@22^+R_L@[?`S_NO\ST-9R4MVB2_65%^:%
+MZ"Z]W$+G+KR=[OS@Z2:GU:?-AV\<=G>:2R;T/7`\K].G;)@+O]3%9*;AUUXS
+MI3`K)`NEQ.KZVAQ=6?>+,.75,P\A^P">DN!%*IZ7CNF+7Z36J,FLUU*$5(38
+M=H)<7;57R([#M,$4(NR0ZI$:D!J1FH`:MGC5!BFX2J6J57*7.4L9MI!C!%E6
+M>AO'+20[/8KS<L)<*QJ:&]4;#XR'N,#SVNS0^8#Y:@F0>]5Y3V6'XJVE7"(^
+M/?)%=2:VXE99?4U263GGX_D#.?>$M8%R*Z1M+?/QM2>>K\2^!OL*Z&N?KWJV
+M'5HF;4>_NY^-]J*TX%T**RXFJU6S%L2/HC@`QX^B^'7\T@K$!4TNFF+SX-;^
+M>+JEHJUL+C"%R>'H<.>PCV]P>'1X<EA:9/$W440W&,017YBBYV7@/`USG]N,
+M3S6IF7'%RQKEU;P88?=M+LJ_:T+ZH[X1$EL#I$'4H-/`1#!H,&HP:;#18&MN
+MJB3L=O-+^-R4','(_,0():.4C%0R6LF(G=\19&.`Y%GR(\=FF8?*_R6/FDW*
+MCLKNE-TK>U#VJ.RIV0.MV(G<=7\XR0NV!F%W_,Y#4VE6RH:<[U^%,)J+V9"S
+MW`&8$9@)F`TP6\_,+RZ>(6`B,!TPH+D#S1UH[D!S!YH[T-R#YAXT]Z"Y!\T]
+M:.Y!<P^:>]#<@^8>-`^@>0#-`V@>0/,`F@?0/,R:TX)*J9/5G&O7@>N6(L[[
+ME^OG[10&S7*S,9`LG&7*.E*)O5CI5PK1*KL#X,N:R:MM^'U4'(I)4#8D`@5(
+M@ZA!M\H[Q^3G=42J6BDFA<B@:%"GD.S9D[%#Q?$Z'%F/'&2:D[=>&$ON5H<F
+M\\:K8EZJR8NULYD<(#)(.S!SK_+',1LM7!;>L_%V/+RJ_W+/Y[8$I)E<QA\&
+MWTX/]OTF^[0/GW*SZB""05["'<K(;AZ;?2V#Z++-+Z2!S'(_WI62_HM?$S'%
+M]5-(,RN/O)BL;@4*:2B\[)\7F'V+)ILWL>?L:=E7MRQDG!TE%=2R6?P4%7!2
+M^7]2!9!]S-7RJ"%M&"TYLLB6BJ=%(ZN?DUDD)T^%8KW6$5'VQ)&LT@[S$NID
+M)N>^;)?]B&PGKU)BY6V+(8\8YG7>`F6+'UMYB;N8I432GA2QLE-$L4MAOM8?
+M\+:29/"FK&1E]=GQA)BM<J1MVLE*TI7/705E=W+!LCFM`-G@)]6^KF"\U.*^
+MF.*]%)<7!=02OMB2O"0'NL7,C>S2MMQEF+82!?6M4+Z3+_77R1MI`<_9.#6!
+MI1J<6Q4_ZY)*>SZR]9KRMVR(SG;.XK1941Z@GQ\Q_Y<6+]ZJDY7CJE&IF&I$
+MJF+PIH7\_Y0;";L3/'Y8,Y0-SGEQ>F;+"NH*R<)H86=A;^%@X6CA9.'&PJV3
+M(;)R$D3^GSSE?*^0KY:A!%G"G7PX2!.2'8]S&X@5\0)@#]QZ[L:^/Q8#\A=)
+MV]J1ZX8A%J\J'R^>C"O>DRCUXSVMX_W'CV)EEW'RT)`1\DS6M;7*#KM?BV-L
+MF<S40?*JY8B-(_K.$[TG!D^,GO!WZ>$N6T<,:T^0)Z(GO-+!*:5HB=WGG3_F
+M%S(F<]SGNR@'=]V39"Y_(B_\7@;98O=5T.[7$'UF#C[O!I]WPV:57#N57DBL
+MD/9MR<SO?\K:6=X_%Z0SUXLX%<@;2,3W8UL&NK`*5/9EIX=<6\PHSJR%K.Y!
+M`86\5,PP!$P$IELU)W$MUB/$>H18CQ#K4<7*<V7I<5XMB4TC,B@:U!G4&S08
+M-!HT&;0Q2`;SLA^WTNM5%(HC#C/VY,//GC0#-"H@/X,,0\!$8#I@>G]+'OS9
+M+)`\^K.%GP_`C,!,P/CX(?/:>)?/HL5L%<_LIS3#DMT;A/(^46%(+IO/GBY#
+MYH8BI")2'=RBR,;[+K-5>MXG*"\`U0SB*BL_;/C#JH6D[R`%R<)H86>ABVJP
+M<+1PLG!CX7;^M#A+/YS_A]UNMM*F`GD=EG,E7O>7EY#?CS4A"<G^=SC\U%:N
+M[.PBEOPJF'>^Y_)]JE]6R2JE^;0O+XO)XDZ?CQ!!)L]G%_(ROQOX*TV<I7*4
+M'WRD,>8"^1--P?N5G8;I'T>-XC2L\GJ.O))#_.6(?QE-R-YGM=:CFM3,V,QN
+M59REE<SKV;BJ=^#BTS+D%TC>TN3L4!R0W/]8_6A=1C/#[C#7W?GIS/M$%,UK
+MLS6,P];B]=KBGI<"7<KB=*XB8O"GK+PFY[WNDH9C'AO,OEG9S!Y$M/RZ]\L3
+MH>S?2D=UW-(+>?9!*_=*+@NL.9>KG$?R-%=IQXI7N'QP0<[;YDJ2B7J`BP>A
+M[BR\))?"X?[NL7N%-0'N+;:D)<WFS&6[/]X6<'IDOCREHWKN7P<?W].CS(2J
+M^2=#TA(9OXX\^=V`WXP;Y#9E@DH\:K84%5@F(4*]7PMY#G7*JY&I1PWDX^7N
+M5A83#3Z@S5*JJ-_O#]WQV.L)*5#7)B$5!:+:)*2B1J0FH(9-I9X?.M^>'SY1
+MSP\O^QGF;"O'I)GU,E%$8#H?0>DDW8T6*,C@XYNI`0FF2[G)_=250`?F>'1U
+M4,%2ZKT/T1E4*4(*[JB37"F,?II6VH],3E=>P]<:KR$66N\7X:7YVN#2?H&E
+M13;^GQO4)NQ^E=JP(S?RB70_?:A$Z?:LL33;B&QIMQT&Y8;;0T@N0Q>]--WY
+M._V^'"8[!K[X5:N/[CZTP*E$U!:H8(KS#*QN6SK`),8T64OYVY8*";?F3^,E
+MWF>."EHD;8:9B'Q^M0:L<=C]<O]^.O[E_?;7]P<$FG3;ENBXN,!U"UR/`FSB
+M-&MR20=\E;HY5'*0YQ<P,#_0EZ(SV5@O'Q>X:97\S<K+2['"[MO[Y2_\[FBI
+MW]BSCJ5^WU_\[_9/+U=VEFCIO[$C0$6IH89*YIW>%9%!T:#.H-Z@P:#1H,F@
+MC4%;+3![0SP=K22M</>;F+]P=HO;%<[%8O##Y/5)07ZKWC3,R5,@:M!IT&LP
+M*-"KRW@1,:]>5I>.&DP:&!5;(VEMD(F/E,2=&E'0EQCA9)338)!11T8>;5RN
+M=?9BHS@:Q='FJ<G4:,1%(RX:<='<+QIQT61>-%HZHZ4S6CI;P$9+9[1T6@MM
+M!W[7_RG]G7%)N$2$ZM\B#^DK.^S2@/[=D.X'\C(A.'NT47;8)7\V=T/6",`)
+MC6&+%QKEK+U&_]$V`<N\JN7J#31%2$6D.J1ZI`:D1J0FH#JXH_BI+F?:H,"%
+M6"-&RS7,QRL?GB5B??0CYZ'#\Z.`C9B<B[SE[2L:A.:PI#+UH,[B""4=.L<_
+MK7,*A^P&))V9PE8]`L"#N1J\7(_[P^'FZ,OKPS'7I^OKZ=627.:.($]$%P]O
+M6KN>WBZ/Y[L+^7G:WY:#N(J`FMU+.D3(7=DO7/G[O\4EE0M@=/\\./KQBEF!
+M5\WDXOTY@+,I._&7(JWFG-O'_<^TRFQ^2NL`SI7$=X8OG[J]9F5(0T/*^W;X
+M=JW1VK9IFV4^X"?(Y,#I)!\CY^*XH!Y/YT%(;ED,09Z(GN@<T4W^BMX3@R=&
+M2^SV\OZ_\9=!S.F*?`A'24Z#H6P1D_92ML!]L0-N80/<!39=O8C#@;K3J\U5
+MBV]ER>8R;W_()98.FFW]Q),U0W&B7CR:W=J*.#FL.#GB:68HSC#Y!\D+4QHI
+M4G9(WIAWQ_O3[=4$?.N'E?7C7WYJF#EOV(BKYE(P/W/:T^>I9@.75L[\>[Y2
+MV7-<%K9W.D/_>#*X5,:&R5[_3WEO-=2_@"H5MN'.X=[AP>'1X<GAC<-;KQJ2
+M09[P$LEK)"^2O$KR,LGK)"^4O-+HE4:O-#JED[LK3>D7=?V2!GES7V])>7MS
+M3+<&AH")P'3`P+VZ`9@1F`F8#3"@N0?-/6CN07,/FGO0W(/F'C3WH+D'S3UH
+M'D#S`)H'T#R`Y@$T#Z!Y`,T#:!Y`\P":1]`\@N81-(^@>03-(V@>0?,(FD?0
+M/(+F"31/H'D"S1-HGKQFG_&IA8'&"5(V0<HF_!6D;(*4;2!E&TC9!E*V@91M
+MH#0VH'GC-6.6;2`1&TC$!A*QA41L(1%;N-<6$K&%1&PA$5O(^"UHWH+F+6BF
+M-8BF-:BF-<BF->BF-0BG-2BG-4BG-6BG-8BG-:HG5$^HGE`]H7I"]83J"=43
+MJB=43Z@^HOJ(ZB.JCZ@^HOJ(ZJ-7W_D^,C7]B/HCIG+I*DPE]L*$W3!A/TS8
+M$1/VQ(1=,6%?3-@9$_;&A-TQ87],V"$3]LB$73)AGTS8*1/VRH3=,F&_3-@Q
+M$_;,A%TS8=],V#D3]LZ$W3-A_TS801/VT(1=-$$?W?D^(-76A>J$G3GYWCS_
+M%E.%G3QA+T_8S1/V\X0=/6%/3]C5$_;U_J58*"PY[.X)^ON9&A8S`]5B#T_8
+MQ1/V\82=/&$O3]C-4R[CX@6PG`/G[+![_TQS(_/7I>:_S8]0<UWQH67(Q^M'
+M<E)9ST*7^!4(NT-ULJ4<E.636?CJM-DAW--*?SYA*\@Z+?DJ#>ECN_V3[VWQ
+M/5:)I]OGD1^U?S879-64);%UD$;987=*GS^:2VZLRL%3H7Q8%Q3$!3V[?OXC
+M?V.K1:/Y:*R0QW;R(G<5W+[$V<6(L^>O<CZH2TZ&TG3Y[&Z8'(X.=P[W#@\.
+MCPY/#F\<WGH](-`K)"^1O$;R(LFK)"^3O$[R0LDKC>M4#XUKMUK?Q^1]JRR5
+M:[/L>>7<[7I_E()\E'W;=J--.BT\FV_9H3/7H&:E)>E\C@;_;]7C7`<(+]G'
+MHZR:2HNF>"2(C3)NG4]"L>;<8N.JG*!2@K37'3[Q0^YPK/<Z5G<[;^^R_[9?
+MY1-K2@3)Y%5EJWQJ20E)!PH65-U1:B"WE:F/Y(U'S@V1&VN7WK<:*1_X;JRP
+MNZ8C-]1.$'VCS\?+]=ZDUEU=<BQ]W@2C@0@R1%KI\;CQ\T,"#B\77J0[__!X
+MJ'^#',O%)RX41\O-7?&ZVOG,%SGBPG+Y\$5+GH^.F//!,7S<C67X,"''\$%'
+M50YWL0W,74P^FH,U-U-D&T@61H;%AUPY0HGM=.YG*HFW1W%>?C^5!1AYT?U3
+M=7JF_2&G(R)KH5S?+[&"\V?:AZ7!_*:R=D1?BBD]:6=IN2&4U9<EL?D0<[F(
+M>PLV?JCGL;+G+NJZ?_M^3PLM%<V_2\N:-,UY9S$Y'!WVO^\='AP>'9XLCO,W
+M1#ZW4HHD'9HG9CHC2_*ZDB_WE[>267(.B[-ETL[@^1758/YDM,3\NI<.FZQ/
+MJJ.Q@AS9(^\+BOM8#^SC0#/#7<.Y^A@\-T9//5[>?CHN]]H5D4'1H,Z@WJ!!
+MW^>6YH+2OAQ+[KZ'M#NG_G(T:#+(7KFU2IUPJYRL=++:R8JGP4(CJ9^_"O:'
+M/#6:#A"6.K+_?BJO+"]OQ_.'L;(O)O:=(`]AJ4OYT,]P+QX:W_,&T.H?[N6^
+M?]0+]D]\[!N#[R_5E5;;=FBG/?@,A]O[4]DV6YRRU[-GSG_LKQ(B>Z*3$]1F
+MBE^87?V1G)`M>M[S)M'Z#..JG'JX:LU5>M!H_G8Y/$IO5T]JKC\I'<T,:A=T
+MD&6;>;)I?I;^.-W.\SMN>4KEWNCUXSUUZK7YU@7992?JN3S*KF6N\+4^3:L5
+M),;[?SUS^.27:<VR*Z'SJCT8+NV83X:[G3Y2([^^'-CG%1OY4&9KI@=CD.5%
+AQ<-AL4)>KE30_(&4[I#+H+Z*SX^/XNG]?[9W/ZV1I@8`
+`
+end
diff --git a/lib/compat/compat21/libg++.so.3.0.gz.uu b/lib/compat/compat21/libg++.so.3.0.gz.uu
new file mode 100644
index 0000000..b378641
--- /dev/null
+++ b/lib/compat/compat21/libg++.so.3.0.gz.uu
@@ -0,0 +1,4253 @@
+begin 644 libg++.so.3.0.gz
+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
+?`?"FP!6H`L>O3RB,_[7!^Y>A^>69_!^!7='O.8P'`+"J
+`
+end
diff --git a/lib/compat/compat21/libgmp.so.2.0.gz.uu b/lib/compat/compat21/libgmp.so.2.0.gz.uu
new file mode 100644
index 0000000..520442d
--- /dev/null
+++ b/lib/compat/compat21/libgmp.so.2.0.gz.uu
@@ -0,0 +1,426 @@
+begin 444 libgmp.so.2.0.gz
+M'XL(""S5R#(``VQI8F=M<"YS;RXR+C``[+U]>%-5MCA\TI[24`()&*$J`B**
+MM>A01"&*T")I@2&05M(*BI6/HC!\EAQHF:8MA`"'8S#J@(XS=\8[ZKW.W/E0
+MKPHXX*0,EQ9O1P-V%)U>J=S>\=14#4R&!FXN^:VU]C[)25O4WWO?YWG?/\RC
+MW6>?_;6^]MIKK[WVH578&10"@B!8!/JU#A2$,8+N9\C(R(2?R']9O7X#ON&7
+M_;_\&?\__KGD_RJ_7T5"/+CMCW<](0B*RZ@X3(ID\9V2!BA/YT*)[P0\*59\
+MN@!/_XJD5+PF^"M;%*\14Z/B%3&=Z*^*/?CPB3\FR0O]5Z0&^/->:.DQ*I*I
+MO$*]"!GO<5.YM]E4H79"QE\5??#A2EUCUM[;;=1U\11U85(:1-D3@XZ4S199
+MBOL2TJ"#!JCQXYZ$;(]Y/3'!,Z!G2:QG25R18C"DO,6B2'%YBPA-;#U2KC)<
+MF6]4BDWR`*78*A<;Y7*3/-\:=BOVN"_HR>@Y+=OCT,R6[<EQ5JCE".HQHX(C
+M&FWU)H^I0HYX@R:G.@U*"D[8'/'Z:P)0IA0;$;@*JV+=(UMW%T%!@XKE,:W<
+M2N7&9'FL0?57=2?Q)GQS=?C^PL]X,E=4RBRR*ZZX3,I6]AP#QF3+L:XOD3,)
+M]P"YI2!6FR.W=)V!%X%`0'9T*_9NCDZ3'/,EZ*D9*&)X5W'%#9=DEVK[P&V6
+M(WFA.^S=7?_,VOG%-W#PO&-R551QJ7YQGY:-(+S6!%#494I46TL!L$2U,3PL
+M$."/R:*$%%4G^I%J5OFXS1-O&):0XE3'6D$UC&$+?T@6)*2(&G^<M;&K<B3?
+MKMHD%60%"K"_TUCFZ180"W]5.]$L37XW0P4D\M,HB\H0O^C'`F=BLU')2(3X
+MZ_FFU'LKOD\36:+_-!W]QT*??BE:KN[!!X]:H6[#!WN[4ZVAAY!374\/QYSJ
+M2GA(2)8$P*R6$29C%+L)!46Q6S"I4.^AUR:04$.#$:3-.]7@'NZW1YW0B'H=
+MQBJ$+0'M38M"T@>H4Y,(-KG.;U>U3@F&ORBLV=6!@/[UXZPM/F-?!.7+2E\0
+M1C`0+#3@$[ROH8&`]FK6E6$P)0>KT,.0>FU,AT&Q&VGJW*`PJB4DH_I?>XCM
+M(`?>K1:<NHLM/8M%@O;\'D[EKCV<[AWTH#K5#^DAZE3?Q8>J@WVT!^?G1!T_
+MR_9P?KZUA_/S5:W?E[61?@X/G(C$REV4-[&\I4+=0M#><F4>SM_3FX?BGK[T
+M&X%($(%AS.OVI-,<7H7D-+HAG;Z0^[)N)(Z<Y'F[ULX4'A[0R0*\;Y2_!0^?
+MEOOEX2P.BQ0J]WO:*S0>+H'7Y>H"^%NASI$Y6PIESI8I^%!U3,\6XL<#.GX<
+MW<WY<:O6_`:9\R-7YOPPRTE^<)C*U;_M1H!&$B5,C!+F'6]#GW[7,=D5+%,_
+MQHY=4=EUN$QQ6;Q'3;+K8)G?U2Z[7B]3?[,;)^KKP!WXJSY#N<.@CJC:*V5^
+M3ZA"E6F$6RJ(Y6[(5%"+H+J;58='OZ26JZNHWCC04D%D49E6^@IV/0MR4'*P
+M0KV;5<-.-.J-IJI!U4Q%EK`3:,Y!_7492@Y06KVT"Q<`!MG+92@;P`.U$]Z6
+M5^!X6`[])J1?)Z27M9[_C5Z:B'JO[M+D>Q>G\,]W<0;MQX>JG^H8U(<_8W=I
+M^D]KO4WKKV:7IO]V]>7/_;N^@3]W[_H:_@S>I>=/S\[^^-.U4\>?MITI_D1V
+MIO'GQ,XT_KRV4\^?%W=J_'EN9Q_^-.QD_%F_\VOXLWAG?_R9M5/CS[*=_?#G
+MIITI_@S=R>EIW,DIG/!Q_ESP]<,?'7-\/F8,@7$#MLH43S:85;_RD45RSC,"
+M+:V27O;(N;HNLH;$_HRM_NRML;Z4O14'DPN,B*R>,VA[,6-HNB>[HER]DPT*
+M9LZU`;T=E&;G*!XPQHQRO:@S>&@\43?>:SMTXREHV<%R_PFBMP7,KG(YQN1[
+M!T?R6M1QB&<ONTK#T^+UQ`5/9D\E#!JYTOJ@QW?2CF^#KWW'_W-\*\J9"1R0
+M8P6G>B[('X+M9I$C\-PC?P`6MBK'PAER!,P2/8U,.ACW>A%&,&A-O@M(':_'
+M)$A#_X#V+PA8<R':.4)X)L#I3R3`'HY3[V#^'J<AX:$9ZBF%1GDB-JT?PEIA
+M^[`)]3[FH&6":EGEJ?3&@N7^*C6-BO^OX//V=K3;3(`25.^#Q^V`Q[YOPB.%
+MP=?#W(??,[=_$[]S8'S7=EK^&,NO"WP+GFM;DUAOT<W9KHE.LA]KKST#]1.C
+M?BSZS0&#/P7[SFUD[S8/(+QI1[9:5(1$"#8TS<5$O>9B4]]":[-@H#).GG3[
+M5T><FV@`4"Y6U&0QR(%F[]J&6M%87JY^N`VIDKO:4*Z^2(]&7[#^SU"6D')!
+M$[T"[U8;*M3=K)HOZ$;+6,M#76D@[=G"18'`V_A@DT;6WX'VCW%U1D6%^A@-
+M!`TJDAV\A_U-U=J[!Q1#DX;W"H));4;\+=2AL*R1:.3W1"O4YD94RJJ`<&56
+MJ)%&,CI]P89KL-M/(0OP7T\P=7TJL+T0JN'?447Q98-D+`AV-6,)K2Q;&A%!
+MK%*N_J21:_%EC7Q57(2CD0F+]9KM080(=@1^Z5@@4*XN3G9Z5<(>!!J6JS,:
+MF>UU-A"@25!PP2:9ZO-A/HW'Q0RZ2MGQJI-`FW<YD;BA&8@#E#`U_)F6CV`#
+M7SX.-'"8?MO`87JI@>]4?@H/<LQ?]7HOG0CTV];="(/K2#@:ZC;[`I<3]'L;
+M_S3['H<LEA.@S;X?038#!<UALODQ8]X51]GR/0O/LF\W_`TH5*OG,]G7"*GO
+M%+,'$M25XL>_%YH,TI(*O[A9\6,+OVE;::DJP_!_$(EV)H4JOYPI>9`WILU\
+M*\>K+S1$RPPMSC+U>+T@S(?JAH2_).&C-NZ3X3G0IMCV!B+B&>^]/*I^@&J'
+MO@,5T)%"(/K%W4XUKP&!PEIA:^^RK`;F"#B"F(2-,'^/("X)PBR%^\ZA^.Z"
+M9RA9`*%Z:A3&^8[(^7<059SSL?!?J!`4>=U8_Q%\C?MOP&L7%6.-BQY>P_-7
+MA8"'NM?VJJNV4B5Q?NV7_I?<4/+@E71MF0>99%1J1:74B/X$R=3T998O46>S
+M73;[IQN(A=Y/1Q]$M-X/WB"^AB0,U@U!VR?NG;9=D#)GUT8+H0^Y2.P:#`UZ
+MSA0$L>QN0<J!]U!IF^"^8#MNWKL7)_5ESRBT"CM&OX6B(C>]?U8.0:V!XJM=
+M[]$D\Q<;8.-GR_!8@'7A.@;?'*/LB#?;HPBV',F+R?:8S1[UC&KZ+$-Q1?WB
+M,]!%,RE\8:;LBBJ.F.V=NO_J-1#4D:VO]GR`P&X4P\L#`=MQ:0G`JHBOS69X
+M4MWWSPX,(>2R^&IX4("5%\KB:Z"BOE=LNUSW10GT8+-Y+!6EZMPZYI`I(^HA
+M$*]B%SUGX*6\5>RU0/;QYYSZ86J]B<)B,PB];7/$GH]D1]3KB<(Z#@M&<PDI
+M[ZY;#4@?K\<B2-<B48J,7',7$>9=.52.W8&=YXB:C\S:'9\\6G[7_#O)8OZ=
+MW=*D9N4=U[ES5/P34QJ,L-85G+*]XQD&""CBDXI'E<5G9MI<T88O%0GZL5LF
+MCSXT"ELUR8Y(S?T!L)%5_#\AQ=0'``7YN&*/83,/<$;%K;L#EHF(^86+FVY(
+M2-&$%"]W8MT)R;H.57;PN@E'I/:W*8LUMA758[=`*T"WAS`MA;6U&]HHXB%9
+M?*M$]G3;>NK^*D?`1NAI1MS=2#AOK4C>(#3U2D3-)R3H?GWE?RM).%#;=P)6
+M>HWLYAW[27M%41)S/#FE9>K2K6RN<U['FC-P7%JH`@'U.D3,'C^IRLW>ST9+
+MV38IZBX/JY!(N0?'(.4`Y9BR\-4X".+G<@A$:4H%4#"&5/F`NK;`"I8-E4#J
+MBD'F+APUN%^FQ4>^^'[';,45&Y@1?@9M!)<)!;BTMVPE\=/;S]6UM!U!>1WJ
+MR2DK59^K9:9+PN8QU8]6EV]%AJ@/06((LHE6<%R>?*@$BAL^!5%:4&-!E&<:
+M`]YI!V&R+ZCM0>F7:_NUH&E\JV[\\S5\>HBRJSLYD7VGZNX$T\C\YHS&PZ.G
+MXD+AODFQ=^-,F[4]+MNC]^[_\+W@YFOXA%=<W7-E5R0\+`#K[<^1X(JCV]MT
+M&631ZXD(=:-!YB.PJ50F'P21<$4//0.M>\Z!'E@@>R*U9T&&F^T1[,G_^PA0
+M%*4THCC0>IS\A/R!__?6#'P9I<5+/O?^9XH=N_%-V^[>6RC;(]Z8<?._`7R%
+M\M&FST<;0H;@N#A,G8Z$U`V2O5IPJN-JT5@P_RAX4X),J`Y.F3[VY=DM;+Z#
+M%54N^DZ!M'[<=#:K["_B.%#7\B7:WGPLGVSZ5%2>'@E-3L_+,7T$1J0]_KH)
+M=-Y':V/0WYEIXQ8O^FAMW'MT0./9>%Z;_%?<]):KOZUAIICZ#S4(1'??#4Y?
+M^=]"OBS%*:+Z`M/9'O-/(P?OVYD"]>8W_9V4[J7W+\DGY1:8)@/\VQ#+5U`;
+MM#C5PAJ2J/FUIX"E@,"4GC/A.TA.8XKU+6`"]41V'.]+L4??5XE23C5#:]VQ
+MH/9/?20ZW?Y\:3-SZ'I,\GE8_[)VA\QOAGJ."K`T25<KWG%H%`0G[YD5,#2I
+M&=X.0SBC((AFH;\X%*X+]&GC'EJFOK"%%LHFU81NZX#BQ;FJ"-#'G4VJ"'VX
+MC?[B7X:GH_^\3_O!9>IR:-^DFM%/E]XV&]I*8D$P/-A??,(6,S^EB48T;2W6
+MKP7')9(-+JK-]M@*(6FJKR!3W1Y/+!!KAU2HG9L);-"?X1PEV_PFZ!XUD0UO
+MO![U-FD\=(&BC)6'5J@'4I4'(XZI^KB2+&NV6W*0<AYUHN2"C)&W-%>HGE3+
+M06GMU!KW`/C[@#0.&EAX`X!K7K]P\6D<(%\FK!KJ36!-,)-],:[4CFCU6-G1
+M[1?G@/Z$M8$.D4`QEN)9`,,;+)X]+A67)RFZVSJ$P_<?4K_P)>S1\+Y`!8[T
+MKTA37)BCQ\6AZ(PO0QMJ'[6SHO)P#P")ZGE89"=6I)!IS/Y6CW[TVS`WVN6P
+M7&DR;@*BX%(0D2--';`/C@P\#A`F'-VU_RE+49"@S)XE4:\]F@F3P!?T9'J#
+MF4VQC-F@\U!'&SPYSE+UPB9^OF1D:[,<P7;^8JR)9L5,$80#`8#7W^_Y)%P2
+M2-88%Y?/X2+=C9"\ZR9(8+D%4`8!2/88B4BW(,$>$]8VL'#>`A49Y=W-KSV0
+M4ETI?*?J_3^;4O9*-VJQS:(LM=`;@#1*;XRR%-%@5W$T\^/3#"A@+?`T.0/G
+M<`NL[.;'T1Y4I&ZV](^%I?]_JGGO_?<%O+=)JGM2P0E0QOGV%MG>86ORW*AX
+M6L`,E#VMN']N]8M[$3=KMB*ILG4`[)\[8/_L:D$7=@!+)C\#J\4@_*O*DY^9
+M6QL&TT+V=';M0F@\+6R7/Q;4Z?IJYH=`(*+H8$$@(JB`\`WLR2,VC^J>B-"T
+MY-N[97L[0',#(-3TUPQ9:E4\`,L3(`&*=0".9<T&6-H1EFX&"W0Z;3^4#\*_
+MJCQM/\(BM<A2I^+I9&Z#KMLS:-X0[?P?DUJ(DWVYI+MG20N#',G94Y])[6`2
+M'4%6H65W&C:C4AP@0<\CV&"GU3\1?4\3<5NX(0CS@%=.0$TZ6SNMOJA5C*`M
+MAQTCBRS`HL4;H60+XD_&4&=X"*Z]2,VH;_(S4N;<VJ_\6PT`%:SQPU,XWJC#
+MT>OI!`/+9F"[Y3AM&H@W%AEX#Q-!B@#!27!!-EI`T&1["X@HP[N%2-2F,V-;
+ML9N8D\'>JJH`H>$X264K1\#3QK@Z$KCZXPUI7-7$%)`AJ:P;(Y\/6U!.Q&=Z
+M0@"*3]R/6'T!VXK.\#T$)X#467!"C@'3@>/C-8Z'\I$=,&RH+]];D.^=X1&<
+M[^)^Z-L3N5%\AMG:<VN[D"KN\0R5A-1)QK6J7K41#0OW:.(!U#Q0#&P&^"25
+MN7F:[9WDT)$ZR2M*GMS#J1E,\W>"WO^QOI_YJUYYSG6R^=O(%HCD_.T&#@`\
+MMLL@=D!<5UO8'$",D<M@-Q'%O@**$=V'>\:6E:LWK/^ZN=V)?5S52UXZF;QT
+M_4<&V_?`^/[]AO0YH!(P'02,!X#I2-@[X)5./-J`INC+.XWV-DR#-O7X>B8A
+M0(`V$@*5SQH^%]IP+IRN('EJ4Y_%VLVD?J`VFQ`=J0DQ9QW@Q4B%,J2B##U`
+M&BH/%&X;",A8_S0"!D!0I-,Z_=3)]%,;RH;:CW[JU.FGMG`YE&._*NF:-KVN
+M@1W/:9W,=3*9:[N2KNG4=(T*;/1ZVKC<Q4'NVDCT.M6?K.-RAU.G4Q;?+D$0
+M8%YT-F<SN6LCN?.T]9SI.DUK'_!4EFC^>B+`8CY_<0P`5TW.7S5%;DU)@<17
+M<,63ORY)[-.,V#9/MWEO(XV%9&`3>3A,Y-`:>%=/LJ--9R1/6[Y=9:IX+(Q$
+M"\/I0+]T;V=TISD).HS-]^B-(E%(!`IU,<4!>CB\$NW9;I#0M+HZW="&$C'"
+M,[RL0IVRAJO(SI2\@W2SN1_A<S]*<[^3S7T%9Q.;O"V]_>GI^X=?_(`?\8B^
+M"W4N=)4DK8;@#YC54&$DAX[1=T&R<&85D?L^_'"`SQS&[7*`]5_7$)]%U"Q@
+M2=P%,((B@3X+/#GEI>J:7GUR+G*%"^U_N`:G$G.H]+/CZ+O_69UVGF.T22;W
+M]#0_.W.1,U?`%ZOUYRKL_`IX79[N8Y?B*=W7_77[AZK5*>)YLB!A)TD>D_M6
+M/F#=:GZ0=$URO'[/D;[VO$R_OSJ_"MT(%O+)B&#O94'2<UI^M^G++-(\V+DM
+M4C\'76SD>NJ8?:/X&AB\[G'%LIX49U>QO4\Q4"`.XB-//AB^-0"S+3P0[0/N
+MB.LI1/N9`I6RG17J;ZA1C(UD\QC=HY&:T?K<?L\KHD!+.P91>>O3_2B]SDOT
+M_H5AJYA_H8SVC[#_PRWM&5`%B&`L+^(+-F3#)LA&^T%TZN4XR]3AJYA4V2W>
+MCM%.K.;D^AJZRIQI=++H(?7FU>0\`'N7']LM[NUTZ"-?VQ\C?XXR1Y0=<=D1
+MT[PZ,>Q!0C\(3`:L&_X!`Q+V'_Z%0PPI!TGM8PPXDG<.(L8Q.4R)C4:_>,"I
+MCB><8X;S;.(\,[,@:(O`ODU$"U(HM$7JHLQ!PZ%>E))+/*]!V@/%YL/FT'>J
+M/JL0-V5`MNR#.$=[/K8UN0?BQCH\&6CF.^$>B(P2;"$)Z3@&WME"YJ>#L`F5
+M6YK4T;:C$FL8SCK(#(%X+_\](@+#%8'T812?>1_;B/:</O%'D)N80;I1*:(!
+M-N=0#_@:QMADI&XA5Q`\\<>W\-D7K,]BOM106GP`R#L/$]PJPCBV9K<QKUF.
+MA=<#_`DW+!Q13[9\N><3%$/F)D4G4`QD=[9BVHX3WKH3,M[@Y1J,4;&=E')1
+MQDT[6='LVB_@519@/PK*..ZQ?G`'*O?KCYJLMW]6XMK50;+FL9(:BC"WJY6[
+M7<$DB?@G>ZB&YJ_2K5<Q;(;NU8CF7K6K(`?#G*6)+1COI@Y\E$4'7%]PRN:*
+MU(,-S!J(`?+M/3D3WC:$DS98NL^WFS85W?4_5'`[[!?YH%'RSHY(^G:QKRCK
+MJ[LA3$MGC)Q1N/9"D5\\Y%0C*]'DZ,8CK43]]^&MM^X0S(&B!31JO8UE)\'6
+M%&V\^CSRL$;#.F.0SZ-NF$2#&,"HHKO9\O"(XHG9/'$W>IIMCC@>"X*1U8$T
+M&R@[VL/7LQTU:M$9?BO1KXSOK7%ZD5O#;Z597\8W^3AK"N0B(VQ2P\O1%H+^
+MI5L9*80T4C!;*:Z@WS])B"\91-(MP!Q=BQBUN"I9/\F$+\G_D0OOV3+)E`-Y
+MTD>"Q8G\ZZZ_*L#V`G0<H(T#EJ,]4NBW^FB,-K!BFCHR:2L"]CB3+<TO;6)4
+M;.H:+3LZ:8L3,A]I1K%I*Y2;WJ\*_6$T5,OWM(%M8][1(U#\21S_Q[U,?#FZ
+M9QF#X5TKFDBY513H8I,BGDS<GURH!X1;O76O`C='S8?L->P9_5F8S8%]D+?N
+M0%QPGT,?J:,5-:.]U>L)"9YZ]+`/8:)37NH,6Z`-&[N;;.56=2M!@%[Z-"">
+M7D'6L@Z(\=HPTO4X:BY['JK!P"%D,.#&#&$X615*.-K,OH$XB^E$`64`]*SZ
+MQ^5,=,C_P7SC9*,DH8@C%(/[0'$3'C@1^M?AN,/9LYG3(<[IP,>"_]2C'#\+
+MLV%P%T8JV^OI$-RYF@RWIR2X@WF'@EJ\:?KY<L8RBGUJMI\F,:CA4]RHS-;F
+M-U,Z:KK2(:.XE]+AWMB4ZHEJJD=-JIX.H,M57/5$U;W+F.H9%4#95=-U#Y\F
+M:DKW=*;K'MQ@VCR=J'LZ=;HGTH_NB;"^.E'WJ"0HL&D`Q:G2S`/=XUZ&NJ<S
+MJ7LB*=W3F:9[.I'@J'LZH5)*]T0TW=.9KGLZF>Y9PW6/A>D>T$&H-E$'X:)_
+MFG0.[E<T'80ZR6_U?RL=!#;/%+D$=5#7CP3:US@BJ-]N!1AUS$"R7&)ZB)^9
+M1=B962?H!_1IHAY*<\?$J,55R?HQ5A_U"=.@MZ3OC**]ZD=9?17U5C?J+4>\
+MV<`V87A"2'IK-M=;G:BW8"G#=O$47+`CL:MZO=7*]5:PV=[.A"]VP6``I444
+M;_IJM.QI!_T[1W:$,`1EVA-<=[6@[OI,]ASCVJM%]K28=UQ-CIR4_@JJTRJ9
+M_D(A81%WK>H#CW#]I>*D59G^"GZM_@KJ]5>0]%?0ZSF&[@`!3PD[/3<S$40=
+M=@NM#2$\;IMV"$!LMK>,0=JL`!W#X.HD+1)4?_9P4K?I`3Q0R;5*$L#Q20`U
+MW?:J7K?U"]_)JF,)1XO9]P6>G#M"9ODQ4G(=I.0\1IBRZB<POK(`YWI2P[U:
+MG(2%%H#\?F#A:NP*>C;.]2P?"G7<)P]K.H[V+EY/.XN!\WI.IW2<HRTU0TXS
+M'=<[&J0___<2.JG@:Q[;69G(&BLX\>.>B_)QW'A,@;UDA3IF"8L9GF]``J'Q
+M:F@Y&6-33IOT%E)]W6P'4VYS1*3!J&V`E3"?HU>8SQ%M/CMH]IJU>>W7S>L(
+MF]+A[Z%L=-L\$>DFG8NH&^;,>9AJR3G337/F?-U70,)N9OKC=81[E^#@-,H"
+M$8^A2D2@*EXO29$QF@(LQLC8T<L?IZ??J0=U].,[4PN_NG+9%S3_'*S=B+_>
+M@.LEVKR&&",97@$Q:MJR&_95+MM%:3`2:ICL`D+165;2_B(O2*2B5".4!SN0
+M[]8(=21%J";"C4@U!6UQ1[?T/3VA^.$4KKCDSW#IZ"6[(D"R;B39:J%4M3R$
+MH\=9'(1&IA$<*E>TZ6P&-.B72KWD[3&]_V.Q%F.E!H!TJUF$K.]!'MD47<PC
+MF\*+>633V<5XJF/UVP\ZU<N+>>QMKM_^:Z?ZU6(>`/^*8-[1B)1P_5IVO>QW
+M'91=+_I=(=GU/`4@_]3O4F77LPGIY83T8D)Z/B']5/W)@]@MOE"GT@CP]F7U
+M-NIQ#%1(2,_ZI6/EZO<78]27)UI1KCY"]9ZM4+-9+:#3L^I_+TK"(/T,[5%W
+M,4$;=5)S$S4'V,O5&ZA5KN+*]6X5!9@7+DOS3+:5O2I`*.'="8OZZ2(62TPZ
+MQ*0^MPCO-1RDR*.]BS`\_Y5%/*[XGQ=QJOUL$:?:OD4L)`T))R_"*'XO%0&Q
+MMN)#U>-]X\.\W2/U]L\B39#Q&M8%$+X%9%S$-5]S#%X.HHDNIO;ELU!92T;;
+M$$]V:;G:\P`M1.AY@TURPO:>V1_-2'H_H&FI$0^6K0=+;)Y8@]KUH79&$A.D
+M^0J9D&`C9)>7JK]Y@';$S+3CICFL%F;_BZG^T+75R7T@:`1)<=NYNO_LVI[!
+MUOZX?N_!_+P%"5Q(A_M.28-*J.TAWRGWW^50S^D;P+8/TI;P;5P7\X[+8&C"
+MHI`7<Y)1=<B)9MJ"110K`O.Y(\L0D=%)&DL>QEC(N-`T(8XU%`8:`OB5X*C6
+MM_N.=8C&:@(KLE2QQW`L"<9ZVXD:ZS\?P+%B;"R,M@$3J=OF4#T#F6>6[H3$
+M\S$@AVR6H;1DT/VJF@H6:!8T[_@(!JC_`6TR(U0ABA4:H&^#/5Z0()=XE"@R
+M&.%T1+\M36BG6JK>2U#B*MBU+H%Q;-H@;,"(:J6A8GRH"`W%:`(*^QO'(IHP
+MR[14/5E!%,&Q,F@L=BDNTQL<W13+`O;[9TW4>557ES-W$`A+O;'@5*!7?=M1
+MSZ!F\1GDW<SP?^G*QL%.N)L")!@N::TH1J\#>I:/IKW/M,<!%5&V[BI$Z2\6
+M_56G^_J#]?[%IUS:%4K0![X+TDW*3)%=\2O$(V4MXQ=]FCT?]R-AK66P(O^5
+M<+.0N^^JU8:*"K731=JRO%P]BF50X*9)(H0S`QA6VSO@J`\\&2XVL5P\?/O;
+MP5-15JXN+6=WF1`88P5`4*A!D,,@R,+SCUXPL/%3PWL7)H?_QG$Q&(`%ZW[B
+M8G3`:Z(#*?2V?2$/H/FF^)EA"WD\CQ7H#\/<42S6#"DO(W6[!;H-5P9LDM$M
+MVGI@`U$L:I=)H\GGIHX,@J:<;M5TWT_25H[Q/-C%9`Y9`Y#A:CR5HA#0Z0LQ
+M<+E"';ZP=P1^'_BJ[^?R86$T0?ART'%_"=J&YQ!8)=\(EBL)EJE"#2YDC$*8
+MC`C&$_?WO0B01J\4./]9EN2/@\A5)-8,*@7NY]]/@=_?S+52SK-K%R9YYF8\
+MN^7^OCSKXZ]>5L;\\;6B?!G/')2-8L\G(*?#4YYA,/<T'W%=ZB0$&W*W,.W.
+M<99`1V08QM77[\>YC$I)UWH<^C_K3.P-1;;GL&>Z2P$;W"*C;,%`-##9M\$J
+M:)C-HF@!+N8TOD)\W3C]_"]%@EII:>UFRRJL`P7G<"5#QR3C:R1U\1=7FTBQ
+M++5C>#)#;5<I#S>)Y'NZ2WR)!@?>(BC6B&%S6,P[.@PL]+]8!``Q>#!BWMO*
+MS^T)$XIH2ZW+$5B7?ZV58ZQL3D6I.JHTJ4OQN"Y&C#`2^)"-TYX?:!N%95T:
+M!V"F#,_/R$"WH`L5[$VVH8TTG$-'G"-N/C+KU:0WQ*&S5MMQ#U2:D-I5-Y&I
+M7495W`$+"@9$J)4$SAB\B(#+B`0;[+U%Z+I<22X.>%@"L.$)51;,8>E[Z8[(
+M=O*+6/%,#_;G^Q5'N\X_B"/9/%'W<.8$-NL=E01W!#C`P@<3^(!+G3JCE%Q-
+MP`1#,XP%`*#_Y$0]^EZ07U&V[33.A[:^"PUA<E%9":%VOB1'G;BXM5-U$[FS
+M5.;.\B7JA\IXN.:M>QOZR/27).1F%L>9='GYJT+]G-_I[W\L8,H$9F^U2"%'
+M(%'H_`9UY<0#FS><?!H,XB'+X5$P!R[4F;A_(IP#\@#/-`%*0/I['Z/UD>_7
+MYC.YX_+-G$(JBO8)?GM=)]G^$@-:D0-@X2Y77YU/PD91&H6^8,,\E$.'R;SC
+M"0,+`"%1YGX/FZ?=[-^<E%>29SIG=+0G3<-VVT6P"TNI$E>/4>WD.:X9;#%-
+MN".VJCCN,9/NG#AWYZ`K#O=,4EP6]\^T7:K["G@-C`$IWDM2W`D4O4\G:,#>
+MSE)0O1WJ;Y$8C@X8!5Y5,$M-_?%\38H?1;$2WP8JA!\F/"PVAU&:F!X-T4XS
+MB?FM8@1'.\'!_%#MA$$<MG?N:U+PDO\)^V;PRNRL`<-4R%#<A6#9Z:`A6(]S
+M-,+T6=9L(/LYBFLQ`\!.;LLYB:5HW7#I?#@E>7WO_\WK<[YH9-\\Z#GC2TAF
+MV%UJNZ#[^!GCW:!KRE1LR,.U\9L"VM<%RM6!\_&JB[=N)].X7WN\R.`9HX]_
+MF\>$IU[4E&UWP4602-WG%'0"*5_*.SK3=ZK!DE*H74,,%+^L'3?FS$O3B5%-
+M"<:U$!GT`"=]L2`J:7(RHU\YV4E`=LB27DXVSM/DY'YRX!XJ"<\-4$1=K/<9
+M2RQUQD*Q2LDS$Y`1DHJAFLYCCF"0"281%5PBI'D8,)SOZC:`,@#%@[$2WKK]
+MI'AF)N2CQ/B,GH^U./:VM)A8O7_DM;F,WN7`?]RCT/DR[B=])S`"U8)GNJF[
+M@6M`5HM8R'YV:9GZV[D4(<(O!=JC!1<*3MBD>/TM>`^^9]P3M/E"KT5D4V8"
+M%DG86+BZ%7M4^U3'1]"=[X([&U]-WHT=RW-%M#@:F*ST=5GTD9?S<WC\O05$
+M%H_'-H(BZ^37&PIZ,.`!ERTF+QT*,I4]=]KL'9YA<DA^1VZ"*A@JXNF`UW2"
+M&B41H5#$^;!N=V1B:=PVW5-A.PF+E2,B#4$O&A3?!3N@\,A`/V=Q>F<0S,;I
+M_3F#Y/GD"5H1L#FBTAT@4OIO@>`PF<P1[NJH+PSHG=0=#>?"MY/_*"+=3-O1
+M9+L(*2",ETYSFI_3W+(@QM%2-7,.WQ%:-5418ZH"?=^I<QDU=2[3S=Q(;5^_
+M7UHV.]T_D='S25H0S0]G<UN(>=9BFKT7)5F[)>DGA)+4DGX>=3CW"G9Y82!8
+M\\"HL6,8H9S-+$LZIUY-BN9F=&!9G.SV1U2=.(="<'*@<K-X`)=)0Z3G='BJ
+M][)!&HU*VF"S6S:#]5_*VF$;$=KTA,+6])Z^G(UM^T9M]))/_?PJ*TG%2T1P
+M"U,F]GR,5S4DMKQ_HM#Y54;/&7YQ"R19!M,"<,,[$CA[<`Y%Y,MR<QHA)Y5P
+M_6O2KD9I"R2_0!.EJQN+D9]U(RM0<<7+U'&SB18;@;+\(E6XRG99NH5A&%<[
+MB[E/PG,U/V8@Q/\.@X77XGTZ?C@8'H_^(.CY;FA]J];ZGY*M1^A;'RA!LH4+
+M].U_F7K&*H^7<!ZY`*[7-!XQ<UVO!_K&_]B_7MX&%?]OY<W7O[P1[=:@O-7U
+MDK=@<5]Y"T\#>GV-O/T(VA2&1P32>ZHOYG2XHL3UD;>SLU+K.9>WKY4VET5V
+M75G:DA%%QV;UDC;L&6]II4O;0R03HS3.EJFOV[F\)?F:+F_N6?W*F\_^K>3M
+MKEG]REN)_1OE;:2]7WDC8Z67O-'M++Y1[F__G23]H_=I7R-"'\)V9,22>%__
+MAM8?;%IF&A7A)M!;#103Y`O6B1@+E'K==T!L;S=Z:\AO5`CU>/R0KCPE"Q_,
+M9'?#%-+ED_@:@1L)Q=#K.TRZ]CIAVC>3WP>R]'OGO8*^UO/+^W2W;M+;N[3V
+MIG[;PYYID#P5[#:2B^M`,&'_:^PY0^](GV=SH^X*_?^]Z!OZ=^OZ[]-7<OZD
+MQ7\6)?U]N"6*,X=Z%@97X>Y.GH+?9./A+$_C:,H4C:[X<2NYA'^T`/>4_013
+MAME7T?3Q:LFAQQ?IY:=LYI7DA^+-P.PSDW^#JR*0`S#=+/`*EA<+7P]/_)&[
+M2O3Q?"R4#,P[E#\9K7O>GMOY7Q]?NKVPC[Y%+3')DUU>IOZLD%T&`G55(:9_
+M+X2K#F7:'GD:B_.\TOVYU%C#"X5O^MY";R&>6##ICLEWWC5EJFWILN4KJE8^
+M^MBJU3]8LW;=^@T;JS>YI<U;:FJWZBH5S;QOEKVX9/:<N=^?YYB_P%E:=O]"
+M5WG%`XL6:[@[=;COG(%!^B:A[FHIN]ENPDM=?F5,,)&`_4EX<*!GB<G_>SMF
+M,;K:U/174?'B%4/%-!'6?F*K1?UOP$ENQ@NVO-`]4:1="=OLQ.BLRHC1!^R+
+M?^_@A<A+_)#52+>+P%"#M<5X//LVZ`:-;]E^6'$QR_UC_$S=*5BK'(>/&R8>
+M+S+@]SFZ_H?=6[:;9OOL)K/O#S@NK&2>#O;M#T?T_<\68/`\+`-HQ\=QD9JW
+M.RX[.LU'+LJ7&L^/IBM.67D`0^C'/9X.WRE0/_:.O)#!'H*AY\HA*%6D4-YQ
+MV=6.%^_1G#[W_E<W8J?J'A'6S,.[#;#'/YPO==2>33C::PKD\[`_@6HGW_^,
+MJK73/G@;F.#>XV/DH]#\\X&7,.X;.\@('X$^#Q_/%KJN0602]*T]`R#NB/E-
+M+):FE?D`7#'S7OP"98#=*-*'EL'\"]?@6@_8AC"6P'K0YHIN&5!P"K\MD(!M
+MOR.$85MUHQ2,QX@KIB=DQS'%?JP'.122Q2<P4*/V+)C5V$/-!&AS6`[AMU%,
+M\G'%H>ZQYNQVO0*`[AXAG\<O.I+[=!!T6_MG.C[S*O;#C5,G2MGJW=/9^9?1
+MYCB,WV+I/BZ:A?`,.O\P%MKLAZ5\0))BY#9?!>\.`Q&@]FXQ!_>)6[[$666'
+M1E/)Z:.&[^6^%8L6#(<1[WGO842_O<U?]:)N_Y_F_YF6O`P.T[IQQFU2=L+>
+M#8)E(@-I$JB*1MM$Z<;&6D.->P#\?4`:Q*\DXL4'?IV1^9W8/4<P#9K.:J)?
+M9\%[]XH5K(S(Q"#H`/G#^"%43>=_*[?TA&;+=A6I%Z&P:C+:LL%H*Y^F"T[3
+M3N_M%I!>B]EWDHFL[.@`""W22`)[HF1M;"`(&P!"H]=NRO#:U<MX<Y#'W9AP
+M,S//G*`X+)/M8O4R!<3[;8/Y[1_E%F8*@LUEV3*T\=)E]PP*>>UZG.8,?CJA
+M_?V.@<=A$VBXB![#BZ/KK\?YX8G+DY\HPAEK;X=]94>^O5W^0&YZ_\L$&\#3
+MN>EGR7HP??@W'=CG&M@W'0#GKJ',)Y8$U"9%ZN^B6##SF]G(!CU\`Q$^2W@U
+M?6?._+OC_LD9"9PW$9NCO:Y50Q5#M]H]%+N.[C5/G';BL`<WS)0_8&]`DM'A
+MAE4OUGWHNV#>\4-RF>O0ZEJ%AW>-EQ)F7QAODWK:A?I'F^U1=A\?OW[P.]RI
+M1&$N8UG#%^G#YP?^;\9W#TXG*>Y!,WN6T)5^LL+Q7*J/\U3@WT]Y74C[?LH9
+M&ZIIJR#E%`2[RD0V+UQHOIN/+`S$09O)^QY"=#U6'D.:XSTZAKTK077JJX$G
+MOO'-:Y-?VH"5?5CL[1@%YKH5%+E"U9L^SU)\6.P7`TYU_=WLR.0(%HW>;%+V
+M85%S!I&%JBGN@W%EX<&8O.^Q9)\O&Z1KY/--GX\POWE*WN>$-^8W=UR+#A?8
+M#V#!\/2"+%@5?)C;YL>_^(&*II?P:83W<D(:UDQE),*D!0,!VQOX9LM`?[F!
+M=:-0E2;5(OL6XH>>\)[^&_C4U,%?&:C&R=_HAA&$QF;?`_!D(=WJ0P1`A5/?
+MK)%"G1N.GOQ\VSM8G0UV\B5LY#V"?T?7-[.QE7U(8CFCV>?&)KB0,D<NZRGO
+MF/S2(SS%J+),(I[L6X,])3+,>V?A1P98N([<=/(B`XSL@2(#_X:`W!S."P0,
+M%Y5]6";/V]<H7YPI4Z9$/D)X8P?R)<-1^<.3"=M%Z7W^$2*%>E/J?(T%%V";
+M=`,'3?'C\'E-`<7ZJN)#L&3K*_BUDJ\2;R`6B3<0IXK$&RLH@_"K?YJ*@6'Y
+M1["\X`3(^4!E'Q8HIK?D=^6+^7[6T$U,P0*_:;?L1^!*]9V6JFNF:K0Q',=/
+M85[.D'+EB[Y$W3"`E[IL%O=@_3FUD=6&U88*!@!KKNZEUM@?QN+Y$3VS?'52
+M`D^J3OUHO-'`9",G>^/4BI$9ZM&[T)#Q'AMG\UCKQII]+PATLLU*T=+Y\5U:
+M>(,?[VTT^^HXJWN1:T.JS[U3\'+:E<O743G@#]OD-["[\O3R8BI?;2CO!YU)
+M4_A'1$V"^WJM&4UEC.*Q0FFFW1J^F70QH"1=G89,ZYVT7\RBSY'($?]+A8G4
+M1W]ZV\LF^D0;KI]X-Z>+;F$[K.13E<;B;:@Z_-*4I5YB9WOBJQAX#2\:SH67
+M89Q-<_S0&&B33Q=LL,90_KDN2_UX?AYH>A54+RPF[W].6C8&2]11V7H`MK/4
+M43LORN5%4C8NG^'L`-:Q6U(7.7K!BW=@\+NOO>"M8?!N[`OOP_W":TC"FZ>'
+M5S[:#\1V!O''6*3B-\H(4KQS!:.DP9JDKS4)K_NV)*!Y".@H,#[P2R8U[/PE
+M@IL.<0^SVR*U7Q8$\9ZAMUG4P^NR((#N)^/R>03K<]D5Q3-C"_O^2<UXBL&#
+M&I.?1!`[R#^"%=5!=HS*DR,X8"W!WT$.>UCMH_ZJSK3S%K+6Z#/?0;IG="O`
+M-QLM;=,NV[GJH04GPA;V':1GY'=Z+L@G$V`GH"LS++?`?K57_`'V9\>>\,[.
+M]UD_8$*:=MH<UBU9T->P`(L+;!;?PD8+,,0?'577TUDJ[-[$`S`,?J/`"$26
+M3\Z'O5QM9Z^A4N/IO\^\?1)=#\:<UY-K<-_<`(9BKN`>UH7>Q``\9[@W=[V$
+MSSS*TI.+[B58?X?)KF/T=3N3,N]`W'O\LBR%;">K+?S.)-XMM0`NS`(?CVMV
+M"-&R[I==+8J]!2&&]B$=T*':OP!596/7ZDQ<DRA&Q^_>'\-KLOP>0%2Q6Q7Z
+M2`.><(24(;9+U=?R$<&D;[:'")7CL`DS)0!.R9(OY4+7,?-N_%H6&))QNB<3
+MDA8VVUM1&V3"1@",:WO(UK1I`@H8XB6_FX]'SFT@`(:3W@\$6:)X;CNP@-V@
+MJJ-83H``MDZ9L!^`BCT?A:^16P#+'KR,WTI;G4A/5:O<)#/,[Y(!84\;#+XE
+M6QIM<QS;=&W"T0HCYSLBWM.`%.R]H@97F\W5MNE#Q=[*/[T.TP;OA1_+>_<Z
+MC+$,R>=@9V.6"U#?0Q.*JI7-77=A`)[BRL7P@(7[X[)+53RY2MW;,;P%8*=P
+M%OI6T#'M.I=+M86J<SGMFNW'\&4"KV)TL"!Y%&__M`/XC0&TMG+]UNVRRYIW
+M'*C9;=[=S+ZMA?3$.]S')!,8C$0:%^UY3$HAB"SLM/!RL7Q2L7?V5+7#Z("`
+M[9TM0Z3O@4P?PZ_)U\<VW0A&9Z9#M3G4+;D*GN0<VT0T=77FN8[9'*$M9]RG
+MM!LBCMR>C_"<S:I,WDM<,2G3GI`]0,;VGK\2H4_C,16,TP8FJLAN&K?1;K@U
+M'U[;C^&N1=RC2*VVR)8-136O4UC`,)`&04C>=0O7L_L;N&%L#6\D>].ZA_,1
+M!Z;QSJ:-%V+'8@!2*#G<[/3QJ@-7&F^0;KR$'5J?MME;-RW@Z*:-GVG=BQ)J
+MW0L#@?3?5%3SJ7KX>[BCLBKB;I(B4Z:XIQ"!PG$!KBU_*:KI`"(KKG:\M08V
+ML?4@7FLSR_?@A_?L<>WKWWV__W@[*89L\Q,>^B1)+EM3;`,H?IV;4@:[R6`W
+MXNV<@;(CZ+UHV%(I%=#!IU,SMCQXQ=$3!/#SCB,^>!@:9+MX7'?P#@+NC2WU
+MHU+=P@82`P*;131\!:KYMX(+=$Y6<`%OC)V1/<=0UH(*[.H])MJ7>$\)L"O!
+M:8-;CV,UG](E.6^3*#NTV]@P+VR>F-F_C\:P-'V:`8L9.S,`%/`.1-";,&S)
+M+[@`B?0`[@[LIGSV@7>@'3XYU5_=SN]"4-PWP..PX#DKAP=$VP'P'$K"`WEC
+MIG@(58EX"/:!QVKH%&`*+%ZRQYC`W7*N#:;UXYMI6ELR[;FPC?.=A&W#[*Y_
+M%]EWZBS0,*@+:P>\+7ZK@Q$XUR\VV(Z:]Z(_!4#P!?%NEXE%%EPW&[+#V;,9
+MGW.`7-ZZ77COP6;/;3`EI%RPC_`#[.$<)[FV<LF8,JJ?_P]].I8^41>T.>(>
+MO/^'1R;B(1RW!*^E0\%[=2J#.M\>Y,$>$7@!.>S?ROM70`(<)HPK#><&6+'N
+MG39H1)5P4"0NQ=H&;9&Z8?BU$E;72.V'LSC<H.X=55&'WL8_2^H>H+XT`76B
+M/6B(=.W*9#XS@$Y$Z&`F!>G^&Q+B@.[^VX'4_3<D'[N#!V2G2Z`%("'L+M9X
+M?BUT-,OFHK^)70P=3!=#637WYS:INV$PG?9;,1P0)GHYT;>;4`VI>^()/.#'
+MCZX$_2+=:(.):SOJL>!R)C[)1?]8`Y`SE^/+][(PX0TA)\A`WD70&J69H&=<
+M+670S"]>=*H%V+%=Y7TJ'A4_$Q$'WIA$_MF.3IO4VG"U-(,!U*(>N)5;^'43
+M\!6MG<%RX"[0R"\^@5]947^?SSX%TM%L;R/%=4N2C\EZ^/F<3O5)74V<=<3-
+M7!*([KI1DH.1@%I9L94Z-3E\`2^3<CD`VG=*75;#T;),>Z=3O2,?S]XG-DIM
+MAO!MR-=^:</ZR71UEJD9^=B^VW"42;)?_!.Y`S#"Q^;JJ!M21M?5$,F.BO!0
+M.E;O+"/H^.MV]<PEI.AI=O^)BH#2[SG]DVD&,JR?OE63/A-K+(OO%8?OP!%9
+M-29SG5>6N<[4O4\F^G@6ULG$/(1B[E1OAT'"8_3R'^+R#Y09"H4&L,7B#(S!
+M-%U#3.O$Z>,E8Q/2:<"G3WNG^A]Y%*$>GLX'MY^NSU(?R<.=X!5:O)!'&ZGT
+M45"3Q^NOYO?*T&%K9*H^WO`E+3:OZ^)7M.]?@QB%<\!^5JP[;2>EG-FU?P-K
+M>"CT00:7[>1F[=)Z+'W_P-J[<GL^=N=I_]:*W91GM^8U!\B&-.T'JTRRYHO[
+MP;RWM6PIF%FC0OU\E\5=HVO0#*9WK_JSJ4'U>S-K/F,-I&SVQ>45^G:LC;\H
+M0:$9+9N^`I-P-.Y>AK#^:-R9-5%`9X)_I@&//@/T?0`,JCEM.UHWE!X"WFG/
+M"-(G<V'J_YU>I&/::[_`0]@1Z_$:,,<9TKB(F9ZD.V.9'.?J(L#9UN.N96BD
+M&C3[3GE6L/68@.P)E_=J7\B(]H<D#=(;#Z&V6$D:!#@R\E@#,-9@^KZOUB]]
+M8_I;?#_^_$WLC!/LQ[DBQ2Q^!)M!(^MW34`I,YJ/+-R#3K^F3[/R3OJ="=]1
+M][WRNP4)^;Q\L;3LS(1Q&,38].T^""F'"L,CS$="T!U=S,S[4+[DGY63P(^O
+M]WN>]4V_,6@-)7.-,_!??7KRNK;WQDTKO^<?=MPP`YUM&:GJ,P;#GWV;CL[>
+M<?-#1U_8UCX=SX@$RQ^VO7GRNHM/#3T^?1!DG_GI7Z1__T7V\'<>>7,Z.N0S
+M>>-_^=6O*)_J_Q^G#\2"=YZ[9_O;'<-^,N8YRN>O51X7/YEW:K[PH^E&:OF/
+MU[SQW`LS?GIR+^5OL/Q\8N6O8\Z7']K#RILN5(RZ9X=;V+J3\MM^<O39HS=G
+M_N9+DY?R8@J_Z=GP=Z-=RCWR9F3^KWU;*=]XV#/N'V?'@RN?E"C_PY4E=\Z4
+MO7<,-&^DO%#X_7G_DM?PFU5?KJ'\]>L6_^#J>Z<5K!B[BK7_]-<_ZOAEZ\$)
+MSU=1_E'ON7>ZUGXQ\]\?7C9]`(V[8M"@(<\^^OOR2LJ7SO4/&?9L[34O;'N(
+M\H6_735L__WJX6L_7D3Y.4^.&/'+S*9E=0]6L/:60R/ON_?.ZUL,+LK_>+;[
+MQL^[KW_7>Z*,M7]Y4_[0?S/7_M/OG)0ONN>ODY^O.GCGKE?G4SZ+8_^GUGF4
+M;YIV:=Z_GOSM+U<DYK+VIZ]Z*._HF>7NDCF4O^:-)]=._-*<7_Y""1]?XV_Q
+M]%[GWV.UPVK?!8GYII2GD>3)(VES\A]?VF+DY]/R%*7$J!V"+U^Z;MUZ]YBE
+M:]:L7[[4735FU;HQ:U8M6[L!V^C/II6Q]*U2=<4X^B"D+R@-]7N=_Y%(.-4B
+M>*6NN3%U6JUO=_]8?J9M5&\8IWV&?IC6=``V+;@1;:Y^VH[@8Y[6];T"3/O%
+M@C#R,4A!ED>N@11D=N0&2&%E&>D.$+U'UD`Z!=*G(%TK"!.>@_1!2'\!Z9V0
+M_@K2ZR!]#=*K(7T+TOL@/0KI"DC?@?112$]!N@S2CR&]"]*SD/X`TL\A?0S2
+M\Y""(IAP"5+0'A,RP/ZZ`](<2#=!.@Q2F-,3KH5T):1C(5T%Z:V03H)T$J1W
+M0WHWI),AG0GI4DCG0GH/I&60`OH3%D.Z!-)ED#X`Z>HG26],J(9T'J1;(2V`
+M=#ND(``3]D!:">E3D,*<F%`'\%T/(#X'^2JD`Z0W(1T@O1WI`.E,2!NA'FP-
+M1[[U).F-"3L@?R_DCT)^'=(%TA%(%TA-2!=(9R!=(!V.='F2=-J$\Y#>@'2!
+M="[2Y2E!F(AT@?1AI`NDMR%=(+T*Z0+I0J0+I-5(EZ?P[BG0!=()2)>GZ)\4
+MG#`7TFF0OKR?^&UZ<3_QV_3\?N*W">=:'M<YTP62#0'$2)@J$!Y("^$6@<8D
+MW8OZ%.@FF/D<=<+_:P2"7;#QMN7P_[7P/W[^%N<CT%$8QNO@(@#\$X8(Q$_2
+MY?E<9]\FL'\&$>PK`?7R**Z+QPN$DS`+YSI_1KT/?$89%.8(Q$/!+I!,(3_P
+M:[ATOH&P?U\@V1<D@7A`,`R%_RL$DF7A?H%X(10+Q"ODLX#_KN`B@61>N)GC
+ML(##M)33XG8.PT2.ZUV\[1V\S4H.>RFG\7R.VU2.\S2.\Q3>UPP.^V3>YYV<
+MUD6<5F6\[]F\SCV\CI./7<C[TGX.SI,MG.;W\38E?&R07^(QS`?B_68.@\#[
+MFLO'_@&ONY;S8#FG]1).L\6\SX4<MDK.DVK>QP.<!P_SL5P<M@<Y359QV@J<
+M5@+'=0/GC<#[7L;;X@]E["&!\5#@8\`\)9ZMYC`]RL<0>-T5'&:!P_((AU7@
+MS_A;RM-E/%W.4VR[CH^!/^3M8WP,@3\+'!<WAP%_2+N-`ILCZP5&0X'W)?!W
+M`L=U$Z^+OVJ>;N*IFZ<23S<+J1^M^0'VC')NT)6AG&?!Y'KD9I8?W:M\`F__
+M"&]_'Z\O<@"1?ED&_F^2&AC>6-[J3,&%^0WE+%^/_4$]U"^H4Y[D^1=Y_I]X
+M_=!X5O]UGG^>$_`(ST?FL?P[6O^Y+/\ASY,B@%]G+WR^X.6-M[#\19X?PRL-
+M,["\A0O"]3P?X?7SM#P7A$D\'^+U[^'YP"J6G\7SK]S)\DZ>'^-@^8>T]D-8
+M?B7//\+Q7:_E>?T?&AB]+2`X3GB_2RL?P<K_@><+.?W^A>>#TUG^@%9_+LO_
+MD>>?OX_EW]/R=I;_B]:>C_^%5LXGWG]K].`*WYS!Z7\5RU_'\QW<:+Z9YPNY
+M_$SE^8E\@MNU_%"6+\U(Y]\B7OX(I_>CO<K7]\I[M?Z*6/Z)7N7/\/)('LN_
+MR/.OS&?YUS3XI['\86U\/E'?T?#A\M[&\ZV\_'.>WW`ORT<U^@QG>4,FRSMO
+M9_E!/!_B\GUU9CJ\U_?*%_#ZP;M9OHCG7^&*S<'SC9-9OH+G)PYD^4=Z];=*
+MJ\_Y[>;Y,2:6WZ;USS=1>WC^^4&<GCPOL(V"\+PV'M^T_)+G"SD]W^3Y"*?/
+MOVGX<*#>Y?E''F+YC[7V(UG^,PU>7C^2R?8'L[>Q?(]6_PZ6%T5.WWM8?BC/
+M-UHY?7G>PN?CS3S_"%?8=_'\X]>R_'T\+W!Y6<CS@6R67Z*UY^7KM#R7]ZTB
+MTW\O<_TG\_(--['RIWA^XO4L_Q.>?YZW_V<MS^7[%3&=GP=X>60,RP=YOH/+
+M7RO/.[EA\&>>?V4<RW^BP5O,Z=VK_R^U_CF\/1J\LWB%+([/]UEV(,\[^7P;
+MEI7>7RXO)P,!?C=DL?7GE?TL?PLO#W'\"WJUGYK%;%2M_KV\_C$NOW-X?B*7
+MUW)M/#Y?5O!\I(3E-_#\CP:S?)TV?@[+RQH^7)XJ*V<MFE_DF'.?4+ETV?IJ
+MMU"Y=L/6RK7K5U1.JJK9`,65E=72NBIW[88JR)3,6S"S:%[E@N+B^^T+*Q<6
+MS9QGKX37:S=4KJA:N51:XZZLKM*VDMAV^9JME>ZERZC*ULI'J]R5F]S5.,2Z
+MRDT;<3!LJC6H7"FM6\Y>I7KA+PDH:0T'BMI+RX3>O6ZM7"_URE0OW2)HW;&W
+MRZ'_3:OPN7(3-%U;M79]=2T-XUZU?MTFUCL2H"!57UK%7TMKV,.*59O9P](5
+M*S@8RU=4U;AU(%&3C96KUJURLZK04:H8>R14ERW=5+6)O=]05;VR:CDTW2@M
+MK:ZJY+5AJ"3:E`/8V#.,S2%CM;1G))3VC,,3GD05>K5)3[`-U>N7+5T&R:JU
+MR1&7KZE>QH#>",]52ZO36;RRNJI*Z-O3RJ7+:53`HGI]=9),G)+2.L`:N7N?
+M5%U=M<Y=!D(U#SB\IBHE<=BZ>NFZ%>O7<MC6;UG;!Q%>G8A`CVG,9=360YL2
+M1VK'&;>5#S0I-1)':=56K,J[K)S%>ND#+4=,DXOJ38^M6LE!8X*-M"/9J*S<
+M5/VH!C:G)A8B[=9):SF5F6BPMRNJUK$,E[:-E4F@U^K9GP8#"AH7R34Z8%:M
+MV\"F`-985_6H4%GE3HHI0EI=M3;5=9+80(]DOTF:(VE6K4-Y3?6=Y'Y*SK1F
+MVOQ,EFB=:[602RA+NBE.$%*C]=6IRDFY1LQ7;I#<?+X`!_6\3,Y#3FOM#9$1
+MF_%!EB[;E"1@<B(EY[J@EV_$H6K%4O?2)#!0S`2YB@V^,0WI1U-,U81B^:ID
+M7WJ2)I\?37&<B366?/?[[O?=[[O?=[_O?M_]OOM]]_ON]]WON]]WO^]^___^
+MX;FU)2`(MP2^?1L\J]L-_S^R3A`:-PA"(3\<1!?R*S\4A&?100[E+08A>2[X
+M3;]`UR4Z,0^HYR$=`.GGD&9#>A92(Z0?0SH0TE.0YD#Z#J2#(#T*J0E2C+@;
+M#.EKD`Z!]%=X:0[27]`5R(#Z'*1#(7T*TF&0XNV[JR#=#JD5TJV07@UI-:3#
+M(5T-Z0A(ET&:"^EB2*^!M`S2:R&="^EUD,Z$="2D=T-Z/:23(!T%Z:UX?Q+2
+ML9".@?1:2&^`=!BD8R'-@?1&2/&;N^,@O70YD;@)\8?T9L0?TEL0?TCS$'](
+M;T7\(<U'_"&]#?&']'N(/Z03$7]("Q!_2"<A_I#>@?A#.AGQA_1.Q!_2NQ!_
+M2*<@_I!.1?PAM2'^D-Z-^$-Z#^(/Z33$'])[$7](IR/^D,Y`_"$MI'@)9#_Z
+MU-$%CFYM/&K#X[H17$8R=?E[,@3ANN'P_()!^%M.IE!Y1Y;PM['_I[WSCHZZ
+M".+XC^0(26@!0B\)B=(3$GHH!@A50NBAA'"$%#@@"7B$HJ"@(*!B:*(B8)`>
+M05"0J@B$(D4@TJ1W07H-4@1G?C?SV[G#`D]X/-^[_8?O[.YO;_>WLS.;>Y^$
+MS`+X_SCHW[O3E^_9^$MX\6\V!UMSZ/]/[?_VO&/[TW[^?VZG\N@/*@\?_O%7
+MQ;%6R^;B:LKNEL/=@RH\<^;*G2>O5[[\!;P+%BI<I&BQXB5*EO+Q+>WG_V3M
+M+[CT[MVG;]_$)/Q[(/U?LUH'I*0,'#1H\)`AK[_QQM!AP]Y\:_CP$2/>?N>=
+MD:-&O3MZ])BQ8]][__T/QHW[,#5U_/@)$R=.FCSYHRE3/O[XDT\_G?K99].F
+M39\QX_.TM)DSOY@U:_;L.7/GSILW?\&"]/0O%RY<M.BKQ8N7+/GZFV^6+EWV
+M[;?+EZ]8L7+5JM6KUZSY[OOOUZ[]8=VZ]>LW;,C(V+AIT^;-6[;\N'7KMFW;
+MM^_8\=/.G;MV[=Z=F?GSGCU[]^[;MW__@0._'#QXZ-#APT>.'#UZ[-CQ$R=.
+MGCQUZO3I,V?.GOWUUW/GSI__[<*%BQ<O7;I\^<J5JU>O7;M^_<:-FS=OW;I]
+M.ROKSIW??[][]]Z]^_<?/,`]?Z2[GHN+JZO)E#V[FUN.'.[N'AZ>GCESYLJ5
+M.W>>/'GS>GEYY<N7/W^!`M[>!0L6*E2H<.$B18H6+5:L>/'B)4J4+%FJE(^/
+MKZ]OZ=)^?O[^_B^]]/++9<J4+5NV7+GRY2M4J%"Q8J5*`0$!@8&5*P<%!04'
+M5ZE2I6K5:M6J5Z]>HT;-FC5KU0H)":E=NTZ=.G7KUJM7[Y570D/KUZ_?H$&#
+MA@W#PL(:-6K<N'&3)DV;-FW6K'GSYJ^^VJ)%B_#P\)8M(R(B6K5JW;IUFS9M
+MVK9MUZY=^_;M.W2(C(SLV+%CITZ=.W?NTJ5+5%14UZ[1T='=NG4SF[MW[QX3
+M$].C1X_8V-BXN/CX^(2$A)X]>_;JU<OB_&K569S%69S%69S%69SE&1=DPG24
+M;KR-B6=6%_$WYG*K:HK)1<R*>=Q(3;&X<9KB<!&]9`9WA*;XVRF:8F]G:XJ[
+M7:0IYG8UCU-$T[9HBK7=JRFN]H2FF%KF:Y&G-0F6UDMPM$4%0^LG^-F*@IVM
+M*;C9,,',MA2\;*1@97L(3C9),+(C!1\[4;"Q,P07FRZ8V.6"A]T@6-B]@H,]
+M)1C8K&R*?W41[&MNP;WZ".:UDN!=F85%MK6)X%;;"D;5+/C41,&F#A)<ZBC!
+MI*8*'G6.8%$7"PZ5F59D4#>[*/YTMXMB2T_PYT9IVB47Q91F\3P]X&=AKH?W
+MXRFXT<*"&?45O&B`8$5K"$XT5#"BX8(/C1)L:)S@0OL))G28X$'?%2SH.,&!
+M3F7&MHZFS>/^WIJVU%6QG]_Q^+WAW;DJYO,@SQG>_P57Q7K>Y/X1BC%%QM-+
+M\)T^@NTL)[C.8,%TUA,\9Q/!;K82W&:48#;C!*^9*%C-@8++?$LPF6-X#A`H
+M)O`XX%=3F6-MKFFS3(JY3&=>%N:VU*38RI4FQ55NY/%A3S-Y'/"3XSP'_&/7
+M)L51,B.*#*5)\)/YLMM^_P!CEP]K>'<!I'%/:Y%&'P@CC7X501K/6A1I]*4$
+MTNAC_4GC?@WE/K"@T:1Q/E.X'M8RAS3ZZC*>#ZPW@\<!G4FZ.ZSK.&GTGPL\
+M)N@L'A/B@YL;:3COWJ0Q5OB11C\,XGK8ZU#2N.\M26,<ZPH:_XQKZXF:9B4]
+M`'0JZ4]`+Z3^&*O7\)@0J[>17@+Z(&D\.^=Y;N"3-TFC[SWD_N!C'CEH3/`K
+M;]+H8SZD,3=5)HTQ-I0TYI16I#%'1/.SH/N01C\<R/7X:^U<#W%I`H\)YS>-
+MQX'XLY`TYHC5W!_.Q2;2&+OV<#WXV"F>#^CK/";$F0>D,9:ZN],:(>9XD\;X
+M4YHTYHN*I#$^AY#&,]N(->2.MMP'SETTUT,>Z4-:/Z<\/IR1D:3Q#*9R'\A'
+MTWD^<&;GD\;XO(R?!9U!&O-C)C\+^CAIC,F7>/Z@'_!G0;S*Z4']01<CC?FE
+M#&G,4]6Y#^@PTABOVI#&^-"5-.:=7J2'@Q[L8;O'H/Z`]!S0:3P.Y-`E'C:_
+M39ND:3NI'N\JA[A^,L0-UA_!D?&D^4.<\2>-N2F8-.:%4-)X]PCG>M"=2.-]
+M(Y8TWD.2N`_<)8:0QOO/2-)X)TGE/I`79O#X<,=(YWK(LZMX/J`S/&WK19WI
+M:<>'.X#A_U,6W(F`/W\$W![]EGCW"\:ZGP[==A+;SX38?EI4^TD8[;^ELY\K
+ME@W+IR@6:$W6*'HD)%EMEKY=+&%O6<*$#8G>Q`8LC26LFR5,B"4LF25-1YJP
+M(.,9^U;KXZU6B[12I*5F;"$-WD3!@&W;P6;+%AR,OKKGL47GS]XTND)T`Q=^
+MW`RT11_K8]6OQ5LM<2GQYL28?H^U6?MCLSEH<'!0D"8"/@]/(9]-<GYIRM9D
+MHP6F;*Q4S=W86]TY67(^9)LCM=%.><H84,\\TDJ1EGBGB:(%3=84`J3)VI9_
+MA&7,(DZ.1MZL&O4P(OK*CK*7L4@YFNAN/ZQZUOX#Q$"V+"4L8U7ZJ126\>KC
+MY&<8!\06ZHR5Q]OY04_A_YQYE2L;!Q)\P&K_H,5J]Z3%:O>HQ3@[1A:T,RW2
+M2I&6<D';*3([3-K!#@P/"_J+NF"[!&P\I^Q`<XPUUF(Q#TC6@Q]?M&R?;NA`
+M<_S`>+C$P)%/'JQ?T.P:D^&%.[1Q`.6!;#9;?>TL_0K`!OB-TNP%26K?D]01
+E2%*;GN2XS9#1*/SJ%R<CU-@N#+JI7^CLE/X2_P0U&_WFG;0``.P%
+`
+end
diff --git a/lib/csu/i386/Makefile b/lib/csu/i386/Makefile
index dfaf293..7a7ab1b 100644
--- a/lib/csu/i386/Makefile
+++ b/lib/csu/i386/Makefile
@@ -1,25 +1,62 @@
-# @(#)Makefile 8.1 (Berkeley) 6/1/93
+# from: @(#)Makefile 5.6 (Berkeley) 5/22/91
+# $Id: Makefile,v 1.30 1997/04/02 16:49:18 jdp Exp $
-CFLAGS= -O -DLIBC_SCCS
-OBJS= crt0.o gcrt0.o
-CLEANFILES+= core a.out
+CFLAGS+= -DLIBC_SCCS -fno-omit-frame-pointer -I${.CURDIR}
+OBJS= crt0.o c++rt0.o gcrt0.o scrt0.o sgcrt0.o
+CLEANFILES+= a.out
+MAN3+= dlopen.3
+MLINKS+= dlopen.3 dlsym.3 \
+ dlopen.3 dlerror.3 \
+ dlopen.3 dlclose.3
all: ${OBJS}
crt0.o: crt0.c
- ${CC} ${CFLAGS} -c -DCRT0 ${.ALLSRC}
+ ${CC} ${CFLAGS} -c -DCRT0 -DDYNAMIC ${.CURDIR}/crt0.c -o ${.TARGET}
${LD} -x -r ${.TARGET}
- mv a.out ${.TARGET}
+ mv -f a.out ${.TARGET}
-gcrt0.o: crt0.c
- ${CC} ${CFLAGS} -c -DMCRT0 ${.ALLSRC} -o ${.TARGET}
+c++rt0.o: c++rt0.c
+ ${CC} ${CFLAGS} -fpic -c ${.CURDIR}/c++rt0.c
+ @${LD} -x -r ${.TARGET}
+ @mv -f a.out ${.TARGET}
+
+#
+# gcrt0.o doesn't really depend on crt0.o, but this is the easiest way
+# to get the dependencies mostly correct.
+#
+gcrt0.o: crt0.o
+ ${CC} ${CFLAGS} -c -DMCRT0 -DDYNAMIC ${.CURDIR}/crt0.c -o ${.TARGET}
+ ${LD} -x -r ${.TARGET}
+ mv -f a.out ${.TARGET}
+
+# dependencies fudged as for gcrt0.o
+scrt0.o: crt0.o
+ ${CC} ${CFLAGS} -c -DCRT0 ${.CURDIR}/crt0.c -o ${.TARGET}
+ ${LD} -x -r ${.TARGET}
+ mv -f a.out ${.TARGET}
+
+# dependencies fudged as for gcrt0.o
+sgcrt0.o: scrt0.o
+ ${CC} ${CFLAGS} -c -DMCRT0 ${.CURDIR}/crt0.c -o ${.TARGET}
${LD} -x -r ${.TARGET}
- mv a.out ${.TARGET}
+ mv -f a.out ${.TARGET}
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/dlfcn.h \
+ ${DESTDIR}/usr/include
+
+realinstall:
+ ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m 444 ${OBJS} \
+ ${DESTDIR}/usr/lib
+
+depend: .depend
-install:
- install -o ${BINOWN} -g ${BINGRP} -m 444 ${OBJS} \
- ${DESTDIR}/usr/lib
+.depend: crt0.c c++rt0.c
+ rm -f .depend
+ mkdep ${CFLAGS} -DCRT0 -DDYNAMIC ${.CURDIR}/crt0.c
+ mkdep -a ${CFLAGS} ${.CURDIR}/c++rt0.c
-depend lint tags:
+lint tags:
.include <bsd.prog.mk>
diff --git a/lib/csu/i386/c++rt0.c b/lib/csu/i386/c++rt0.c
new file mode 100644
index 0000000..413524f
--- /dev/null
+++ b/lib/csu/i386/c++rt0.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1993 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.
+ *
+ * $Id: c++rt0.c,v 1.7 1997/02/22 14:57:42 peter Exp $
+ */
+
+/*
+ * Run-time module for GNU C++ compiled shared libraries.
+ *
+ * The linker constructs the following arrays of pointers to global
+ * constructors and destructors. The first element contains the
+ * number of pointers in each.
+ * The tables are also null-terminated.
+ */
+extern void (*__CTOR_LIST__[])(void);
+extern void (*__DTOR_LIST__[])(void);
+
+static void
+__dtors(void)
+{
+ unsigned long i = (unsigned long) __DTOR_LIST__[0];
+ void (**p)(void) = __DTOR_LIST__ + i;
+
+ while (i--)
+ (**p--)();
+}
+
+static void
+__ctors(void)
+{
+ void (**p)(void) = __CTOR_LIST__ + 1;
+
+ while (*p)
+ (**p++)();
+}
+
+extern void __init() asm(".init");
+extern void __fini() asm(".fini");
+
+void
+__init(void)
+{
+ static int initialized = 0;
+
+ /*
+ * Call global constructors.
+ * Arrange to call global destructors at exit.
+ */
+ if (!initialized) {
+ initialized = 1;
+ __ctors();
+ }
+
+}
+
+void
+__fini(void)
+{
+ __dtors();
+}
+
+/*
+ * Make sure there is at least one constructor and one destructor in the
+ * shared library. Otherwise, the linker does not realize that the
+ * constructor and destructor lists are linker sets. It treats them as
+ * commons and resolves them to the lists from the main program. That
+ * causes multiple invocations of the main program's static constructors
+ * and destructors, which is very bad.
+ */
+
+static void
+do_nothing(void)
+{
+}
+
+/* Linker magic to add an element to a constructor or destructor list. */
+#define TEXT_SET(set, sym) \
+ asm(".stabs \"_" #set "\", 23, 0, 0, _" #sym)
+
+TEXT_SET(__CTOR_LIST__, do_nothing);
+TEXT_SET(__DTOR_LIST__, do_nothing);
diff --git a/lib/csu/i386/crt0.c b/lib/csu/i386/crt0.c
index 77f9382..5f7e4ab 100644
--- a/lib/csu/i386/crt0.c
+++ b/lib/csu/i386/crt0.c
@@ -1,6 +1,6 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -12,54 +12,122 @@
* 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 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.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (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$
*/
-#ifndef lint
-static char sccsid[] = "@(#)crt0.c 8.1 (Berkeley) 6/1/93";
-#endif /* not lint */
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <dlfcn.h>
+
+#ifdef DYNAMIC
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <a.out.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <link.h>
+
+/* !!!
+ * This is gross, ld.so is a ZMAGIC a.out, but has `sizeof(hdr)' for
+ * an entry point and not at PAGSIZ as the N_*ADDR macros assume.
+ */
+#undef N_DATADDR
+#define N_DATADDR(x) ((x).a_text)
+
+#undef N_BSSADDR
+#define N_BSSADDR(x) ((x).a_text + (x).a_data)
+
+#ifndef N_GETMAGIC
+#define N_GETMAGIC(x) ((x).a_magic)
+#endif /* N_GETMAGIC */
+
+#ifndef MAP_PRIVATE
+#define MAP_PRIVATE MAP_COPY
+#endif /* MAP_PRIVATE */
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif /* MAP_FILE */
+#ifndef MAP_ANON
+#define MAP_ANON 0
+#endif /* MAP_ANON */
+
+#ifdef DEBUG
/*
- * C start up routine.
- * Robert Henry, UCB, 20 Oct 81
- *
- * We make the following (true) assumption:
- * 1) The only register variable that we can trust is ebp,
- * which points to the base of the kernel calling frame.
+ * We need these two because we are going to call them before the ld.so is
+ * finished (as a matter of fact before we know if it exists !) so we must
+ * provide these versions for them
*/
+static char *_getenv();
+static int _strncmp();
+#endif /* DEBUG */
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
+#ifndef LDSO
+#define LDSO "/usr/libexec/ld.so"
+#endif /* LDSO */
-char **environ = (char **)0;
-static char empty[1];
-char *__progname = empty;
-static int fd;
+extern struct _dynamic _DYNAMIC;
+static struct ld_entry *ld_entry;
+static void __do_dynamic_link ();
+#endif /* DYNAMIC */
-asm(".text");
-asm(".long 0xc000c000");
+int _callmain();
+int errno;
+static char empty[1];
+char *__progname = empty;
+char **environ;
extern unsigned char etext;
extern unsigned char eprol asm ("eprol");
extern start() asm("start");
+extern mcount() asm ("mcount");
+extern int main(int argc, char **argv, char **envp);
+int __syscall(int syscall,...);
+#ifdef MCRT0
+void monstartup(void *low, void *high);
+#endif /* MCRT0 */
+
+/*
+ * We need these system calls, but can't use library stubs because the are
+ * not accessible until we have done the ld.so stunt.
+ */
+
+#define _exit(v) \
+ __syscall(SYS_exit, (int)(v))
+#define _open(name, f, m) \
+ __syscall(SYS_open, (char *)(name), (int)(f), (int)(m))
+#define _read(fd, s, n) \
+ __syscall(SYS_read, (int)(fd), (void *)(s), (size_t)(n))
+#define _write(fd, s, n) \
+ __syscall(SYS_write, (int)(fd), (void *)(s), (size_t)(n))
+#define _mmap(addr, len, prot, flags, fd, off) \
+ (caddr_t) __syscall(SYS_mmap, (caddr_t)(addr), (size_t)(len), \
+ (int)(prot), (int)(flags), (int)(fd), (long)0L, (off_t)(off))
+
+#define _PUTNMSG(str, len) _write(2, (str), (len))
+#define _PUTMSG(str) _PUTNMSG((str), sizeof (str) - 1)
+#define _FATAL(str) ( _PUTMSG(str), _exit(1) )
+
+
+int
start()
{
struct kframe {
@@ -71,60 +139,295 @@ start()
/*
* ALL REGISTER VARIABLES!!!
*/
- register struct kframe *kfp; /* r10 */
+ register struct kframe *kfp;
register char **targv;
register char **argv;
- extern int errno;
extern void _mcleanup();
+#ifdef DYNAMIC
+ volatile caddr_t x;
+#endif
#ifdef lint
kfp = 0;
- initcode = initcode = 0;
-#else
- asm("lea 4(%ebp),%ebx"); /* catch it quick */
-#endif
+#else /* not lint */
+ /* just above the saved frame pointer */
+ asm ("lea 4(%%ebp), %0" : "=r" (kfp) );
+#endif /* not lint */
for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
/* void */ ;
if (targv >= (char **)(*argv))
--targv;
environ = targv;
-asm("eprol:");
-#ifdef paranoid
- /*
- * The standard I/O library assumes that file descriptors 0, 1, and 2
- * are open. If one of these descriptors is closed prior to the start
- * of the process, I/O gets very confused. To avoid this problem, we
- * insure that the first three file descriptors are open before calling
- * main(). Normally this is undefined, as it adds two unnecessary
- * system calls.
- */
- do {
- fd = open("/dev/null", 2);
- } while (fd >= 0 && fd < 3);
- close(fd);
-#endif
+ if (argv[0]) {
+ register char *s;
+ __progname = argv[0];
+ for (s=__progname; *s != '\0'; s++)
+ if (*s == '/')
+ __progname = s+1;
+ }
+
+#ifdef DYNAMIC
+ /* ld(1) convention: if DYNAMIC = 0 then statically linked */
+ /* sometimes GCC is too smart/stupid for its own good */
+ x = (caddr_t)&_DYNAMIC;
+ if (x)
+ __do_dynamic_link();
+#endif /* DYNAMIC */
+
+asm("eprol:");
#ifdef MCRT0
atexit(_mcleanup);
monstartup(&eprol, &etext);
-#endif
- errno = 0;
- if (argv[0])
- if ((__progname = strrchr(argv[0], '/')) == NULL)
- __progname = argv[0];
- else
- ++__progname;
+#endif /* MCRT0 */
+
+asm ("__callmain:"); /* Defined for the benefit of debuggers */
exit(main(kfp->kargc, argv, environ));
}
-#ifdef CRT0
+#ifdef DYNAMIC
+static void
+__do_dynamic_link ()
+{
+ struct crt_ldso crt;
+ struct exec hdr;
+ char *ldso;
+ int (*entry)();
+ int ret;
+
+#ifdef DEBUG
+ /* Provision for alternate ld.so - security risk! */
+ if (!(ldso = _getenv("LDSO")))
+#endif
+ ldso = LDSO;
+
+ crt.crt_ldfd = _open(ldso, 0, 0);
+ if (crt.crt_ldfd == -1) {
+ _PUTMSG("Couldn't open ");
+ _PUTMSG(LDSO);
+ _FATAL(".\n");
+ }
+
+ /* Read LDSO exec header */
+ if (_read(crt.crt_ldfd, &hdr, sizeof hdr) < sizeof hdr) {
+ _FATAL("Failure reading ld.so\n");
+ }
+ if ((N_GETMAGIC_NET(hdr) != ZMAGIC) && (N_GETMAGIC(hdr) != QMAGIC)) {
+ _FATAL("Bad magic: ld.so\n");
+ }
+
+ /* We use MAP_ANON */
+ crt.crt_dzfd = -1;
+
+ /* Map in ld.so */
+ crt.crt_ba = (int)_mmap(0, hdr.a_text,
+ PROT_READ|PROT_EXEC,
+ MAP_FILE|MAP_PRIVATE,
+ crt.crt_ldfd, N_TXTOFF(hdr));
+ if (crt.crt_ba == -1) {
+ _FATAL("Cannot map ld.so (text)\n");
+ }
+
+ /* Map in data segment of ld.so writable */
+ if ((int)_mmap((caddr_t)(crt.crt_ba+N_DATADDR(hdr)), hdr.a_data,
+ PROT_READ|PROT_WRITE,
+ MAP_FIXED|MAP_FILE|MAP_PRIVATE,
+ crt.crt_ldfd, N_DATOFF(hdr)) == -1) {
+ _FATAL("Cannot map ld.so (data)\n");
+ }
+
+ /* Map bss segment of ld.so zero */
+ if (hdr.a_bss && (int)_mmap((caddr_t)(crt.crt_ba+N_BSSADDR(hdr)),
+ hdr.a_bss,
+ PROT_READ|PROT_WRITE,
+ MAP_FIXED|MAP_ANON|MAP_PRIVATE,
+ crt.crt_dzfd, 0) == -1) {
+ _FATAL("Cannot map ld.so (bss)\n");
+ }
+
+ crt.crt_dp = &_DYNAMIC;
+ crt.crt_ep = environ;
+ crt.crt_bp = (caddr_t)_callmain;
+ crt.crt_prog = __progname;
+ crt.crt_ldso = ldso;
+ crt.crt_ldentry = NULL;
+
+ entry = (int (*)())(crt.crt_ba + sizeof hdr);
+ ret = (*entry)(CRT_VERSION_BSD_4, &crt);
+ ld_entry = crt.crt_ldentry;
+ if (ret == -1 && ld_entry == NULL) {
+ /* if version 4 not recognised, try version 3 */
+ ret = (*entry)(CRT_VERSION_BSD_3, &crt);
+ ld_entry = _DYNAMIC.d_entry;
+ }
+ if (ret == -1) {
+ _PUTMSG("ld.so failed");
+ if (ld_entry != NULL) {
+ char *msg = (ld_entry->dlerror)();
+ if(msg != NULL) {
+ char *endp;
+ _PUTMSG(": ");
+ for(endp = msg; *endp != '\0'; ++endp)
+ ; /* Find the end */
+ _PUTNMSG(msg, endp - msg);
+ }
+ }
+ _FATAL("\n");
+ }
+
+
+ if (ret >= LDSO_VERSION_HAS_DLEXIT)
+ atexit(ld_entry->dlexit);
+
+ return;
+}
+
+/*
+ * DL stubs
+ */
+
+void *
+dlopen(name, mode)
+char *name;
+int mode;
+{
+ if (ld_entry == NULL)
+ return NULL;
+
+ return (ld_entry->dlopen)(name, mode);
+}
+
+int
+dlclose(fd)
+void *fd;
+{
+ if (ld_entry == NULL)
+ return -1;
+
+ return (ld_entry->dlclose)(fd);
+}
+
+void *
+dlsym(fd, name)
+void *fd;
+char *name;
+{
+ if (ld_entry == NULL)
+ return NULL;
+
+ return (ld_entry->dlsym)(fd, name);
+}
+
+
+char *
+dlerror()
+{
+ if (ld_entry == NULL)
+ return "Service unavailable";
+
+ return (ld_entry->dlerror)();
+}
+
+
+/*
+ * Support routines
+ */
+
+#ifdef DEBUG
+static int
+_strncmp(s1, s2, n)
+ register char *s1, *s2;
+ register n;
+{
+
+ if (n == 0)
+ return (0);
+ do {
+ if (*s1 != *s2++)
+ return (*(unsigned char *)s1 - *(unsigned char *)--s2);
+ if (*s1++ == 0)
+ break;
+ } while (--n != 0);
+ return (0);
+}
+
+static char *
+_getenv(name)
+ register char *name;
+{
+ extern char **environ;
+ register int len;
+ register char **P, *C;
+
+ for (C = name, len = 0; *C && *C != '='; ++C, ++len);
+ for (P = environ; *P; ++P)
+ if (!_strncmp(*P, name, len))
+ if (*(C = *P + len) == '=') {
+ return(++C);
+ }
+ return (char *)0;
+}
+
+#endif /* DEBUG */
+
+ asm(" ___syscall:");
+ asm(" popl %ecx");
+ asm(" popl %eax");
+ asm(" pushl %ecx");
+ asm(" .byte 0x9a");
+ asm(" .long 0");
+ asm(" .word 7");
+ asm(" pushl %ecx");
+ asm(" jc 1f");
+ asm(" ret");
+ asm(" 1:");
+ asm(" movl $-1,%eax");
+ asm(" ret");
+
+#else /* DYNAMIC */
+
/*
- * null moncontrol just in case some routine is compiled for profiling
+ * DL stubs for static linking case (just return error)
*/
-moncontrol(val)
- int val;
+
+void *
+dlopen(name, mode)
+char *name;
+int mode;
+{
+ return NULL;
+}
+
+int
+dlclose(fd)
+void *fd;
{
+ return -1;
+}
+void *
+dlsym(fd, name)
+void *fd;
+char *name;
+{
+ return NULL;
+}
+
+
+char *
+dlerror()
+{
+ return "Service unavailable";
}
+#endif /* DYNAMIC */
+
+
+/*
+ * Support routines
+ */
+
+#ifdef MCRT0
+asm (" .text");
+asm ("_eprol:");
#endif
diff --git a/lib/csu/i386/dlfcn.h b/lib/csu/i386/dlfcn.h
new file mode 100644
index 0000000..feadf90
--- /dev/null
+++ b/lib/csu/i386/dlfcn.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ *
+ * @(#)err.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _DLFCN_H_
+#define _DLFCN_H_
+#include <sys/cdefs.h>
+
+/*
+ * Modes for dlopen().
+ */
+#define RTLD_LAZY 1 /* Bind function calls lazily */
+#define RTLD_NOW 2 /* Bind function calls immediately */
+
+__BEGIN_DECLS
+void *dlopen __P((char *, int));
+void *dlsym __P((void *, char *));
+char *dlerror __P((void));
+int dlclose __P((void *));
+__END_DECLS
+
+#endif /* !_DLFCN_H_ */
diff --git a/lib/csu/i386/dlopen.3 b/lib/csu/i386/dlopen.3
new file mode 100644
index 0000000..82651c6
--- /dev/null
+++ b/lib/csu/i386/dlopen.3
@@ -0,0 +1,213 @@
+.\" 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
+.Dd September 24, 1989
+.Os FreeBSD
+.Dt DLOPEN 3
+.Sh NAME
+.Nm dlopen, dlsym, dlerror, dlclose
+.Nd programmatic interface to the dynamic linker
+.Sh SYNOPSIS
+.Fd #include <dlfcn.h>
+.Ft void *
+.Fn dlopen "char *path" "int mode"
+.Ft void *
+.Fn dlsym "void *handle" "char *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
+.Fn dlopen
+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.
+(Note that
+.Ql _init
+is the name as expressed in the C language.
+From assembly language, the name would appear as
+.Ql __init
+instead.)
+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.
+.Fa mode
+controls the way in which external function references from the
+loaded object are bound to their referents.
+It must contains one of the following values:
+.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 .
+If
+.Fn dlopen
+fails, it returns a null pointer, and sets an error condition which may
+be interrogated with
+.Fn dlerror .
+.Pp
+.Fn dlsym
+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 .
+Note that
+.Fa symbol
+is the assembly language representation of the symbol name.
+The assembly language representation of a C language symbol contains an
+extra underscore at the beginning.
+For example, the symbol
+.Ql foo
+in C would appear as
+.Ql _foo
+in assembly language, and in the
+.Fa symbol
+argument to
+.Fn dlsym .
+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.
+A null pointer supplied as the value of
+.Fa handle
+is interpreted as a reference to the executable from which the call to
+.Fn dlsym
+is being made. Thus a shared object can reference its own symbols.
+.Fn dlsym
+returns a null pointer if the symbol cannot be found, and sets an error
+condition which may be queried with
+.Fn dlerror .
+.Pp
+.Fn dlerror
+returns a null-terminated character string describing the last error that
+occurred during a call to
+.Fn dlopen ,
+.Fn dlsym ,
+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
+.Fn dlclose
+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.
+As with
+.Ql _init ,
+.Ql _fini
+is the C language name of the function.
+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 ERRORS
+.Fn dlopen
+and
+.Fn dlsym
+return the null pointer in the event of errors.
+.Fn dlclose
+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 link 5 ,
+.Xr rtld 1
diff --git a/lib/libF77/F77_aloc.c b/lib/libF77/F77_aloc.c
new file mode 100644
index 0000000..e8ba744
--- /dev/null
+++ b/lib/libF77/F77_aloc.c
@@ -0,0 +1,32 @@
+#include "f2c.h"
+#undef abs
+#undef min
+#undef max
+#include "stdio.h"
+
+static integer memfailure = 3;
+
+#ifdef KR_headers
+extern char *malloc();
+extern void exit_();
+
+ char *
+F77_aloc(Len, whence) integer Len; char *whence;
+#else
+#include "stdlib.h"
+extern void exit_(integer*);
+
+ char *
+F77_aloc(integer Len, char *whence)
+#endif
+{
+ char *rv;
+ unsigned int uLen = (unsigned int) Len; /* for K&R C */
+
+ if (!(rv = (char*)malloc(uLen))) {
+ fprintf(stderr, "malloc(%u) failure in %s\n",
+ uLen, whence);
+ exit_(&memfailure);
+ }
+ return rv;
+ }
diff --git a/lib/libF77/Notice b/lib/libF77/Notice
new file mode 100644
index 0000000..64af9f1
--- /dev/null
+++ b/lib/libF77/Notice
@@ -0,0 +1,23 @@
+/****************************************************************
+Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories and Bellcore.
+
+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 names of AT&T Bell Laboratories or
+Bellcore or any of their entities not be used in advertising or
+publicity pertaining to distribution of the software without
+specific, written prior permission.
+
+AT&T and Bellcore disclaim all warranties with regard to this
+software, including all implied warranties of merchantability
+and fitness. In no event shall AT&T or Bellcore 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.
+****************************************************************/
+
diff --git a/lib/libF77/README b/lib/libF77/README
new file mode 100644
index 0000000..7668215
--- /dev/null
+++ b/lib/libF77/README
@@ -0,0 +1,108 @@
+If your compiler does not recognize ANSI C headers,
+compile with KR_headers defined: either add -DKR_headers
+to the definition of CFLAGS in the makefile, or insert
+
+#define KR_headers
+
+at the top of f2c.h , cabs.c , main.c , and sig_die.c .
+
+Under MS-DOS, compile s_paus.c with -DMSDOS.
+
+If you have a really ancient K&R C compiler that does not understand
+void, add -Dvoid=int to the definition of CFLAGS in the makefile.
+
+If you use a C++ compiler, first create a local f2c.h by appending
+f2ch.add to the usual f2c.h, e.g., by issuing the command
+ make f2c.h
+which assumes f2c.h is installed in /usr/include .
+
+If your system lacks onexit() and you are not using an ANSI C
+compiler, then you should compile main.c, s_paus.c, s_stop.c, and
+sig_die.c with NO_ONEXIT defined. See the comments about onexit in
+the makefile.
+
+If your system has a double drem() function such that drem(a,b)
+is the IEEE remainder function (with double a, b), then you may
+wish to compile r_mod.c and d_mod.c with IEEE_drem defined.
+On some systems, you may also need to compile with -Ddrem=remainder .
+
+To check for transmission errors, issue the command
+ make check
+This assumes you have the xsum program whose source, xsum.c,
+is distributed as part of "all from f2c/src". If you do not
+have xsum, you can obtain xsum.c by sending the following E-mail
+message to netlib@netlib.bell-labs.com
+ send xsum.c from f2c/src
+
+The makefile assumes you have installed f2c.h in a standard
+place (and does not cause recompilation when f2c.h is changed);
+f2c.h comes with "all from f2c" (the source for f2c) and is
+available separately ("f2c.h from f2c").
+
+Most of the routines in libF77 are support routines for Fortran
+intrinsic functions or for operations that f2c chooses not
+to do "in line". There are a few exceptions, summarized below --
+functions and subroutines that appear to your program as ordinary
+external Fortran routines.
+
+1. CALL ABORT prints a message and causes a core dump.
+
+2. ERF(r) and DERF(d) and the REAL and DOUBLE PRECISION
+ error functions (with x REAL and d DOUBLE PRECISION);
+ DERF must be declared DOUBLE PRECISION in your program.
+ Both ERF and DERF assume your C library provides the
+ underlying erf() function (which not all systems do).
+
+3. ERFC(r) and DERFC(d) are the complementary error functions:
+ ERFC(r) = 1 - ERF(r) and DERFC(d) = 1.d0 - DERFC(d)
+ (except that their results may be more accurate than
+ explicitly evaluating the above formulae would give).
+ Again, ERFC and r are REAL, and DERFC and d are DOUBLE
+ PRECISION (and must be declared as such in your program),
+ and ERFC and DERFC rely on your system's erfc().
+
+4. CALL GETARG(n,s), where n is an INTEGER and s is a CHARACTER
+ variable, sets s to the n-th command-line argument (or to
+ all blanks if there are fewer than n command-line arguments);
+ CALL GETARG(0,s) sets s to the name of the program (on systems
+ that support this feature). See IARGC below.
+
+5. CALL GETENV(name, value), where name and value are of type
+ CHARACTER, sets value to the environment value, $name, of
+ name (or to blanks if $name has not been set).
+
+6. NARGS = IARGC() sets NARGS to the number of command-line
+ arguments (an INTEGER value).
+
+7. CALL SIGNAL(n,func), where n is an INTEGER and func is an
+ EXTERNAL procedure, arranges for func to be invoked when
+ signal n occurs (on systems where this makes sense).
+
+8. CALL SYSTEM(cmd), where cmd is of type CHARACTER, passes
+ cmd to the system's command processor (on systems where
+ this can be done).
+
+The makefile does not attempt to compile pow_qq.c, qbitbits.c,
+and qbitshft.c, which are meant for use with INTEGER*8. To use
+INTEGER*8, you must modify f2c.h to declare longint and ulongint
+appropriately; then add pow_qq.o to the POW = line in the makefile,
+and add " qbitbits.o qbitshft.o" to the makefile's F90BIT = line.
+
+Following Fortran 90, s_cat.c and s_copy.c allow the target of a
+(character string) assignment to be appear on its right-hand, at
+the cost of some extra overhead for all run-time concatenations.
+If you prefer the extra efficiency that comes with the Fortran 77
+requirement that the left-hand side of a character assignment not
+be involved in the right-hand side, compile s_cat.c and s_copy.c
+with -DNO_OVERWRITE .
+
+If your system lacks a ranlib command, you don't need it.
+Either comment out the makefile's ranlib invocation, or install
+a harmless "ranlib" command somewhere in your PATH, such as the
+one-line shell script
+
+ exit 0
+
+or (on some systems)
+
+ exec /usr/bin/ar lts $1 >/dev/null
diff --git a/lib/libF77/Version.c b/lib/libF77/Version.c
new file mode 100644
index 0000000..eb4fa2d
--- /dev/null
+++ b/lib/libF77/Version.c
@@ -0,0 +1,49 @@
+static char junk[] = "\n@(#)LIBF77 VERSION 19970226\n";
+
+/*
+2.00 11 June 1980. File version.c added to library.
+2.01 31 May 1988. s_paus() flushes stderr; names of hl_* fixed
+ [ d]erf[c ] added
+ 8 Aug. 1989: #ifdefs for f2c -i2 added to s_cat.c
+ 29 Nov. 1989: s_cmp returns long (for f2c)
+ 30 Nov. 1989: arg types from f2c.h
+ 12 Dec. 1989: s_rnge allows long names
+ 19 Dec. 1989: getenv_ allows unsorted environment
+ 28 Mar. 1990: add exit(0) to end of main()
+ 2 Oct. 1990: test signal(...) == SIG_IGN rather than & 01 in main
+ 17 Oct. 1990: abort() calls changed to sig_die(...,1)
+ 22 Oct. 1990: separate sig_die from main
+ 25 Apr. 1991: minor, theoretically invisible tweaks to s_cat, sig_die
+ 31 May 1991: make system_ return status
+ 18 Dec. 1991: change long to ftnlen (for -i2) many places
+ 28 Feb. 1992: repair z_sqrt.c (scribbled on input, gave wrong answer)
+ 18 July 1992: for n < 0, repair handling of 0**n in pow_[dr]i.c
+ and m**n in pow_hh.c and pow_ii.c;
+ catch SIGTRAP in main() for error msg before abort
+ 23 July 1992: switch to ANSI prototypes unless KR_headers is #defined
+ 23 Oct. 1992: fix botch in signal_.c (erroneous deref of 2nd arg);
+ change Cabs to f__cabs.
+ 12 March 1993: various tweaks for C++
+ 2 June 1994: adjust so abnormal terminations invoke f_exit just once
+ 16 Sept. 1994: s_cmp: treat characters as unsigned in comparisons.
+ 19 Sept. 1994: s_paus: flush after end of PAUSE; add -DMSDOS
+ 12 Jan. 1995: pow_[dhiqrz][hiq]: adjust x**i to work on machines
+ that sign-extend right shifts when i is the most
+ negative integer.
+ 26 Jan. 1995: adjust s_cat.c, s_copy.c to permit the left-hand side
+ of character assignments to appear on the right-hand
+ side (unless compiled with -DNO_OVERWRITE).
+ 27 Jan. 1995: minor tweak to s_copy.c: copy forward whenever
+ possible (for better cache behavior).
+ 30 May 1995: added subroutine exit(rc) integer rc. Version not changed.
+ 29 Aug. 1995: add F77_aloc.c; use it in s_cat.c and system_.c.
+ 6 Sept. 1995: fix return type of system_ under -DKR_headers.
+ 19 Dec. 1995: s_cat.c: fix bug when 2nd or later arg overlaps lhs.
+ 19 Mar. 1996: s_cat.c: supply missing break after overlap detection.
+ 13 May 1996: add [lq]bitbits.c and [lq]bitshft.c (f90 bit intrinsics).
+ 19 June 1996: add casts to unsigned in [lq]bitshft.c.
+ 26 Feb. 1997: adjust functions with a complex output argument
+ to permit aliasing it with input arguments.
+ (For now, at least, this is just for possible
+ benefit of g77.)
+*/
diff --git a/lib/libF77/abort_.c b/lib/libF77/abort_.c
new file mode 100644
index 0000000..9d4a056
--- /dev/null
+++ b/lib/libF77/abort_.c
@@ -0,0 +1,18 @@
+#include "stdio.h"
+#include "f2c.h"
+
+#ifdef KR_headers
+extern VOID sig_die();
+
+int abort_()
+#else
+extern void sig_die(char*,int);
+
+int abort_(void)
+#endif
+{
+sig_die("Fortran abort routine called", 1);
+#ifdef __cplusplus
+return 0;
+#endif
+}
diff --git a/lib/libF77/c_abs.c b/lib/libF77/c_abs.c
new file mode 100644
index 0000000..041fbd3
--- /dev/null
+++ b/lib/libF77/c_abs.c
@@ -0,0 +1,14 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern double f__cabs();
+
+double c_abs(z) complex *z;
+#else
+extern double f__cabs(double, double);
+
+double c_abs(complex *z)
+#endif
+{
+return( f__cabs( z->r, z->i ) );
+}
diff --git a/lib/libF77/c_cos.c b/lib/libF77/c_cos.c
new file mode 100644
index 0000000..4aea0c3
--- /dev/null
+++ b/lib/libF77/c_cos.c
@@ -0,0 +1,17 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern double sin(), cos(), sinh(), cosh();
+
+VOID c_cos(r, z) complex *r, *z;
+#else
+#undef abs
+#include "math.h"
+
+void c_cos(complex *r, complex *z)
+#endif
+{
+ double zr = z->r;
+ r->r = cos(zr) * cosh(z->i);
+ r->i = - sin(zr) * sinh(z->i);
+ }
diff --git a/lib/libF77/c_div.c b/lib/libF77/c_div.c
new file mode 100644
index 0000000..57139a0
--- /dev/null
+++ b/lib/libF77/c_div.c
@@ -0,0 +1,37 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern VOID sig_die();
+VOID c_div(c, a, b)
+complex *a, *b, *c;
+#else
+extern void sig_die(char*,int);
+void c_div(complex *c, complex *a, complex *b)
+#endif
+{
+ double ratio, den;
+ double abr, abi;
+ double ai = a->i, ar = a->r, bi = b->i, br = b->r;
+
+ if( (abr = br) < 0.)
+ abr = - abr;
+ if( (abi = bi) < 0.)
+ abi = - abi;
+ if( abr <= abi )
+ {
+ if(abi == 0)
+ sig_die("complex division by zero", 1);
+ ratio = (double)br / bi ;
+ den = bi * (1 + ratio*ratio);
+ c->r = (ar*ratio + ai) / den;
+ c->i = (ai*ratio - ar) / den;
+ }
+
+ else
+ {
+ ratio = (double)bi / br ;
+ den = br * (1 + ratio*ratio);
+ c->r = (ar + ai*ratio) / den;
+ c->i = (ai - ar*ratio) / den;
+ }
+ }
diff --git a/lib/libF77/c_exp.c b/lib/libF77/c_exp.c
new file mode 100644
index 0000000..8252c7f
--- /dev/null
+++ b/lib/libF77/c_exp.c
@@ -0,0 +1,19 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern double exp(), cos(), sin();
+
+ VOID c_exp(r, z) complex *r, *z;
+#else
+#undef abs
+#include "math.h"
+
+void c_exp(complex *r, complex *z)
+#endif
+{
+double expx;
+
+expx = exp(z->r);
+r->r = expx * cos(z->i);
+r->i = expx * sin(z->i);
+}
diff --git a/lib/libF77/c_log.c b/lib/libF77/c_log.c
new file mode 100644
index 0000000..6ac990c
--- /dev/null
+++ b/lib/libF77/c_log.c
@@ -0,0 +1,17 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern double log(), f__cabs(), atan2();
+VOID c_log(r, z) complex *r, *z;
+#else
+#undef abs
+#include "math.h"
+extern double f__cabs(double, double);
+
+void c_log(complex *r, complex *z)
+#endif
+{
+ double zi;
+ r->i = atan2(zi = z->i, z->r);
+ r->r = log( f__cabs(z->r, zi) );
+ }
diff --git a/lib/libF77/c_sin.c b/lib/libF77/c_sin.c
new file mode 100644
index 0000000..15acccc
--- /dev/null
+++ b/lib/libF77/c_sin.c
@@ -0,0 +1,17 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern double sin(), cos(), sinh(), cosh();
+
+VOID c_sin(r, z) complex *r, *z;
+#else
+#undef abs
+#include "math.h"
+
+void c_sin(complex *r, complex *z)
+#endif
+{
+ double zr = z->r;
+ r->r = sin(zr) * cosh(z->i);
+ r->i = cos(zr) * sinh(z->i);
+ }
diff --git a/lib/libF77/c_sqrt.c b/lib/libF77/c_sqrt.c
new file mode 100644
index 0000000..8481ee4
--- /dev/null
+++ b/lib/libF77/c_sqrt.c
@@ -0,0 +1,35 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern double sqrt(), f__cabs();
+
+VOID c_sqrt(r, z) complex *r, *z;
+#else
+#undef abs
+#include "math.h"
+extern double f__cabs(double, double);
+
+void c_sqrt(complex *r, complex *z)
+#endif
+{
+ double mag, t;
+ double zi = z->i, zr = z->r;
+
+ if( (mag = f__cabs(zr, zi)) == 0.)
+ r->r = r->i = 0.;
+ else if(zr > 0)
+ {
+ r->r = t = sqrt(0.5 * (mag + zr) );
+ t = zi / t;
+ r->i = 0.5 * t;
+ }
+ else
+ {
+ t = sqrt(0.5 * (mag - zr) );
+ if(zi < 0)
+ t = -t;
+ r->i = t;
+ t = zi / t;
+ r->r = 0.5 * t;
+ }
+ }
diff --git a/lib/libF77/cabs.c b/lib/libF77/cabs.c
new file mode 100644
index 0000000..09e90af
--- /dev/null
+++ b/lib/libF77/cabs.c
@@ -0,0 +1,27 @@
+#ifdef KR_headers
+extern double sqrt();
+double f__cabs(real, imag) double real, imag;
+#else
+#undef abs
+#include "math.h"
+double f__cabs(double real, double imag)
+#endif
+{
+double temp;
+
+if(real < 0)
+ real = -real;
+if(imag < 0)
+ imag = -imag;
+if(imag > real){
+ temp = real;
+ real = imag;
+ imag = temp;
+}
+if((real+imag) == real)
+ return(real);
+
+temp = imag/real;
+temp = real*sqrt(1.0 + temp*temp); /*overflow!!*/
+return(temp);
+}
diff --git a/lib/libF77/d_abs.c b/lib/libF77/d_abs.c
new file mode 100644
index 0000000..cb157e0
--- /dev/null
+++ b/lib/libF77/d_abs.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double d_abs(x) doublereal *x;
+#else
+double d_abs(doublereal *x)
+#endif
+{
+if(*x >= 0)
+ return(*x);
+return(- *x);
+}
diff --git a/lib/libF77/d_acos.c b/lib/libF77/d_acos.c
new file mode 100644
index 0000000..ecb56e8
--- /dev/null
+++ b/lib/libF77/d_acos.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double acos();
+double d_acos(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_acos(doublereal *x)
+#endif
+{
+return( acos(*x) );
+}
diff --git a/lib/libF77/d_asin.c b/lib/libF77/d_asin.c
new file mode 100644
index 0000000..045e733
--- /dev/null
+++ b/lib/libF77/d_asin.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double asin();
+double d_asin(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_asin(doublereal *x)
+#endif
+{
+return( asin(*x) );
+}
diff --git a/lib/libF77/d_atan.c b/lib/libF77/d_atan.c
new file mode 100644
index 0000000..03530a1
--- /dev/null
+++ b/lib/libF77/d_atan.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double atan();
+double d_atan(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_atan(doublereal *x)
+#endif
+{
+return( atan(*x) );
+}
diff --git a/lib/libF77/d_atn2.c b/lib/libF77/d_atn2.c
new file mode 100644
index 0000000..7c25ac0
--- /dev/null
+++ b/lib/libF77/d_atn2.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double atan2();
+double d_atn2(x,y) doublereal *x, *y;
+#else
+#undef abs
+#include "math.h"
+double d_atn2(doublereal *x, doublereal *y)
+#endif
+{
+return( atan2(*x,*y) );
+}
diff --git a/lib/libF77/d_cnjg.c b/lib/libF77/d_cnjg.c
new file mode 100644
index 0000000..c778c38
--- /dev/null
+++ b/lib/libF77/d_cnjg.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+ VOID
+#ifdef KR_headers
+d_cnjg(r, z) doublecomplex *r, *z;
+#else
+d_cnjg(doublecomplex *r, doublecomplex *z)
+#endif
+{
+r->r = z->r;
+r->i = - z->i;
+}
diff --git a/lib/libF77/d_cos.c b/lib/libF77/d_cos.c
new file mode 100644
index 0000000..45c4838
--- /dev/null
+++ b/lib/libF77/d_cos.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double cos();
+double d_cos(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_cos(doublereal *x)
+#endif
+{
+return( cos(*x) );
+}
diff --git a/lib/libF77/d_cosh.c b/lib/libF77/d_cosh.c
new file mode 100644
index 0000000..1181833
--- /dev/null
+++ b/lib/libF77/d_cosh.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double cosh();
+double d_cosh(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_cosh(doublereal *x)
+#endif
+{
+return( cosh(*x) );
+}
diff --git a/lib/libF77/d_dim.c b/lib/libF77/d_dim.c
new file mode 100644
index 0000000..1d0ecb7
--- /dev/null
+++ b/lib/libF77/d_dim.c
@@ -0,0 +1,10 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double d_dim(a,b) doublereal *a, *b;
+#else
+double d_dim(doublereal *a, doublereal *b)
+#endif
+{
+return( *a > *b ? *a - *b : 0);
+}
diff --git a/lib/libF77/d_exp.c b/lib/libF77/d_exp.c
new file mode 100644
index 0000000..3f2b6ff
--- /dev/null
+++ b/lib/libF77/d_exp.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double exp();
+double d_exp(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_exp(doublereal *x)
+#endif
+{
+return( exp(*x) );
+}
diff --git a/lib/libF77/d_imag.c b/lib/libF77/d_imag.c
new file mode 100644
index 0000000..793a3f9
--- /dev/null
+++ b/lib/libF77/d_imag.c
@@ -0,0 +1,10 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double d_imag(z) doublecomplex *z;
+#else
+double d_imag(doublecomplex *z)
+#endif
+{
+return(z->i);
+}
diff --git a/lib/libF77/d_int.c b/lib/libF77/d_int.c
new file mode 100644
index 0000000..6c0e642
--- /dev/null
+++ b/lib/libF77/d_int.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double floor();
+double d_int(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_int(doublereal *x)
+#endif
+{
+return( (*x>0) ? floor(*x) : -floor(- *x) );
+}
diff --git a/lib/libF77/d_lg10.c b/lib/libF77/d_lg10.c
new file mode 100644
index 0000000..3135881
--- /dev/null
+++ b/lib/libF77/d_lg10.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double log10();
+double d_lg10(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_lg10(doublereal *x)
+#endif
+{
+return( log10(*x) );
+}
diff --git a/lib/libF77/d_log.c b/lib/libF77/d_log.c
new file mode 100644
index 0000000..d7a1941
--- /dev/null
+++ b/lib/libF77/d_log.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double log();
+double d_log(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_log(doublereal *x)
+#endif
+{
+return( log(*x) );
+}
diff --git a/lib/libF77/d_mod.c b/lib/libF77/d_mod.c
new file mode 100644
index 0000000..0d3ffbf
--- /dev/null
+++ b/lib/libF77/d_mod.c
@@ -0,0 +1,40 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+#ifdef IEEE_drem
+double drem();
+#else
+double floor();
+#endif
+double d_mod(x,y) doublereal *x, *y;
+#else
+#ifdef IEEE_drem
+double drem(double, double);
+#else
+#undef abs
+#include "math.h"
+#endif
+double d_mod(doublereal *x, doublereal *y)
+#endif
+{
+#ifdef IEEE_drem
+ double xa, ya, z;
+ if ((ya = *y) < 0.)
+ ya = -ya;
+ z = drem(xa = *x, ya);
+ if (xa > 0) {
+ if (z < 0)
+ z += ya;
+ }
+ else if (z > 0)
+ z -= ya;
+ return z;
+#else
+ double quotient;
+ if( (quotient = *x / *y) >= 0)
+ quotient = floor(quotient);
+ else
+ quotient = -floor(-quotient);
+ return(*x - (*y) * quotient );
+#endif
+}
diff --git a/lib/libF77/d_nint.c b/lib/libF77/d_nint.c
new file mode 100644
index 0000000..2ead3df
--- /dev/null
+++ b/lib/libF77/d_nint.c
@@ -0,0 +1,14 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double floor();
+double d_nint(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_nint(doublereal *x)
+#endif
+{
+return( (*x)>=0 ?
+ floor(*x + .5) : -floor(.5 - *x) );
+}
diff --git a/lib/libF77/d_prod.c b/lib/libF77/d_prod.c
new file mode 100644
index 0000000..3d4cef7
--- /dev/null
+++ b/lib/libF77/d_prod.c
@@ -0,0 +1,10 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double d_prod(x,y) real *x, *y;
+#else
+double d_prod(real *x, real *y)
+#endif
+{
+return( (*x) * (*y) );
+}
diff --git a/lib/libF77/d_sign.c b/lib/libF77/d_sign.c
new file mode 100644
index 0000000..514ff0b
--- /dev/null
+++ b/lib/libF77/d_sign.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double d_sign(a,b) doublereal *a, *b;
+#else
+double d_sign(doublereal *a, doublereal *b)
+#endif
+{
+double x;
+x = (*a >= 0 ? *a : - *a);
+return( *b >= 0 ? x : -x);
+}
diff --git a/lib/libF77/d_sin.c b/lib/libF77/d_sin.c
new file mode 100644
index 0000000..0013af0
--- /dev/null
+++ b/lib/libF77/d_sin.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double sin();
+double d_sin(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_sin(doublereal *x)
+#endif
+{
+return( sin(*x) );
+}
diff --git a/lib/libF77/d_sinh.c b/lib/libF77/d_sinh.c
new file mode 100644
index 0000000..1ccd02e
--- /dev/null
+++ b/lib/libF77/d_sinh.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double sinh();
+double d_sinh(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_sinh(doublereal *x)
+#endif
+{
+return( sinh(*x) );
+}
diff --git a/lib/libF77/d_sqrt.c b/lib/libF77/d_sqrt.c
new file mode 100644
index 0000000..bee10a3
--- /dev/null
+++ b/lib/libF77/d_sqrt.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double sqrt();
+double d_sqrt(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_sqrt(doublereal *x)
+#endif
+{
+return( sqrt(*x) );
+}
diff --git a/lib/libF77/d_tan.c b/lib/libF77/d_tan.c
new file mode 100644
index 0000000..23fa423
--- /dev/null
+++ b/lib/libF77/d_tan.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double tan();
+double d_tan(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_tan(doublereal *x)
+#endif
+{
+return( tan(*x) );
+}
diff --git a/lib/libF77/d_tanh.c b/lib/libF77/d_tanh.c
new file mode 100644
index 0000000..0363a49
--- /dev/null
+++ b/lib/libF77/d_tanh.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double tanh();
+double d_tanh(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+double d_tanh(doublereal *x)
+#endif
+{
+return( tanh(*x) );
+}
diff --git a/lib/libF77/derf_.c b/lib/libF77/derf_.c
new file mode 100644
index 0000000..6afaccd
--- /dev/null
+++ b/lib/libF77/derf_.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double erf();
+double derf_(x) doublereal *x;
+#else
+extern double erf(double);
+double derf_(doublereal *x)
+#endif
+{
+return( erf(*x) );
+}
diff --git a/lib/libF77/derfc_.c b/lib/libF77/derfc_.c
new file mode 100644
index 0000000..e199f91
--- /dev/null
+++ b/lib/libF77/derfc_.c
@@ -0,0 +1,14 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern double erfc();
+
+double derfc_(x) doublereal *x;
+#else
+extern double erfc(double);
+
+double derfc_(doublereal *x)
+#endif
+{
+return( erfc(*x) );
+}
diff --git a/lib/libF77/ef1asc_.c b/lib/libF77/ef1asc_.c
new file mode 100644
index 0000000..b2b8d72
--- /dev/null
+++ b/lib/libF77/ef1asc_.c
@@ -0,0 +1,21 @@
+/* EFL support routine to copy string b to string a */
+
+#include "f2c.h"
+
+
+#define M ( (long) (sizeof(long) - 1) )
+#define EVEN(x) ( ( (x)+ M) & (~M) )
+
+#ifdef KR_headers
+extern VOID s_copy();
+ef1asc_(a, la, b, lb) ftnint *a, *b; ftnlen *la, *lb;
+#else
+extern void s_copy(char*,char*,ftnlen,ftnlen);
+int ef1asc_(ftnint *a, ftnlen *la, ftnint *b, ftnlen *lb)
+#endif
+{
+s_copy( (char *)a, (char *)b, EVEN(*la), *lb );
+#ifdef __cplusplus
+return 0;
+#endif
+}
diff --git a/lib/libF77/ef1cmc_.c b/lib/libF77/ef1cmc_.c
new file mode 100644
index 0000000..8239a6b
--- /dev/null
+++ b/lib/libF77/ef1cmc_.c
@@ -0,0 +1,14 @@
+/* EFL support routine to compare two character strings */
+
+#include "f2c.h"
+
+#ifdef KR_headers
+extern integer s_cmp();
+integer ef1cmc_(a, la, b, lb) ftnint *a, *b; ftnlen *la, *lb;
+#else
+extern integer s_cmp(char*,char*,ftnlen,ftnlen);
+integer ef1cmc_(ftnint *a, ftnlen *la, ftnint *b, ftnlen *lb)
+#endif
+{
+return( s_cmp( (char *)a, (char *)b, *la, *lb) );
+}
diff --git a/lib/libF77/erf_.c b/lib/libF77/erf_.c
new file mode 100644
index 0000000..f7565ae
--- /dev/null
+++ b/lib/libF77/erf_.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double erf();
+double erf_(x) real *x;
+#else
+extern double erf(double);
+double erf_(real *x)
+#endif
+{
+return( erf(*x) );
+}
diff --git a/lib/libF77/erfc_.c b/lib/libF77/erfc_.c
new file mode 100644
index 0000000..56adb2f
--- /dev/null
+++ b/lib/libF77/erfc_.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double erfc();
+double erfc_(x) real *x;
+#else
+extern double erfc(double);
+double erfc_(real *x)
+#endif
+{
+return( erfc(*x) );
+}
diff --git a/lib/libF77/f2ch.add b/lib/libF77/f2ch.add
new file mode 100644
index 0000000..a2acc17
--- /dev/null
+++ b/lib/libF77/f2ch.add
@@ -0,0 +1,162 @@
+/* If you are using a C++ compiler, append the following to f2c.h
+ for compiling libF77 and libI77. */
+
+#ifdef __cplusplus
+extern "C" {
+extern int abort_(void);
+extern double c_abs(complex *);
+extern void c_cos(complex *, complex *);
+extern void c_div(complex *, complex *, complex *);
+extern void c_exp(complex *, complex *);
+extern void c_log(complex *, complex *);
+extern void c_sin(complex *, complex *);
+extern void c_sqrt(complex *, complex *);
+extern double d_abs(double *);
+extern double d_acos(double *);
+extern double d_asin(double *);
+extern double d_atan(double *);
+extern double d_atn2(double *, double *);
+extern void d_cnjg(doublecomplex *, doublecomplex *);
+extern double d_cos(double *);
+extern double d_cosh(double *);
+extern double d_dim(double *, double *);
+extern double d_exp(double *);
+extern double d_imag(doublecomplex *);
+extern double d_int(double *);
+extern double d_lg10(double *);
+extern double d_log(double *);
+extern double d_mod(double *, double *);
+extern double d_nint(double *);
+extern double d_prod(float *, float *);
+extern double d_sign(double *, double *);
+extern double d_sin(double *);
+extern double d_sinh(double *);
+extern double d_sqrt(double *);
+extern double d_tan(double *);
+extern double d_tanh(double *);
+extern double derf_(double *);
+extern double derfc_(double *);
+extern integer do_fio(ftnint *, char *, ftnlen);
+extern integer do_lio(ftnint *, ftnint *, char *, ftnlen);
+extern integer do_uio(ftnint *, char *, ftnlen);
+extern integer e_rdfe(void);
+extern integer e_rdue(void);
+extern integer e_rsfe(void);
+extern integer e_rsfi(void);
+extern integer e_rsle(void);
+extern integer e_rsli(void);
+extern integer e_rsue(void);
+extern integer e_wdfe(void);
+extern integer e_wdue(void);
+extern integer e_wsfe(void);
+extern integer e_wsfi(void);
+extern integer e_wsle(void);
+extern integer e_wsli(void);
+extern integer e_wsue(void);
+extern int ef1asc_(ftnint *, ftnlen *, ftnint *, ftnlen *);
+extern integer ef1cmc_(ftnint *, ftnlen *, ftnint *, ftnlen *);
+extern double erf(double);
+extern double erf_(float *);
+extern double erfc(double);
+extern double erfc_(float *);
+extern integer f_back(alist *);
+extern integer f_clos(cllist *);
+extern integer f_end(alist *);
+extern void f_exit(void);
+extern integer f_inqu(inlist *);
+extern integer f_open(olist *);
+extern integer f_rew(alist *);
+extern int flush_(void);
+extern void getarg_(integer *, char *, ftnlen);
+extern void getenv_(char *, char *, ftnlen, ftnlen);
+extern short h_abs(short *);
+extern short h_dim(short *, short *);
+extern short h_dnnt(double *);
+extern short h_indx(char *, char *, ftnlen, ftnlen);
+extern short h_len(char *, ftnlen);
+extern short h_mod(short *, short *);
+extern short h_nint(float *);
+extern short h_sign(short *, short *);
+extern short hl_ge(char *, char *, ftnlen, ftnlen);
+extern short hl_gt(char *, char *, ftnlen, ftnlen);
+extern short hl_le(char *, char *, ftnlen, ftnlen);
+extern short hl_lt(char *, char *, ftnlen, ftnlen);
+extern integer i_abs(integer *);
+extern integer i_dim(integer *, integer *);
+extern integer i_dnnt(double *);
+extern integer i_indx(char *, char *, ftnlen, ftnlen);
+extern integer i_len(char *, ftnlen);
+extern integer i_mod(integer *, integer *);
+extern integer i_nint(float *);
+extern integer i_sign(integer *, integer *);
+extern integer iargc_(void);
+extern ftnlen l_ge(char *, char *, ftnlen, ftnlen);
+extern ftnlen l_gt(char *, char *, ftnlen, ftnlen);
+extern ftnlen l_le(char *, char *, ftnlen, ftnlen);
+extern ftnlen l_lt(char *, char *, ftnlen, ftnlen);
+extern void pow_ci(complex *, complex *, integer *);
+extern double pow_dd(double *, double *);
+extern double pow_di(double *, integer *);
+extern short pow_hh(short *, shortint *);
+extern integer pow_ii(integer *, integer *);
+extern double pow_ri(float *, integer *);
+extern void pow_zi(doublecomplex *, doublecomplex *, integer *);
+extern void pow_zz(doublecomplex *, doublecomplex *, doublecomplex *);
+extern double r_abs(float *);
+extern double r_acos(float *);
+extern double r_asin(float *);
+extern double r_atan(float *);
+extern double r_atn2(float *, float *);
+extern void r_cnjg(complex *, complex *);
+extern double r_cos(float *);
+extern double r_cosh(float *);
+extern double r_dim(float *, float *);
+extern double r_exp(float *);
+extern double r_imag(complex *);
+extern double r_int(float *);
+extern double r_lg10(float *);
+extern double r_log(float *);
+extern double r_mod(float *, float *);
+extern double r_nint(float *);
+extern double r_sign(float *, float *);
+extern double r_sin(float *);
+extern double r_sinh(float *);
+extern double r_sqrt(float *);
+extern double r_tan(float *);
+extern double r_tanh(float *);
+extern void s_cat(char *, char **, integer *, integer *, ftnlen);
+extern integer s_cmp(char *, char *, ftnlen, ftnlen);
+extern void s_copy(char *, char *, ftnlen, ftnlen);
+extern int s_paus(char *, ftnlen);
+extern integer s_rdfe(cilist *);
+extern integer s_rdue(cilist *);
+extern integer s_rnge(char *, integer, char *, integer);
+extern integer s_rsfe(cilist *);
+extern integer s_rsfi(icilist *);
+extern integer s_rsle(cilist *);
+extern integer s_rsli(icilist *);
+extern integer s_rsne(cilist *);
+extern integer s_rsni(icilist *);
+extern integer s_rsue(cilist *);
+extern int s_stop(char *, ftnlen);
+extern integer s_wdfe(cilist *);
+extern integer s_wdue(cilist *);
+extern integer s_wsfe(cilist *);
+extern integer s_wsfi(icilist *);
+extern integer s_wsle(cilist *);
+extern integer s_wsli(icilist *);
+extern integer s_wsne(cilist *);
+extern integer s_wsni(icilist *);
+extern integer s_wsue(cilist *);
+extern void sig_die(char *, int);
+extern integer signal_(integer *, void (*)(int));
+extern integer system_(char *, ftnlen);
+extern double z_abs(doublecomplex *);
+extern void z_cos(doublecomplex *, doublecomplex *);
+extern void z_div(doublecomplex *, doublecomplex *, doublecomplex *);
+extern void z_exp(doublecomplex *, doublecomplex *);
+extern void z_log(doublecomplex *, doublecomplex *);
+extern void z_sin(doublecomplex *, doublecomplex *);
+extern void z_sqrt(doublecomplex *, doublecomplex *);
+ }
+#endif
diff --git a/lib/libF77/getarg_.c b/lib/libF77/getarg_.c
new file mode 100644
index 0000000..fef0da7
--- /dev/null
+++ b/lib/libF77/getarg_.c
@@ -0,0 +1,28 @@
+#include "f2c.h"
+
+/*
+ * subroutine getarg(k, c)
+ * returns the kth unix command argument in fortran character
+ * variable argument c
+*/
+
+#ifdef KR_headers
+VOID getarg_(n, s, ls) ftnint *n; register char *s; ftnlen ls;
+#else
+void getarg_(ftnint *n, register char *s, ftnlen ls)
+#endif
+{
+extern int xargc;
+extern char **xargv;
+register char *t;
+register int i;
+
+if(*n>=0 && *n<xargc)
+ t = xargv[*n];
+else
+ t = "";
+for(i = 0; i<ls && *t!='\0' ; ++i)
+ *s++ = *t++;
+for( ; i<ls ; ++i)
+ *s++ = ' ';
+}
diff --git a/lib/libF77/getenv_.c b/lib/libF77/getenv_.c
new file mode 100644
index 0000000..2a035ea
--- /dev/null
+++ b/lib/libF77/getenv_.c
@@ -0,0 +1,51 @@
+#include "f2c.h"
+
+/*
+ * getenv - f77 subroutine to return environment variables
+ *
+ * called by:
+ * call getenv (ENV_NAME, char_var)
+ * where:
+ * ENV_NAME is the name of an environment variable
+ * char_var is a character variable which will receive
+ * the current value of ENV_NAME, or all blanks
+ * if ENV_NAME is not defined
+ */
+
+#ifdef KR_headers
+VOID getenv_(fname, value, flen, vlen) char *value, *fname; ftnlen vlen, flen;
+#else
+void getenv_(char *fname, char *value, ftnlen flen, ftnlen vlen)
+#endif
+{
+extern char **environ;
+register char *ep, *fp, *flast;
+register char **env = environ;
+
+flast = fname + flen;
+for(fp = fname ; fp < flast ; ++fp)
+ if(*fp == ' ')
+ {
+ flast = fp;
+ break;
+ }
+
+while (ep = *env++)
+ {
+ for(fp = fname; fp<flast ; )
+ if(*fp++ != *ep++)
+ goto endloop;
+
+ if(*ep++ == '=') { /* copy right hand side */
+ while( *ep && --vlen>=0 )
+ *value++ = *ep++;
+
+ goto blank;
+ }
+endloop: ;
+ }
+
+blank:
+ while( --vlen >= 0 )
+ *value++ = ' ';
+}
diff --git a/lib/libF77/h_abs.c b/lib/libF77/h_abs.c
new file mode 100644
index 0000000..73b8215
--- /dev/null
+++ b/lib/libF77/h_abs.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+shortint h_abs(x) shortint *x;
+#else
+shortint h_abs(shortint *x)
+#endif
+{
+if(*x >= 0)
+ return(*x);
+return(- *x);
+}
diff --git a/lib/libF77/h_dim.c b/lib/libF77/h_dim.c
new file mode 100644
index 0000000..ceff660
--- /dev/null
+++ b/lib/libF77/h_dim.c
@@ -0,0 +1,10 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+shortint h_dim(a,b) shortint *a, *b;
+#else
+shortint h_dim(shortint *a, shortint *b)
+#endif
+{
+return( *a > *b ? *a - *b : 0);
+}
diff --git a/lib/libF77/h_dnnt.c b/lib/libF77/h_dnnt.c
new file mode 100644
index 0000000..9fbeb5c
--- /dev/null
+++ b/lib/libF77/h_dnnt.c
@@ -0,0 +1,14 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double floor();
+shortint h_dnnt(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+shortint h_dnnt(doublereal *x)
+#endif
+{
+return( (*x)>=0 ?
+ floor(*x + .5) : -floor(.5 - *x) );
+}
diff --git a/lib/libF77/h_indx.c b/lib/libF77/h_indx.c
new file mode 100644
index 0000000..a211cc7
--- /dev/null
+++ b/lib/libF77/h_indx.c
@@ -0,0 +1,26 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+shortint h_indx(a, b, la, lb) char *a, *b; ftnlen la, lb;
+#else
+shortint h_indx(char *a, char *b, ftnlen la, ftnlen lb)
+#endif
+{
+ftnlen i, n;
+char *s, *t, *bend;
+
+n = la - lb + 1;
+bend = b + lb;
+
+for(i = 0 ; i < n ; ++i)
+ {
+ s = a + i;
+ t = b;
+ while(t < bend)
+ if(*s++ != *t++)
+ goto no;
+ return((shortint)i+1);
+ no: ;
+ }
+return(0);
+}
diff --git a/lib/libF77/h_len.c b/lib/libF77/h_len.c
new file mode 100644
index 0000000..00a2151
--- /dev/null
+++ b/lib/libF77/h_len.c
@@ -0,0 +1,10 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+shortint h_len(s, n) char *s; ftnlen n;
+#else
+shortint h_len(char *s, ftnlen n)
+#endif
+{
+return(n);
+}
diff --git a/lib/libF77/h_mod.c b/lib/libF77/h_mod.c
new file mode 100644
index 0000000..43431c1
--- /dev/null
+++ b/lib/libF77/h_mod.c
@@ -0,0 +1,10 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+shortint h_mod(a,b) short *a, *b;
+#else
+shortint h_mod(short *a, short *b)
+#endif
+{
+return( *a % *b);
+}
diff --git a/lib/libF77/h_nint.c b/lib/libF77/h_nint.c
new file mode 100644
index 0000000..bf63df1
--- /dev/null
+++ b/lib/libF77/h_nint.c
@@ -0,0 +1,14 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double floor();
+shortint h_nint(x) real *x;
+#else
+#undef abs
+#include "math.h"
+shortint h_nint(real *x)
+#endif
+{
+return( (*x)>=0 ?
+ floor(*x + .5) : -floor(.5 - *x) );
+}
diff --git a/lib/libF77/h_sign.c b/lib/libF77/h_sign.c
new file mode 100644
index 0000000..7b06c15
--- /dev/null
+++ b/lib/libF77/h_sign.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+shortint h_sign(a,b) shortint *a, *b;
+#else
+shortint h_sign(shortint *a, shortint *b)
+#endif
+{
+shortint x;
+x = (*a >= 0 ? *a : - *a);
+return( *b >= 0 ? x : -x);
+}
diff --git a/lib/libF77/hl_ge.c b/lib/libF77/hl_ge.c
new file mode 100644
index 0000000..4c29527
--- /dev/null
+++ b/lib/libF77/hl_ge.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern integer s_cmp();
+shortlogical hl_ge(a,b,la,lb) char *a, *b; ftnlen la, lb;
+#else
+extern integer s_cmp(char *, char *, ftnlen, ftnlen);
+shortlogical hl_ge(char *a, char *b, ftnlen la, ftnlen lb)
+#endif
+{
+return(s_cmp(a,b,la,lb) >= 0);
+}
diff --git a/lib/libF77/hl_gt.c b/lib/libF77/hl_gt.c
new file mode 100644
index 0000000..c4f345a
--- /dev/null
+++ b/lib/libF77/hl_gt.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern integer s_cmp();
+shortlogical hl_gt(a,b,la,lb) char *a, *b; ftnlen la, lb;
+#else
+extern integer s_cmp(char *, char *, ftnlen, ftnlen);
+shortlogical hl_gt(char *a, char *b, ftnlen la, ftnlen lb)
+#endif
+{
+return(s_cmp(a,b,la,lb) > 0);
+}
diff --git a/lib/libF77/hl_le.c b/lib/libF77/hl_le.c
new file mode 100644
index 0000000..a9cce59
--- /dev/null
+++ b/lib/libF77/hl_le.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern integer s_cmp();
+shortlogical hl_le(a,b,la,lb) char *a, *b; ftnlen la, lb;
+#else
+extern integer s_cmp(char *, char *, ftnlen, ftnlen);
+shortlogical hl_le(char *a, char *b, ftnlen la, ftnlen lb)
+#endif
+{
+return(s_cmp(a,b,la,lb) <= 0);
+}
diff --git a/lib/libF77/hl_lt.c b/lib/libF77/hl_lt.c
new file mode 100644
index 0000000..162d919
--- /dev/null
+++ b/lib/libF77/hl_lt.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern integer s_cmp();
+shortlogical hl_lt(a,b,la,lb) char *a, *b; ftnlen la, lb;
+#else
+extern integer s_cmp(char *, char *, ftnlen, ftnlen);
+shortlogical hl_lt(char *a, char *b, ftnlen la, ftnlen lb)
+#endif
+{
+return(s_cmp(a,b,la,lb) < 0);
+}
diff --git a/lib/libF77/i_abs.c b/lib/libF77/i_abs.c
new file mode 100644
index 0000000..be21295
--- /dev/null
+++ b/lib/libF77/i_abs.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+integer i_abs(x) integer *x;
+#else
+integer i_abs(integer *x)
+#endif
+{
+if(*x >= 0)
+ return(*x);
+return(- *x);
+}
diff --git a/lib/libF77/i_dim.c b/lib/libF77/i_dim.c
new file mode 100644
index 0000000..6e1b170
--- /dev/null
+++ b/lib/libF77/i_dim.c
@@ -0,0 +1,10 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+integer i_dim(a,b) integer *a, *b;
+#else
+integer i_dim(integer *a, integer *b)
+#endif
+{
+return( *a > *b ? *a - *b : 0);
+}
diff --git a/lib/libF77/i_dnnt.c b/lib/libF77/i_dnnt.c
new file mode 100644
index 0000000..9d46c4b
--- /dev/null
+++ b/lib/libF77/i_dnnt.c
@@ -0,0 +1,14 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double floor();
+integer i_dnnt(x) doublereal *x;
+#else
+#undef abs
+#include "math.h"
+integer i_dnnt(doublereal *x)
+#endif
+{
+return( (*x)>=0 ?
+ floor(*x + .5) : -floor(.5 - *x) );
+}
diff --git a/lib/libF77/i_indx.c b/lib/libF77/i_indx.c
new file mode 100644
index 0000000..96e7bc5
--- /dev/null
+++ b/lib/libF77/i_indx.c
@@ -0,0 +1,26 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+integer i_indx(a, b, la, lb) char *a, *b; ftnlen la, lb;
+#else
+integer i_indx(char *a, char *b, ftnlen la, ftnlen lb)
+#endif
+{
+ftnlen i, n;
+char *s, *t, *bend;
+
+n = la - lb + 1;
+bend = b + lb;
+
+for(i = 0 ; i < n ; ++i)
+ {
+ s = a + i;
+ t = b;
+ while(t < bend)
+ if(*s++ != *t++)
+ goto no;
+ return(i+1);
+ no: ;
+ }
+return(0);
+}
diff --git a/lib/libF77/i_len.c b/lib/libF77/i_len.c
new file mode 100644
index 0000000..4020fee
--- /dev/null
+++ b/lib/libF77/i_len.c
@@ -0,0 +1,10 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+integer i_len(s, n) char *s; ftnlen n;
+#else
+integer i_len(char *s, ftnlen n)
+#endif
+{
+return(n);
+}
diff --git a/lib/libF77/i_mod.c b/lib/libF77/i_mod.c
new file mode 100644
index 0000000..6937c42
--- /dev/null
+++ b/lib/libF77/i_mod.c
@@ -0,0 +1,10 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+integer i_mod(a,b) integer *a, *b;
+#else
+integer i_mod(integer *a, integer *b)
+#endif
+{
+return( *a % *b);
+}
diff --git a/lib/libF77/i_nint.c b/lib/libF77/i_nint.c
new file mode 100644
index 0000000..ccde785
--- /dev/null
+++ b/lib/libF77/i_nint.c
@@ -0,0 +1,14 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double floor();
+integer i_nint(x) real *x;
+#else
+#undef abs
+#include "math.h"
+integer i_nint(real *x)
+#endif
+{
+return( (*x)>=0 ?
+ floor(*x + .5) : -floor(.5 - *x) );
+}
diff --git a/lib/libF77/i_sign.c b/lib/libF77/i_sign.c
new file mode 100644
index 0000000..94009b8
--- /dev/null
+++ b/lib/libF77/i_sign.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+integer i_sign(a,b) integer *a, *b;
+#else
+integer i_sign(integer *a, integer *b)
+#endif
+{
+integer x;
+x = (*a >= 0 ? *a : - *a);
+return( *b >= 0 ? x : -x);
+}
diff --git a/lib/libF77/iargc_.c b/lib/libF77/iargc_.c
new file mode 100644
index 0000000..29614ec
--- /dev/null
+++ b/lib/libF77/iargc_.c
@@ -0,0 +1,11 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+ftnint iargc_()
+#else
+ftnint iargc_(void)
+#endif
+{
+extern int xargc;
+return ( xargc - 1 );
+}
diff --git a/lib/libF77/l_ge.c b/lib/libF77/l_ge.c
new file mode 100644
index 0000000..86b4a1f
--- /dev/null
+++ b/lib/libF77/l_ge.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern integer s_cmp();
+logical l_ge(a,b,la,lb) char *a, *b; ftnlen la, lb;
+#else
+extern integer s_cmp(char *, char *, ftnlen, ftnlen);
+logical l_ge(char *a, char *b, ftnlen la, ftnlen lb)
+#endif
+{
+return(s_cmp(a,b,la,lb) >= 0);
+}
diff --git a/lib/libF77/l_gt.c b/lib/libF77/l_gt.c
new file mode 100644
index 0000000..c4b52f5
--- /dev/null
+++ b/lib/libF77/l_gt.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern integer s_cmp();
+logical l_gt(a,b,la,lb) char *a, *b; ftnlen la, lb;
+#else
+extern integer s_cmp(char *, char *, ftnlen, ftnlen);
+logical l_gt(char *a, char *b, ftnlen la, ftnlen lb)
+#endif
+{
+return(s_cmp(a,b,la,lb) > 0);
+}
diff --git a/lib/libF77/l_le.c b/lib/libF77/l_le.c
new file mode 100644
index 0000000..f2740a2
--- /dev/null
+++ b/lib/libF77/l_le.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern integer s_cmp();
+logical l_le(a,b,la,lb) char *a, *b; ftnlen la, lb;
+#else
+extern integer s_cmp(char *, char *, ftnlen, ftnlen);
+logical l_le(char *a, char *b, ftnlen la, ftnlen lb)
+#endif
+{
+return(s_cmp(a,b,la,lb) <= 0);
+}
diff --git a/lib/libF77/l_lt.c b/lib/libF77/l_lt.c
new file mode 100644
index 0000000..c48dc94
--- /dev/null
+++ b/lib/libF77/l_lt.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern integer s_cmp();
+logical l_lt(a,b,la,lb) char *a, *b; ftnlen la, lb;
+#else
+extern integer s_cmp(char *, char *, ftnlen, ftnlen);
+logical l_lt(char *a, char *b, ftnlen la, ftnlen lb)
+#endif
+{
+return(s_cmp(a,b,la,lb) < 0);
+}
diff --git a/lib/libF77/lbitbits.c b/lib/libF77/lbitbits.c
new file mode 100644
index 0000000..75e9f9c
--- /dev/null
+++ b/lib/libF77/lbitbits.c
@@ -0,0 +1,62 @@
+#include "f2c.h"
+
+#ifndef LONGBITS
+#define LONGBITS 32
+#endif
+
+ integer
+#ifdef KR_headers
+lbit_bits(a, b, len) integer a, b, len;
+#else
+lbit_bits(integer a, integer b, integer len)
+#endif
+{
+ /* Assume 2's complement arithmetic */
+
+ unsigned long x, y;
+
+ x = (unsigned long) a;
+ y = (unsigned long)-1L;
+ x >>= b;
+ y <<= len;
+ return (integer)(x & ~y);
+ }
+
+ integer
+#ifdef KR_headers
+lbit_cshift(a, b, len) integer a, b, len;
+#else
+lbit_cshift(integer a, integer b, integer len)
+#endif
+{
+ unsigned long x, y, z;
+
+ x = (unsigned long)a;
+ if (len <= 0) {
+ if (len == 0)
+ return 0;
+ goto full_len;
+ }
+ if (len >= LONGBITS) {
+ full_len:
+ if (b >= 0) {
+ b %= LONGBITS;
+ return (integer)(x << b | x >> LONGBITS -b );
+ }
+ b = -b;
+ b %= LONGBITS;
+ return (integer)(x << LONGBITS - b | x >> b);
+ }
+ y = z = (unsigned long)-1;
+ y <<= len;
+ z &= ~y;
+ y &= x;
+ x &= z;
+ if (b >= 0) {
+ b %= len;
+ return (integer)(y | z & (x << b | x >> len - b));
+ }
+ b = -b;
+ b %= len;
+ return (integer)(y | z & (x >> b | x << len - b));
+ }
diff --git a/lib/libF77/lbitshft.c b/lib/libF77/lbitshft.c
new file mode 100644
index 0000000..81b0fdb
--- /dev/null
+++ b/lib/libF77/lbitshft.c
@@ -0,0 +1,11 @@
+#include "f2c.h"
+
+ integer
+#ifdef KR_headers
+lbit_shift(a, b) integer a; integer b;
+#else
+lbit_shift(integer a, integer b)
+#endif
+{
+ return b >= 0 ? a << b : (integer)((uinteger)a >> -b);
+ }
diff --git a/lib/libF77/main.c b/lib/libF77/main.c
new file mode 100644
index 0000000..d6ff84a
--- /dev/null
+++ b/lib/libF77/main.c
@@ -0,0 +1,135 @@
+/* STARTUP PROCEDURE FOR UNIX FORTRAN PROGRAMS */
+
+#include "stdio.h"
+#include "signal1.h"
+
+#ifndef SIGIOT
+#ifdef SIGABRT
+#define SIGIOT SIGABRT
+#endif
+#endif
+
+#ifndef KR_headers
+#undef VOID
+#include "stdlib.h"
+#endif
+
+#ifndef VOID
+#define VOID void
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef NO__STDC
+#define ONEXIT onexit
+extern VOID f_exit();
+#else
+#ifndef KR_headers
+extern void f_exit(void);
+#ifndef NO_ONEXIT
+#define ONEXIT atexit
+extern int atexit(void (*)(void));
+#endif
+#else
+#ifndef NO_ONEXIT
+#define ONEXIT onexit
+extern VOID f_exit();
+#endif
+#endif
+#endif
+
+#ifdef KR_headers
+extern VOID f_init(), sig_die();
+extern int MAIN__();
+#define Int /* int */
+#else
+extern void f_init(void), sig_die(char*, int);
+extern int MAIN__(void);
+#define Int int
+#endif
+
+static VOID sigfdie(Int n)
+{
+sig_die("Floating Exception", 1);
+}
+
+
+static VOID sigidie(Int n)
+{
+sig_die("IOT Trap", 1);
+}
+
+#ifdef SIGQUIT
+static VOID sigqdie(Int n)
+{
+sig_die("Quit signal", 1);
+}
+#endif
+
+
+static VOID sigindie(Int n)
+{
+sig_die("Interrupt", 0);
+}
+
+static VOID sigtdie(Int n)
+{
+sig_die("Killed", 0);
+}
+
+#ifdef SIGTRAP
+static VOID sigtrdie(Int n)
+{
+sig_die("Trace trap", 1);
+}
+#endif
+
+
+int xargc;
+char **xargv;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#ifdef KR_headers
+main(argc, argv) int argc; char **argv;
+#else
+main(int argc, char **argv)
+#endif
+{
+xargc = argc;
+xargv = argv;
+signal1(SIGFPE, sigfdie); /* ignore underflow, enable overflow */
+#ifdef SIGIOT
+signal1(SIGIOT, sigidie);
+#endif
+#ifdef SIGTRAP
+signal1(SIGTRAP, sigtrdie);
+#endif
+#ifdef SIGQUIT
+if(signal1(SIGQUIT,sigqdie) == SIG_IGN)
+ signal1(SIGQUIT, SIG_IGN);
+#endif
+if(signal1(SIGINT, sigindie) == SIG_IGN)
+ signal1(SIGINT, SIG_IGN);
+signal1(SIGTERM,sigtdie);
+
+#ifdef pdp11
+ ldfps(01200); /* detect overflow as an exception */
+#endif
+
+f_init();
+#ifndef NO_ONEXIT
+ONEXIT(f_exit);
+#endif
+MAIN__();
+#ifdef NO_ONEXIT
+f_exit();
+#endif
+exit(0); /* exit(0) rather than return(0) to bypass Cray bug */
+return 0; /* For compilers that complain of missing return values; */
+ /* others will complain that this is unreachable code. */
+}
diff --git a/lib/libF77/pow_ci.c b/lib/libF77/pow_ci.c
new file mode 100644
index 0000000..37e2ce0
--- /dev/null
+++ b/lib/libF77/pow_ci.c
@@ -0,0 +1,20 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+VOID pow_ci(p, a, b) /* p = a**b */
+ complex *p, *a; integer *b;
+#else
+extern void pow_zi(doublecomplex*, doublecomplex*, integer*);
+void pow_ci(complex *p, complex *a, integer *b) /* p = a**b */
+#endif
+{
+doublecomplex p1, a1;
+
+a1.r = a->r;
+a1.i = a->i;
+
+pow_zi(&p1, &a1, b);
+
+p->r = p1.r;
+p->i = p1.i;
+}
diff --git a/lib/libF77/pow_dd.c b/lib/libF77/pow_dd.c
new file mode 100644
index 0000000..d2bb0e3
--- /dev/null
+++ b/lib/libF77/pow_dd.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double pow();
+double pow_dd(ap, bp) doublereal *ap, *bp;
+#else
+#undef abs
+#include "math.h"
+double pow_dd(doublereal *ap, doublereal *bp)
+#endif
+{
+return(pow(*ap, *bp) );
+}
diff --git a/lib/libF77/pow_di.c b/lib/libF77/pow_di.c
new file mode 100644
index 0000000..affed62
--- /dev/null
+++ b/lib/libF77/pow_di.c
@@ -0,0 +1,35 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double pow_di(ap, bp) doublereal *ap; integer *bp;
+#else
+double pow_di(doublereal *ap, integer *bp)
+#endif
+{
+double pow, x;
+integer n;
+unsigned long u;
+
+pow = 1;
+x = *ap;
+n = *bp;
+
+if(n != 0)
+ {
+ if(n < 0)
+ {
+ n = -n;
+ x = 1/x;
+ }
+ for(u = n; ; )
+ {
+ if(u & 01)
+ pow *= x;
+ if(u >>= 1)
+ x *= x;
+ else
+ break;
+ }
+ }
+return(pow);
+}
diff --git a/lib/libF77/pow_hh.c b/lib/libF77/pow_hh.c
new file mode 100644
index 0000000..24a0197
--- /dev/null
+++ b/lib/libF77/pow_hh.c
@@ -0,0 +1,33 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+shortint pow_hh(ap, bp) shortint *ap, *bp;
+#else
+shortint pow_hh(shortint *ap, shortint *bp)
+#endif
+{
+ shortint pow, x, n;
+ unsigned u;
+
+ x = *ap;
+ n = *bp;
+
+ if (n <= 0) {
+ if (n == 0 || x == 1)
+ return 1;
+ if (x != -1)
+ return x == 0 ? 1/x : 0;
+ n = -n;
+ }
+ u = n;
+ for(pow = 1; ; )
+ {
+ if(u & 01)
+ pow *= x;
+ if(u >>= 1)
+ x *= x;
+ else
+ break;
+ }
+ return(pow);
+ }
diff --git a/lib/libF77/pow_ii.c b/lib/libF77/pow_ii.c
new file mode 100644
index 0000000..84d1c7e
--- /dev/null
+++ b/lib/libF77/pow_ii.c
@@ -0,0 +1,33 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+integer pow_ii(ap, bp) integer *ap, *bp;
+#else
+integer pow_ii(integer *ap, integer *bp)
+#endif
+{
+ integer pow, x, n;
+ unsigned long u;
+
+ x = *ap;
+ n = *bp;
+
+ if (n <= 0) {
+ if (n == 0 || x == 1)
+ return 1;
+ if (x != -1)
+ return x == 0 ? 1/x : 0;
+ n = -n;
+ }
+ u = n;
+ for(pow = 1; ; )
+ {
+ if(u & 01)
+ pow *= x;
+ if(u >>= 1)
+ x *= x;
+ else
+ break;
+ }
+ return(pow);
+ }
diff --git a/lib/libF77/pow_qq.c b/lib/libF77/pow_qq.c
new file mode 100644
index 0000000..3bc80e0
--- /dev/null
+++ b/lib/libF77/pow_qq.c
@@ -0,0 +1,33 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+longint pow_qq(ap, bp) longint *ap, *bp;
+#else
+longint pow_qq(longint *ap, longint *bp)
+#endif
+{
+ longint pow, x, n;
+ unsigned long long u; /* system-dependent */
+
+ x = *ap;
+ n = *bp;
+
+ if (n <= 0) {
+ if (n == 0 || x == 1)
+ return 1;
+ if (x != -1)
+ return x == 0 ? 1/x : 0;
+ n = -n;
+ }
+ u = n;
+ for(pow = 1; ; )
+ {
+ if(u & 01)
+ pow *= x;
+ if(u >>= 1)
+ x *= x;
+ else
+ break;
+ }
+ return(pow);
+ }
diff --git a/lib/libF77/pow_ri.c b/lib/libF77/pow_ri.c
new file mode 100644
index 0000000..6e5816b
--- /dev/null
+++ b/lib/libF77/pow_ri.c
@@ -0,0 +1,35 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double pow_ri(ap, bp) real *ap; integer *bp;
+#else
+double pow_ri(real *ap, integer *bp)
+#endif
+{
+double pow, x;
+integer n;
+unsigned long u;
+
+pow = 1;
+x = *ap;
+n = *bp;
+
+if(n != 0)
+ {
+ if(n < 0)
+ {
+ n = -n;
+ x = 1/x;
+ }
+ for(u = n; ; )
+ {
+ if(u & 01)
+ pow *= x;
+ if(u >>= 1)
+ x *= x;
+ else
+ break;
+ }
+ }
+return(pow);
+}
diff --git a/lib/libF77/pow_zi.c b/lib/libF77/pow_zi.c
new file mode 100644
index 0000000..abb3cb2
--- /dev/null
+++ b/lib/libF77/pow_zi.c
@@ -0,0 +1,54 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+VOID pow_zi(p, a, b) /* p = a**b */
+ doublecomplex *p, *a; integer *b;
+#else
+extern void z_div(doublecomplex*, doublecomplex*, doublecomplex*);
+void pow_zi(doublecomplex *p, doublecomplex *a, integer *b) /* p = a**b */
+#endif
+{
+ integer n;
+ unsigned long u;
+ double t;
+ doublecomplex q, x;
+ static doublecomplex one = {1.0, 0.0};
+
+ n = *b;
+ q.r = 1;
+ q.i = 0;
+
+ if(n == 0)
+ goto done;
+ if(n < 0)
+ {
+ n = -n;
+ z_div(&x, &one, a);
+ }
+ else
+ {
+ x.r = a->r;
+ x.i = a->i;
+ }
+
+ for(u = n; ; )
+ {
+ if(u & 01)
+ {
+ t = q.r * x.r - q.i * x.i;
+ q.i = q.r * x.i + q.i * x.r;
+ q.r = t;
+ }
+ if(u >>= 1)
+ {
+ t = x.r * x.r - x.i * x.i;
+ x.i = 2 * x.r * x.i;
+ x.r = t;
+ }
+ else
+ break;
+ }
+ done:
+ p->i = q.i;
+ p->r = q.r;
+ }
diff --git a/lib/libF77/pow_zz.c b/lib/libF77/pow_zz.c
new file mode 100644
index 0000000..55785df
--- /dev/null
+++ b/lib/libF77/pow_zz.c
@@ -0,0 +1,23 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double log(), exp(), cos(), sin(), atan2(), f__cabs();
+VOID pow_zz(r,a,b) doublecomplex *r, *a, *b;
+#else
+#undef abs
+#include "math.h"
+extern double f__cabs(double,double);
+void pow_zz(doublecomplex *r, doublecomplex *a, doublecomplex *b)
+#endif
+{
+double logr, logi, x, y;
+
+logr = log( f__cabs(a->r, a->i) );
+logi = atan2(a->i, a->r);
+
+x = exp( logr * b->r - logi * b->i );
+y = logr * b->i + logi * b->r;
+
+r->r = x * cos(y);
+r->i = x * sin(y);
+}
diff --git a/lib/libF77/r_abs.c b/lib/libF77/r_abs.c
new file mode 100644
index 0000000..7b22296
--- /dev/null
+++ b/lib/libF77/r_abs.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double r_abs(x) real *x;
+#else
+double r_abs(real *x)
+#endif
+{
+if(*x >= 0)
+ return(*x);
+return(- *x);
+}
diff --git a/lib/libF77/r_acos.c b/lib/libF77/r_acos.c
new file mode 100644
index 0000000..328812a
--- /dev/null
+++ b/lib/libF77/r_acos.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double acos();
+double r_acos(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_acos(real *x)
+#endif
+{
+return( acos(*x) );
+}
diff --git a/lib/libF77/r_asin.c b/lib/libF77/r_asin.c
new file mode 100644
index 0000000..a30c670
--- /dev/null
+++ b/lib/libF77/r_asin.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double asin();
+double r_asin(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_asin(real *x)
+#endif
+{
+return( asin(*x) );
+}
diff --git a/lib/libF77/r_atan.c b/lib/libF77/r_atan.c
new file mode 100644
index 0000000..1e3817b
--- /dev/null
+++ b/lib/libF77/r_atan.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double atan();
+double r_atan(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_atan(real *x)
+#endif
+{
+return( atan(*x) );
+}
diff --git a/lib/libF77/r_atn2.c b/lib/libF77/r_atn2.c
new file mode 100644
index 0000000..3832a27
--- /dev/null
+++ b/lib/libF77/r_atn2.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double atan2();
+double r_atn2(x,y) real *x, *y;
+#else
+#undef abs
+#include "math.h"
+double r_atn2(real *x, real *y)
+#endif
+{
+return( atan2(*x,*y) );
+}
diff --git a/lib/libF77/r_cnjg.c b/lib/libF77/r_cnjg.c
new file mode 100644
index 0000000..e127ca9
--- /dev/null
+++ b/lib/libF77/r_cnjg.c
@@ -0,0 +1,11 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+VOID r_cnjg(r, z) complex *r, *z;
+#else
+VOID r_cnjg(complex *r, complex *z)
+#endif
+{
+r->r = z->r;
+r->i = - z->i;
+}
diff --git a/lib/libF77/r_cos.c b/lib/libF77/r_cos.c
new file mode 100644
index 0000000..cf5c8eb
--- /dev/null
+++ b/lib/libF77/r_cos.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double cos();
+double r_cos(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_cos(real *x)
+#endif
+{
+return( cos(*x) );
+}
diff --git a/lib/libF77/r_cosh.c b/lib/libF77/r_cosh.c
new file mode 100644
index 0000000..5756c17
--- /dev/null
+++ b/lib/libF77/r_cosh.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double cosh();
+double r_cosh(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_cosh(real *x)
+#endif
+{
+return( cosh(*x) );
+}
diff --git a/lib/libF77/r_dim.c b/lib/libF77/r_dim.c
new file mode 100644
index 0000000..baca95c
--- /dev/null
+++ b/lib/libF77/r_dim.c
@@ -0,0 +1,10 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double r_dim(a,b) real *a, *b;
+#else
+double r_dim(real *a, real *b)
+#endif
+{
+return( *a > *b ? *a - *b : 0);
+}
diff --git a/lib/libF77/r_exp.c b/lib/libF77/r_exp.c
new file mode 100644
index 0000000..a95f4bc
--- /dev/null
+++ b/lib/libF77/r_exp.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double exp();
+double r_exp(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_exp(real *x)
+#endif
+{
+return( exp(*x) );
+}
diff --git a/lib/libF77/r_imag.c b/lib/libF77/r_imag.c
new file mode 100644
index 0000000..d51252b
--- /dev/null
+++ b/lib/libF77/r_imag.c
@@ -0,0 +1,10 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double r_imag(z) complex *z;
+#else
+double r_imag(complex *z)
+#endif
+{
+return(z->i);
+}
diff --git a/lib/libF77/r_int.c b/lib/libF77/r_int.c
new file mode 100644
index 0000000..11264bf
--- /dev/null
+++ b/lib/libF77/r_int.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double floor();
+double r_int(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_int(real *x)
+#endif
+{
+return( (*x>0) ? floor(*x) : -floor(- *x) );
+}
diff --git a/lib/libF77/r_lg10.c b/lib/libF77/r_lg10.c
new file mode 100644
index 0000000..c40138e
--- /dev/null
+++ b/lib/libF77/r_lg10.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+float log10f();
+double r_lg10(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_lg10(real *x)
+#endif
+{
+return( log10f(*x) );
+}
diff --git a/lib/libF77/r_log.c b/lib/libF77/r_log.c
new file mode 100644
index 0000000..aec6726
--- /dev/null
+++ b/lib/libF77/r_log.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double log();
+double r_log(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_log(real *x)
+#endif
+{
+return( log(*x) );
+}
diff --git a/lib/libF77/r_mod.c b/lib/libF77/r_mod.c
new file mode 100644
index 0000000..7adb44c
--- /dev/null
+++ b/lib/libF77/r_mod.c
@@ -0,0 +1,40 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+#ifdef IEEE_drem
+double drem();
+#else
+double floor();
+#endif
+double r_mod(x,y) real *x, *y;
+#else
+#ifdef IEEE_drem
+double drem(double, double);
+#else
+#undef abs
+#include "math.h"
+#endif
+double r_mod(real *x, real *y)
+#endif
+{
+#ifdef IEEE_drem
+ double xa, ya, z;
+ if ((ya = *y) < 0.)
+ ya = -ya;
+ z = drem(xa = *x, ya);
+ if (xa > 0) {
+ if (z < 0)
+ z += ya;
+ }
+ else if (z > 0)
+ z -= ya;
+ return z;
+#else
+ double quotient;
+ if( (quotient = (double)*x / *y) >= 0)
+ quotient = floor(quotient);
+ else
+ quotient = -floor(-quotient);
+ return(*x - (*y) * quotient );
+#endif
+}
diff --git a/lib/libF77/r_nint.c b/lib/libF77/r_nint.c
new file mode 100644
index 0000000..c45bac6
--- /dev/null
+++ b/lib/libF77/r_nint.c
@@ -0,0 +1,14 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double floor();
+double r_nint(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_nint(real *x)
+#endif
+{
+return( (*x)>=0 ?
+ floor(*x + .5) : -floor(.5 - *x) );
+}
diff --git a/lib/libF77/r_sign.c b/lib/libF77/r_sign.c
new file mode 100644
index 0000000..df6d02a
--- /dev/null
+++ b/lib/libF77/r_sign.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double r_sign(a,b) real *a, *b;
+#else
+double r_sign(real *a, real *b)
+#endif
+{
+double x;
+x = (*a >= 0 ? *a : - *a);
+return( *b >= 0 ? x : -x);
+}
diff --git a/lib/libF77/r_sin.c b/lib/libF77/r_sin.c
new file mode 100644
index 0000000..d2a3dac
--- /dev/null
+++ b/lib/libF77/r_sin.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double sin();
+double r_sin(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_sin(real *x)
+#endif
+{
+return( sin(*x) );
+}
diff --git a/lib/libF77/r_sinh.c b/lib/libF77/r_sinh.c
new file mode 100644
index 0000000..00cba0c
--- /dev/null
+++ b/lib/libF77/r_sinh.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double sinh();
+double r_sinh(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_sinh(real *x)
+#endif
+{
+return( sinh(*x) );
+}
diff --git a/lib/libF77/r_sqrt.c b/lib/libF77/r_sqrt.c
new file mode 100644
index 0000000..26b4545
--- /dev/null
+++ b/lib/libF77/r_sqrt.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double sqrt();
+double r_sqrt(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_sqrt(real *x)
+#endif
+{
+return( sqrt(*x) );
+}
diff --git a/lib/libF77/r_tan.c b/lib/libF77/r_tan.c
new file mode 100644
index 0000000..736b378
--- /dev/null
+++ b/lib/libF77/r_tan.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double tan();
+double r_tan(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_tan(real *x)
+#endif
+{
+return( tan(*x) );
+}
diff --git a/lib/libF77/r_tanh.c b/lib/libF77/r_tanh.c
new file mode 100644
index 0000000..044255a
--- /dev/null
+++ b/lib/libF77/r_tanh.c
@@ -0,0 +1,13 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double tanh();
+double r_tanh(x) real *x;
+#else
+#undef abs
+#include "math.h"
+double r_tanh(real *x)
+#endif
+{
+return( tanh(*x) );
+}
diff --git a/lib/libF77/s_cat.c b/lib/libF77/s_cat.c
new file mode 100644
index 0000000..038f0ec
--- /dev/null
+++ b/lib/libF77/s_cat.c
@@ -0,0 +1,75 @@
+/* Unless compiled with -DNO_OVERWRITE, this variant of s_cat allows the
+ * target of a concatenation to appear on its right-hand side (contrary
+ * to the Fortran 77 Standard, but in accordance with Fortran 90).
+ */
+
+#include "f2c.h"
+#ifndef NO_OVERWRITE
+#include "stdio.h"
+#undef abs
+#ifdef KR_headers
+ extern char *F77_aloc();
+ extern void free();
+ extern void exit_();
+#else
+#undef min
+#undef max
+#include "stdlib.h"
+ extern char *F77_aloc(ftnlen, char*);
+#endif
+#include "string.h"
+#endif /* NO_OVERWRITE */
+
+ VOID
+#ifdef KR_headers
+s_cat(lp, rpp, rnp, np, ll) char *lp, *rpp[]; ftnlen rnp[], *np, ll;
+#else
+s_cat(char *lp, char *rpp[], ftnlen rnp[], ftnlen *np, ftnlen ll)
+#endif
+{
+ ftnlen i, nc;
+ char *rp;
+ ftnlen n = *np;
+#ifndef NO_OVERWRITE
+ ftnlen L, m;
+ char *lp0, *lp1;
+
+ lp0 = 0;
+ lp1 = lp;
+ L = ll;
+ i = 0;
+ while(i < n) {
+ rp = rpp[i];
+ m = rnp[i++];
+ if (rp >= lp1 || rp + m <= lp) {
+ if ((L -= m) <= 0) {
+ n = i;
+ break;
+ }
+ lp1 += m;
+ continue;
+ }
+ lp0 = lp;
+ lp = lp1 = F77_aloc(L = ll, "s_cat");
+ break;
+ }
+ lp1 = lp;
+#endif /* NO_OVERWRITE */
+ for(i = 0 ; i < n ; ++i) {
+ nc = ll;
+ if(rnp[i] < nc)
+ nc = rnp[i];
+ ll -= nc;
+ rp = rpp[i];
+ while(--nc >= 0)
+ *lp++ = *rp++;
+ }
+ while(--ll >= 0)
+ *lp++ = ' ';
+#ifndef NO_OVERWRITE
+ if (lp0) {
+ memcpy(lp0, lp1, L);
+ free(lp1);
+ }
+#endif
+ }
diff --git a/lib/libF77/s_cmp.c b/lib/libF77/s_cmp.c
new file mode 100644
index 0000000..1e052f2
--- /dev/null
+++ b/lib/libF77/s_cmp.c
@@ -0,0 +1,44 @@
+#include "f2c.h"
+
+/* compare two strings */
+
+#ifdef KR_headers
+integer s_cmp(a0, b0, la, lb) char *a0, *b0; ftnlen la, lb;
+#else
+integer s_cmp(char *a0, char *b0, ftnlen la, ftnlen lb)
+#endif
+{
+register unsigned char *a, *aend, *b, *bend;
+a = (unsigned char *)a0;
+b = (unsigned char *)b0;
+aend = a + la;
+bend = b + lb;
+
+if(la <= lb)
+ {
+ while(a < aend)
+ if(*a != *b)
+ return( *a - *b );
+ else
+ { ++a; ++b; }
+
+ while(b < bend)
+ if(*b != ' ')
+ return( ' ' - *b );
+ else ++b;
+ }
+
+else
+ {
+ while(b < bend)
+ if(*a == *b)
+ { ++a; ++b; }
+ else
+ return( *a - *b );
+ while(a < aend)
+ if(*a != ' ')
+ return(*a - ' ');
+ else ++a;
+ }
+return(0);
+}
diff --git a/lib/libF77/s_copy.c b/lib/libF77/s_copy.c
new file mode 100644
index 0000000..d167351
--- /dev/null
+++ b/lib/libF77/s_copy.c
@@ -0,0 +1,51 @@
+/* Unless compiled with -DNO_OVERWRITE, this variant of s_copy allows the
+ * target of an assignment to appear on its right-hand side (contrary
+ * to the Fortran 77 Standard, but in accordance with Fortran 90),
+ * as in a(2:5) = a(4:7) .
+ */
+
+#include "f2c.h"
+
+/* assign strings: a = b */
+
+#ifdef KR_headers
+VOID s_copy(a, b, la, lb) register char *a, *b; ftnlen la, lb;
+#else
+void s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
+#endif
+{
+ register char *aend, *bend;
+
+ aend = a + la;
+
+ if(la <= lb)
+#ifndef NO_OVERWRITE
+ if (a <= b || a >= b + la)
+#endif
+ while(a < aend)
+ *a++ = *b++;
+#ifndef NO_OVERWRITE
+ else
+ for(b += la; a < aend; )
+ *--aend = *--b;
+#endif
+
+ else {
+ bend = b + lb;
+#ifndef NO_OVERWRITE
+ if (a <= b || a >= bend)
+#endif
+ while(b < bend)
+ *a++ = *b++;
+#ifndef NO_OVERWRITE
+ else {
+ a += lb;
+ while(b < bend)
+ *--a = *--bend;
+ a += lb;
+ }
+#endif
+ while(a < aend)
+ *a++ = ' ';
+ }
+ }
diff --git a/lib/libF77/s_paus.c b/lib/libF77/s_paus.c
new file mode 100644
index 0000000..2501cb5a
--- /dev/null
+++ b/lib/libF77/s_paus.c
@@ -0,0 +1,88 @@
+#include "stdio.h"
+#include "f2c.h"
+#define PAUSESIG 15
+
+#ifdef KR_headers
+#define Void /* void */
+#define Int /* int */
+#else
+#define Void void
+#define Int int
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#include "signal1.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int getpid(void), isatty(int), pause(void);
+#endif
+
+extern VOID f_exit(Void);
+
+ static VOID
+waitpause(Int n)
+{ n = n; /* shut up compiler warning */
+ return;
+ }
+
+ static VOID
+#ifdef KR_headers
+s_1paus(fin) FILE *fin;
+#else
+s_1paus(FILE *fin)
+#endif
+{
+ fprintf(stderr,
+ "To resume execution, type go. Other input will terminate the job.\n");
+ fflush(stderr);
+ if( getc(fin)!='g' || getc(fin)!='o' || getc(fin)!='\n' ) {
+ fprintf(stderr, "STOP\n");
+#ifdef NO_ONEXIT
+ f_exit();
+#endif
+ exit(0);
+ }
+ }
+
+ int
+#ifdef KR_headers
+s_paus(s, n) char *s; ftnlen n;
+#else
+s_paus(char *s, ftnlen n)
+#endif
+{
+ fprintf(stderr, "PAUSE ");
+ if(n > 0)
+ fprintf(stderr, " %.*s", (int)n, s);
+ fprintf(stderr, " statement executed\n");
+ if( isatty(fileno(stdin)) )
+ s_1paus(stdin);
+ else {
+#ifdef MSDOS
+ FILE *fin;
+ fin = fopen("con", "r");
+ if (!fin) {
+ fprintf(stderr, "s_paus: can't open con!\n");
+ fflush(stderr);
+ exit(1);
+ }
+ s_1paus(fin);
+ fclose(fin);
+#else
+ fprintf(stderr,
+ "To resume execution, execute a kill -%d %d command\n",
+ PAUSESIG, getpid() );
+ signal1(PAUSESIG, waitpause);
+ fflush(stderr);
+ pause();
+#endif
+ }
+ fprintf(stderr, "Execution resumes after PAUSE.\n");
+ fflush(stderr);
+ return 0; /* NOT REACHED */
+#ifdef __cplusplus
+ }
+#endif
+}
diff --git a/lib/libF77/s_rnge.c b/lib/libF77/s_rnge.c
new file mode 100644
index 0000000..b200fce
--- /dev/null
+++ b/lib/libF77/s_rnge.c
@@ -0,0 +1,26 @@
+#include "stdio.h"
+#include "f2c.h"
+
+/* called when a subscript is out of range */
+
+#ifdef KR_headers
+extern VOID sig_die();
+integer s_rnge(varn, offset, procn, line) char *varn, *procn; ftnint offset, line;
+#else
+extern VOID sig_die(char*,int);
+integer s_rnge(char *varn, ftnint offset, char *procn, ftnint line)
+#endif
+{
+register int i;
+
+fprintf(stderr, "Subscript out of range on file line %ld, procedure ", line);
+while((i = *procn) && i != '_' && i != ' ')
+ putc(*procn++, stderr);
+fprintf(stderr, ".\nAttempt to access the %ld-th element of variable ", offset+1);
+while((i = *varn) && i != ' ')
+ putc(*varn++, stderr);
+sig_die(".", 1);
+#ifdef __cplusplus
+return 0;
+#endif
+}
diff --git a/lib/libF77/s_stop.c b/lib/libF77/s_stop.c
new file mode 100644
index 0000000..be3c28b
--- /dev/null
+++ b/lib/libF77/s_stop.c
@@ -0,0 +1,37 @@
+#include "stdio.h"
+#include "f2c.h"
+
+#ifdef KR_headers
+extern void f_exit();
+VOID s_stop(s, n) char *s; ftnlen n;
+#else
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+void f_exit(void);
+
+int s_stop(char *s, ftnlen n)
+#endif
+{
+int i;
+
+if(n > 0)
+ {
+ fprintf(stderr, "STOP ");
+ for(i = 0; i<n ; ++i)
+ putc(*s++, stderr);
+ fprintf(stderr, " statement executed\n");
+ }
+#ifdef NO_ONEXIT
+f_exit();
+#endif
+exit(0);
+#ifdef __cplusplus
+return 0; /* NOT REACHED */
+}
+#endif
+}
diff --git a/lib/libF77/sig_die.c b/lib/libF77/sig_die.c
new file mode 100644
index 0000000..dba1521
--- /dev/null
+++ b/lib/libF77/sig_die.c
@@ -0,0 +1,45 @@
+#include "stdio.h"
+#include "signal.h"
+
+#ifndef SIGIOT
+#ifdef SIGABRT
+#define SIGIOT SIGABRT
+#endif
+#endif
+
+#ifdef KR_headers
+void sig_die(s, kill) register char *s; int kill;
+#else
+#include "stdlib.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+ extern void f_exit(void);
+
+void sig_die(register char *s, int kill)
+#endif
+{
+ /* print error message, then clear buffers */
+ fprintf(stderr, "%s\n", s);
+
+ if(kill)
+ {
+ fflush(stderr);
+ f_exit();
+ fflush(stderr);
+ /* now get a core */
+#ifdef SIGIOT
+ signal(SIGIOT, SIG_DFL);
+#endif
+ abort();
+ }
+ else {
+#ifdef NO_ONEXIT
+ f_exit();
+#endif
+ exit(1);
+ }
+ }
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib/libF77/signal1.h b/lib/libF77/signal1.h
new file mode 100644
index 0000000..8800a18
--- /dev/null
+++ b/lib/libF77/signal1.h
@@ -0,0 +1,25 @@
+/* You may need to adjust the definition of signal1 to supply a */
+/* cast to the correct argument type. This detail is system- and */
+/* compiler-dependent. The #define below assumes signal.h declares */
+/* type SIG_PF for the signal function's second argument. */
+
+#include <signal.h>
+
+#ifndef Sigret_t
+#define Sigret_t void
+#endif
+#ifndef Sigarg_t
+#ifdef KR_headers
+#define Sigarg_t
+#else
+#define Sigarg_t int
+#endif
+#endif /*Sigarg_t*/
+
+#ifdef USE_SIG_PF /* compile with -DUSE_SIG_PF under IRIX */
+#define sig_pf SIG_PF
+#else
+typedef Sigret_t (*sig_pf)(Sigarg_t);
+#endif
+
+#define signal1(a,b) signal(a,(sig_pf)b)
diff --git a/lib/libF77/signal_.c b/lib/libF77/signal_.c
new file mode 100644
index 0000000..9b31f5a
--- /dev/null
+++ b/lib/libF77/signal_.c
@@ -0,0 +1,19 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+typedef VOID (*sig_pf)();
+extern sig_pf signal();
+#define signal1 signal
+
+ftnint signal_(sigp, proc) integer *sigp; sig_pf proc;
+#else
+#include "signal1.h"
+
+ftnint signal_(integer *sigp, sig_pf proc)
+#endif
+{
+ int sig;
+ sig = (int)*sigp;
+
+ return (ftnint)signal(sig, proc);
+ }
diff --git a/lib/libF77/system_.c b/lib/libF77/system_.c
new file mode 100644
index 0000000..e6b3a02
--- /dev/null
+++ b/lib/libF77/system_.c
@@ -0,0 +1,36 @@
+/* f77 interface to system routine */
+
+#include "f2c.h"
+
+#ifdef KR_headers
+extern char *F77_aloc();
+
+ integer
+system_(s, n) register char *s; ftnlen n;
+#else
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+extern char *F77_aloc(ftnlen, char*);
+
+ integer
+system_(register char *s, ftnlen n)
+#endif
+{
+ char buff0[256], *buff;
+ register char *bp, *blast;
+ integer rv;
+
+ buff = bp = n < sizeof(buff0)
+ ? buff0 : F77_aloc(n+1, "system_");
+ blast = bp + n;
+
+ while(bp < blast && *s)
+ *bp++ = *s++;
+ *bp = 0;
+ rv = system(buff);
+ if (buff != buff0)
+ free(buff);
+ return rv;
+ }
diff --git a/lib/libF77/z_abs.c b/lib/libF77/z_abs.c
new file mode 100644
index 0000000..7e67ad2
--- /dev/null
+++ b/lib/libF77/z_abs.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double f__cabs();
+double z_abs(z) doublecomplex *z;
+#else
+double f__cabs(double, double);
+double z_abs(doublecomplex *z)
+#endif
+{
+return( f__cabs( z->r, z->i ) );
+}
diff --git a/lib/libF77/z_cos.c b/lib/libF77/z_cos.c
new file mode 100644
index 0000000..fdd1510
--- /dev/null
+++ b/lib/libF77/z_cos.c
@@ -0,0 +1,15 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double sin(), cos(), sinh(), cosh();
+VOID z_cos(r, z) doublecomplex *r, *z;
+#else
+#undef abs
+#include "math.h"
+void z_cos(doublecomplex *r, doublecomplex *z)
+#endif
+{
+ double zr = z->r;
+ r->r = cos(zr) * cosh(z->i);
+ r->i = - sin(zr) * sinh(z->i);
+ }
diff --git a/lib/libF77/z_div.c b/lib/libF77/z_div.c
new file mode 100644
index 0000000..ed7ee66
--- /dev/null
+++ b/lib/libF77/z_div.c
@@ -0,0 +1,36 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+extern void sig_die();
+VOID z_div(c, a, b) doublecomplex *a, *b, *c;
+#else
+extern void sig_die(char*, int);
+void z_div(doublecomplex *c, doublecomplex *a, doublecomplex *b)
+#endif
+{
+ double ratio, den;
+ double abr, abi;
+ double ai = a->i, ar = a->r, bi = b->i, br = b->r;
+
+ if( (abr = br) < 0.)
+ abr = - abr;
+ if( (abi = bi) < 0.)
+ abi = - abi;
+ if( abr <= abi )
+ {
+ if(abi == 0)
+ sig_die("complex division by zero", 1);
+ ratio = br / bi ;
+ den = bi * (1 + ratio*ratio);
+ c->r = (ar*ratio + ai) / den;
+ c->i = (ai*ratio - ar) / den;
+ }
+
+ else
+ {
+ ratio = bi / br ;
+ den = br * (1 + ratio*ratio);
+ c->r = (ar + ai*ratio) / den;
+ c->i = (ai - ar*ratio) / den;
+ }
+ }
diff --git a/lib/libF77/z_exp.c b/lib/libF77/z_exp.c
new file mode 100644
index 0000000..56138f3
--- /dev/null
+++ b/lib/libF77/z_exp.c
@@ -0,0 +1,17 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double exp(), cos(), sin();
+VOID z_exp(r, z) doublecomplex *r, *z;
+#else
+#undef abs
+#include "math.h"
+void z_exp(doublecomplex *r, doublecomplex *z)
+#endif
+{
+double expx;
+
+expx = exp(z->r);
+r->r = expx * cos(z->i);
+r->i = expx * sin(z->i);
+}
diff --git a/lib/libF77/z_log.c b/lib/libF77/z_log.c
new file mode 100644
index 0000000..2d52b94
--- /dev/null
+++ b/lib/libF77/z_log.c
@@ -0,0 +1,16 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double log(), f__cabs(), atan2();
+VOID z_log(r, z) doublecomplex *r, *z;
+#else
+#undef abs
+#include "math.h"
+extern double f__cabs(double, double);
+void z_log(doublecomplex *r, doublecomplex *z)
+#endif
+{
+ double zi = z->i;
+ r->i = atan2(zi, z->r);
+ r->r = log( f__cabs( z->r, zi ) );
+ }
diff --git a/lib/libF77/z_sin.c b/lib/libF77/z_sin.c
new file mode 100644
index 0000000..577be1d
--- /dev/null
+++ b/lib/libF77/z_sin.c
@@ -0,0 +1,15 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double sin(), cos(), sinh(), cosh();
+VOID z_sin(r, z) doublecomplex *r, *z;
+#else
+#undef abs
+#include "math.h"
+void z_sin(doublecomplex *r, doublecomplex *z)
+#endif
+{
+ double zr = z->r;
+ r->r = sin(zr) * cosh(z->i);
+ r->i = cos(zr) * sinh(z->i);
+ }
diff --git a/lib/libF77/z_sqrt.c b/lib/libF77/z_sqrt.c
new file mode 100644
index 0000000..c04e8f0
--- /dev/null
+++ b/lib/libF77/z_sqrt.c
@@ -0,0 +1,29 @@
+#include "f2c.h"
+
+#ifdef KR_headers
+double sqrt(), f__cabs();
+VOID z_sqrt(r, z) doublecomplex *r, *z;
+#else
+#undef abs
+#include "math.h"
+extern double f__cabs(double, double);
+void z_sqrt(doublecomplex *r, doublecomplex *z)
+#endif
+{
+ double mag, zi = z->i, zr = z->r;
+
+ if( (mag = f__cabs(zr, zi)) == 0.)
+ r->r = r->i = 0.;
+ else if(zr > 0)
+ {
+ r->r = sqrt(0.5 * (mag + zr) );
+ r->i = zi / r->r / 2;
+ }
+ else
+ {
+ r->i = sqrt(0.5 * (mag - zr) );
+ if(zi < 0)
+ r->i = - r->i;
+ r->r = zi / r->i / 2;
+ }
+ }
diff --git a/lib/libI77/Notice b/lib/libI77/Notice
new file mode 100644
index 0000000..8db1d7b
--- /dev/null
+++ b/lib/libI77/Notice
@@ -0,0 +1,23 @@
+/****************************************************************
+Copyright 1990 - 1997 by AT&T Bell Laboratories and Bellcore.
+
+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 names of AT&T Bell Laboratories or
+Bellcore or any of their entities not be used in advertising or
+publicity pertaining to distribution of the software without
+specific, written prior permission.
+
+AT&T and Bellcore disclaim all warranties with regard to this
+software, including all implied warranties of merchantability
+and fitness. In no event shall AT&T or Bellcore 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.
+****************************************************************/
+
diff --git a/lib/libI77/README b/lib/libI77/README
new file mode 100644
index 0000000..30dd5b5
--- /dev/null
+++ b/lib/libI77/README
@@ -0,0 +1,225 @@
+If your compiler does not recognize ANSI C headers,
+compile with KR_headers defined: either add -DKR_headers
+to the definition of CFLAGS in the makefile, or insert
+
+#define KR_headers
+
+at the top of f2c.h and fmtlib.c .
+
+
+If you have a really ancient K&R C compiler that does not understand
+void, add -Dvoid=int to the definition of CFLAGS in the makefile.
+
+If you use a C++ compiler, first create a local f2c.h by appending
+f2ch.add to the usual f2c.h, e.g., by issuing the command
+ make f2c.h
+which assumes f2c.h is installed in /usr/include .
+
+If your system lacks /usr/include/fcntl.h , then you
+should simply create an empty fcntl.h in this directory.
+If your compiler then complains about creat and open not
+having a prototype, compile with OPEN_DECL defined.
+On many systems, open and creat are declared in fcntl.h .
+
+If your system has /usr/include/fcntl.h, you may need to add
+-D_POSIX_SOURCE to the makefile's definition of CFLAGS.
+
+If your system's sprintf does not work the way ANSI C
+specifies -- specifically, if it does not return the
+number of characters transmitted -- then insert the line
+
+#define USE_STRLEN
+
+at the end of fmt.h . This is necessary with
+at least some versions of Sun and DEC software.
+In particular, if you get a warning about an improper
+pointer/integer combination in compiling wref.c, then
+you need to compile with -DUSE_STRLEN .
+
+If your system's fopen does not like the ANSI binary
+reading and writing modes "rb" and "wb", then you should
+compile open.c with NON_ANSI_RW_MODES #defined.
+
+If you get error messages about references to cf->_ptr
+and cf->_base when compiling wrtfmt.c and wsfe.c or to
+stderr->_flag when compiling err.c, then insert the line
+
+#define NON_UNIX_STDIO
+
+at the beginning of fio.h, and recompile everything (or
+at least those modules that contain NON_UNIX_STDIO).
+
+Unformatted sequential records consist of a length of record
+contents, the record contents themselves, and the length of
+record contents again (for backspace). Prior to 17 Oct. 1991,
+the length was of type int; now it is of type long, but you
+can change it back to int by inserting
+
+#define UIOLEN_int
+
+at the beginning of fio.h. This affects only sue.c and uio.c .
+
+On VAX, Cray, or Research Tenth-Edition Unix systems, you may
+need to add -DVAX, -DCRAY, or -DV10 (respectively) to CFLAGS
+to make fp.h work correctly. Alternatively, you may need to
+edit fp.h to suit your machine.
+
+You may need to supply the following non-ANSI routines:
+
+ fstat(int fileds, struct stat *buf) is similar
+to stat(char *name, struct stat *buf), except that
+the first argument, fileds, is the file descriptor
+returned by open rather than the name of the file.
+fstat is used in the system-dependent routine
+canseek (in the libI77 source file err.c), which
+is supposed to return 1 if it's possible to issue
+seeks on the file in question, 0 if it's not; you may
+need to suitably modify err.c . On non-UNIX systems,
+you can avoid references to fstat and stat by compiling
+with NON_UNIX_STDIO defined; in that case, you may need
+to supply access(char *Name,0), which is supposed to
+return 0 if file Name exists, nonzero otherwise.
+
+ char * mktemp(char *buf) is supposed to replace the
+6 trailing X's in buf with a unique number and then
+return buf. The idea is to get a unique name for
+a temporary file.
+
+On non-UNIX systems, you may need to change a few other,
+e.g.: the form of name computed by mktemp() in endfile.c and
+open.c; the use of the open(), close(), and creat() system
+calls in endfile.c, err.c, open.c; and the modes in calls on
+fopen() and fdopen() (and perhaps the use of fdopen() itself
+-- it's supposed to return a FILE* corresponding to a given
+an integer file descriptor) in err.c and open.c (component ufmt
+of struct unit is 1 for formatted I/O -- text mode on some systems
+-- and 0 for unformatted I/O -- binary mode on some systems).
+Compiling with -DNON_UNIX_STDIO omits all references to creat()
+and almost all references to open() and close(), the exception
+being in the function f__isdev() (in open.c).
+
+For MS-DOS, compile all of libI77 with -DMSDOS (which implies
+-DNON_UNIX_STDIO). You may need to make other compiler-dependent
+adjustments; for example, for Turbo C++ you need to adjust the mktemp
+invocations and to #undef ungetc in lread.c and rsne.c .
+
+If you want to be able to load against libI77 but not libF77,
+then you will need to add sig_die.o (from libF77) to libI77.
+
+If you wish to use translated Fortran that has funny notions
+of record length for direct unformatted I/O (i.e., that assumes
+RECL= values in OPEN statements are not bytes but rather counts
+of some other units -- e.g., 4-character words for VMS), then you
+should insert an appropriate #define for url_Adjust at the
+beginning of open.c . For VMS Fortran, for example,
+#define url_Adjust(x) x *= 4
+would suffice.
+
+To check for transmission errors, issue the command
+ make check
+This assumes you have the xsum program whose source, xsum.c,
+is distributed as part of "all from f2c/src". If you do not
+have xsum, you can obtain xsum.c by sending the following E-mail
+message to netlib@netlib.bell-labs.com
+ send xsum.c from f2c/src
+
+The makefile assumes you have installed f2c.h in a standard
+place (and does not cause recompilation when f2c.h is changed);
+f2c.h comes with "all from f2c" (the source for f2c) and is
+available separately ("f2c.h from f2c").
+
+By default, Fortran I/O units 5, 6, and 0 are pre-connected to
+stdin, stdout, and stderr, respectively. You can change this
+behavior by changing f_init() in err.c to suit your needs.
+Note that f2c assumes READ(*... means READ(5... and WRITE(*...
+means WRITE(6... . Moreover, an OPEN(n,... statement that does
+not specify a file name (and does not specify STATUS='SCRATCH')
+assumes FILE='fort.n' . You can change this by editing open.c
+and endfile.c suitably.
+
+Unless you adjust the "#define MXUNIT" line in fio.h, Fortran units
+0, 1, ..., 99 are available, i.e., the highest allowed unit number
+is MXUNIT - 1.
+
+Lines protected from compilation by #ifdef Allow_TYQUAD
+are for a possible extension to 64-bit integers in which
+integer = int = 32 bits and longint = long = 64 bits.
+
+Extensions (Feb. 1993) to NAMELIST processing:
+ 1. Reading a ? instead of &name (the start of a namelist) causes
+the namelist being sought to be written to stdout (unit 6);
+to omit this feature, compile rsne.c with -DNo_Namelist_Questions.
+ 2. Reading the wrong namelist name now leads to an error message
+and an attempt to skip input until the right namelist name is found;
+to omit this feature, compile rsne.c with -DNo_Bad_Namelist_Skip.
+ 3. Namelist writes now insert newlines before each variable; to omit
+this feature, compile xwsne.c with -DNo_Extra_Namelist_Newlines.
+ 4. (Sept. 1995) When looking for the &name that starts namelist
+input, lines whose first non-blank character is something other
+than &, $, or ? are treated as comment lines and ignored, unless
+rsne.c is compiled with -DNo_Namelist_Comments.
+
+Nonstandard extension (Feb. 1993) to open: for sequential files,
+ACCESS='APPEND' (or access='anything else starting with "A" or "a"')
+causes the file to be positioned at end-of-file, so a write will
+append to the file.
+
+Some buggy Fortran programs use unformatted direct I/O to write
+an incomplete record and later read more from that record than
+they have written. For records other than the last, the unwritten
+portion of the record reads as binary zeros. The last record is
+a special case: attempting to read more from it than was written
+gives end-of-file -- which may help one find a bug. Some other
+Fortran I/O libraries treat the last record no differently than
+others and thus give no help in finding the bug of reading more
+than was written. If you wish to have this behavior, compile
+uio.c with -DPad_UDread .
+
+If you want to be able to catch write failures (e.g., due to a
+disk being full) with an ERR= specifier, compile dfe.c, due.c,
+sfe.c, sue.c, and wsle.c with -DALWAYS_FLUSH. This will lead to
+slower execution and more I/O, but should make ERR= work as
+expected, provided fflush returns an error return when its
+physical write fails.
+
+Carriage controls are meant to be interpreted by the UNIX col
+program (or a similar program). Sometimes it's convenient to use
+only ' ' as the carriage control character (normal single spacing).
+If you compile lwrite.c and wsfe.c with -DOMIT_BLANK_CC, formatted
+external output lines will have an initial ' ' quietly omitted,
+making use of the col program unnecessary with output that only
+has ' ' for carriage control.
+
+The Fortran 77 Standard leaves it up to the implementation whether
+formatted writes of floating-point numbers of absolute value < 1 have
+a zero before the decimal point. By default, libI77 omits such
+superfluous zeros, but you can cause them to appear by compiling
+lwrite.c, wref.c, and wrtfmt.c with -DWANT_LEAD_0 .
+
+If your system lacks a ranlib command, you don't need it.
+Either comment out the makefile's ranlib invocation, or install
+a harmless "ranlib" command somewhere in your PATH, such as the
+one-line shell script
+
+ exit 0
+
+or (on some systems)
+
+ exec /usr/bin/ar lts $1 >/dev/null
+
+Most of the routines in libI77 are support routines for Fortran
+I/O. There are a few exceptions, summarized below -- I/O related
+functions and subroutines that appear to your program as ordinary
+external Fortran routines.
+
+1. CALL FLUSH flushes all buffers.
+
+2. FTELL(i) is an INTEGER function that returns the current
+ offset of Fortran unit i (or -1 if unit i is not open).
+
+3. CALL FSEEK(i, offset, whence, *errlab) attemps to move
+ Fortran unit i to the specified offset: absolute offset
+ if whence = 0; relative to the current offset if whence = 1;
+ relative to the end of the file if whence = 2. It branches
+ to label errlab if unit i is not open or if the call
+ otherwise fails.
diff --git a/lib/libI77/Version.c b/lib/libI77/Version.c
new file mode 100644
index 0000000..b73ae67
--- /dev/null
+++ b/lib/libI77/Version.c
@@ -0,0 +1,244 @@
+static char junk[] = "\n@(#) LIBI77 VERSION pjw,dmg-mods 19970226\n";
+
+/*
+2.01 $ format added
+2.02 Coding bug in open.c repaired
+2.03 fixed bugs in lread.c (read * with negative f-format) and lio.c
+ and lio.h (e-format conforming to spec)
+2.04 changed open.c and err.c (fopen and freopen respectively) to
+ update to new c-library (append mode)
+2.05 added namelist capability
+2.06 allow internal list and namelist I/O
+*/
+
+/*
+close.c:
+ allow upper-case STATUS= values
+endfile.c
+ create fort.nnn if unit nnn not open;
+ else if (file length == 0) use creat() rather than copy;
+ use local copy() rather than forking /bin/cp;
+ rewind, fseek to clear buffer (for no reading past EOF)
+err.c
+ use neither setbuf nor setvbuf; make stderr buffered
+fio.h
+ #define _bufend
+inquire.c
+ upper case responses;
+ omit byfile test from SEQUENTIAL=
+ answer "YES" to DIRECT= for unopened file (open to debate)
+lio.c
+ flush stderr, stdout at end of each stmt
+ space before character strings in list output only at line start
+lio.h
+ adjust LEW, LED consistent with old libI77
+lread.c
+ use atof()
+ allow "nnn*," when reading complex constants
+open.c
+ try opening for writing when open for read fails, with
+ special uwrt value (2) delaying creat() to first write;
+ set curunit so error messages don't drop core;
+ no file name ==> fort.nnn except for STATUS='SCRATCH'
+rdfmt.c
+ use atof(); trust EOF == end-of-file (so don't read past
+ end-of-file after endfile stmt)
+sfe.c
+ flush stderr, stdout at end of each stmt
+wrtfmt.c:
+ use upper case
+ put wrt_E and wrt_F into wref.c, use sprintf()
+ rather than ecvt() and fcvt() [more accurate on VAX]
+*/
+
+/* 16 Oct. 1988: uwrt = 3 after write, rewind, so close won't zap the file. */
+
+/* 10 July 1989: change _bufend to buf_end in fio.h, wsfe.c, wrtfmt.c */
+
+/* 28 Nov. 1989: corrections for IEEE and Cray arithmetic */
+/* 29 Nov. 1989: change various int return types to long for f2c */
+/* 30 Nov. 1989: various types from f2c.h */
+/* 6 Dec. 1989: types corrected various places */
+/* 19 Dec. 1989: make iostat= work right for internal I/O */
+/* 8 Jan. 1990: add rsne, wsne -- routines for handling NAMELIST */
+/* 28 Jan. 1990: have NAMELIST read treat $ as &, general white
+ space as blank */
+/* 27 Mar. 1990: change an = to == in rd_L(rdfmt.c) so formatted reads
+ of logical values reject letters other than fFtT;
+ have nowwriting reset cf */
+/* 14 Aug. 1990: adjust lread.c to treat tabs as spaces in list input */
+/* 17 Aug. 1990: adjust open.c to recognize blank='Z...' as well as
+ blank='z...' when reopening an open file */
+/* 30 Aug. 1990: prevent embedded blanks in list output of complex values;
+ omit exponent field in list output of values of
+ magnitude between 10 and 1e8; prevent writing stdin
+ and reading stdout or stderr; don't close stdin, stdout,
+ or stderr when reopening units 5, 6, 0. */
+/* 18 Sep. 1990: add component udev to unit and consider old == new file
+ iff uinode and udev values agree; use stat rather than
+ access to check existence of file (when STATUS='OLD')*/
+/* 2 Oct. 1990: adjust rewind.c so two successive rewinds after a write
+ don't clobber the file. */
+/* 9 Oct. 1990: add #include "fcntl.h" to endfile.c, err.c, open.c;
+ adjust g_char in util.c for segmented memories. */
+/* 17 Oct. 1990: replace abort() and _cleanup() with calls on
+ sig_die(...,1) (defined in main.c). */
+/* 5 Nov. 1990: changes to open.c: complain if new= is specified and the
+ file already exists; allow file= to be omitted in open stmts
+ and allow status='replace' (Fortran 90 extensions). */
+/* 11 Dec. 1990: adjustments for POSIX. */
+/* 15 Jan. 1991: tweak i_ungetc in rsli.c to allow reading from
+ strings in read-only memory. */
+/* 25 Apr. 1991: adjust namelist stuff to work with f2c -i2 */
+/* 26 Apr. 1991: fix some bugs with NAMELIST read of multi-dim. arrays */
+/* 16 May 1991: increase LEFBL in lio.h to bypass NeXT bug */
+/* 17 Oct. 1991: change type of length field in sequential unformatted
+ records from int to long (for systems where sizeof(int)
+ can vary, depending on the compiler or compiler options). */
+/* 14 Nov. 1991: change uint to Uint in fmt.h, rdfmt.c, wrtfmt.c. */
+/* 25 Nov. 1991: change uint to Uint in lwrite.c; change sizeof(int) to
+ sizeof(uioint) in fseeks in sue.c (missed on 17 Oct.). */
+/* 1 Dec. 1991: uio.c: add test for read failure (seq. unformatted reads);
+ adjust an error return from EOF to off end of record */
+/* 12 Dec. 1991: rsli.c: fix bug with internal list input that caused
+ the last character of each record to be ignored.
+ iio.c: adjust error message in internal formatted
+ input from "end-of-file" to "off end of record" if
+ the format specifies more characters than the
+ record contains. */
+/* 17 Jan. 1992: lread.c, rsne.c: in list and namelist input,
+ treat "r* ," and "r*," alike (where r is a
+ positive integer constant), and fix a bug in
+ handling null values following items with repeat
+ counts (e.g., 2*1,,3); for namelist reading
+ of a numeric array, allow a new name-value subsequence
+ to terminate the current one (as though the current
+ one ended with the right number of null values).
+ lio.h, lwrite.c: omit insignificant zeros in
+ list and namelist output. To get the old
+ behavior, compile with -DOld_list_output . */
+/* 18 Jan. 1992: make list output consistent with F format by
+ printing .1 rather than 0.1 (introduced yesterday). */
+/* 3 Feb. 1992: rsne.c: fix namelist read bug that caused the
+ character following a comma to be ignored. */
+/* 19 May 1992: adjust iio.c, ilnw.c, rdfmt.c and rsli.c to make err=
+ work with internal list and formatted I/O. */
+/* 18 July 1992: adjust rsne.c to allow namelist input to stop at
+ an & (e.g. &end). */
+/* 23 July 1992: switch to ANSI prototypes unless KR_headers is #defined ;
+ recognize Z format (assuming 8-bit bytes). */
+/* 14 Aug. 1992: tweak wrt_E in wref.c to avoid -NaN */
+/* 23 Oct. 1992: Supply missing l_eof = 0 assignment to s_rsne() in rsne.c
+ (so end-of-file on other files won't confuse namelist
+ reads of external files). Prepend f__ to external
+ names that are only of internal interest to lib[FI]77. */
+/* 1 Feb. 1993: backspace.c: fix bug that bit when last char of 2nd
+ buffer == '\n'.
+ endfile.c: guard against tiny L_tmpnam; close and reopen
+ files in t_runc().
+ lio.h: lengthen LINTW (buffer size in lwrite.c).
+ err.c, open.c: more prepending of f__ (to [rw]_mode). */
+/* 5 Feb. 1993: tweaks to NAMELIST: rsne.c: ? prints the namelist being
+ sought; namelists of the wrong name are skipped (after
+ an error message; xwsne.c: namelist writes have a
+ newline before each new variable.
+ open.c: ACCESS='APPEND' positions sequential files
+ at EOF (nonstandard extension -- that doesn't require
+ changing data structures). */
+/* 9 Feb. 1993: Change some #ifdef MSDOS lines to #ifdef NON_UNIX_STDIO.
+ err.c: under NON_UNIX_STDIO, avoid close(creat(name,0666))
+ when the unit has another file descriptor for name. */
+/* 4 March 1993: err.c, open.c: take declaration of fdopen from rawio.h;
+ open.c: always give f__w_mode[] 4 elements for use
+ in t_runc (in endfile.c -- for change of 1 Feb. 1993). */
+/* 6 March 1993: uio.c: adjust off-end-of-record test for sequential
+ unformatted reads to respond to err= rather than end=. */
+/* 12 March 1993: various tweaks for C++ */
+/* 6 April 1993: adjust error returns for formatted inputs to flush
+ the current input line when err=label is specified.
+ To restore the old behavior (input left mid-line),
+ either adjust the #definition of errfl in fio.h or
+ omit the invocation of f__doend in err__fl (in err.c). */
+/* 23 June 1993: iio.c: fix bug in format reversions for internal writes. */
+/* 5 Aug. 1993: lread.c: fix bug in handling repetition counts for
+ logical data (during list or namelist input).
+ Change struct f__syl to struct syl (for buggy compilers). */
+/* 7 Aug. 1993: lread.c: fix bug in namelist reading of incomplete
+ logical arrays. */
+/* 9 Aug. 1993: lread.c: fix bug in namelist reading of an incomplete
+ array of numeric data followed by another namelist
+ item whose name starts with 'd', 'D', 'e', or 'E'. */
+/* 8 Sept. 1993: open.c: protect #include "sys/..." with
+ #ifndef NON_UNIX_STDIO; Version date not changed. */
+/* 10 Nov. 1993: backspace.c: add nonsense for #ifdef MSDOS */
+/* 8 Dec. 1993: iio.c: adjust internal formatted reads to treat
+ short records as though padded with blanks
+ (rather than causing an "off end of record" error). */
+/* 22 Feb. 1994: lread.c: check that realloc did not return NULL. */
+/* 6 June 1994: Under NON_UNIX_STDIO, use binary mode for direct
+ formatted files (avoiding any confusion regarding \n). */
+/* 5 July 1994: Fix bug (introduced 6 June 1994?) in reopening files
+ under NON_UNIX_STDIO. */
+/* 6 July 1994: wref.c: protect with #ifdef GOOD_SPRINTF_EXPONENT an
+ optimization that requires exponents to have 2 digits
+ when 2 digits suffice.
+ lwrite.c wsfe.c (list and formatted external output):
+ omit ' ' carriage-control when compiled with
+ -DOMIT_BLANK_CC . Off-by-one bug fixed in character
+ count for list output of character strings.
+ Omit '.' in list-directed printing of Nan, Infinity. */
+/* 12 July 1994: wrtfmt.c: under G11.4, write 0. as " .0000 " rather
+ than " .0000E+00". */
+/* 3 Aug. 1994: lwrite.c: do not insert a newline when appending an
+ oversize item to an empty line. */
+/* 12 Aug. 1994: rsli.c rsne.c: fix glitch (reset nml_read) that kept
+ ERR= (in list- or format-directed input) from working
+ after a NAMELIST READ. */
+/* 7 Sept. 1994: typesize.c: adjust to allow types LOGICAL*1, LOGICAL*2,
+ INTEGER*1, and (under -DAllow_TYQUAD) INTEGER*8
+ in NAMELISTs. */
+/* 6 Oct. 1994: util.c: omit f__mvgbt, as it is never used. */
+/* 2 Nov. 1994: add #ifdef ALWAYS_FLUSH logic. */
+/* 26 Jan. 1995: wref.c: fix glitch in printing the exponent of 0 when
+ GOOD_SPRINTF_EXPONENT is not #defined. */
+/* 24 Feb. 1995: iio.c: z_getc: insert (unsigned char *) to allow
+ internal reading of characters with high-bit set
+ (on machines that sign-extend characters). */
+/* 14 March 1995:lread.c and rsfe.c: adjust s_rsle and s_rsfe to
+ check for end-of-file (to prevent infinite loops
+ with empty read statements). */
+/* 26 May 1995: iio.c: z_wnew: fix bug in handling T format items
+ in internal writes whose last item is written to
+ an earlier position than some previous item. */
+/* 29 Aug. 1995: backspace.c: adjust MSDOS logic. */
+/* 6 Sept. 1995: Adjust namelist input to treat a subscripted name
+ whose subscripts do not involve colons similarly
+ to the name without a subscript: accept several
+ values, stored in successive elements starting at
+ the indicated subscript. Adjust namelist output
+ to quote character strings (avoiding confusion with
+ arrays of character strings). Adjust f_init calls
+ for people who don't use libF77's main(); now open and
+ namelist read statements invoke f_init if needed. */
+/* 7 Sept. 1995: Fix some bugs with -DAllow_TYQUAD (for integer*8).
+ Add -DNo_Namelist_Comments lines to rsne.c. */
+/* 5 Oct. 1995: wrtfmt.c: fix bug with t editing (f__cursor was not
+ always zeroed in mv_cur). */
+/* 11 Oct. 1995: move defs of f__hiwater, f__svic, f__icptr from wrtfmt.c
+ to err.c */
+/* 15 Mar. 1996: lread.c, rsfe.c: honor END= in READ stmt with empty iolist */
+
+/* 13 May 1996: add ftell_.c and fseek_.c */
+/* 9 June 1996: Adjust rsli.c and lread.c so internal list input with
+ too few items in the input string will honor end= . */
+/* 12 Sept. 1995:fmtlib.c: fix glitch in printing the most negative integer. */
+/* 25 Sept. 1995:fmt.h: for formatted writes of negative integer*1 values,
+ make ic signed on ANSI systems. If formatted writes of
+ integer*1 values trouble you when using a K&R C compiler,
+ switch to an ANSI compiler or use a compiler flag that
+ makes characters signed. */
+/* 9 Dec. 1996: d[fu]e.c, err.c: complain about non-positive rec=
+ in direct read and write statements.
+ ftell_.c: change param "unit" to "Unit" for -DKR_headers. */
+/* 26 Feb. 1997: ftell_.c: on systems that define SEEK_SET, etc., use
+ SEEK_SET, SEEK_CUR, SEEK_END for *whence = 0, 1, 2. */
diff --git a/lib/libI77/backspace.c b/lib/libI77/backspace.c
new file mode 100644
index 0000000..3771cd9
--- /dev/null
+++ b/lib/libI77/backspace.c
@@ -0,0 +1,98 @@
+#include "f2c.h"
+#include "fio.h"
+#ifdef KR_headers
+integer f_back(a) alist *a;
+#else
+integer f_back(alist *a)
+#endif
+{ unit *b;
+ int i, n, ndec;
+#ifdef MSDOS
+ int j, k;
+ long w, z;
+#endif
+ long x, y;
+ char buf[32];
+ if(a->aunit >= MXUNIT || a->aunit < 0)
+ err(a->aerr,101,"backspace")
+ b= &f__units[a->aunit];
+ if(b->useek==0) err(a->aerr,106,"backspace")
+ if(b->ufd==NULL) {
+ fk_open(1, 1, a->aunit);
+ return(0);
+ }
+ if(b->uend==1)
+ { b->uend=0;
+ return(0);
+ }
+ if(b->uwrt) {
+ (void) t_runc(a);
+ if (f__nowreading(b))
+ err(a->aerr,errno,"backspace")
+ }
+ if(b->url>0)
+ {
+ x=ftell(b->ufd);
+ y = x % b->url;
+ if(y == 0) x--;
+ x /= b->url;
+ x *= b->url;
+ (void) fseek(b->ufd,x,SEEK_SET);
+ return(0);
+ }
+
+ if(b->ufmt==0)
+ { (void) fseek(b->ufd,-(long)sizeof(int),SEEK_CUR);
+ (void) fread((char *)&n,sizeof(int),1,b->ufd);
+ (void) fseek(b->ufd,-(long)n-2*sizeof(int),SEEK_CUR);
+ return(0);
+ }
+#ifdef MSDOS
+ w = -1;
+#endif
+ for(ndec = 1;; ndec = 0)
+ {
+ y = x = ftell(b->ufd);
+ if(x < sizeof(buf))
+ x = 0;
+ else
+ x -= sizeof(buf);
+ (void) fseek(b->ufd,x,SEEK_SET);
+ n=fread(buf,1,(int)(y-x), b->ufd);
+ for(i = n - ndec; --i >= 0; )
+ {
+ if(buf[i]!='\n') continue;
+#ifdef MSDOS
+ for(j = k = 0; j <= i; j++)
+ if (buf[j] == '\n')
+ k++;
+ fseek(b->ufd,x,SEEK_SET);
+ for(;;)
+ if (getc(b->ufd) == '\n') {
+ if ((z = ftell(b->ufd)) >= y && ndec) {
+ if (w == -1)
+ goto break2;
+ break;
+ }
+ if (--k <= 0)
+ return 0;
+ w = z;
+ }
+ fseek(b->ufd, w, SEEK_SET);
+#else
+ fseek(b->ufd,(long)(i+1-n),SEEK_CUR);
+#endif
+ return(0);
+ }
+#ifdef MSDOS
+ break2:
+#endif
+ if(x==0)
+ {
+ (void) fseek(b->ufd, 0L, SEEK_SET);
+ return(0);
+ }
+ else if(n<=0) err(a->aerr,(EOF),"backspace")
+ (void) fseek(b->ufd, x, SEEK_SET);
+ }
+}
diff --git a/lib/libI77/close.c b/lib/libI77/close.c
new file mode 100644
index 0000000..29a7af5
--- /dev/null
+++ b/lib/libI77/close.c
@@ -0,0 +1,95 @@
+#include "f2c.h"
+#include "fio.h"
+#ifdef KR_headers
+integer f_clos(a) cllist *a;
+#else
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#ifdef NON_UNIX_STDIO
+#ifndef unlink
+#define unlink remove
+#endif
+#else
+#ifdef MSDOS
+#include "io.h"
+#else
+#ifdef __cplusplus
+extern "C" int unlink(const char*);
+#else
+extern int unlink(const char*);
+#endif
+#endif
+#endif
+
+integer f_clos(cllist *a)
+#endif
+{ unit *b;
+
+ if(a->cunit >= MXUNIT) return(0);
+ b= &f__units[a->cunit];
+ if(b->ufd==NULL)
+ goto done;
+ if (!a->csta)
+ if (b->uscrtch == 1)
+ goto Delete;
+ else
+ goto Keep;
+ switch(*a->csta) {
+ default:
+ Keep:
+ case 'k':
+ case 'K':
+ if(b->uwrt == 1)
+ t_runc((alist *)a);
+ if(b->ufnm) {
+ fclose(b->ufd);
+ free(b->ufnm);
+ }
+ break;
+ case 'd':
+ case 'D':
+ Delete:
+ if(b->ufnm) {
+ fclose(b->ufd);
+ unlink(b->ufnm); /*SYSDEP*/
+ free(b->ufnm);
+ }
+ }
+ b->ufd=NULL;
+ done:
+ b->uend=0;
+ b->ufnm=NULL;
+ return(0);
+ }
+ void
+#ifdef KR_headers
+f_exit()
+#else
+f_exit(void)
+#endif
+{ int i;
+ static cllist xx;
+ if (!xx.cerr) {
+ xx.cerr=1;
+ xx.csta=NULL;
+ for(i=0;i<MXUNIT;i++)
+ {
+ xx.cunit=i;
+ (void) f_clos(&xx);
+ }
+ }
+}
+ int
+#ifdef KR_headers
+flush_()
+#else
+flush_(void)
+#endif
+{ int i;
+ for(i=0;i<MXUNIT;i++)
+ if(f__units[i].ufd != NULL && f__units[i].uwrt)
+ fflush(f__units[i].ufd);
+return 0;
+}
diff --git a/lib/libI77/dfe.c b/lib/libI77/dfe.c
new file mode 100644
index 0000000..51023d5
--- /dev/null
+++ b/lib/libI77/dfe.c
@@ -0,0 +1,152 @@
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+
+y_rsk(Void)
+{
+ if(f__curunit->uend || f__curunit->url <= f__recpos
+ || f__curunit->url == 1) return 0;
+ do {
+ getc(f__cf);
+ } while(++f__recpos < f__curunit->url);
+ return 0;
+}
+y_getc(Void)
+{
+ int ch;
+ if(f__curunit->uend) return(-1);
+ if((ch=getc(f__cf))!=EOF)
+ {
+ f__recpos++;
+ if(f__curunit->url>=f__recpos ||
+ f__curunit->url==1)
+ return(ch);
+ else return(' ');
+ }
+ if(feof(f__cf))
+ {
+ f__curunit->uend=1;
+ errno=0;
+ return(-1);
+ }
+ err(f__elist->cierr,errno,"readingd");
+}
+#ifdef KR_headers
+y_putc(c)
+#else
+y_putc(int c)
+#endif
+{
+ f__recpos++;
+ if(f__recpos <= f__curunit->url || f__curunit->url==1)
+ putc(c,f__cf);
+ else
+ err(f__elist->cierr,110,"dout");
+ return(0);
+}
+y_rev(Void)
+{ /*what about work done?*/
+ if(f__curunit->url==1 || f__recpos==f__curunit->url)
+ return(0);
+ while(f__recpos<f__curunit->url)
+ (*f__putn)(' ');
+ f__recpos=0;
+ return(0);
+}
+y_err(Void)
+{
+ err(f__elist->cierr, 110, "dfe");
+}
+
+y_newrec(Void)
+{
+ if(f__curunit->url == 1 || f__recpos == f__curunit->url) {
+ f__hiwater = f__recpos = f__cursor = 0;
+ return(1);
+ }
+ if(f__hiwater > f__recpos)
+ f__recpos = f__hiwater;
+ y_rev();
+ f__hiwater = f__cursor = 0;
+ return(1);
+}
+
+#ifdef KR_headers
+c_dfe(a) cilist *a;
+#else
+c_dfe(cilist *a)
+#endif
+{
+ f__sequential=0;
+ f__formatted=f__external=1;
+ f__elist=a;
+ f__cursor=f__scale=f__recpos=0;
+ if(a->ciunit>MXUNIT || a->ciunit<0)
+ err(a->cierr,101,"startchk");
+ f__curunit = &f__units[a->ciunit];
+ if(f__curunit->ufd==NULL && fk_open(DIR,FMT,a->ciunit))
+ err(a->cierr,104,"dfe");
+ f__cf=f__curunit->ufd;
+ if(!f__curunit->ufmt) err(a->cierr,102,"dfe")
+ if(!f__curunit->useek) err(a->cierr,104,"dfe")
+ f__fmtbuf=a->cifmt;
+ if(a->cirec <= 0)
+ err(a->cierr,130,"dfe")
+ fseek(f__cf,(long)f__curunit->url * (a->cirec-1),SEEK_SET);
+ f__curunit->uend = 0;
+ return(0);
+}
+#ifdef KR_headers
+integer s_rdfe(a) cilist *a;
+#else
+integer s_rdfe(cilist *a)
+#endif
+{
+ int n;
+ if(!f__init) f_init();
+ f__reading=1;
+ if(n=c_dfe(a))return(n);
+ if(f__curunit->uwrt && f__nowreading(f__curunit))
+ err(a->cierr,errno,"read start");
+ f__getn = y_getc;
+ f__doed = rd_ed;
+ f__doned = rd_ned;
+ f__dorevert = f__donewrec = y_err;
+ f__doend = y_rsk;
+ if(pars_f(f__fmtbuf)<0)
+ err(a->cierr,100,"read start");
+ fmt_bg();
+ return(0);
+}
+#ifdef KR_headers
+integer s_wdfe(a) cilist *a;
+#else
+integer s_wdfe(cilist *a)
+#endif
+{
+ int n;
+ if(!f__init) f_init();
+ f__reading=0;
+ if(n=c_dfe(a)) return(n);
+ if(f__curunit->uwrt != 1 && f__nowwriting(f__curunit))
+ err(a->cierr,errno,"startwrt");
+ f__putn = y_putc;
+ f__doed = w_ed;
+ f__doned= w_ned;
+ f__dorevert = y_err;
+ f__donewrec = y_newrec;
+ f__doend = y_rev;
+ if(pars_f(f__fmtbuf)<0)
+ err(a->cierr,100,"startwrt");
+ fmt_bg();
+ return(0);
+}
+integer e_rdfe(Void)
+{
+ (void) en_fio();
+ return(0);
+}
+integer e_wdfe(Void)
+{
+ return en_fio();
+}
diff --git a/lib/libI77/dolio.c b/lib/libI77/dolio.c
new file mode 100644
index 0000000..4b5a2ca
--- /dev/null
+++ b/lib/libI77/dolio.c
@@ -0,0 +1,20 @@
+#include "f2c.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef KR_headers
+extern int (*f__lioproc)();
+
+integer do_lio(type,number,ptr,len) ftnint *number,*type; char *ptr; ftnlen len;
+#else
+extern int (*f__lioproc)(ftnint*, char*, ftnlen, ftnint);
+
+integer do_lio(ftnint *type, ftnint *number, char *ptr, ftnlen len)
+#endif
+{
+ return((*f__lioproc)(number,ptr,len,*type));
+}
+#ifdef __cplusplus
+ }
+#endif
diff --git a/lib/libI77/due.c b/lib/libI77/due.c
new file mode 100644
index 0000000..670b0f1
--- /dev/null
+++ b/lib/libI77/due.c
@@ -0,0 +1,70 @@
+#include "f2c.h"
+#include "fio.h"
+
+#ifdef KR_headers
+c_due(a) cilist *a;
+#else
+c_due(cilist *a)
+#endif
+{
+ if(!f__init) f_init();
+ if(a->ciunit>=MXUNIT || a->ciunit<0)
+ err(a->cierr,101,"startio");
+ f__sequential=f__formatted=f__recpos=0;
+ f__external=1;
+ f__curunit = &f__units[a->ciunit];
+ f__elist=a;
+ if(f__curunit->ufd==NULL && fk_open(DIR,UNF,a->ciunit) ) err(a->cierr,104,"due");
+ f__cf=f__curunit->ufd;
+ if(f__curunit->ufmt) err(a->cierr,102,"cdue")
+ if(!f__curunit->useek) err(a->cierr,104,"cdue")
+ if(f__curunit->ufd==NULL) err(a->cierr,114,"cdue")
+ if(a->cirec <= 0)
+ err(a->cierr,130,"due")
+ fseek(f__cf,(long)(a->cirec-1)*f__curunit->url,SEEK_SET);
+ f__curunit->uend = 0;
+ return(0);
+}
+#ifdef KR_headers
+integer s_rdue(a) cilist *a;
+#else
+integer s_rdue(cilist *a)
+#endif
+{
+ int n;
+ f__reading=1;
+ if(n=c_due(a)) return(n);
+ if(f__curunit->uwrt && f__nowreading(f__curunit))
+ err(a->cierr,errno,"read start");
+ return(0);
+}
+#ifdef KR_headers
+integer s_wdue(a) cilist *a;
+#else
+integer s_wdue(cilist *a)
+#endif
+{
+ int n;
+ f__reading=0;
+ if(n=c_due(a)) return(n);
+ if(f__curunit->uwrt != 1 && f__nowwriting(f__curunit))
+ err(a->cierr,errno,"write start");
+ return(0);
+}
+integer e_rdue(Void)
+{
+ if(f__curunit->url==1 || f__recpos==f__curunit->url)
+ return(0);
+ fseek(f__cf,(long)(f__curunit->url-f__recpos),SEEK_CUR);
+ if(ftell(f__cf)%f__curunit->url)
+ err(f__elist->cierr,200,"syserr");
+ return(0);
+}
+integer e_wdue(Void)
+{
+#ifdef ALWAYS_FLUSH
+ if (fflush(f__cf))
+ err(f__elist->cierr,errno,"write end");
+#endif
+ return(e_rdue());
+}
diff --git a/lib/libI77/endfile.c b/lib/libI77/endfile.c
new file mode 100644
index 0000000..f5990e3
--- /dev/null
+++ b/lib/libI77/endfile.c
@@ -0,0 +1,195 @@
+#include "f2c.h"
+#include "fio.h"
+#ifndef NON_UNIX_STDIO
+#include "sys/types.h"
+#endif
+#include "rawio.h"
+
+#ifdef KR_headers
+extern char *strcpy();
+#else
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#include "string.h"
+#endif
+
+#ifdef NON_UNIX_STDIO
+#ifndef unlink
+#define unlink remove
+#endif
+#else
+#ifdef MSDOS
+#include "io.h"
+#endif
+#endif
+
+#ifdef NON_UNIX_STDIO
+extern char *f__r_mode[], *f__w_mode[];
+#endif
+
+#ifdef KR_headers
+integer f_end(a) alist *a;
+#else
+integer f_end(alist *a)
+#endif
+{
+ unit *b;
+ if(a->aunit>=MXUNIT || a->aunit<0) err(a->aerr,101,"endfile");
+ b = &f__units[a->aunit];
+ if(b->ufd==NULL) {
+ char nbuf[10];
+ (void) sprintf(nbuf,"fort.%ld",a->aunit);
+#ifdef NON_UNIX_STDIO
+ { FILE *tf;
+ if (tf = fopen(nbuf, f__w_mode[0]))
+ fclose(tf);
+ }
+#else
+ close(creat(nbuf, 0666));
+#endif
+ return(0);
+ }
+ b->uend=1;
+ return(b->useek ? t_runc(a) : 0);
+}
+
+ static int
+#ifdef NON_UNIX_STDIO
+#ifdef KR_headers
+copy(from, len, to) char *from, *to; register long len;
+#else
+copy(FILE *from, register long len, FILE *to)
+#endif
+{
+ int k, len1;
+ char buf[BUFSIZ];
+
+ while(fread(buf, len1 = len > BUFSIZ ? BUFSIZ : (int)len, 1, from)) {
+ if (!fwrite(buf, len1, 1, to))
+ return 1;
+ if ((len -= len1) <= 0)
+ break;
+ }
+ return 0;
+ }
+#else
+#ifdef KR_headers
+copy(from, len, to) char *from, *to; register long len;
+#else
+copy(char *from, register long len, char *to)
+#endif
+{
+ register int n;
+ int k, rc = 0, tmp;
+ char buf[BUFSIZ];
+
+ if ((k = open(from, O_RDONLY)) < 0)
+ return 1;
+ if ((tmp = creat(to,0666)) < 0)
+ return 1;
+ while((n = read(k, buf, len > BUFSIZ ? BUFSIZ : (int)len)) > 0) {
+ if (write(tmp, buf, n) != n)
+ { rc = 1; break; }
+ if ((len -= n) <= 0)
+ break;
+ }
+ close(k);
+ close(tmp);
+ return n < 0 ? 1 : rc;
+ }
+#endif
+
+#ifndef L_tmpnam
+#define L_tmpnam 16
+#endif
+
+ int
+#ifdef KR_headers
+t_runc(a) alist *a;
+#else
+t_runc(alist *a)
+#endif
+{
+ char nm[L_tmpnam+12]; /* extra space in case L_tmpnam is tiny */
+ long loc, len;
+ unit *b;
+#ifdef NON_UNIX_STDIO
+ FILE *bf, *tf;
+#else
+ FILE *bf;
+#endif
+ int rc = 0;
+
+ b = &f__units[a->aunit];
+ if(b->url)
+ return(0); /*don't truncate direct files*/
+ loc=ftell(bf = b->ufd);
+ fseek(bf,0L,SEEK_END);
+ len=ftell(bf);
+ if (loc >= len || b->useek == 0 || b->ufnm == NULL)
+ return(0);
+#ifdef NON_UNIX_STDIO
+ fclose(b->ufd);
+#else
+ rewind(b->ufd); /* empty buffer */
+#endif
+ if (!loc) {
+#ifdef NON_UNIX_STDIO
+ if (!(bf = fopen(b->ufnm, f__w_mode[b->ufmt])))
+#else
+ if (close(creat(b->ufnm,0666)))
+#endif
+ rc = 1;
+ if (b->uwrt)
+ b->uwrt = 1;
+ goto done;
+ }
+#ifdef _POSIX_SOURCE
+ tmpnam(nm);
+#else
+ strcpy(nm,"tmp.FXXXXXX");
+ mktemp(nm);
+#endif
+#ifdef NON_UNIX_STDIO
+ if (!(bf = fopen(b->ufnm, f__r_mode[0]))) {
+ bad:
+ rc = 1;
+ goto done;
+ }
+ if (!(tf = fopen(nm, f__w_mode[0])))
+ goto bad;
+ if (copy(bf, loc, tf)) {
+ bad1:
+ rc = 1;
+ goto done1;
+ }
+ if (!(bf = freopen(b->ufnm, f__w_mode[0], bf)))
+ goto bad1;
+ if (!(tf = freopen(nm, f__r_mode[0], tf)))
+ goto bad1;
+ if (copy(tf, loc, bf))
+ goto bad1;
+ if (f__w_mode[0] != f__w_mode[b->ufmt]) {
+ if (!(bf = freopen(b->ufnm, f__w_mode[b->ufmt|2], bf)))
+ goto bad1;
+ fseek(bf, loc, SEEK_SET);
+ }
+done1:
+ fclose(tf);
+ unlink(nm);
+done:
+ f__cf = b->ufd = bf;
+#else
+ if (copy(b->ufnm, loc, nm)
+ || copy(nm, loc, b->ufnm))
+ rc = 1;
+ unlink(nm);
+ fseek(b->ufd, loc, SEEK_SET);
+done:
+#endif
+ if (rc)
+ err(a->aerr,111,"endfile");
+ return 0;
+ }
diff --git a/lib/libI77/err.c b/lib/libI77/err.c
new file mode 100644
index 0000000..29747ff
--- /dev/null
+++ b/lib/libI77/err.c
@@ -0,0 +1,278 @@
+#ifndef NON_UNIX_STDIO
+#include "sys/types.h"
+#include "sys/stat.h"
+#endif
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h" /* for struct syl */
+#include "rawio.h" /* for fcntl.h, fdopen */
+#ifdef NON_UNIX_STDIO
+#ifdef KR_headers
+extern char *malloc();
+#else
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#endif
+#endif
+
+/*global definitions*/
+unit f__units[MXUNIT]; /*unit table*/
+flag f__init; /*0 on entry, 1 after initializations*/
+cilist *f__elist; /*active external io list*/
+icilist *f__svic; /*active internal io list*/
+flag f__reading; /*1 if reading, 0 if writing*/
+flag f__cplus,f__cblank;
+char *f__fmtbuf;
+flag f__external; /*1 if external io, 0 if internal */
+#ifdef KR_headers
+int (*f__doed)(),(*f__doned)();
+int (*f__doend)(),(*f__donewrec)(),(*f__dorevert)();
+int (*f__getn)(),(*f__putn)(); /*for formatted io*/
+#else
+int (*f__getn)(void),(*f__putn)(int); /*for formatted io*/
+int (*f__doed)(struct syl*, char*, ftnlen),(*f__doned)(struct syl*);
+int (*f__dorevert)(void),(*f__donewrec)(void),(*f__doend)(void);
+#endif
+flag f__sequential; /*1 if sequential io, 0 if direct*/
+flag f__formatted; /*1 if formatted io, 0 if unformatted*/
+FILE *f__cf; /*current file*/
+unit *f__curunit; /*current unit*/
+int f__recpos; /*place in current record*/
+int f__cursor, f__hiwater, f__scale;
+char *f__icptr;
+
+/*error messages*/
+char *F_err[] =
+{
+ "error in format", /* 100 */
+ "illegal unit number", /* 101 */
+ "formatted io not allowed", /* 102 */
+ "unformatted io not allowed", /* 103 */
+ "direct io not allowed", /* 104 */
+ "sequential io not allowed", /* 105 */
+ "can't backspace file", /* 106 */
+ "null file name", /* 107 */
+ "can't stat file", /* 108 */
+ "unit not connected", /* 109 */
+ "off end of record", /* 110 */
+ "truncation failed in endfile", /* 111 */
+ "incomprehensible list input", /* 112 */
+ "out of free space", /* 113 */
+ "unit not connected", /* 114 */
+ "read unexpected character", /* 115 */
+ "bad logical input field", /* 116 */
+ "bad variable type", /* 117 */
+ "bad namelist name", /* 118 */
+ "variable not in namelist", /* 119 */
+ "no end record", /* 120 */
+ "variable count incorrect", /* 121 */
+ "subscript for scalar variable", /* 122 */
+ "invalid array section", /* 123 */
+ "substring out of bounds", /* 124 */
+ "subscript out of bounds", /* 125 */
+ "can't read file", /* 126 */
+ "can't write file", /* 127 */
+ "'new' file exists", /* 128 */
+ "can't append to file", /* 129 */
+ "non-positive record number" /* 130 */
+};
+#define MAXERR (sizeof(F_err)/sizeof(char *)+100)
+
+#ifdef KR_headers
+f__canseek(f) FILE *f; /*SYSDEP*/
+#else
+f__canseek(FILE *f) /*SYSDEP*/
+#endif
+{
+#ifdef NON_UNIX_STDIO
+ return !isatty(fileno(f));
+#else
+ struct stat x;
+
+ if (fstat(fileno(f),&x) < 0)
+ return(0);
+#ifdef S_IFMT
+ switch(x.st_mode & S_IFMT) {
+ case S_IFDIR:
+ case S_IFREG:
+ if(x.st_nlink > 0) /* !pipe */
+ return(1);
+ else
+ return(0);
+ case S_IFCHR:
+ if(isatty(fileno(f)))
+ return(0);
+ return(1);
+#ifdef S_IFBLK
+ case S_IFBLK:
+ return(1);
+#endif
+ }
+#else
+#ifdef S_ISDIR
+ /* POSIX version */
+ if (S_ISREG(x.st_mode) || S_ISDIR(x.st_mode)) {
+ if(x.st_nlink > 0) /* !pipe */
+ return(1);
+ else
+ return(0);
+ }
+ if (S_ISCHR(x.st_mode)) {
+ if(isatty(fileno(f)))
+ return(0);
+ return(1);
+ }
+ if (S_ISBLK(x.st_mode))
+ return(1);
+#else
+ Help! How does fstat work on this system?
+#endif
+#endif
+ return(0); /* who knows what it is? */
+#endif
+}
+
+ void
+#ifdef KR_headers
+f__fatal(n,s) char *s;
+#else
+f__fatal(int n, char *s)
+#endif
+{
+ if(n<100 && n>=0) perror(s); /*SYSDEP*/
+ else if(n >= (int)MAXERR || n < -1)
+ { fprintf(stderr,"%s: illegal error number %d\n",s,n);
+ }
+ else if(n == -1) fprintf(stderr,"%s: end of file\n",s);
+ else
+ fprintf(stderr,"%s: %s\n",s,F_err[n-100]);
+ if (f__curunit) {
+ fprintf(stderr,"apparent state: unit %d ",f__curunit-f__units);
+ fprintf(stderr, f__curunit->ufnm ? "named %s\n" : "(unnamed)\n",
+ f__curunit->ufnm);
+ }
+ else
+ fprintf(stderr,"apparent state: internal I/O\n");
+ if (f__fmtbuf)
+ fprintf(stderr,"last format: %s\n",f__fmtbuf);
+ fprintf(stderr,"lately %s %s %s %s",f__reading?"reading":"writing",
+ f__sequential?"sequential":"direct",f__formatted?"formatted":"unformatted",
+ f__external?"external":"internal");
+ sig_die(" IO", 1);
+}
+/*initialization routine*/
+ VOID
+f_init(Void)
+{ unit *p;
+
+ f__init=1;
+ p= &f__units[0];
+ p->ufd=stderr;
+ p->useek=f__canseek(stderr);
+#ifdef NON_UNIX_STDIO
+ setbuf(stderr, (char *)malloc(BUFSIZ));
+#else
+ stderr->_flag &= ~_IONBF;
+#endif
+ p->ufmt=1;
+ p->uwrt=1;
+ p = &f__units[5];
+ p->ufd=stdin;
+ p->useek=f__canseek(stdin);
+ p->ufmt=1;
+ p->uwrt=0;
+ p= &f__units[6];
+ p->ufd=stdout;
+ p->useek=f__canseek(stdout);
+ p->ufmt=1;
+ p->uwrt=1;
+}
+#ifdef KR_headers
+f__nowreading(x) unit *x;
+#else
+f__nowreading(unit *x)
+#endif
+{
+ long loc;
+ int ufmt;
+ extern char *f__r_mode[];
+
+ if (!x->ufnm)
+ goto cantread;
+ ufmt = x->ufmt;
+ loc=ftell(x->ufd);
+ if(freopen(x->ufnm,f__r_mode[ufmt],x->ufd) == NULL) {
+ cantread:
+ errno = 126;
+ return(1);
+ }
+ x->uwrt=0;
+ (void) fseek(x->ufd,loc,SEEK_SET);
+ return(0);
+}
+#ifdef KR_headers
+f__nowwriting(x) unit *x;
+#else
+f__nowwriting(unit *x)
+#endif
+{
+ long loc;
+ int ufmt;
+ extern char *f__w_mode[];
+#ifndef NON_UNIX_STDIO
+ int k;
+#endif
+
+ if (!x->ufnm)
+ goto cantwrite;
+ ufmt = x->ufmt;
+#ifdef NON_UNIX_STDIO
+ ufmt |= 2;
+#endif
+ if (x->uwrt == 3) { /* just did write, rewind */
+#ifdef NON_UNIX_STDIO
+ if (!(f__cf = x->ufd =
+ freopen(x->ufnm,f__w_mode[ufmt],x->ufd)))
+#else
+ if (close(creat(x->ufnm,0666)))
+#endif
+ goto cantwrite;
+ }
+ else {
+ loc=ftell(x->ufd);
+#ifdef NON_UNIX_STDIO
+ if (!(f__cf = x->ufd =
+ freopen(x->ufnm, f__w_mode[ufmt], x->ufd)))
+#else
+ if (fclose(x->ufd) < 0
+ || (k = x->uwrt == 2 ? creat(x->ufnm,0666)
+ : open(x->ufnm,O_WRONLY)) < 0
+ || (f__cf = x->ufd = fdopen(k,f__w_mode[ufmt])) == NULL)
+#endif
+ {
+ x->ufd = NULL;
+ cantwrite:
+ errno = 127;
+ return(1);
+ }
+ (void) fseek(x->ufd,loc,SEEK_SET);
+ }
+ x->uwrt = 1;
+ return(0);
+}
+
+ int
+#ifdef KR_headers
+err__fl(f, m, s) int f, m; char *s;
+#else
+err__fl(int f, int m, char *s)
+#endif
+{
+ if (!f)
+ f__fatal(m, s);
+ if (f__doend)
+ (*f__doend)();
+ return errno = m;
+ }
diff --git a/lib/libI77/f2ch.add b/lib/libI77/f2ch.add
new file mode 100644
index 0000000..a2acc17
--- /dev/null
+++ b/lib/libI77/f2ch.add
@@ -0,0 +1,162 @@
+/* If you are using a C++ compiler, append the following to f2c.h
+ for compiling libF77 and libI77. */
+
+#ifdef __cplusplus
+extern "C" {
+extern int abort_(void);
+extern double c_abs(complex *);
+extern void c_cos(complex *, complex *);
+extern void c_div(complex *, complex *, complex *);
+extern void c_exp(complex *, complex *);
+extern void c_log(complex *, complex *);
+extern void c_sin(complex *, complex *);
+extern void c_sqrt(complex *, complex *);
+extern double d_abs(double *);
+extern double d_acos(double *);
+extern double d_asin(double *);
+extern double d_atan(double *);
+extern double d_atn2(double *, double *);
+extern void d_cnjg(doublecomplex *, doublecomplex *);
+extern double d_cos(double *);
+extern double d_cosh(double *);
+extern double d_dim(double *, double *);
+extern double d_exp(double *);
+extern double d_imag(doublecomplex *);
+extern double d_int(double *);
+extern double d_lg10(double *);
+extern double d_log(double *);
+extern double d_mod(double *, double *);
+extern double d_nint(double *);
+extern double d_prod(float *, float *);
+extern double d_sign(double *, double *);
+extern double d_sin(double *);
+extern double d_sinh(double *);
+extern double d_sqrt(double *);
+extern double d_tan(double *);
+extern double d_tanh(double *);
+extern double derf_(double *);
+extern double derfc_(double *);
+extern integer do_fio(ftnint *, char *, ftnlen);
+extern integer do_lio(ftnint *, ftnint *, char *, ftnlen);
+extern integer do_uio(ftnint *, char *, ftnlen);
+extern integer e_rdfe(void);
+extern integer e_rdue(void);
+extern integer e_rsfe(void);
+extern integer e_rsfi(void);
+extern integer e_rsle(void);
+extern integer e_rsli(void);
+extern integer e_rsue(void);
+extern integer e_wdfe(void);
+extern integer e_wdue(void);
+extern integer e_wsfe(void);
+extern integer e_wsfi(void);
+extern integer e_wsle(void);
+extern integer e_wsli(void);
+extern integer e_wsue(void);
+extern int ef1asc_(ftnint *, ftnlen *, ftnint *, ftnlen *);
+extern integer ef1cmc_(ftnint *, ftnlen *, ftnint *, ftnlen *);
+extern double erf(double);
+extern double erf_(float *);
+extern double erfc(double);
+extern double erfc_(float *);
+extern integer f_back(alist *);
+extern integer f_clos(cllist *);
+extern integer f_end(alist *);
+extern void f_exit(void);
+extern integer f_inqu(inlist *);
+extern integer f_open(olist *);
+extern integer f_rew(alist *);
+extern int flush_(void);
+extern void getarg_(integer *, char *, ftnlen);
+extern void getenv_(char *, char *, ftnlen, ftnlen);
+extern short h_abs(short *);
+extern short h_dim(short *, short *);
+extern short h_dnnt(double *);
+extern short h_indx(char *, char *, ftnlen, ftnlen);
+extern short h_len(char *, ftnlen);
+extern short h_mod(short *, short *);
+extern short h_nint(float *);
+extern short h_sign(short *, short *);
+extern short hl_ge(char *, char *, ftnlen, ftnlen);
+extern short hl_gt(char *, char *, ftnlen, ftnlen);
+extern short hl_le(char *, char *, ftnlen, ftnlen);
+extern short hl_lt(char *, char *, ftnlen, ftnlen);
+extern integer i_abs(integer *);
+extern integer i_dim(integer *, integer *);
+extern integer i_dnnt(double *);
+extern integer i_indx(char *, char *, ftnlen, ftnlen);
+extern integer i_len(char *, ftnlen);
+extern integer i_mod(integer *, integer *);
+extern integer i_nint(float *);
+extern integer i_sign(integer *, integer *);
+extern integer iargc_(void);
+extern ftnlen l_ge(char *, char *, ftnlen, ftnlen);
+extern ftnlen l_gt(char *, char *, ftnlen, ftnlen);
+extern ftnlen l_le(char *, char *, ftnlen, ftnlen);
+extern ftnlen l_lt(char *, char *, ftnlen, ftnlen);
+extern void pow_ci(complex *, complex *, integer *);
+extern double pow_dd(double *, double *);
+extern double pow_di(double *, integer *);
+extern short pow_hh(short *, shortint *);
+extern integer pow_ii(integer *, integer *);
+extern double pow_ri(float *, integer *);
+extern void pow_zi(doublecomplex *, doublecomplex *, integer *);
+extern void pow_zz(doublecomplex *, doublecomplex *, doublecomplex *);
+extern double r_abs(float *);
+extern double r_acos(float *);
+extern double r_asin(float *);
+extern double r_atan(float *);
+extern double r_atn2(float *, float *);
+extern void r_cnjg(complex *, complex *);
+extern double r_cos(float *);
+extern double r_cosh(float *);
+extern double r_dim(float *, float *);
+extern double r_exp(float *);
+extern double r_imag(complex *);
+extern double r_int(float *);
+extern double r_lg10(float *);
+extern double r_log(float *);
+extern double r_mod(float *, float *);
+extern double r_nint(float *);
+extern double r_sign(float *, float *);
+extern double r_sin(float *);
+extern double r_sinh(float *);
+extern double r_sqrt(float *);
+extern double r_tan(float *);
+extern double r_tanh(float *);
+extern void s_cat(char *, char **, integer *, integer *, ftnlen);
+extern integer s_cmp(char *, char *, ftnlen, ftnlen);
+extern void s_copy(char *, char *, ftnlen, ftnlen);
+extern int s_paus(char *, ftnlen);
+extern integer s_rdfe(cilist *);
+extern integer s_rdue(cilist *);
+extern integer s_rnge(char *, integer, char *, integer);
+extern integer s_rsfe(cilist *);
+extern integer s_rsfi(icilist *);
+extern integer s_rsle(cilist *);
+extern integer s_rsli(icilist *);
+extern integer s_rsne(cilist *);
+extern integer s_rsni(icilist *);
+extern integer s_rsue(cilist *);
+extern int s_stop(char *, ftnlen);
+extern integer s_wdfe(cilist *);
+extern integer s_wdue(cilist *);
+extern integer s_wsfe(cilist *);
+extern integer s_wsfi(icilist *);
+extern integer s_wsle(cilist *);
+extern integer s_wsli(icilist *);
+extern integer s_wsne(cilist *);
+extern integer s_wsni(icilist *);
+extern integer s_wsue(cilist *);
+extern void sig_die(char *, int);
+extern integer signal_(integer *, void (*)(int));
+extern integer system_(char *, ftnlen);
+extern double z_abs(doublecomplex *);
+extern void z_cos(doublecomplex *, doublecomplex *);
+extern void z_div(doublecomplex *, doublecomplex *, doublecomplex *);
+extern void z_exp(doublecomplex *, doublecomplex *);
+extern void z_log(doublecomplex *, doublecomplex *);
+extern void z_sin(doublecomplex *, doublecomplex *);
+extern void z_sqrt(doublecomplex *, doublecomplex *);
+ }
+#endif
diff --git a/lib/libI77/fio.h b/lib/libI77/fio.h
new file mode 100644
index 0000000..e8c693b
--- /dev/null
+++ b/lib/libI77/fio.h
@@ -0,0 +1,102 @@
+#include "stdio.h"
+#include "errno.h"
+#ifndef NULL
+/* ANSI C */
+#include "stddef.h"
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+#ifdef MSDOS
+#ifndef NON_UNIX_STDIO
+#define NON_UNIX_STDIO
+#endif
+#endif
+
+#ifdef UIOLEN_int
+typedef int uiolen;
+#else
+typedef long uiolen;
+#endif
+
+/*units*/
+typedef struct
+{ FILE *ufd; /*0=unconnected*/
+ char *ufnm;
+#ifndef MSDOS
+ long uinode;
+ int udev;
+#endif
+ int url; /*0=sequential*/
+ flag useek; /*true=can backspace, use dir, ...*/
+ flag ufmt;
+ flag uprnt;
+ flag ublnk;
+ flag uend;
+ flag uwrt; /*last io was write*/
+ flag uscrtch;
+} unit;
+
+extern flag f__init;
+extern cilist *f__elist; /*active external io list*/
+extern flag f__reading,f__external,f__sequential,f__formatted;
+#undef Void
+#ifdef KR_headers
+#define Void /*void*/
+extern int (*f__getn)(),(*f__putn)(); /*for formatted io*/
+extern long f__inode();
+extern VOID sig_die();
+extern int (*f__donewrec)(), t_putc(), x_wSL();
+extern int c_sfe(), err__fl(), xrd_SL();
+#else
+#define Void void
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int (*f__getn)(void),(*f__putn)(int); /*for formatted io*/
+extern long f__inode(char*,int*);
+extern void sig_die(char*,int);
+extern void f__fatal(int,char*);
+extern int t_runc(alist*);
+extern int f__nowreading(unit*), f__nowwriting(unit*);
+extern int fk_open(int,int,ftnint);
+extern int en_fio(void);
+extern void f_init(void);
+extern int (*f__donewrec)(void), t_putc(int), x_wSL(void);
+extern void b_char(char*,char*,ftnlen), g_char(char*,ftnlen,char*);
+extern int c_sfe(cilist*), z_rnew(void);
+extern int isatty(int);
+extern int err__fl(int,int,char*);
+extern int xrd_SL(void);
+#ifdef __cplusplus
+ }
+#endif
+#endif
+extern int (*f__doend)(Void);
+extern FILE *f__cf; /*current file*/
+extern unit *f__curunit; /*current unit*/
+extern unit f__units[];
+#define err(f,m,s) {if(f) errno= m; else f__fatal(m,s); return(m);}
+#define errfl(f,m,s) return err__fl((int)f,m,s)
+
+/*Table sizes*/
+#define MXUNIT 100
+
+extern int f__recpos; /*position in current record*/
+extern int f__cursor; /* offset to move to */
+extern int f__hiwater; /* so TL doesn't confuse us */
+
+#define WRITE 1
+#define READ 2
+#define SEQ 3
+#define DIR 4
+#define FMT 5
+#define UNF 6
+#define EXT 7
+#define INT 8
+
+#define buf_end(x) (x->_flag & _IONBF ? x->_ptr : x->_base + BUFSIZ)
diff --git a/lib/libI77/fmt.c b/lib/libI77/fmt.c
new file mode 100644
index 0000000..12792fc
--- /dev/null
+++ b/lib/libI77/fmt.c
@@ -0,0 +1,488 @@
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+#define skip(s) while(*s==' ') s++
+#ifdef interdata
+#define SYLMX 300
+#endif
+#ifdef pdp11
+#define SYLMX 300
+#endif
+#ifdef vax
+#define SYLMX 300
+#endif
+#ifndef SYLMX
+#define SYLMX 300
+#endif
+#define GLITCH '\2'
+ /* special quote character for stu */
+extern int f__cursor,f__scale;
+extern flag f__cblank,f__cplus; /*blanks in I and compulsory plus*/
+struct syl f__syl[SYLMX];
+int f__parenlvl,f__pc,f__revloc;
+
+#ifdef KR_headers
+char *ap_end(s) char *s;
+#else
+char *ap_end(char *s)
+#endif
+{ char quote;
+ quote= *s++;
+ for(;*s;s++)
+ { if(*s!=quote) continue;
+ if(*++s!=quote) return(s);
+ }
+ if(f__elist->cierr) {
+ errno = 100;
+ return(NULL);
+ }
+ f__fatal(100, "bad string");
+ /*NOTREACHED*/ return 0;
+}
+#ifdef KR_headers
+op_gen(a,b,c,d)
+#else
+op_gen(int a, int b, int c, int d)
+#endif
+{ struct syl *p= &f__syl[f__pc];
+ if(f__pc>=SYLMX)
+ { fprintf(stderr,"format too complicated:\n");
+ sig_die(f__fmtbuf, 1);
+ }
+ p->op=a;
+ p->p1=b;
+ p->p2=c;
+ p->p3=d;
+ return(f__pc++);
+}
+#ifdef KR_headers
+char *f_list();
+char *gt_num(s,n) char *s; int *n;
+#else
+char *f_list(char*);
+char *gt_num(char *s, int *n)
+#endif
+{ int m=0,f__cnt=0;
+ char c;
+ for(c= *s;;c = *s)
+ { if(c==' ')
+ { s++;
+ continue;
+ }
+ if(c>'9' || c<'0') break;
+ m=10*m+c-'0';
+ f__cnt++;
+ s++;
+ }
+ if(f__cnt==0) *n=1;
+ else *n=m;
+ return(s);
+}
+#ifdef KR_headers
+char *f_s(s,curloc) char *s;
+#else
+char *f_s(char *s, int curloc)
+#endif
+{
+ skip(s);
+ if(*s++!='(')
+ {
+ return(NULL);
+ }
+ if(f__parenlvl++ ==1) f__revloc=curloc;
+ if(op_gen(RET1,curloc,0,0)<0 ||
+ (s=f_list(s))==NULL)
+ {
+ return(NULL);
+ }
+ skip(s);
+ return(s);
+}
+#ifdef KR_headers
+ne_d(s,p) char *s,**p;
+#else
+ne_d(char *s, char **p)
+#endif
+{ int n,x,sign=0;
+ struct syl *sp;
+ switch(*s)
+ {
+ default:
+ return(0);
+ case ':': (void) op_gen(COLON,0,0,0); break;
+ case '$':
+ (void) op_gen(NONL, 0, 0, 0); break;
+ case 'B':
+ case 'b':
+ if(*++s=='z' || *s == 'Z') (void) op_gen(BZ,0,0,0);
+ else (void) op_gen(BN,0,0,0);
+ break;
+ case 'S':
+ case 's':
+ if(*(s+1)=='s' || *(s+1) == 'S')
+ { x=SS;
+ s++;
+ }
+ else if(*(s+1)=='p' || *(s+1) == 'P')
+ { x=SP;
+ s++;
+ }
+ else x=S;
+ (void) op_gen(x,0,0,0);
+ break;
+ case '/': (void) op_gen(SLASH,0,0,0); break;
+ case '-': sign=1;
+ case '+': s++; /*OUTRAGEOUS CODING TRICK*/
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ s=gt_num(s,&n);
+ switch(*s)
+ {
+ default:
+ return(0);
+ case 'P':
+ case 'p': if(sign) n= -n; (void) op_gen(P,n,0,0); break;
+ case 'X':
+ case 'x': (void) op_gen(X,n,0,0); break;
+ case 'H':
+ case 'h':
+ sp = &f__syl[op_gen(H,n,0,0)];
+ *(char **)&sp->p2 = s + 1;
+ s+=n;
+ break;
+ }
+ break;
+ case GLITCH:
+ case '"':
+ case '\'':
+ sp = &f__syl[op_gen(APOS,0,0,0)];
+ *(char **)&sp->p2 = s;
+ if((*p = ap_end(s)) == NULL)
+ return(0);
+ return(1);
+ case 'T':
+ case 't':
+ if(*(s+1)=='l' || *(s+1) == 'L')
+ { x=TL;
+ s++;
+ }
+ else if(*(s+1)=='r'|| *(s+1) == 'R')
+ { x=TR;
+ s++;
+ }
+ else x=T;
+ s=gt_num(s+1,&n);
+ s--;
+ (void) op_gen(x,n,0,0);
+ break;
+ case 'X':
+ case 'x': (void) op_gen(X,1,0,0); break;
+ case 'P':
+ case 'p': (void) op_gen(P,1,0,0); break;
+ }
+ s++;
+ *p=s;
+ return(1);
+}
+#ifdef KR_headers
+e_d(s,p) char *s,**p;
+#else
+e_d(char *s, char **p)
+#endif
+{ int i,im,n,w,d,e,found=0,x=0;
+ char *sv=s;
+ s=gt_num(s,&n);
+ (void) op_gen(STACK,n,0,0);
+ switch(*s++)
+ {
+ default: break;
+ case 'E':
+ case 'e': x=1;
+ case 'G':
+ case 'g':
+ found=1;
+ s=gt_num(s,&w);
+ if(w==0) break;
+ if(*s=='.')
+ { s++;
+ s=gt_num(s,&d);
+ }
+ else d=0;
+ if(*s!='E' && *s != 'e')
+ (void) op_gen(x==1?E:G,w,d,0); /* default is Ew.dE2 */
+ else
+ { s++;
+ s=gt_num(s,&e);
+ (void) op_gen(x==1?EE:GE,w,d,e);
+ }
+ break;
+ case 'O':
+ case 'o':
+ i = O;
+ im = OM;
+ goto finish_I;
+ case 'Z':
+ case 'z':
+ i = Z;
+ im = ZM;
+ goto finish_I;
+ case 'L':
+ case 'l':
+ found=1;
+ s=gt_num(s,&w);
+ if(w==0) break;
+ (void) op_gen(L,w,0,0);
+ break;
+ case 'A':
+ case 'a':
+ found=1;
+ skip(s);
+ if(*s>='0' && *s<='9')
+ { s=gt_num(s,&w);
+ if(w==0) break;
+ (void) op_gen(AW,w,0,0);
+ break;
+ }
+ (void) op_gen(A,0,0,0);
+ break;
+ case 'F':
+ case 'f':
+ found=1;
+ s=gt_num(s,&w);
+ if(w==0) break;
+ if(*s=='.')
+ { s++;
+ s=gt_num(s,&d);
+ }
+ else d=0;
+ (void) op_gen(F,w,d,0);
+ break;
+ case 'D':
+ case 'd':
+ found=1;
+ s=gt_num(s,&w);
+ if(w==0) break;
+ if(*s=='.')
+ { s++;
+ s=gt_num(s,&d);
+ }
+ else d=0;
+ (void) op_gen(D,w,d,0);
+ break;
+ case 'I':
+ case 'i':
+ i = I;
+ im = IM;
+ finish_I:
+ found=1;
+ s=gt_num(s,&w);
+ if(w==0) break;
+ if(*s!='.')
+ { (void) op_gen(i,w,0,0);
+ break;
+ }
+ s++;
+ s=gt_num(s,&d);
+ (void) op_gen(im,w,d,0);
+ break;
+ }
+ if(found==0)
+ { f__pc--; /*unSTACK*/
+ *p=sv;
+ return(0);
+ }
+ *p=s;
+ return(1);
+}
+#ifdef KR_headers
+char *i_tem(s) char *s;
+#else
+char *i_tem(char *s)
+#endif
+{ char *t;
+ int n,curloc;
+ if(*s==')') return(s);
+ if(ne_d(s,&t)) return(t);
+ if(e_d(s,&t)) return(t);
+ s=gt_num(s,&n);
+ if((curloc=op_gen(STACK,n,0,0))<0) return(NULL);
+ return(f_s(s,curloc));
+}
+#ifdef KR_headers
+char *f_list(s) char *s;
+#else
+char *f_list(char *s)
+#endif
+{
+ for(;*s!=0;)
+ { skip(s);
+ if((s=i_tem(s))==NULL) return(NULL);
+ skip(s);
+ if(*s==',') s++;
+ else if(*s==')')
+ { if(--f__parenlvl==0)
+ {
+ (void) op_gen(REVERT,f__revloc,0,0);
+ return(++s);
+ }
+ (void) op_gen(GOTO,0,0,0);
+ return(++s);
+ }
+ }
+ return(NULL);
+}
+
+#ifdef KR_headers
+pars_f(s) char *s;
+#else
+pars_f(char *s)
+#endif
+{
+ f__parenlvl=f__revloc=f__pc=0;
+ if(f_s(s,0) == NULL)
+ {
+ return(-1);
+ }
+ return(0);
+}
+#define STKSZ 10
+int f__cnt[STKSZ],f__ret[STKSZ],f__cp,f__rp;
+flag f__workdone, f__nonl;
+
+#ifdef KR_headers
+type_f(n)
+#else
+type_f(int n)
+#endif
+{
+ switch(n)
+ {
+ default:
+ return(n);
+ case RET1:
+ return(RET1);
+ case REVERT: return(REVERT);
+ case GOTO: return(GOTO);
+ case STACK: return(STACK);
+ case X:
+ case SLASH:
+ case APOS: case H:
+ case T: case TL: case TR:
+ return(NED);
+ case F:
+ case I:
+ case IM:
+ case A: case AW:
+ case O: case OM:
+ case L:
+ case E: case EE: case D:
+ case G: case GE:
+ case Z: case ZM:
+ return(ED);
+ }
+}
+#ifdef KR_headers
+integer do_fio(number,ptr,len) ftnint *number; ftnlen len; char *ptr;
+#else
+integer do_fio(ftnint *number, char *ptr, ftnlen len)
+#endif
+{ struct syl *p;
+ int n,i;
+ for(i=0;i<*number;i++,ptr+=len)
+ {
+loop: switch(type_f((p= &f__syl[f__pc])->op))
+ {
+ default:
+ fprintf(stderr,"unknown code in do_fio: %d\n%s\n",
+ p->op,f__fmtbuf);
+ err(f__elist->cierr,100,"do_fio");
+ case NED:
+ if((*f__doned)(p))
+ { f__pc++;
+ goto loop;
+ }
+ f__pc++;
+ continue;
+ case ED:
+ if(f__cnt[f__cp]<=0)
+ { f__cp--;
+ f__pc++;
+ goto loop;
+ }
+ if(ptr==NULL)
+ return((*f__doend)());
+ f__cnt[f__cp]--;
+ f__workdone=1;
+ if((n=(*f__doed)(p,ptr,len))>0)
+ errfl(f__elist->cierr,errno,"fmt");
+ if(n<0)
+ err(f__elist->ciend,(EOF),"fmt");
+ continue;
+ case STACK:
+ f__cnt[++f__cp]=p->p1;
+ f__pc++;
+ goto loop;
+ case RET1:
+ f__ret[++f__rp]=p->p1;
+ f__pc++;
+ goto loop;
+ case GOTO:
+ if(--f__cnt[f__cp]<=0)
+ { f__cp--;
+ f__rp--;
+ f__pc++;
+ goto loop;
+ }
+ f__pc=1+f__ret[f__rp--];
+ goto loop;
+ case REVERT:
+ f__rp=f__cp=0;
+ f__pc = p->p1;
+ if(ptr==NULL)
+ return((*f__doend)());
+ if(!f__workdone) return(0);
+ if((n=(*f__dorevert)()) != 0) return(n);
+ goto loop;
+ case COLON:
+ if(ptr==NULL)
+ return((*f__doend)());
+ f__pc++;
+ goto loop;
+ case NONL:
+ f__nonl = 1;
+ f__pc++;
+ goto loop;
+ case S:
+ case SS:
+ f__cplus=0;
+ f__pc++;
+ goto loop;
+ case SP:
+ f__cplus = 1;
+ f__pc++;
+ goto loop;
+ case P: f__scale=p->p1;
+ f__pc++;
+ goto loop;
+ case BN:
+ f__cblank=0;
+ f__pc++;
+ goto loop;
+ case BZ:
+ f__cblank=1;
+ f__pc++;
+ goto loop;
+ }
+ }
+ return(0);
+}
+en_fio(Void)
+{ ftnint one=1;
+ return(do_fio(&one,(char *)NULL,(ftnint)0));
+}
+ VOID
+fmt_bg(Void)
+{
+ f__workdone=f__cp=f__rp=f__pc=f__cursor=0;
+ f__cnt[0]=f__ret[0]=0;
+}
diff --git a/lib/libI77/fmt.h b/lib/libI77/fmt.h
new file mode 100644
index 0000000..509746e
--- /dev/null
+++ b/lib/libI77/fmt.h
@@ -0,0 +1,99 @@
+struct syl
+{ int op,p1,p2,p3;
+};
+#define RET1 1
+#define REVERT 2
+#define GOTO 3
+#define X 4
+#define SLASH 5
+#define STACK 6
+#define I 7
+#define ED 8
+#define NED 9
+#define IM 10
+#define APOS 11
+#define H 12
+#define TL 13
+#define TR 14
+#define T 15
+#define COLON 16
+#define S 17
+#define SP 18
+#define SS 19
+#define P 20
+#define BN 21
+#define BZ 22
+#define F 23
+#define E 24
+#define EE 25
+#define D 26
+#define G 27
+#define GE 28
+#define L 29
+#define A 30
+#define AW 31
+#define O 32
+#define NONL 33
+#define OM 34
+#define Z 35
+#define ZM 36
+extern struct syl f__syl[];
+extern int f__pc,f__parenlvl,f__revloc;
+typedef union
+{ real pf;
+ doublereal pd;
+} ufloat;
+typedef union
+{ short is;
+#ifndef KR_headers
+ signed
+#endif
+ char ic;
+ integer il;
+#ifdef Allow_TYQUAD
+ longint ili;
+#endif
+} Uint;
+#ifdef KR_headers
+extern int (*f__doed)(),(*f__doned)();
+extern int (*f__dorevert)();
+extern int rd_ed(),rd_ned();
+extern int w_ed(),w_ned();
+#else
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int (*f__doed)(struct syl*, char*, ftnlen),(*f__doned)(struct syl*);
+extern int (*f__dorevert)(void);
+extern void fmt_bg(void);
+extern int pars_f(char*);
+extern int rd_ed(struct syl*, char*, ftnlen),rd_ned(struct syl*);
+extern int w_ed(struct syl*, char*, ftnlen),w_ned(struct syl*);
+extern int wrt_E(ufloat*, int, int, int, ftnlen);
+extern int wrt_F(ufloat*, int, int, ftnlen);
+extern int wrt_L(Uint*, int, ftnlen);
+#ifdef __cplusplus
+ }
+#endif
+#endif
+extern flag f__cblank,f__cplus,f__workdone, f__nonl;
+extern char *f__fmtbuf;
+extern int f__scale;
+#define GET(x) if((x=(*f__getn)())<0) return(x)
+#define VAL(x) (x!='\n'?x:' ')
+#define PUT(x) (*f__putn)(x)
+extern int f__cursor;
+
+#undef TYQUAD
+#ifndef Allow_TYQUAD
+#undef longint
+#define longint long
+#else
+#define TYQUAD 14
+#endif
+
+#ifdef KR_headers
+extern char *f__icvt();
+#else
+extern char *f__icvt(longint, int*, int*, int);
+#endif
diff --git a/lib/libI77/fmtlib.c b/lib/libI77/fmtlib.c
new file mode 100644
index 0000000..91483fc
--- /dev/null
+++ b/lib/libI77/fmtlib.c
@@ -0,0 +1,45 @@
+/* @(#)fmtlib.c 1.2 */
+#define MAXINTLENGTH 23
+
+#include "f2c.h"
+#ifndef Allow_TYQUAD
+#undef longint
+#define longint long
+#undef ulongint
+#define ulongint unsigned long
+#endif
+
+#ifdef KR_headers
+char *f__icvt(value,ndigit,sign, base) longint value; int *ndigit,*sign;
+ register int base;
+#else
+char *f__icvt(longint value, int *ndigit, int *sign, int base)
+#endif
+{
+ static char buf[MAXINTLENGTH+1];
+ register int i;
+ ulongint uvalue;
+
+ if(value > 0) {
+ uvalue = value;
+ *sign = 0;
+ }
+ else if (value < 0) {
+ uvalue = -value;
+ *sign = 1;
+ }
+ else {
+ *sign = 0;
+ *ndigit = 1;
+ buf[MAXINTLENGTH-1] = '0';
+ return &buf[MAXINTLENGTH-1];
+ }
+ i = MAXINTLENGTH;
+ do {
+ buf[--i] = (uvalue%base) + '0';
+ uvalue /= base;
+ }
+ while(uvalue > 0);
+ *ndigit = MAXINTLENGTH - i;
+ return &buf[i];
+ }
diff --git a/lib/libI77/fp.h b/lib/libI77/fp.h
new file mode 100644
index 0000000..40743d7
--- /dev/null
+++ b/lib/libI77/fp.h
@@ -0,0 +1,28 @@
+#define FMAX 40
+#define EXPMAXDIGS 8
+#define EXPMAX 99999999
+/* FMAX = max number of nonzero digits passed to atof() */
+/* EXPMAX = 10^EXPMAXDIGS - 1 = largest allowed exponent absolute value */
+
+#ifdef V10 /* Research Tenth-Edition Unix */
+#include "local.h"
+#endif
+
+/* MAXFRACDIGS and MAXINTDIGS are for wrt_F -- bounds (not necessarily
+ tight) on the maximum number of digits to the right and left of
+ * the decimal point.
+ */
+
+#ifdef VAX
+#define MAXFRACDIGS 56
+#define MAXINTDIGS 38
+#else
+#ifdef CRAY
+#define MAXFRACDIGS 9880
+#define MAXINTDIGS 9864
+#else
+/* values that suffice for IEEE double */
+#define MAXFRACDIGS 344
+#define MAXINTDIGS 308
+#endif
+#endif
diff --git a/lib/libI77/iio.c b/lib/libI77/iio.c
new file mode 100644
index 0000000..4c8eb9d
--- /dev/null
+++ b/lib/libI77/iio.c
@@ -0,0 +1,142 @@
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+extern char *f__icptr;
+char *f__icend;
+extern icilist *f__svic;
+int f__icnum;
+extern int f__hiwater;
+z_getc(Void)
+{
+ if(f__recpos++ < f__svic->icirlen) {
+ if(f__icptr >= f__icend) err(f__svic->iciend,(EOF),"endfile");
+ return(*(unsigned char *)f__icptr++);
+ }
+ return '\n';
+}
+#ifdef KR_headers
+z_putc(c)
+#else
+z_putc(int c)
+#endif
+{
+ if(f__icptr >= f__icend) err(f__svic->icierr,110,"inwrite");
+ if(f__recpos++ < f__svic->icirlen)
+ *f__icptr++ = c;
+ else err(f__svic->icierr,110,"recend");
+ return 0;
+}
+z_rnew(Void)
+{
+ f__icptr = f__svic->iciunit + (++f__icnum)*f__svic->icirlen;
+ f__recpos = 0;
+ f__cursor = 0;
+ f__hiwater = 0;
+ return 1;
+}
+
+ static int
+z_endp(Void)
+{
+ (*f__donewrec)();
+ return 0;
+ }
+
+#ifdef KR_headers
+c_si(a) icilist *a;
+#else
+c_si(icilist *a)
+#endif
+{
+ f__elist = (cilist *)a;
+ f__fmtbuf=a->icifmt;
+ if(pars_f(f__fmtbuf)<0)
+ err(a->icierr,100,"startint");
+ fmt_bg();
+ f__sequential=f__formatted=1;
+ f__external=0;
+ f__cblank=f__cplus=f__scale=0;
+ f__svic=a;
+ f__icnum=f__recpos=0;
+ f__cursor = 0;
+ f__hiwater = 0;
+ f__icptr = a->iciunit;
+ f__icend = f__icptr + a->icirlen*a->icirnum;
+ f__curunit = 0;
+ f__cf = 0;
+ return(0);
+}
+
+ int
+iw_rev(Void)
+{
+ if(f__workdone)
+ z_endp();
+ f__hiwater = f__recpos = f__cursor = 0;
+ return(f__workdone=0);
+ }
+
+#ifdef KR_headers
+integer s_rsfi(a) icilist *a;
+#else
+integer s_rsfi(icilist *a)
+#endif
+{ int n;
+ if(n=c_si(a)) return(n);
+ f__reading=1;
+ f__doed=rd_ed;
+ f__doned=rd_ned;
+ f__getn=z_getc;
+ f__dorevert = z_endp;
+ f__donewrec = z_rnew;
+ f__doend = z_endp;
+ return(0);
+}
+
+z_wnew(Void)
+{
+ if (f__recpos < f__hiwater) {
+ f__icptr += f__hiwater - f__recpos;
+ f__recpos = f__hiwater;
+ }
+ while(f__recpos++ < f__svic->icirlen)
+ *f__icptr++ = ' ';
+ f__recpos = 0;
+ f__cursor = 0;
+ f__hiwater = 0;
+ f__icnum++;
+ return 1;
+}
+#ifdef KR_headers
+integer s_wsfi(a) icilist *a;
+#else
+integer s_wsfi(icilist *a)
+#endif
+{ int n;
+ if(n=c_si(a)) return(n);
+ f__reading=0;
+ f__doed=w_ed;
+ f__doned=w_ned;
+ f__putn=z_putc;
+ f__dorevert = iw_rev;
+ f__donewrec = z_wnew;
+ f__doend = z_endp;
+ return(0);
+}
+integer e_rsfi(Void)
+{ int n;
+ n = en_fio();
+ f__fmtbuf = NULL;
+ return(n);
+}
+integer e_wsfi(Void)
+{
+ int n;
+ n = en_fio();
+ f__fmtbuf = NULL;
+ if(f__icnum >= f__svic->icirnum)
+ return(n);
+ while(f__recpos++ < f__svic->icirlen)
+ *f__icptr++ = ' ';
+ return(n);
+}
diff --git a/lib/libI77/ilnw.c b/lib/libI77/ilnw.c
new file mode 100644
index 0000000..b415686
--- /dev/null
+++ b/lib/libI77/ilnw.c
@@ -0,0 +1,77 @@
+#include "f2c.h"
+#include "fio.h"
+#include "lio.h"
+extern char *f__icptr;
+extern char *f__icend;
+extern icilist *f__svic;
+extern int f__icnum;
+#ifdef KR_headers
+extern int z_putc();
+#else
+extern int z_putc(int);
+#endif
+
+ static int
+z_wSL(Void)
+{
+ while(f__recpos < f__svic->icirlen)
+ z_putc(' ');
+ return z_rnew();
+ }
+
+ VOID
+#ifdef KR_headers
+c_liw(a) icilist *a;
+#else
+c_liw(icilist *a)
+#endif
+{
+ f__reading = 0;
+ f__external = 0;
+ f__formatted = 1;
+ f__putn = z_putc;
+ L_len = a->icirlen;
+ f__donewrec = z_wSL;
+ f__svic = a;
+ f__icnum = f__recpos = 0;
+ f__cursor = 0;
+ f__cf = 0;
+ f__curunit = 0;
+ f__icptr = a->iciunit;
+ f__icend = f__icptr + a->icirlen*a->icirnum;
+ f__elist = (cilist *)a;
+ }
+
+ integer
+#ifdef KR_headers
+s_wsni(a) icilist *a;
+#else
+s_wsni(icilist *a)
+#endif
+{
+ cilist ca;
+
+ c_liw(a);
+ ca.cifmt = a->icifmt;
+ x_wsne(&ca);
+ z_wSL();
+ return 0;
+ }
+
+ integer
+#ifdef KR_headers
+s_wsli(a) icilist *a;
+#else
+s_wsli(icilist *a)
+#endif
+{
+ f__lioproc = l_write;
+ c_liw(a);
+ return(0);
+ }
+
+integer e_wsli(Void)
+{
+ z_wSL();
+ return(0);
+ }
diff --git a/lib/libI77/inquire.c b/lib/libI77/inquire.c
new file mode 100644
index 0000000..ec98b22
--- /dev/null
+++ b/lib/libI77/inquire.c
@@ -0,0 +1,106 @@
+#include "f2c.h"
+#include "fio.h"
+#ifdef KR_headers
+integer f_inqu(a) inlist *a;
+#else
+#ifdef MSDOS
+#undef abs
+#undef min
+#undef max
+#include "string.h"
+#include "io.h"
+#endif
+integer f_inqu(inlist *a)
+#endif
+{ flag byfile;
+ int i, n;
+ unit *p;
+ char buf[256];
+ long x;
+ if(a->infile!=NULL)
+ { byfile=1;
+ g_char(a->infile,a->infilen,buf);
+#ifdef NON_UNIX_STDIO
+ x = access(buf,0) ? -1 : 0;
+ for(i=0,p=NULL;i<MXUNIT;i++)
+ if(f__units[i].ufd != NULL
+ && f__units[i].ufnm != NULL
+ && !strcmp(f__units[i].ufnm,buf)) {
+ p = &f__units[i];
+ break;
+ }
+#else
+ x=f__inode(buf, &n);
+ for(i=0,p=NULL;i<MXUNIT;i++)
+ if(f__units[i].uinode==x
+ && f__units[i].ufd!=NULL
+ && f__units[i].udev == n) {
+ p = &f__units[i];
+ break;
+ }
+#endif
+ }
+ else
+ {
+ byfile=0;
+ if(a->inunit<MXUNIT && a->inunit>=0)
+ {
+ p= &f__units[a->inunit];
+ }
+ else
+ {
+ p=NULL;
+ }
+ }
+ if(a->inex!=NULL)
+ if(byfile && x != -1 || !byfile && p!=NULL)
+ *a->inex=1;
+ else *a->inex=0;
+ if(a->inopen!=NULL)
+ if(byfile) *a->inopen=(p!=NULL);
+ else *a->inopen=(p!=NULL && p->ufd!=NULL);
+ if(a->innum!=NULL) *a->innum= p-f__units;
+ if(a->innamed!=NULL)
+ if(byfile || p!=NULL && p->ufnm!=NULL)
+ *a->innamed=1;
+ else *a->innamed=0;
+ if(a->inname!=NULL)
+ if(byfile)
+ b_char(buf,a->inname,a->innamlen);
+ else if(p!=NULL && p->ufnm!=NULL)
+ b_char(p->ufnm,a->inname,a->innamlen);
+ if(a->inacc!=NULL && p!=NULL && p->ufd!=NULL)
+ if(p->url)
+ b_char("DIRECT",a->inacc,a->inacclen);
+ else b_char("SEQUENTIAL",a->inacc,a->inacclen);
+ if(a->inseq!=NULL)
+ if(p!=NULL && p->url)
+ b_char("NO",a->inseq,a->inseqlen);
+ else b_char("YES",a->inseq,a->inseqlen);
+ if(a->indir!=NULL)
+ if(p==NULL || p->url)
+ b_char("YES",a->indir,a->indirlen);
+ else b_char("NO",a->indir,a->indirlen);
+ if(a->infmt!=NULL)
+ if(p!=NULL && p->ufmt==0)
+ b_char("UNFORMATTED",a->infmt,a->infmtlen);
+ else b_char("FORMATTED",a->infmt,a->infmtlen);
+ if(a->inform!=NULL)
+ if(p!=NULL && p->ufmt==0)
+ b_char("NO",a->inform,a->informlen);
+ else b_char("YES",a->inform,a->informlen);
+ if(a->inunf)
+ if(p!=NULL && p->ufmt==0)
+ b_char("YES",a->inunf,a->inunflen);
+ else if (p!=NULL) b_char("NO",a->inunf,a->inunflen);
+ else b_char("UNKNOWN",a->inunf,a->inunflen);
+ if(a->inrecl!=NULL && p!=NULL)
+ *a->inrecl=p->url;
+ if(a->innrec!=NULL && p!=NULL && p->url>0)
+ *a->innrec=ftell(p->ufd)/p->url+1;
+ if(a->inblank && p!=NULL && p->ufmt)
+ if(p->ublnk)
+ b_char("ZERO",a->inblank,a->inblanklen);
+ else b_char("NULL",a->inblank,a->inblanklen);
+ return(0);
+}
diff --git a/lib/libI77/lio.h b/lib/libI77/lio.h
new file mode 100644
index 0000000..0123172
--- /dev/null
+++ b/lib/libI77/lio.h
@@ -0,0 +1,74 @@
+/* copy of ftypes from the compiler */
+/* variable types
+ * numeric assumptions:
+ * int < reals < complexes
+ * TYDREAL-TYREAL = TYDCOMPLEX-TYCOMPLEX
+ */
+
+/* 0-10 retain their old (pre LOGICAL*1, etc.) */
+/* values to allow mixing old and new objects. */
+
+#define TYUNKNOWN 0
+#define TYADDR 1
+#define TYSHORT 2
+#define TYLONG 3
+#define TYREAL 4
+#define TYDREAL 5
+#define TYCOMPLEX 6
+#define TYDCOMPLEX 7
+#define TYLOGICAL 8
+#define TYCHAR 9
+#define TYSUBR 10
+#define TYINT1 11
+#define TYLOGICAL1 12
+#define TYLOGICAL2 13
+#ifdef Allow_TYQUAD
+#undef TYQUAD
+#define TYQUAD 14
+#endif
+
+#define LINTW 24
+#define LINE 80
+#define LLOGW 2
+#ifdef Old_list_output
+#define LLOW 1.0
+#define LHIGH 1.e9
+#define LEFMT " %# .8E"
+#define LFFMT " %# .9g"
+#else
+#define LGFMT "%.9G"
+#endif
+/* LEFBL 20 should suffice; 24 overcomes a NeXT bug. */
+#define LEFBL 24
+
+typedef union
+{
+ char flchar;
+ short flshort;
+ ftnint flint;
+#ifdef Allow_TYQUAD
+ longint fllongint;
+#endif
+ real flreal;
+ doublereal fldouble;
+} flex;
+extern int f__scale;
+#ifdef KR_headers
+extern int (*f__lioproc)(), (*l_getc)(), (*l_ungetc)();
+extern int l_read(), l_write();
+#else
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int (*f__lioproc)(ftnint*, char*, ftnlen, ftnint);
+extern int l_write(ftnint*, char*, ftnlen, ftnint);
+extern void x_wsne(cilist*);
+extern int c_le(cilist*), (*l_getc)(void), (*l_ungetc)(int,FILE*);
+extern int l_read(ftnint*,char*,ftnlen,ftnint);
+extern integer e_rsle(void), e_wsle(void), s_wsne(cilist*);
+extern int z_rnew(void);
+#ifdef __cplusplus
+ }
+#endif
+#endif
+extern ftnint L_len;
diff --git a/lib/libI77/lread.c b/lib/libI77/lread.c
new file mode 100644
index 0000000..27f0269
--- /dev/null
+++ b/lib/libI77/lread.c
@@ -0,0 +1,659 @@
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+#include "lio.h"
+#include "ctype.h"
+#include "fp.h"
+
+extern char *f__fmtbuf;
+
+#ifdef Allow_TYQUAD
+static longint f__llx;
+static int quad_read;
+#endif
+
+#ifdef KR_headers
+extern double atof();
+extern char *malloc(), *realloc();
+int (*f__lioproc)(), (*l_getc)(), (*l_ungetc)();
+#else
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+int (*f__lioproc)(ftnint*, char*, ftnlen, ftnint), (*l_getc)(void),
+ (*l_ungetc)(int,FILE*);
+#endif
+int l_eof;
+
+#define isblnk(x) (f__ltab[x+1]&B)
+#define issep(x) (f__ltab[x+1]&SX)
+#define isapos(x) (f__ltab[x+1]&AX)
+#define isexp(x) (f__ltab[x+1]&EX)
+#define issign(x) (f__ltab[x+1]&SG)
+#define iswhit(x) (f__ltab[x+1]&WH)
+#define SX 1
+#define B 2
+#define AX 4
+#define EX 8
+#define SG 16
+#define WH 32
+char f__ltab[128+1] = { /* offset one for EOF */
+ 0,
+ 0,0,AX,0,0,0,0,0,0,WH|B,SX|WH,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ SX|B|WH,0,AX,0,0,0,0,AX,0,0,0,SG,SX,SG,0,SX,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,EX,EX,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,
+ AX,0,0,0,EX,EX,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
+};
+
+#ifdef ungetc
+ static int
+#ifdef KR_headers
+un_getc(x,f__cf) int x; FILE *f__cf;
+#else
+un_getc(int x, FILE *f__cf)
+#endif
+{ return ungetc(x,f__cf); }
+#else
+#define un_getc ungetc
+#ifdef KR_headers
+ extern int ungetc();
+#else
+extern int ungetc(int, FILE*); /* for systems with a buggy stdio.h */
+#endif
+#endif
+
+t_getc(Void)
+{ int ch;
+ if(f__curunit->uend) return(EOF);
+ if((ch=getc(f__cf))!=EOF) return(ch);
+ if(feof(f__cf))
+ f__curunit->uend = l_eof = 1;
+ return(EOF);
+}
+integer e_rsle(Void)
+{
+ int ch;
+ if(f__curunit->uend) return(0);
+ while((ch=t_getc())!='\n')
+ if (ch == EOF) {
+ if(feof(f__cf))
+ f__curunit->uend = l_eof = 1;
+ return EOF;
+ }
+ return(0);
+}
+
+flag f__lquit;
+int f__lcount,f__ltype,nml_read;
+char *f__lchar;
+double f__lx,f__ly;
+#define ERR(x) if(n=(x)) return(n)
+#define GETC(x) (x=(*l_getc)())
+#define Ungetc(x,y) (*l_ungetc)(x,y)
+
+#ifdef KR_headers
+l_R(poststar) int poststar;
+#else
+l_R(int poststar)
+#endif
+{
+ char s[FMAX+EXPMAXDIGS+4];
+ register int ch;
+ register char *sp, *spe, *sp1;
+ long e, exp;
+ int havenum, havestar, se;
+
+ if (!poststar) {
+ if (f__lcount > 0)
+ return(0);
+ f__lcount = 1;
+ }
+#ifdef Allow_TYQUAD
+ f__llx = 0;
+#endif
+ f__ltype = 0;
+ exp = 0;
+ havestar = 0;
+retry:
+ sp1 = sp = s;
+ spe = sp + FMAX;
+ havenum = 0;
+
+ switch(GETC(ch)) {
+ case '-': *sp++ = ch; sp1++; spe++;
+ case '+':
+ GETC(ch);
+ }
+ while(ch == '0') {
+ ++havenum;
+ GETC(ch);
+ }
+ while(isdigit(ch)) {
+ if (sp < spe) *sp++ = ch;
+ else ++exp;
+ GETC(ch);
+ }
+ if (ch == '*' && !poststar) {
+ if (sp == sp1 || exp || *s == '-') {
+ errfl(f__elist->cierr,112,"bad repetition count");
+ }
+ poststar = havestar = 1;
+ *sp = 0;
+ f__lcount = atoi(s);
+ goto retry;
+ }
+ if (ch == '.') {
+ GETC(ch);
+ if (sp == sp1)
+ while(ch == '0') {
+ ++havenum;
+ --exp;
+ GETC(ch);
+ }
+ while(isdigit(ch)) {
+ if (sp < spe)
+ { *sp++ = ch; --exp; }
+ GETC(ch);
+ }
+ }
+ havenum += sp - sp1;
+ se = 0;
+ if (issign(ch))
+ goto signonly;
+ if (havenum && isexp(ch)) {
+ GETC(ch);
+ if (issign(ch)) {
+signonly:
+ if (ch == '-') se = 1;
+ GETC(ch);
+ }
+ if (!isdigit(ch)) {
+bad:
+ errfl(f__elist->cierr,112,"exponent field");
+ }
+
+ e = ch - '0';
+ while(isdigit(GETC(ch))) {
+ e = 10*e + ch - '0';
+ if (e > EXPMAX)
+ goto bad;
+ }
+ if (se)
+ exp -= e;
+ else
+ exp += e;
+ }
+ (void) Ungetc(ch, f__cf);
+ if (sp > sp1) {
+ ++havenum;
+ while(*--sp == '0')
+ ++exp;
+ if (exp)
+ sprintf(sp+1, "e%ld", exp);
+ else
+ sp[1] = 0;
+ f__lx = atof(s);
+#ifdef Allow_TYQUAD
+ if (quad_read && (se = sp - sp1 + exp) > 14 && se < 20) {
+ /* Assuming 64-bit longint and 32-bit long. */
+ if (exp < 0)
+ sp += exp;
+ if (sp1 <= sp) {
+ f__llx = *sp1 - '0';
+ while(++sp1 <= sp)
+ f__llx = 10*f__llx + (*sp1 - '0');
+ }
+ while(--exp >= 0)
+ f__llx *= 10;
+ if (*s == '-')
+ f__llx = -f__llx;
+ }
+#endif
+ }
+ else
+ f__lx = 0.;
+ if (havenum)
+ f__ltype = TYLONG;
+ else
+ switch(ch) {
+ case ',':
+ case '/':
+ break;
+ default:
+ if (havestar && ( ch == ' '
+ ||ch == '\t'
+ ||ch == '\n'))
+ break;
+ if (nml_read > 1) {
+ f__lquit = 2;
+ return 0;
+ }
+ errfl(f__elist->cierr,112,"invalid number");
+ }
+ return 0;
+ }
+
+ static int
+#ifdef KR_headers
+rd_count(ch) register int ch;
+#else
+rd_count(register int ch)
+#endif
+{
+ if (ch < '0' || ch > '9')
+ return 1;
+ f__lcount = ch - '0';
+ while(GETC(ch) >= '0' && ch <= '9')
+ f__lcount = 10*f__lcount + ch - '0';
+ Ungetc(ch,f__cf);
+ return f__lcount <= 0;
+ }
+
+l_C(Void)
+{ int ch, nml_save;
+ double lz;
+ if(f__lcount>0) return(0);
+ f__ltype=0;
+ GETC(ch);
+ if(ch!='(')
+ {
+ if (nml_read > 1 && (ch < '0' || ch > '9')) {
+ Ungetc(ch,f__cf);
+ f__lquit = 2;
+ return 0;
+ }
+ if (rd_count(ch))
+ if(!f__cf || !feof(f__cf))
+ errfl(f__elist->cierr,112,"complex format");
+ else
+ err(f__elist->cierr,(EOF),"lread");
+ if(GETC(ch)!='*')
+ {
+ if(!f__cf || !feof(f__cf))
+ errfl(f__elist->cierr,112,"no star");
+ else
+ err(f__elist->cierr,(EOF),"lread");
+ }
+ if(GETC(ch)!='(')
+ { Ungetc(ch,f__cf);
+ return(0);
+ }
+ }
+ else
+ f__lcount = 1;
+ while(iswhit(GETC(ch)));
+ Ungetc(ch,f__cf);
+ nml_save = nml_read;
+ nml_read = 0;
+ if (ch = l_R(1))
+ return ch;
+ if (!f__ltype)
+ errfl(f__elist->cierr,112,"no real part");
+ lz = f__lx;
+ while(iswhit(GETC(ch)));
+ if(ch!=',')
+ { (void) Ungetc(ch,f__cf);
+ errfl(f__elist->cierr,112,"no comma");
+ }
+ while(iswhit(GETC(ch)));
+ (void) Ungetc(ch,f__cf);
+ if (ch = l_R(1))
+ return ch;
+ if (!f__ltype)
+ errfl(f__elist->cierr,112,"no imaginary part");
+ while(iswhit(GETC(ch)));
+ if(ch!=')') errfl(f__elist->cierr,112,"no )");
+ f__ly = f__lx;
+ f__lx = lz;
+#ifdef Allow_TYQUAD
+ f__llx = 0;
+#endif
+ nml_read = nml_save;
+ return(0);
+}
+l_L(Void)
+{
+ int ch;
+ if(f__lcount>0) return(0);
+ f__lcount = 1;
+ f__ltype=0;
+ GETC(ch);
+ if(isdigit(ch))
+ {
+ rd_count(ch);
+ if(GETC(ch)!='*')
+ if(!f__cf || !feof(f__cf))
+ errfl(f__elist->cierr,112,"no star");
+ else
+ err(f__elist->cierr,(EOF),"lread");
+ GETC(ch);
+ }
+ if(ch == '.') GETC(ch);
+ switch(ch)
+ {
+ case 't':
+ case 'T':
+ f__lx=1;
+ break;
+ case 'f':
+ case 'F':
+ f__lx=0;
+ break;
+ default:
+ if(isblnk(ch) || issep(ch) || ch==EOF)
+ { (void) Ungetc(ch,f__cf);
+ return(0);
+ }
+ if (nml_read > 1) {
+ Ungetc(ch,f__cf);
+ f__lquit = 2;
+ return 0;
+ }
+ errfl(f__elist->cierr,112,"logical");
+ }
+ f__ltype=TYLONG;
+ while(!issep(GETC(ch)) && ch!=EOF);
+ (void) Ungetc(ch, f__cf);
+ return(0);
+}
+#define BUFSIZE 128
+l_CHAR(Void)
+{ int ch,size,i;
+ static char rafail[] = "realloc failure";
+ char quote,*p;
+ if(f__lcount>0) return(0);
+ f__ltype=0;
+ if(f__lchar!=NULL) free(f__lchar);
+ size=BUFSIZE;
+ p=f__lchar = (char *)malloc((unsigned int)size);
+ if(f__lchar == NULL)
+ errfl(f__elist->cierr,113,"no space");
+
+ GETC(ch);
+ if(isdigit(ch)) {
+ /* allow Fortran 8x-style unquoted string... */
+ /* either find a repetition count or the string */
+ f__lcount = ch - '0';
+ *p++ = ch;
+ for(i = 1;;) {
+ switch(GETC(ch)) {
+ case '*':
+ if (f__lcount == 0) {
+ f__lcount = 1;
+ goto noquote;
+ }
+ p = f__lchar;
+ goto have_lcount;
+ case ',':
+ case ' ':
+ case '\t':
+ case '\n':
+ case '/':
+ Ungetc(ch,f__cf);
+ /* no break */
+ case EOF:
+ f__lcount = 1;
+ f__ltype = TYCHAR;
+ return *p = 0;
+ }
+ if (!isdigit(ch)) {
+ f__lcount = 1;
+ goto noquote;
+ }
+ *p++ = ch;
+ f__lcount = 10*f__lcount + ch - '0';
+ if (++i == size) {
+ f__lchar = (char *)realloc(f__lchar,
+ (unsigned int)(size += BUFSIZE));
+ if(f__lchar == NULL)
+ errfl(f__elist->cierr,113,rafail);
+ p = f__lchar + i;
+ }
+ }
+ }
+ else (void) Ungetc(ch,f__cf);
+ have_lcount:
+ if(GETC(ch)=='\'' || ch=='"') quote=ch;
+ else if(isblnk(ch) || (issep(ch) && ch != '\n') || ch==EOF)
+ { (void) Ungetc(ch,f__cf);
+ return(0);
+ }
+ else {
+ /* Fortran 8x-style unquoted string */
+ *p++ = ch;
+ for(i = 1;;) {
+ switch(GETC(ch)) {
+ case ',':
+ case ' ':
+ case '\t':
+ case '\n':
+ case '/':
+ Ungetc(ch,f__cf);
+ /* no break */
+ case EOF:
+ f__ltype = TYCHAR;
+ return *p = 0;
+ }
+ noquote:
+ *p++ = ch;
+ if (++i == size) {
+ f__lchar = (char *)realloc(f__lchar,
+ (unsigned int)(size += BUFSIZE));
+ if(f__lchar == NULL)
+ errfl(f__elist->cierr,113,rafail);
+ p = f__lchar + i;
+ }
+ }
+ }
+ f__ltype=TYCHAR;
+ for(i=0;;)
+ { while(GETC(ch)!=quote && ch!='\n'
+ && ch!=EOF && ++i<size) *p++ = ch;
+ if(i==size)
+ {
+ newone:
+ f__lchar= (char *)realloc(f__lchar,
+ (unsigned int)(size += BUFSIZE));
+ if(f__lchar == NULL)
+ errfl(f__elist->cierr,113,rafail);
+ p=f__lchar+i-1;
+ *p++ = ch;
+ }
+ else if(ch==EOF) return(EOF);
+ else if(ch=='\n')
+ { if(*(p-1) != '\\') continue;
+ i--;
+ p--;
+ if(++i<size) *p++ = ch;
+ else goto newone;
+ }
+ else if(GETC(ch)==quote)
+ { if(++i<size) *p++ = ch;
+ else goto newone;
+ }
+ else
+ { (void) Ungetc(ch,f__cf);
+ *p = 0;
+ return(0);
+ }
+ }
+}
+#ifdef KR_headers
+c_le(a) cilist *a;
+#else
+c_le(cilist *a)
+#endif
+{
+ if(!f__init)
+ f_init();
+ f__fmtbuf="list io";
+ if(a->ciunit>=MXUNIT || a->ciunit<0)
+ err(a->cierr,101,"stler");
+ f__scale=f__recpos=0;
+ f__elist=a;
+ f__curunit = &f__units[a->ciunit];
+ if(f__curunit->ufd==NULL && fk_open(SEQ,FMT,a->ciunit))
+ err(a->cierr,102,"lio");
+ f__cf=f__curunit->ufd;
+ if(!f__curunit->ufmt) err(a->cierr,103,"lio")
+ return(0);
+}
+#ifdef KR_headers
+l_read(number,ptr,len,type) ftnint *number,type; char *ptr; ftnlen len;
+#else
+l_read(ftnint *number, char *ptr, ftnlen len, ftnint type)
+#endif
+{
+#define Ptr ((flex *)ptr)
+ int i,n,ch;
+ doublereal *yy;
+ real *xx;
+ for(i=0;i<*number;i++)
+ {
+ if(f__lquit) return(0);
+ if(l_eof)
+ err(f__elist->ciend, EOF, "list in")
+ if(f__lcount == 0) {
+ f__ltype = 0;
+ for(;;) {
+ GETC(ch);
+ switch(ch) {
+ case EOF:
+ err(f__elist->ciend,(EOF),"list in")
+ case ' ':
+ case '\t':
+ case '\n':
+ continue;
+ case '/':
+ f__lquit = 1;
+ goto loopend;
+ case ',':
+ f__lcount = 1;
+ goto loopend;
+ default:
+ (void) Ungetc(ch, f__cf);
+ goto rddata;
+ }
+ }
+ }
+ rddata:
+ switch((int)type)
+ {
+ case TYINT1:
+ case TYSHORT:
+ case TYLONG:
+ case TYREAL:
+ case TYDREAL:
+ ERR(l_R(0));
+ break;
+#ifdef TYQUAD
+ case TYQUAD:
+ quad_read = 1;
+ n = l_R(0);
+ quad_read = 0;
+ if (n)
+ return n;
+ break;
+#endif
+ case TYCOMPLEX:
+ case TYDCOMPLEX:
+ ERR(l_C());
+ break;
+ case TYLOGICAL1:
+ case TYLOGICAL2:
+ case TYLOGICAL:
+ ERR(l_L());
+ break;
+ case TYCHAR:
+ ERR(l_CHAR());
+ break;
+ }
+ while (GETC(ch) == ' ' || ch == '\t');
+ if (ch != ',' || f__lcount > 1)
+ Ungetc(ch,f__cf);
+ loopend:
+ if(f__lquit) return(0);
+ if(f__cf && ferror(f__cf)) {
+ clearerr(f__cf);
+ errfl(f__elist->cierr,errno,"list in");
+ }
+ if(f__ltype==0) goto bump;
+ switch((int)type)
+ {
+ case TYINT1:
+ case TYLOGICAL1:
+ Ptr->flchar = (char)f__lx;
+ break;
+ case TYLOGICAL2:
+ case TYSHORT:
+ Ptr->flshort = (short)f__lx;
+ break;
+ case TYLOGICAL:
+ case TYLONG:
+ Ptr->flint=f__lx;
+ break;
+#ifdef Allow_TYQUAD
+ case TYQUAD:
+ if (!(Ptr->fllongint = f__llx))
+ Ptr->fllongint = f__lx;
+ break;
+#endif
+ case TYREAL:
+ Ptr->flreal=f__lx;
+ break;
+ case TYDREAL:
+ Ptr->fldouble=f__lx;
+ break;
+ case TYCOMPLEX:
+ xx=(real *)ptr;
+ *xx++ = f__lx;
+ *xx = f__ly;
+ break;
+ case TYDCOMPLEX:
+ yy=(doublereal *)ptr;
+ *yy++ = f__lx;
+ *yy = f__ly;
+ break;
+ case TYCHAR:
+ b_char(f__lchar,ptr,len);
+ break;
+ }
+ bump:
+ if(f__lcount>0) f__lcount--;
+ ptr += len;
+ if (nml_read)
+ nml_read++;
+ }
+ return(0);
+#undef Ptr
+}
+#ifdef KR_headers
+integer s_rsle(a) cilist *a;
+#else
+integer s_rsle(cilist *a)
+#endif
+{
+ int n;
+
+ if(n=c_le(a)) return(n);
+ f__reading=1;
+ f__external=1;
+ f__formatted=1;
+ f__lioproc = l_read;
+ f__lquit = 0;
+ f__lcount = 0;
+ l_eof = 0;
+ if(f__curunit->uwrt && f__nowreading(f__curunit))
+ err(a->cierr,errno,"read start");
+ if(f__curunit->uend)
+ err(f__elist->ciend,(EOF),"read start");
+ l_getc = t_getc;
+ l_ungetc = un_getc;
+ f__doend = xrd_SL;
+ return(0);
+}
diff --git a/lib/libI77/lwrite.c b/lib/libI77/lwrite.c
new file mode 100644
index 0000000..5da7dfb
--- /dev/null
+++ b/lib/libI77/lwrite.c
@@ -0,0 +1,310 @@
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+#include "lio.h"
+
+ftnint L_len;
+int f__Aquote;
+
+ static VOID
+donewrec(Void)
+{
+ if (f__recpos)
+ (*f__donewrec)();
+ }
+
+#ifdef KR_headers
+t_putc(c)
+#else
+t_putc(int c)
+#endif
+{
+ f__recpos++;
+ putc(c,f__cf);
+ return(0);
+}
+ static VOID
+#ifdef KR_headers
+lwrt_I(n) longint n;
+#else
+lwrt_I(longint n)
+#endif
+{
+ char *p;
+ int ndigit, sign;
+
+ p = f__icvt(n, &ndigit, &sign, 10);
+ if(f__recpos + ndigit >= L_len)
+ donewrec();
+ PUT(' ');
+ if (sign)
+ PUT('-');
+ while(*p)
+ PUT(*p++);
+}
+ static VOID
+#ifdef KR_headers
+lwrt_L(n, len) ftnint n; ftnlen len;
+#else
+lwrt_L(ftnint n, ftnlen len)
+#endif
+{
+ if(f__recpos+LLOGW>=L_len)
+ donewrec();
+ wrt_L((Uint *)&n,LLOGW, len);
+}
+ static VOID
+#ifdef KR_headers
+lwrt_A(p,len) char *p; ftnlen len;
+#else
+lwrt_A(char *p, ftnlen len)
+#endif
+{
+ int a;
+ char *p1, *pe;
+
+ a = 0;
+ pe = p + len;
+ if (f__Aquote) {
+ a = 3;
+ if (len > 1 && p[len-1] == ' ') {
+ while(--len > 1 && p[len-1] == ' ');
+ pe = p + len;
+ }
+ p1 = p;
+ while(p1 < pe)
+ if (*p1++ == '\'')
+ a++;
+ }
+ if(f__recpos+len+a >= L_len)
+ donewrec();
+ if (a
+#ifndef OMIT_BLANK_CC
+ || !f__recpos
+#endif
+ )
+ PUT(' ');
+ if (a) {
+ PUT('\'');
+ while(p < pe) {
+ if (*p == '\'')
+ PUT('\'');
+ PUT(*p++);
+ }
+ PUT('\'');
+ }
+ else
+ while(p < pe)
+ PUT(*p++);
+}
+
+ static int
+#ifdef KR_headers
+l_g(buf, n) char *buf; double n;
+#else
+l_g(char *buf, double n)
+#endif
+{
+#ifdef Old_list_output
+ doublereal absn;
+ char *fmt;
+
+ absn = n;
+ if (absn < 0)
+ absn = -absn;
+ fmt = LLOW <= absn && absn < LHIGH ? LFFMT : LEFMT;
+#ifdef USE_STRLEN
+ sprintf(buf, fmt, n);
+ return strlen(buf);
+#else
+ return sprintf(buf, fmt, n);
+#endif
+
+#else
+ register char *b, c, c1;
+
+ b = buf;
+ *b++ = ' ';
+ if (n < 0) {
+ *b++ = '-';
+ n = -n;
+ }
+ else
+ *b++ = ' ';
+ if (n == 0) {
+ *b++ = '0';
+ *b++ = '.';
+ *b = 0;
+ goto f__ret;
+ }
+ sprintf(b, LGFMT, n);
+ switch(*b) {
+#ifndef WANT_LEAD_0
+ case '0':
+ while(b[0] = b[1])
+ b++;
+ break;
+#endif
+ case 'i':
+ case 'I':
+ /* Infinity */
+ case 'n':
+ case 'N':
+ /* NaN */
+ while(*++b);
+ break;
+
+ default:
+ /* Fortran 77 insists on having a decimal point... */
+ for(;; b++)
+ switch(*b) {
+ case 0:
+ *b++ = '.';
+ *b = 0;
+ goto f__ret;
+ case '.':
+ while(*++b);
+ goto f__ret;
+ case 'E':
+ for(c1 = '.', c = 'E'; *b = c1;
+ c1 = c, c = *++b);
+ goto f__ret;
+ }
+ }
+ f__ret:
+ return b - buf;
+#endif
+ }
+
+ static VOID
+#ifdef KR_headers
+l_put(s) register char *s;
+#else
+l_put(register char *s)
+#endif
+{
+#ifdef KR_headers
+ register int c, (*pn)() = f__putn;
+#else
+ register int c, (*pn)(int) = f__putn;
+#endif
+ while(c = *s++)
+ (*pn)(c);
+ }
+
+ static VOID
+#ifdef KR_headers
+lwrt_F(n) double n;
+#else
+lwrt_F(double n)
+#endif
+{
+ char buf[LEFBL];
+
+ if(f__recpos + l_g(buf,n) >= L_len)
+ donewrec();
+ l_put(buf);
+}
+ static VOID
+#ifdef KR_headers
+lwrt_C(a,b) double a,b;
+#else
+lwrt_C(double a, double b)
+#endif
+{
+ char *ba, *bb, bufa[LEFBL], bufb[LEFBL];
+ int al, bl;
+
+ al = l_g(bufa, a);
+ for(ba = bufa; *ba == ' '; ba++)
+ --al;
+ bl = l_g(bufb, b) + 1; /* intentionally high by 1 */
+ for(bb = bufb; *bb == ' '; bb++)
+ --bl;
+ if(f__recpos + al + bl + 3 >= L_len)
+ donewrec();
+#ifdef OMIT_BLANK_CC
+ else
+#endif
+ PUT(' ');
+ PUT('(');
+ l_put(ba);
+ PUT(',');
+ if (f__recpos + bl >= L_len) {
+ (*f__donewrec)();
+#ifndef OMIT_BLANK_CC
+ PUT(' ');
+#endif
+ }
+ l_put(bb);
+ PUT(')');
+}
+#ifdef KR_headers
+l_write(number,ptr,len,type) ftnint *number,type; char *ptr; ftnlen len;
+#else
+l_write(ftnint *number, char *ptr, ftnlen len, ftnint type)
+#endif
+{
+#define Ptr ((flex *)ptr)
+ int i;
+ longint x;
+ double y,z;
+ real *xx;
+ doublereal *yy;
+ for(i=0;i< *number; i++)
+ {
+ switch((int)type)
+ {
+ default: f__fatal(204,"unknown type in lio");
+ case TYINT1:
+ x = Ptr->flchar;
+ goto xint;
+ case TYSHORT:
+ x=Ptr->flshort;
+ goto xint;
+#ifdef Allow_TYQUAD
+ case TYQUAD:
+ x = Ptr->fllongint;
+ goto xint;
+#endif
+ case TYLONG:
+ x=Ptr->flint;
+ xint: lwrt_I(x);
+ break;
+ case TYREAL:
+ y=Ptr->flreal;
+ goto xfloat;
+ case TYDREAL:
+ y=Ptr->fldouble;
+ xfloat: lwrt_F(y);
+ break;
+ case TYCOMPLEX:
+ xx= &Ptr->flreal;
+ y = *xx++;
+ z = *xx;
+ goto xcomplex;
+ case TYDCOMPLEX:
+ yy = &Ptr->fldouble;
+ y= *yy++;
+ z = *yy;
+ xcomplex:
+ lwrt_C(y,z);
+ break;
+ case TYLOGICAL1:
+ x = Ptr->flchar;
+ goto xlog;
+ case TYLOGICAL2:
+ x = Ptr->flshort;
+ goto xlog;
+ case TYLOGICAL:
+ x = Ptr->flint;
+ xlog: lwrt_L(Ptr->flint, len);
+ break;
+ case TYCHAR:
+ lwrt_A(ptr,len);
+ break;
+ }
+ ptr += len;
+ }
+ return(0);
+}
diff --git a/lib/libI77/open.c b/lib/libI77/open.c
new file mode 100644
index 0000000..75386b9
--- /dev/null
+++ b/lib/libI77/open.c
@@ -0,0 +1,239 @@
+#ifndef NON_UNIX_STDIO
+#include "sys/types.h"
+#include "sys/stat.h"
+#endif
+#include "f2c.h"
+#include "fio.h"
+#include "string.h"
+#include "rawio.h"
+
+#ifdef KR_headers
+extern char *malloc(), *mktemp();
+extern integer f_clos();
+#else
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+extern int f__canseek(FILE*);
+extern integer f_clos(cllist*);
+#endif
+
+#ifdef NON_ANSI_RW_MODES
+char *f__r_mode[2] = {"r", "r"};
+char *f__w_mode[4] = {"w", "w", "r+w", "r+w"};
+#else
+char *f__r_mode[2] = {"rb", "r"};
+char *f__w_mode[4] = {"wb", "w", "r+b", "r+"};
+#endif
+
+#ifdef KR_headers
+f__isdev(s) char *s;
+#else
+f__isdev(char *s)
+#endif
+{
+#ifdef NON_UNIX_STDIO
+ int i, j;
+
+ i = open(s,O_RDONLY);
+ if (i == -1)
+ return 0;
+ j = isatty(i);
+ close(i);
+ return j;
+#else
+ struct stat x;
+
+ if(stat(s, &x) == -1) return(0);
+#ifdef S_IFMT
+ switch(x.st_mode&S_IFMT) {
+ case S_IFREG:
+ case S_IFDIR:
+ return(0);
+ }
+#else
+#ifdef S_ISREG
+ /* POSIX version */
+ if(S_ISREG(x.st_mode) || S_ISDIR(x.st_mode))
+ return(0);
+ else
+#else
+ Help! How does stat work on this system?
+#endif
+#endif
+ return(1);
+#endif
+}
+#ifdef KR_headers
+integer f_open(a) olist *a;
+#else
+integer f_open(olist *a)
+#endif
+{ unit *b;
+ integer rv;
+ char buf[256], *s;
+ cllist x;
+ int ufmt;
+#ifdef NON_UNIX_STDIO
+ FILE *tf;
+#else
+ int n;
+ struct stat stb;
+#endif
+ if(a->ounit>=MXUNIT || a->ounit<0)
+ err(a->oerr,101,"open")
+ if (!f__init)
+ f_init();
+ f__curunit = b = &f__units[a->ounit];
+ if(b->ufd) {
+ if(a->ofnm==0)
+ {
+ same: if (a->oblnk)
+ b->ublnk = *a->oblnk == 'z' || *a->oblnk == 'Z';
+ return(0);
+ }
+#ifdef NON_UNIX_STDIO
+ if (b->ufnm
+ && strlen(b->ufnm) == a->ofnmlen
+ && !strncmp(b->ufnm, b->ufnm, (unsigned)a->ofnmlen))
+ goto same;
+#else
+ g_char(a->ofnm,a->ofnmlen,buf);
+ if (f__inode(buf,&n) == b->uinode && n == b->udev)
+ goto same;
+#endif
+ x.cunit=a->ounit;
+ x.csta=0;
+ x.cerr=a->oerr;
+ if ((rv = f_clos(&x)) != 0)
+ return rv;
+ }
+ b->url = (int)a->orl;
+ b->ublnk = a->oblnk && (*a->oblnk == 'z' || *a->oblnk == 'Z');
+ if(a->ofm==0)
+ { if(b->url>0) b->ufmt=0;
+ else b->ufmt=1;
+ }
+ else if(*a->ofm=='f' || *a->ofm == 'F') b->ufmt=1;
+ else b->ufmt=0;
+ ufmt = b->ufmt;
+#ifdef url_Adjust
+ if (b->url && !ufmt)
+ url_Adjust(b->url);
+#endif
+ if (a->ofnm) {
+ g_char(a->ofnm,a->ofnmlen,buf);
+ if (!buf[0])
+ err(a->oerr,107,"open")
+ }
+ else
+ sprintf(buf, "fort.%ld", a->ounit);
+ b->uscrtch = 0;
+ switch(a->osta ? *a->osta : 'u')
+ {
+ case 'o':
+ case 'O':
+#ifdef NON_UNIX_STDIO
+ if(access(buf,0))
+#else
+ if(stat(buf,&stb))
+#endif
+ err(a->oerr,errno,"open")
+ break;
+ case 's':
+ case 'S':
+ b->uscrtch=1;
+#ifdef _POSIX_SOURCE
+ tmpnam(buf);
+#else
+ (void) strcpy(buf,"tmp.FXXXXXX");
+ (void) mktemp(buf);
+#endif
+ goto replace;
+ case 'n':
+ case 'N':
+#ifdef NON_UNIX_STDIO
+ if(!access(buf,0))
+#else
+ if(!stat(buf,&stb))
+#endif
+ err(a->oerr,128,"open")
+ /* no break */
+ case 'r': /* Fortran 90 replace option */
+ case 'R':
+ replace:
+#ifdef NON_UNIX_STDIO
+ if (tf = fopen(buf,f__w_mode[0]))
+ fclose(tf);
+#else
+ (void) close(creat(buf, 0666));
+#endif
+ }
+
+ b->ufnm=(char *) malloc((unsigned int)(strlen(buf)+1));
+ if(b->ufnm==NULL) err(a->oerr,113,"no space");
+ (void) strcpy(b->ufnm,buf);
+ b->uend=0;
+ b->uwrt = 0;
+#ifdef NON_UNIX_STDIO
+ if ((s = a->oacc) && (*s == 'd' || *s == 'D'))
+ ufmt = 0;
+#endif
+ if(f__isdev(buf))
+ { b->ufd = fopen(buf,f__r_mode[ufmt]);
+ if(b->ufd==NULL) err(a->oerr,errno,buf)
+ }
+ else {
+ if(!(b->ufd = fopen(buf, f__r_mode[ufmt]))) {
+#ifdef NON_UNIX_STDIO
+ if (b->ufd = fopen(buf, f__w_mode[ufmt|2]))
+ b->uwrt = 2;
+ else if (b->ufd = fopen(buf, f__w_mode[ufmt]))
+ b->uwrt = 1;
+ else
+#else
+ if ((n = open(buf,O_WRONLY)) >= 0)
+ b->uwrt = 2;
+ else {
+ n = creat(buf, 0666);
+ b->uwrt = 1;
+ }
+ if (n < 0
+ || (b->ufd = fdopen(n, f__w_mode[ufmt])) == NULL)
+#endif
+ err(a->oerr, errno, "open");
+ }
+ }
+ b->useek=f__canseek(b->ufd);
+#ifndef NON_UNIX_STDIO
+ if((b->uinode=f__inode(buf,&b->udev))==-1)
+ err(a->oerr,108,"open")
+#endif
+ if(b->useek)
+ if (a->orl)
+ rewind(b->ufd);
+ else if ((s = a->oacc) && (*s == 'a' || *s == 'A')
+ && fseek(b->ufd, 0L, SEEK_END))
+ err(a->oerr,129,"open");
+ return(0);
+}
+#ifdef KR_headers
+fk_open(seq,fmt,n) ftnint n;
+#else
+fk_open(int seq, int fmt, ftnint n)
+#endif
+{ char nbuf[10];
+ olist a;
+ (void) sprintf(nbuf,"fort.%ld",n);
+ a.oerr=1;
+ a.ounit=n;
+ a.ofnm=nbuf;
+ a.ofnmlen=strlen(nbuf);
+ a.osta=NULL;
+ a.oacc= seq==SEQ?"s":"d";
+ a.ofm = fmt==FMT?"f":"u";
+ a.orl = seq==DIR?1:0;
+ a.oblnk=NULL;
+ return(f_open(&a));
+}
diff --git a/lib/libI77/rawio.h b/lib/libI77/rawio.h
new file mode 100644
index 0000000..4cbd847
--- /dev/null
+++ b/lib/libI77/rawio.h
@@ -0,0 +1,43 @@
+#ifdef KR_headers
+extern FILE *fdopen();
+#else
+#ifdef MSDOS
+#include "io.h"
+#ifndef WATCOM
+#define close _close
+#define creat _creat
+#define open _open
+#define read _read
+#define write _write
+#endif /*WATCOM*/
+#endif /*MSDOS*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifndef MSDOS
+#ifdef OPEN_DECL
+extern int creat(const char*,int), open(const char*,int);
+#endif
+extern int close(int);
+extern int read(int,void*,size_t), write(int,void*,size_t);
+extern int unlink(const char*);
+#ifndef _POSIX_SOURCE
+#ifndef NON_UNIX_STDIO
+extern FILE *fdopen(int, const char*);
+#endif
+#endif
+#endif /*KR_HEADERS*/
+
+extern char *mktemp(char*);
+
+#ifdef __cplusplus
+ }
+#endif
+#endif
+
+#include "fcntl.h"
+
+#ifndef O_WRONLY
+#define O_RDONLY 0
+#define O_WRONLY 1
+#endif
diff --git a/lib/libI77/rdfmt.c b/lib/libI77/rdfmt.c
new file mode 100644
index 0000000..03b325e
--- /dev/null
+++ b/lib/libI77/rdfmt.c
@@ -0,0 +1,475 @@
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+#include "fp.h"
+#include "ctype.h"
+
+extern int f__cursor;
+#ifdef KR_headers
+extern double atof();
+#else
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#endif
+
+ static int
+#ifdef KR_headers
+rd_Z(n,w,len) Uint *n; ftnlen len;
+#else
+rd_Z(Uint *n, int w, ftnlen len)
+#endif
+{
+ long x[9];
+ char *s, *s0, *s1, *se, *t;
+ int ch, i, w1, w2;
+ static char hex[256];
+ static int one = 1;
+ int bad = 0;
+
+ if (!hex['0']) {
+ s = "0123456789";
+ while(ch = *s++)
+ hex[ch] = ch - '0' + 1;
+ s = "ABCDEF";
+ while(ch = *s++)
+ hex[ch] = hex[ch + 'a' - 'A'] = ch - 'A' + 11;
+ }
+ s = s0 = (char *)x;
+ s1 = (char *)&x[4];
+ se = (char *)&x[8];
+ if (len > 4*sizeof(long))
+ return errno = 117;
+ while (w) {
+ GET(ch);
+ if (ch==',' || ch=='\n')
+ break;
+ w--;
+ if (ch > ' ') {
+ if (!hex[ch & 0xff])
+ bad++;
+ *s++ = ch;
+ if (s == se) {
+ /* discard excess characters */
+ for(t = s0, s = s1; t < s1;)
+ *t++ = *s++;
+ s = s1;
+ }
+ }
+ }
+ if (bad)
+ return errno = 115;
+ w = (int)len;
+ w1 = s - s0;
+ w2 = w1+1 >> 1;
+ t = (char *)n;
+ if (*(char *)&one) {
+ /* little endian */
+ t += w - 1;
+ i = -1;
+ }
+ else
+ i = 1;
+ for(; w > w2; t += i, --w)
+ *t = 0;
+ if (!w)
+ return 0;
+ if (w < w2)
+ s0 = s - (w << 1);
+ else if (w1 & 1) {
+ *t = hex[*s0++ & 0xff] - 1;
+ if (!--w)
+ return 0;
+ t += i;
+ }
+ do {
+ *t = hex[*s0 & 0xff]-1 << 4 | hex[s0[1] & 0xff]-1;
+ t += i;
+ s0 += 2;
+ }
+ while(--w);
+ return 0;
+ }
+
+ static int
+#ifdef KR_headers
+rd_I(n,w,len, base) Uint *n; int w; ftnlen len; register int base;
+#else
+rd_I(Uint *n, int w, ftnlen len, register int base)
+#endif
+{ longint x;
+ int sign,ch;
+ char s[84], *ps;
+ ps=s; x=0;
+ while (w)
+ {
+ GET(ch);
+ if (ch==',' || ch=='\n') break;
+ *ps=ch; ps++; w--;
+ }
+ *ps='\0';
+ ps=s;
+ while (*ps==' ') ps++;
+ if (*ps=='-') { sign=1; ps++; }
+ else { sign=0; if (*ps=='+') ps++; }
+loop: while (*ps>='0' && *ps<='9') { x=x*base+(*ps-'0'); ps++; }
+ if (*ps==' ') {if (f__cblank) x *= base; ps++; goto loop;}
+ if(sign) x = -x;
+ if(len==sizeof(integer)) n->il=x;
+ else if(len == sizeof(char)) n->ic = (char)x;
+#ifdef Allow_TYQUAD
+ else if (len == sizeof(longint)) n->ili = x;
+#endif
+ else n->is = (short)x;
+ if (*ps) return(errno=115); else return(0);
+}
+ static int
+#ifdef KR_headers
+rd_L(n,w,len) ftnint *n; ftnlen len;
+#else
+rd_L(ftnint *n, int w, ftnlen len)
+#endif
+{ int ch, lv;
+ char s[84], *ps;
+ ps=s;
+ while (w) {
+ GET(ch);
+ if (ch==','||ch=='\n') break;
+ *ps=ch;
+ ps++; w--;
+ }
+ *ps='\0';
+ ps=s; while (*ps==' ') ps++;
+ if (*ps=='.') ps++;
+ if (*ps=='t' || *ps == 'T')
+ lv = 1;
+ else if (*ps == 'f' || *ps == 'F')
+ lv = 0;
+ else return(errno=116);
+ switch(len) {
+ case sizeof(char): *(char *)n = (char)lv; break;
+ case sizeof(short): *(short *)n = (short)lv; break;
+ default: *n = lv;
+ }
+ return 0;
+}
+
+ static int
+#ifdef KR_headers
+rd_F(p, w, d, len) ufloat *p; ftnlen len;
+#else
+rd_F(ufloat *p, int w, int d, ftnlen len)
+#endif
+{
+ char s[FMAX+EXPMAXDIGS+4];
+ register int ch;
+ register char *sp, *spe, *sp1;
+ double x;
+ int scale1, se;
+ long e, exp;
+
+ sp1 = sp = s;
+ spe = sp + FMAX;
+ exp = -d;
+ x = 0.;
+
+ do {
+ GET(ch);
+ w--;
+ } while (ch == ' ' && w);
+ switch(ch) {
+ case '-': *sp++ = ch; sp1++; spe++;
+ case '+':
+ if (!w) goto zero;
+ --w;
+ GET(ch);
+ }
+ while(ch == ' ') {
+blankdrop:
+ if (!w--) goto zero; GET(ch); }
+ while(ch == '0')
+ { if (!w--) goto zero; GET(ch); }
+ if (ch == ' ' && f__cblank)
+ goto blankdrop;
+ scale1 = f__scale;
+ while(isdigit(ch)) {
+digloop1:
+ if (sp < spe) *sp++ = ch;
+ else ++exp;
+digloop1e:
+ if (!w--) goto done;
+ GET(ch);
+ }
+ if (ch == ' ') {
+ if (f__cblank)
+ { ch = '0'; goto digloop1; }
+ goto digloop1e;
+ }
+ if (ch == '.') {
+ exp += d;
+ if (!w--) goto done;
+ GET(ch);
+ if (sp == sp1) { /* no digits yet */
+ while(ch == '0') {
+skip01:
+ --exp;
+skip0:
+ if (!w--) goto done;
+ GET(ch);
+ }
+ if (ch == ' ') {
+ if (f__cblank) goto skip01;
+ goto skip0;
+ }
+ }
+ while(isdigit(ch)) {
+digloop2:
+ if (sp < spe)
+ { *sp++ = ch; --exp; }
+digloop2e:
+ if (!w--) goto done;
+ GET(ch);
+ }
+ if (ch == ' ') {
+ if (f__cblank)
+ { ch = '0'; goto digloop2; }
+ goto digloop2e;
+ }
+ }
+ switch(ch) {
+ default:
+ break;
+ case '-': se = 1; goto signonly;
+ case '+': se = 0; goto signonly;
+ case 'e':
+ case 'E':
+ case 'd':
+ case 'D':
+ if (!w--)
+ goto bad;
+ GET(ch);
+ while(ch == ' ') {
+ if (!w--)
+ goto bad;
+ GET(ch);
+ }
+ se = 0;
+ switch(ch) {
+ case '-': se = 1;
+ case '+':
+signonly:
+ if (!w--)
+ goto bad;
+ GET(ch);
+ }
+ while(ch == ' ') {
+ if (!w--)
+ goto bad;
+ GET(ch);
+ }
+ if (!isdigit(ch))
+ goto bad;
+
+ e = ch - '0';
+ for(;;) {
+ if (!w--)
+ { ch = '\n'; break; }
+ GET(ch);
+ if (!isdigit(ch)) {
+ if (ch == ' ') {
+ if (f__cblank)
+ ch = '0';
+ else continue;
+ }
+ else
+ break;
+ }
+ e = 10*e + ch - '0';
+ if (e > EXPMAX && sp > sp1)
+ goto bad;
+ }
+ if (se)
+ exp -= e;
+ else
+ exp += e;
+ scale1 = 0;
+ }
+ switch(ch) {
+ case '\n':
+ case ',':
+ break;
+ default:
+bad:
+ return (errno = 115);
+ }
+done:
+ if (sp > sp1) {
+ while(*--sp == '0')
+ ++exp;
+ if (exp -= scale1)
+ sprintf(sp+1, "e%ld", exp);
+ else
+ sp[1] = 0;
+ x = atof(s);
+ }
+zero:
+ if (len == sizeof(real))
+ p->pf = x;
+ else
+ p->pd = x;
+ return(0);
+ }
+
+
+ static int
+#ifdef KR_headers
+rd_A(p,len) char *p; ftnlen len;
+#else
+rd_A(char *p, ftnlen len)
+#endif
+{ int i,ch;
+ for(i=0;i<len;i++)
+ { GET(ch);
+ *p++=VAL(ch);
+ }
+ return(0);
+}
+ static int
+#ifdef KR_headers
+rd_AW(p,w,len) char *p; ftnlen len;
+#else
+rd_AW(char *p, int w, ftnlen len)
+#endif
+{ int i,ch;
+ if(w>=len)
+ { for(i=0;i<w-len;i++)
+ GET(ch);
+ for(i=0;i<len;i++)
+ { GET(ch);
+ *p++=VAL(ch);
+ }
+ return(0);
+ }
+ for(i=0;i<w;i++)
+ { GET(ch);
+ *p++=VAL(ch);
+ }
+ for(i=0;i<len-w;i++) *p++=' ';
+ return(0);
+}
+ static int
+#ifdef KR_headers
+rd_H(n,s) char *s;
+#else
+rd_H(int n, char *s)
+#endif
+{ int i,ch;
+ for(i=0;i<n;i++)
+ if((ch=(*f__getn)())<0) return(ch);
+ else *s++ = ch=='\n'?' ':ch;
+ return(1);
+}
+ static int
+#ifdef KR_headers
+rd_POS(s) char *s;
+#else
+rd_POS(char *s)
+#endif
+{ char quote;
+ int ch;
+ quote= *s++;
+ for(;*s;s++)
+ if(*s==quote && *(s+1)!=quote) break;
+ else if((ch=(*f__getn)())<0) return(ch);
+ else *s = ch=='\n'?' ':ch;
+ return(1);
+}
+#ifdef KR_headers
+rd_ed(p,ptr,len) struct syl *p; char *ptr; ftnlen len;
+#else
+rd_ed(struct syl *p, char *ptr, ftnlen len)
+#endif
+{ int ch;
+ for(;f__cursor>0;f__cursor--) if((ch=(*f__getn)())<0) return(ch);
+ if(f__cursor<0)
+ { if(f__recpos+f__cursor < 0) /*err(elist->cierr,110,"fmt")*/
+ f__cursor = -f__recpos; /* is this in the standard? */
+ if(f__external == 0) {
+ extern char *f__icptr;
+ f__icptr += f__cursor;
+ }
+ else if(f__curunit && f__curunit->useek)
+ (void) fseek(f__cf,(long) f__cursor,SEEK_CUR);
+ else
+ err(f__elist->cierr,106,"fmt");
+ f__recpos += f__cursor;
+ f__cursor=0;
+ }
+ switch(p->op)
+ {
+ default: fprintf(stderr,"rd_ed, unexpected code: %d\n", p->op);
+ sig_die(f__fmtbuf, 1);
+ case IM:
+ case I: ch = rd_I((Uint *)ptr,p->p1,len, 10);
+ break;
+
+ /* O and OM don't work right for character, double, complex, */
+ /* or doublecomplex, and they differ from Fortran 90 in */
+ /* showing a minus sign for negative values. */
+
+ case OM:
+ case O: ch = rd_I((Uint *)ptr, p->p1, len, 8);
+ break;
+ case L: ch = rd_L((ftnint *)ptr,p->p1,len);
+ break;
+ case A: ch = rd_A(ptr,len);
+ break;
+ case AW:
+ ch = rd_AW(ptr,p->p1,len);
+ break;
+ case E: case EE:
+ case D:
+ case G:
+ case GE:
+ case F: ch = rd_F((ufloat *)ptr,p->p1,p->p2,len);
+ break;
+
+ /* Z and ZM assume 8-bit bytes. */
+
+ case ZM:
+ case Z:
+ ch = rd_Z((Uint *)ptr, p->p1, len);
+ break;
+ }
+ if(ch == 0) return(ch);
+ else if(ch == EOF) return(EOF);
+ if (f__cf)
+ clearerr(f__cf);
+ return(errno);
+}
+#ifdef KR_headers
+rd_ned(p) struct syl *p;
+#else
+rd_ned(struct syl *p)
+#endif
+{
+ switch(p->op)
+ {
+ default: fprintf(stderr,"rd_ned, unexpected code: %d\n", p->op);
+ sig_die(f__fmtbuf, 1);
+ case APOS:
+ return(rd_POS(*(char **)&p->p2));
+ case H: return(rd_H(p->p1,*(char **)&p->p2));
+ case SLASH: return((*f__donewrec)());
+ case TR:
+ case X: f__cursor += p->p1;
+ return(1);
+ case T: f__cursor=p->p1-f__recpos - 1;
+ return(1);
+ case TL: f__cursor -= p->p1;
+ if(f__cursor < -f__recpos) /* TL1000, 1X */
+ f__cursor = -f__recpos;
+ return(1);
+ }
+}
diff --git a/lib/libI77/rewind.c b/lib/libI77/rewind.c
new file mode 100644
index 0000000..e58daad7
--- /dev/null
+++ b/lib/libI77/rewind.c
@@ -0,0 +1,24 @@
+#include "f2c.h"
+#include "fio.h"
+#ifdef KR_headers
+integer f_rew(a) alist *a;
+#else
+integer f_rew(alist *a)
+#endif
+{
+ unit *b;
+ if(a->aunit>=MXUNIT || a->aunit<0)
+ err(a->aerr,101,"rewind");
+ b = &f__units[a->aunit];
+ if(b->ufd == NULL || b->uwrt == 3)
+ return(0);
+ if(!b->useek)
+ err(a->aerr,106,"rewind")
+ if(b->uwrt) {
+ (void) t_runc(a);
+ b->uwrt = 3;
+ }
+ rewind(b->ufd);
+ b->uend=0;
+ return(0);
+}
diff --git a/lib/libI77/rsfe.c b/lib/libI77/rsfe.c
new file mode 100644
index 0000000..41ff257
--- /dev/null
+++ b/lib/libI77/rsfe.c
@@ -0,0 +1,79 @@
+/* read sequential formatted external */
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+
+xrd_SL(Void)
+{ int ch;
+ if(!f__curunit->uend)
+ while((ch=getc(f__cf))!='\n')
+ if (ch == EOF) {
+ f__curunit->uend = 1;
+ break;
+ }
+ f__cursor=f__recpos=0;
+ return(1);
+}
+x_getc(Void)
+{ int ch;
+ if(f__curunit->uend) return(EOF);
+ ch = getc(f__cf);
+ if(ch!=EOF && ch!='\n')
+ { f__recpos++;
+ return(ch);
+ }
+ if(ch=='\n')
+ { (void) ungetc(ch,f__cf);
+ return(ch);
+ }
+ if(f__curunit->uend || feof(f__cf))
+ { errno=0;
+ f__curunit->uend=1;
+ return(-1);
+ }
+ return(-1);
+}
+x_endp(Void)
+{
+ xrd_SL();
+ return f__curunit->uend == 1 ? EOF : 0;
+}
+x_rev(Void)
+{
+ (void) xrd_SL();
+ return(0);
+}
+#ifdef KR_headers
+integer s_rsfe(a) cilist *a; /* start */
+#else
+integer s_rsfe(cilist *a) /* start */
+#endif
+{ int n;
+ if(!f__init) f_init();
+ if(n=c_sfe(a)) return(n);
+ f__reading=1;
+ f__sequential=1;
+ f__formatted=1;
+ f__external=1;
+ f__elist=a;
+ f__cursor=f__recpos=0;
+ f__scale=0;
+ f__fmtbuf=a->cifmt;
+ f__curunit= &f__units[a->ciunit];
+ f__cf=f__curunit->ufd;
+ if(pars_f(f__fmtbuf)<0) err(a->cierr,100,"startio");
+ f__getn= x_getc;
+ f__doed= rd_ed;
+ f__doned= rd_ned;
+ fmt_bg();
+ f__doend=x_endp;
+ f__donewrec=xrd_SL;
+ f__dorevert=x_rev;
+ f__cblank=f__curunit->ublnk;
+ f__cplus=0;
+ if(f__curunit->uwrt && f__nowreading(f__curunit))
+ err(a->cierr,errno,"read start");
+ if(f__curunit->uend)
+ err(f__elist->ciend,(EOF),"read start");
+ return(0);
+}
diff --git a/lib/libI77/rsli.c b/lib/libI77/rsli.c
new file mode 100644
index 0000000..a081cd5
--- /dev/null
+++ b/lib/libI77/rsli.c
@@ -0,0 +1,103 @@
+#include "f2c.h"
+#include "fio.h"
+#include "lio.h"
+#include "fmt.h" /* for f__doend */
+
+extern flag f__lquit;
+extern int f__lcount;
+extern char *f__icptr;
+extern char *f__icend;
+extern icilist *f__svic;
+extern int f__icnum, f__recpos;
+
+static int i_getc(Void)
+{
+ if(f__recpos >= f__svic->icirlen) {
+ if (f__recpos++ == f__svic->icirlen)
+ return '\n';
+ z_rnew();
+ }
+ f__recpos++;
+ if(f__icptr >= f__icend)
+ return EOF;
+ return(*f__icptr++);
+ }
+
+ static
+#ifdef KR_headers
+int i_ungetc(ch, f) int ch; FILE *f;
+#else
+int i_ungetc(int ch, FILE *f)
+#endif
+{
+ if (--f__recpos == f__svic->icirlen)
+ return '\n';
+ if (f__recpos < -1)
+ err(f__svic->icierr,110,"recend");
+ /* *--icptr == ch, and icptr may point to read-only memory */
+ return *--f__icptr /* = ch */;
+ }
+
+ static void
+#ifdef KR_headers
+c_lir(a) icilist *a;
+#else
+c_lir(icilist *a)
+#endif
+{
+ extern int l_eof;
+ f__reading = 1;
+ f__external = 0;
+ f__formatted = 1;
+ f__svic = a;
+ L_len = a->icirlen;
+ f__recpos = -1;
+ f__icnum = f__recpos = 0;
+ f__cursor = 0;
+ l_getc = i_getc;
+ l_ungetc = i_ungetc;
+ l_eof = 0;
+ f__icptr = a->iciunit;
+ f__icend = f__icptr + a->icirlen*a->icirnum;
+ f__cf = 0;
+ f__curunit = 0;
+ f__elist = (cilist *)a;
+ }
+
+
+#ifdef KR_headers
+integer s_rsli(a) icilist *a;
+#else
+integer s_rsli(icilist *a)
+#endif
+{
+ f__lioproc = l_read;
+ f__lquit = 0;
+ f__lcount = 0;
+ c_lir(a);
+ f__doend = 0;
+ return(0);
+ }
+
+integer e_rsli(Void)
+{ return 0; }
+
+#ifdef KR_headers
+integer s_rsni(a) icilist *a;
+#else
+extern int x_rsne(cilist*);
+
+integer s_rsni(icilist *a)
+#endif
+{
+ extern int nml_read;
+ integer rv;
+ cilist ca;
+ ca.ciend = a->iciend;
+ ca.cierr = a->icierr;
+ ca.cifmt = a->icifmt;
+ c_lir(a);
+ rv = x_rsne(&ca);
+ nml_read = 0;
+ return rv;
+ }
diff --git a/lib/libI77/rsne.c b/lib/libI77/rsne.c
new file mode 100644
index 0000000..cc679c7
--- /dev/null
+++ b/lib/libI77/rsne.c
@@ -0,0 +1,609 @@
+#include "f2c.h"
+#include "fio.h"
+#include "lio.h"
+
+#define MAX_NL_CACHE 3 /* maximum number of namelist hash tables to cache */
+#define MAXDIM 20 /* maximum number of subscripts */
+
+ struct dimen {
+ ftnlen extent;
+ ftnlen curval;
+ ftnlen delta;
+ ftnlen stride;
+ };
+ typedef struct dimen dimen;
+
+ struct hashentry {
+ struct hashentry *next;
+ char *name;
+ Vardesc *vd;
+ };
+ typedef struct hashentry hashentry;
+
+ struct hashtab {
+ struct hashtab *next;
+ Namelist *nl;
+ int htsize;
+ hashentry *tab[1];
+ };
+ typedef struct hashtab hashtab;
+
+ static hashtab *nl_cache;
+ static int n_nlcache;
+ static hashentry **zot;
+ static int colonseen;
+ extern ftnlen f__typesize[];
+
+ extern flag f__lquit;
+ extern int f__lcount, nml_read;
+ extern t_getc(Void);
+
+#ifdef KR_headers
+ extern char *malloc(), *memset();
+
+#ifdef ungetc
+ static int
+un_getc(x,f__cf) int x; FILE *f__cf;
+{ return ungetc(x,f__cf); }
+#else
+#define un_getc ungetc
+ extern int ungetc();
+#endif
+
+#else
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#include "string.h"
+
+#ifdef ungetc
+ static int
+un_getc(int x, FILE *f__cf)
+{ return ungetc(x,f__cf); }
+#else
+#define un_getc ungetc
+extern int ungetc(int, FILE*); /* for systems with a buggy stdio.h */
+#endif
+#endif
+
+ static Vardesc *
+#ifdef KR_headers
+hash(ht, s) hashtab *ht; register char *s;
+#else
+hash(hashtab *ht, register char *s)
+#endif
+{
+ register int c, x;
+ register hashentry *h;
+ char *s0 = s;
+
+ for(x = 0; c = *s++; x = x & 0x4000 ? ((x << 1) & 0x7fff) + 1 : x << 1)
+ x += c;
+ for(h = *(zot = ht->tab + x % ht->htsize); h; h = h->next)
+ if (!strcmp(s0, h->name))
+ return h->vd;
+ return 0;
+ }
+
+ hashtab *
+#ifdef KR_headers
+mk_hashtab(nl) Namelist *nl;
+#else
+mk_hashtab(Namelist *nl)
+#endif
+{
+ int nht, nv;
+ hashtab *ht;
+ Vardesc *v, **vd, **vde;
+ hashentry *he;
+
+ hashtab **x, **x0, *y;
+ for(x = &nl_cache; y = *x; x0 = x, x = &y->next)
+ if (nl == y->nl)
+ return y;
+ if (n_nlcache >= MAX_NL_CACHE) {
+ /* discard least recently used namelist hash table */
+ y = *x0;
+ free((char *)y->next);
+ y->next = 0;
+ }
+ else
+ n_nlcache++;
+ nv = nl->nvars;
+ if (nv >= 0x4000)
+ nht = 0x7fff;
+ else {
+ for(nht = 1; nht < nv; nht <<= 1);
+ nht += nht - 1;
+ }
+ ht = (hashtab *)malloc(sizeof(hashtab) + (nht-1)*sizeof(hashentry *)
+ + nv*sizeof(hashentry));
+ if (!ht)
+ return 0;
+ he = (hashentry *)&ht->tab[nht];
+ ht->nl = nl;
+ ht->htsize = nht;
+ ht->next = nl_cache;
+ nl_cache = ht;
+ memset((char *)ht->tab, 0, nht*sizeof(hashentry *));
+ vd = nl->vars;
+ vde = vd + nv;
+ while(vd < vde) {
+ v = *vd++;
+ if (!hash(ht, v->name)) {
+ he->next = *zot;
+ *zot = he;
+ he->name = v->name;
+ he->vd = v;
+ he++;
+ }
+ }
+ return ht;
+ }
+
+static char Alpha[256], Alphanum[256];
+
+ static VOID
+nl_init(Void) {
+ register char *s;
+ register int c;
+
+ if(!f__init)
+ f_init();
+ for(s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; c = *s++; )
+ Alpha[c]
+ = Alphanum[c]
+ = Alpha[c + 'a' - 'A']
+ = Alphanum[c + 'a' - 'A']
+ = c;
+ for(s = "0123456789_"; c = *s++; )
+ Alphanum[c] = c;
+ }
+
+#define GETC(x) (x=(*l_getc)())
+#define Ungetc(x,y) (*l_ungetc)(x,y)
+
+ static int
+#ifdef KR_headers
+getname(s, slen) register char *s; int slen;
+#else
+getname(register char *s, int slen)
+#endif
+{
+ register char *se = s + slen - 1;
+ register int ch;
+
+ GETC(ch);
+ if (!(*s++ = Alpha[ch & 0xff])) {
+ if (ch != EOF)
+ ch = 115;
+ errfl(f__elist->cierr, ch, "namelist read");
+ }
+ while(*s = Alphanum[GETC(ch) & 0xff])
+ if (s < se)
+ s++;
+ if (ch == EOF)
+ err(f__elist->cierr, EOF, "namelist read");
+ if (ch > ' ')
+ Ungetc(ch,f__cf);
+ return *s = 0;
+ }
+
+ static int
+#ifdef KR_headers
+getnum(chp, val) int *chp; ftnlen *val;
+#else
+getnum(int *chp, ftnlen *val)
+#endif
+{
+ register int ch, sign;
+ register ftnlen x;
+
+ while(GETC(ch) <= ' ' && ch >= 0);
+ if (ch == '-') {
+ sign = 1;
+ GETC(ch);
+ }
+ else {
+ sign = 0;
+ if (ch == '+')
+ GETC(ch);
+ }
+ x = ch - '0';
+ if (x < 0 || x > 9)
+ return 115;
+ while(GETC(ch) >= '0' && ch <= '9')
+ x = 10*x + ch - '0';
+ while(ch <= ' ' && ch >= 0)
+ GETC(ch);
+ if (ch == EOF)
+ return EOF;
+ *val = sign ? -x : x;
+ *chp = ch;
+ return 0;
+ }
+
+ static int
+#ifdef KR_headers
+getdimen(chp, d, delta, extent, x1)
+ int *chp; dimen *d; ftnlen delta, extent, *x1;
+#else
+getdimen(int *chp, dimen *d, ftnlen delta, ftnlen extent, ftnlen *x1)
+#endif
+{
+ register int k;
+ ftnlen x2, x3;
+
+ if (k = getnum(chp, x1))
+ return k;
+ x3 = 1;
+ if (*chp == ':') {
+ if (k = getnum(chp, &x2))
+ return k;
+ x2 -= *x1;
+ if (*chp == ':') {
+ if (k = getnum(chp, &x3))
+ return k;
+ if (!x3)
+ return 123;
+ x2 /= x3;
+ colonseen = 1;
+ }
+ if (x2 < 0 || x2 >= extent)
+ return 123;
+ d->extent = x2 + 1;
+ }
+ else
+ d->extent = 1;
+ d->curval = 0;
+ d->delta = delta;
+ d->stride = x3;
+ return 0;
+ }
+
+#ifndef No_Namelist_Questions
+ static Void
+#ifdef KR_headers
+print_ne(a) cilist *a;
+#else
+print_ne(cilist *a)
+#endif
+{
+ flag intext = f__external;
+ int rpsave = f__recpos;
+ FILE *cfsave = f__cf;
+ unit *usave = f__curunit;
+ cilist t;
+ t = *a;
+ t.ciunit = 6;
+ s_wsne(&t);
+ fflush(f__cf);
+ f__external = intext;
+ f__reading = 1;
+ f__recpos = rpsave;
+ f__cf = cfsave;
+ f__curunit = usave;
+ f__elist = a;
+ }
+#endif
+
+ static char where0[] = "namelist read start ";
+
+#ifdef KR_headers
+x_rsne(a) cilist *a;
+#else
+x_rsne(cilist *a)
+#endif
+{
+ int ch, got1, k, n, nd, quote, readall;
+ Namelist *nl;
+ static char where[] = "namelist read";
+ char buf[64];
+ hashtab *ht;
+ Vardesc *v;
+ dimen *dn, *dn0, *dn1;
+ ftnlen *dims, *dims1;
+ ftnlen b, b0, b1, ex, no, no1, nomax, size, span;
+ ftnint type;
+ char *vaddr;
+ long iva, ivae;
+ dimen dimens[MAXDIM], substr;
+
+ if (!Alpha['a'])
+ nl_init();
+ f__reading=1;
+ f__formatted=1;
+ got1 = 0;
+ top:
+ for(;;) switch(GETC(ch)) {
+ case EOF:
+ eof:
+ err(a->ciend,(EOF),where0);
+ case '&':
+ case '$':
+ goto have_amp;
+#ifndef No_Namelist_Questions
+ case '?':
+ print_ne(a);
+ continue;
+#endif
+ default:
+ if (ch <= ' ' && ch >= 0)
+ continue;
+#ifndef No_Namelist_Comments
+ while(GETC(ch) != '\n')
+ if (ch == EOF)
+ goto eof;
+#else
+ errfl(a->cierr, 115, where0);
+#endif
+ }
+ have_amp:
+ if (ch = getname(buf,sizeof(buf)))
+ return ch;
+ nl = (Namelist *)a->cifmt;
+ if (strcmp(buf, nl->name))
+#ifdef No_Bad_Namelist_Skip
+ errfl(a->cierr, 118, where0);
+#else
+ {
+ fprintf(stderr,
+ "Skipping namelist \"%s\": seeking namelist \"%s\".\n",
+ buf, nl->name);
+ fflush(stderr);
+ for(;;) switch(GETC(ch)) {
+ case EOF:
+ err(a->ciend, EOF, where0);
+ case '/':
+ case '&':
+ case '$':
+ if (f__external)
+ e_rsle();
+ else
+ z_rnew();
+ goto top;
+ case '"':
+ case '\'':
+ quote = ch;
+ more_quoted:
+ while(GETC(ch) != quote)
+ if (ch == EOF)
+ err(a->ciend, EOF, where0);
+ if (GETC(ch) == quote)
+ goto more_quoted;
+ Ungetc(ch,f__cf);
+ default:
+ continue;
+ }
+ }
+#endif
+ ht = mk_hashtab(nl);
+ if (!ht)
+ errfl(f__elist->cierr, 113, where0);
+ for(;;) {
+ for(;;) switch(GETC(ch)) {
+ case EOF:
+ if (got1)
+ return 0;
+ err(a->ciend, EOF, where0);
+ case '/':
+ case '$':
+ case '&':
+ return 0;
+ default:
+ if (ch <= ' ' && ch >= 0 || ch == ',')
+ continue;
+ Ungetc(ch,f__cf);
+ if (ch = getname(buf,sizeof(buf)))
+ return ch;
+ goto havename;
+ }
+ havename:
+ v = hash(ht,buf);
+ if (!v)
+ errfl(a->cierr, 119, where);
+ while(GETC(ch) <= ' ' && ch >= 0);
+ vaddr = v->addr;
+ type = v->type;
+ if (type < 0) {
+ size = -type;
+ type = TYCHAR;
+ }
+ else
+ size = f__typesize[type];
+ ivae = size;
+ iva = readall = 0;
+ if (ch == '(' /*)*/ ) {
+ dn = dimens;
+ if (!(dims = v->dims)) {
+ if (type != TYCHAR)
+ errfl(a->cierr, 122, where);
+ if (k = getdimen(&ch, dn, (ftnlen)size,
+ (ftnlen)size, &b))
+ errfl(a->cierr, k, where);
+ if (ch != ')')
+ errfl(a->cierr, 115, where);
+ b1 = dn->extent;
+ if (--b < 0 || b + b1 > size)
+ return 124;
+ iva += b;
+ size = b1;
+ while(GETC(ch) <= ' ' && ch >= 0);
+ goto scalar;
+ }
+ nd = (int)dims[0];
+ nomax = span = dims[1];
+ ivae = iva + size*nomax;
+ colonseen = 0;
+ if (k = getdimen(&ch, dn, size, nomax, &b))
+ errfl(a->cierr, k, where);
+ no = dn->extent;
+ b0 = dims[2];
+ dims1 = dims += 3;
+ ex = 1;
+ for(n = 1; n++ < nd; dims++) {
+ if (ch != ',')
+ errfl(a->cierr, 115, where);
+ dn1 = dn + 1;
+ span /= *dims;
+ if (k = getdimen(&ch, dn1, dn->delta**dims,
+ span, &b1))
+ errfl(a->cierr, k, where);
+ ex *= *dims;
+ b += b1*ex;
+ no *= dn1->extent;
+ dn = dn1;
+ }
+ if (ch != ')')
+ errfl(a->cierr, 115, where);
+ readall = 1 - colonseen;
+ b -= b0;
+ if (b < 0 || b >= nomax)
+ errfl(a->cierr, 125, where);
+ iva += size * b;
+ dims = dims1;
+ while(GETC(ch) <= ' ' && ch >= 0);
+ no1 = 1;
+ dn0 = dimens;
+ if (type == TYCHAR && ch == '(' /*)*/) {
+ if (k = getdimen(&ch, &substr, size, size, &b))
+ errfl(a->cierr, k, where);
+ if (ch != ')')
+ errfl(a->cierr, 115, where);
+ b1 = substr.extent;
+ if (--b < 0 || b + b1 > size)
+ return 124;
+ iva += b;
+ b0 = size;
+ size = b1;
+ while(GETC(ch) <= ' ' && ch >= 0);
+ if (b1 < b0)
+ goto delta_adj;
+ }
+ if (readall)
+ goto delta_adj;
+ for(; dn0 < dn; dn0++) {
+ if (dn0->extent != *dims++ || dn0->stride != 1)
+ break;
+ no1 *= dn0->extent;
+ }
+ if (dn0 == dimens && dimens[0].stride == 1) {
+ no1 = dimens[0].extent;
+ dn0++;
+ }
+ delta_adj:
+ ex = 0;
+ for(dn1 = dn0; dn1 <= dn; dn1++)
+ ex += (dn1->extent-1)
+ * (dn1->delta *= dn1->stride);
+ for(dn1 = dn; dn1 > dn0; dn1--) {
+ ex -= (dn1->extent - 1) * dn1->delta;
+ dn1->delta -= ex;
+ }
+ }
+ else if (dims = v->dims) {
+ no = no1 = dims[1];
+ ivae = iva + no*size;
+ }
+ else
+ scalar:
+ no = no1 = 1;
+ if (ch != '=')
+ errfl(a->cierr, 115, where);
+ got1 = nml_read = 1;
+ f__lcount = 0;
+ readloop:
+ for(;;) {
+ if (iva >= ivae || iva < 0) {
+ f__lquit = 1;
+ goto mustend;
+ }
+ else if (iva + no1*size > ivae)
+ no1 = (ivae - iva)/size;
+ f__lquit = 0;
+ if (k = l_read(&no1, vaddr + iva, size, type))
+ return k;
+ if (f__lquit == 1)
+ return 0;
+ if (readall) {
+ iva += dn0->delta;
+ if (f__lcount > 0) {
+ no1 = (ivae - iva)/size;
+ if (no1 > f__lcount)
+ no1 = f__lcount;
+ iva += no1 * dn0->delta;
+ if (k = l_read(&no1, vaddr + iva,
+ size, type))
+ return k;
+ }
+ }
+ mustend:
+ GETC(ch);
+ if (readall)
+ if (iva >= ivae)
+ readall = 0;
+ else for(;;) {
+ switch(ch) {
+ case ' ':
+ case '\t':
+ case '\n':
+ GETC(ch);
+ continue;
+ }
+ break;
+ }
+ if (ch == '/' || ch == '$' || ch == '&') {
+ f__lquit = 1;
+ return 0;
+ }
+ else if (f__lquit) {
+ while(ch <= ' ' && ch >= 0)
+ GETC(ch);
+ Ungetc(ch,f__cf);
+ if (!Alpha[ch & 0xff] && ch >= 0)
+ errfl(a->cierr, 125, where);
+ break;
+ }
+ Ungetc(ch,f__cf);
+ if (readall && !Alpha[ch & 0xff])
+ goto readloop;
+ if ((no -= no1) <= 0)
+ break;
+ for(dn1 = dn0; dn1 <= dn; dn1++) {
+ if (++dn1->curval < dn1->extent) {
+ iva += dn1->delta;
+ goto readloop;
+ }
+ dn1->curval = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ integer
+#ifdef KR_headers
+s_rsne(a) cilist *a;
+#else
+s_rsne(cilist *a)
+#endif
+{
+ extern int l_eof;
+ int n;
+
+ f__external=1;
+ l_eof = 0;
+ if(n = c_le(a))
+ return n;
+ if(f__curunit->uwrt && f__nowreading(f__curunit))
+ err(a->cierr,errno,where0);
+ l_getc = t_getc;
+ l_ungetc = un_getc;
+ f__doend = xrd_SL;
+ n = x_rsne(a);
+ nml_read = 0;
+ if (n)
+ return n;
+ return e_rsle();
+ }
diff --git a/lib/libI77/sfe.c b/lib/libI77/sfe.c
new file mode 100644
index 0000000..eea9078
--- /dev/null
+++ b/lib/libI77/sfe.c
@@ -0,0 +1,42 @@
+/* sequential formatted external common routines*/
+#include "f2c.h"
+#include "fio.h"
+
+extern char *f__fmtbuf;
+
+integer e_rsfe(Void)
+{ int n;
+ n=en_fio();
+ if (f__cf == stdout)
+ fflush(stdout);
+ else if (f__cf == stderr)
+ fflush(stderr);
+ f__fmtbuf=NULL;
+ return(n);
+}
+#ifdef KR_headers
+c_sfe(a) cilist *a; /* check */
+#else
+c_sfe(cilist *a) /* check */
+#endif
+{ unit *p;
+ if(a->ciunit >= MXUNIT || a->ciunit<0)
+ err(a->cierr,101,"startio");
+ p = &f__units[a->ciunit];
+ if(p->ufd==NULL && fk_open(SEQ,FMT,a->ciunit)) err(a->cierr,114,"sfe")
+ if(!p->ufmt) err(a->cierr,102,"sfe")
+ return(0);
+}
+integer e_wsfe(Void)
+{
+#ifdef ALWAYS_FLUSH
+ int n;
+ n = en_fio();
+ f__fmtbuf=NULL;
+ if (!n && fflush(f__cf))
+ err(f__elist->cierr, errno, "write end");
+ return n;
+#else
+ return(e_rsfe());
+#endif
+}
diff --git a/lib/libI77/sue.c b/lib/libI77/sue.c
new file mode 100644
index 0000000..b1b8bc3
--- /dev/null
+++ b/lib/libI77/sue.c
@@ -0,0 +1,83 @@
+#include "f2c.h"
+#include "fio.h"
+extern uiolen f__reclen;
+long f__recloc;
+
+#ifdef KR_headers
+c_sue(a) cilist *a;
+#else
+c_sue(cilist *a)
+#endif
+{
+ if(a->ciunit >= MXUNIT || a->ciunit < 0)
+ err(a->cierr,101,"startio");
+ f__external=f__sequential=1;
+ f__formatted=0;
+ f__curunit = &f__units[a->ciunit];
+ f__elist=a;
+ if(f__curunit->ufd==NULL && fk_open(SEQ,UNF,a->ciunit))
+ err(a->cierr,114,"sue");
+ f__cf=f__curunit->ufd;
+ if(f__curunit->ufmt) err(a->cierr,103,"sue")
+ if(!f__curunit->useek) err(a->cierr,103,"sue")
+ return(0);
+}
+#ifdef KR_headers
+integer s_rsue(a) cilist *a;
+#else
+integer s_rsue(cilist *a)
+#endif
+{
+ int n;
+ if(!f__init) f_init();
+ f__reading=1;
+ if(n=c_sue(a)) return(n);
+ f__recpos=0;
+ if(f__curunit->uwrt && f__nowreading(f__curunit))
+ err(a->cierr, errno, "read start");
+ if(fread((char *)&f__reclen,sizeof(uiolen),1,f__cf)
+ != 1)
+ { if(feof(f__cf))
+ { f__curunit->uend = 1;
+ err(a->ciend, EOF, "start");
+ }
+ clearerr(f__cf);
+ err(a->cierr, errno, "start");
+ }
+ return(0);
+}
+#ifdef KR_headers
+integer s_wsue(a) cilist *a;
+#else
+integer s_wsue(cilist *a)
+#endif
+{
+ int n;
+ if(!f__init) f_init();
+ if(n=c_sue(a)) return(n);
+ f__reading=0;
+ f__reclen=0;
+ if(f__curunit->uwrt != 1 && f__nowwriting(f__curunit))
+ err(a->cierr, errno, "write start");
+ f__recloc=ftell(f__cf);
+ (void) fseek(f__cf,(long)sizeof(uiolen),SEEK_CUR);
+ return(0);
+}
+integer e_wsue(Void)
+{ long loc;
+ fwrite((char *)&f__reclen,sizeof(uiolen),1,f__cf);
+#ifdef ALWAYS_FLUSH
+ if (fflush(f__cf))
+ err(f__elist->cierr, errno, "write end");
+#endif
+ loc=ftell(f__cf);
+ fseek(f__cf,f__recloc,SEEK_SET);
+ fwrite((char *)&f__reclen,sizeof(uiolen),1,f__cf);
+ fseek(f__cf,loc,SEEK_SET);
+ return(0);
+}
+integer e_rsue(Void)
+{
+ (void) fseek(f__cf,(long)(f__reclen-f__recpos+sizeof(uiolen)),SEEK_CUR);
+ return(0);
+}
diff --git a/lib/libI77/typesize.c b/lib/libI77/typesize.c
new file mode 100644
index 0000000..1cb20ff
--- /dev/null
+++ b/lib/libI77/typesize.c
@@ -0,0 +1,12 @@
+#include "f2c.h"
+
+ftnlen f__typesize[] = { 0, 0, sizeof(shortint), sizeof(integer),
+ sizeof(real), sizeof(doublereal),
+ sizeof(complex), sizeof(doublecomplex),
+ sizeof(logical), sizeof(char),
+ 0, sizeof(integer1),
+ sizeof(logical1), sizeof(shortlogical),
+#ifdef Allow_TYQUAD
+ sizeof(longint),
+#endif
+ 0};
diff --git a/lib/libI77/uio.c b/lib/libI77/uio.c
new file mode 100644
index 0000000..e40875e
--- /dev/null
+++ b/lib/libI77/uio.c
@@ -0,0 +1,68 @@
+#include "f2c.h"
+#include "fio.h"
+uiolen f__reclen;
+
+#ifdef KR_headers
+do_us(number,ptr,len) ftnint *number; char *ptr; ftnlen len;
+#else
+do_us(ftnint *number, char *ptr, ftnlen len)
+#endif
+{
+ if(f__reading)
+ {
+ f__recpos += (int)(*number * len);
+ if(f__recpos>f__reclen)
+ err(f__elist->cierr, 110, "do_us");
+ if (fread(ptr,(int)len,(int)(*number),f__cf) != *number)
+ err(f__elist->ciend, EOF, "do_us");
+ return(0);
+ }
+ else
+ {
+ f__reclen += *number * len;
+ (void) fwrite(ptr,(int)len,(int)(*number),f__cf);
+ return(0);
+ }
+}
+#ifdef KR_headers
+integer do_ud(number,ptr,len) ftnint *number; char *ptr; ftnlen len;
+#else
+integer do_ud(ftnint *number, char *ptr, ftnlen len)
+#endif
+{
+ f__recpos += (int)(*number * len);
+ if(f__recpos > f__curunit->url && f__curunit->url!=1)
+ err(f__elist->cierr,110,"do_ud");
+ if(f__reading)
+ {
+#ifdef Pad_UDread
+#ifdef KR_headers
+ int i;
+#else
+ size_t i;
+#endif
+ if (!(i = fread(ptr,(int)len,(int)(*number),f__cf))
+ && !(f__recpos - *number*len))
+ err(f__elist->cierr,EOF,"do_ud")
+ if (i < *number)
+ memset(ptr + i*len, 0, (*number - i)*len);
+ return 0;
+#else
+ if(fread(ptr,(int)len,(int)(*number),f__cf) != *number)
+ err(f__elist->cierr,EOF,"do_ud")
+ else return(0);
+#endif
+ }
+ (void) fwrite(ptr,(int)len,(int)(*number),f__cf);
+ return(0);
+}
+#ifdef KR_headers
+integer do_uio(number,ptr,len) ftnint *number; char *ptr; ftnlen len;
+#else
+integer do_uio(ftnint *number, char *ptr, ftnlen len)
+#endif
+{
+ if(f__sequential)
+ return(do_us(number,ptr,len));
+ else return(do_ud(number,ptr,len));
+}
diff --git a/lib/libI77/util.c b/lib/libI77/util.c
new file mode 100644
index 0000000..5275499
--- /dev/null
+++ b/lib/libI77/util.c
@@ -0,0 +1,51 @@
+#ifndef NON_UNIX_STDIO
+#include "sys/types.h"
+#include "sys/stat.h"
+#endif
+#include "f2c.h"
+#include "fio.h"
+
+ VOID
+#ifdef KR_headers
+g_char(a,alen,b) char *a,*b; ftnlen alen;
+#else
+g_char(char *a, ftnlen alen, char *b)
+#endif
+{
+ char *x = a + alen, *y = b + alen;
+
+ for(;; y--) {
+ if (x <= a) {
+ *b = 0;
+ return;
+ }
+ if (*--x != ' ')
+ break;
+ }
+ *y-- = 0;
+ do *y-- = *x;
+ while(x-- > a);
+ }
+
+ VOID
+#ifdef KR_headers
+b_char(a,b,blen) char *a,*b; ftnlen blen;
+#else
+b_char(char *a, char *b, ftnlen blen)
+#endif
+{ int i;
+ for(i=0;i<blen && *a!=0;i++) *b++= *a++;
+ for(;i<blen;i++) *b++=' ';
+}
+#ifndef NON_UNIX_STDIO
+#ifdef KR_headers
+long f__inode(a, dev) char *a; int *dev;
+#else
+long f__inode(char *a, int *dev)
+#endif
+{ struct stat x;
+ if(stat(a,&x)<0) return(-1);
+ *dev = x.st_dev;
+ return(x.st_ino);
+}
+#endif
diff --git a/lib/libI77/wref.c b/lib/libI77/wref.c
new file mode 100644
index 0000000..5e4871d
--- /dev/null
+++ b/lib/libI77/wref.c
@@ -0,0 +1,275 @@
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+#include "fp.h"
+#ifndef VAX
+#include "ctype.h"
+#endif
+
+#ifndef KR_headers
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#include "string.h"
+#endif
+
+#ifdef KR_headers
+wrt_E(p,w,d,e,len) ufloat *p; ftnlen len;
+#else
+wrt_E(ufloat *p, int w, int d, int e, ftnlen len)
+#endif
+{
+ char buf[FMAX+EXPMAXDIGS+4], *s, *se;
+ int d1, delta, e1, i, sign, signspace;
+ double dd;
+#ifdef WANT_LEAD_0
+ int insert0 = 0;
+#endif
+#ifndef VAX
+ int e0 = e;
+#endif
+
+ if(e <= 0)
+ e = 2;
+ if(f__scale) {
+ if(f__scale >= d + 2 || f__scale <= -d)
+ goto nogood;
+ }
+ if(f__scale <= 0)
+ --d;
+ if (len == sizeof(real))
+ dd = p->pf;
+ else
+ dd = p->pd;
+ if (dd < 0.) {
+ signspace = sign = 1;
+ dd = -dd;
+ }
+ else {
+ sign = 0;
+ signspace = (int)f__cplus;
+#ifndef VAX
+ if (!dd)
+ dd = 0.; /* avoid -0 */
+#endif
+ }
+ delta = w - (2 /* for the . and the d adjustment above */
+ + 2 /* for the E+ */ + signspace + d + e);
+#ifdef WANT_LEAD_0
+ if (f__scale <= 0 && delta > 0) {
+ delta--;
+ insert0 = 1;
+ }
+ else
+#endif
+ if (delta < 0) {
+nogood:
+ while(--w >= 0)
+ PUT('*');
+ return(0);
+ }
+ if (f__scale < 0)
+ d += f__scale;
+ if (d > FMAX) {
+ d1 = d - FMAX;
+ d = FMAX;
+ }
+ else
+ d1 = 0;
+ sprintf(buf,"%#.*E", d, dd);
+#ifndef VAX
+ /* check for NaN, Infinity */
+ if (!isdigit(buf[0])) {
+ switch(buf[0]) {
+ case 'n':
+ case 'N':
+ signspace = 0; /* no sign for NaNs */
+ }
+ delta = w - strlen(buf) - signspace;
+ if (delta < 0)
+ goto nogood;
+ while(--delta >= 0)
+ PUT(' ');
+ if (signspace)
+ PUT(sign ? '-' : '+');
+ for(s = buf; *s; s++)
+ PUT(*s);
+ return 0;
+ }
+#endif
+ se = buf + d + 3;
+#ifdef GOOD_SPRINTF_EXPONENT /* When possible, exponent has 2 digits. */
+ if (f__scale != 1 && dd)
+ sprintf(se, "%+.2d", atoi(se) + 1 - f__scale);
+#else
+ if (dd)
+ sprintf(se, "%+.2d", atoi(se) + 1 - f__scale);
+ else
+ strcpy(se, "+00");
+#endif
+ s = ++se;
+ if (e < 2) {
+ if (*s != '0')
+ goto nogood;
+ }
+#ifndef VAX
+ /* accommodate 3 significant digits in exponent */
+ if (s[2]) {
+#ifdef Pedantic
+ if (!e0 && !s[3])
+ e1 = 2;/* for(s -= 2, e1 = 2; s[0] = s[1]; s++);
+
+ /* Pedantic gives the behavior that Fortran 77 specifies, */
+ /* i.e., requires that E be specified for exponent fields */
+ /* of more than 3 digits. With Pedantic undefined, we get */
+ /* the behavior that Cray displays -- you get a bigger */
+ /* exponent field if it fits. */
+#else
+ if (!e0) {
+ for(s -= 2, e1 = 2; s[0] = s[1]; s++)
+#ifdef CRAY
+ delta--;
+ if ((delta += 4) < 0)
+ goto nogood
+#endif
+ ;
+ }
+#endif
+ else if (e0 >= 0)
+ goto shift;
+ else
+ e1 = e;
+ }
+ else
+ shift:
+#endif
+ for(s += 2, e1 = 2; *s; ++e1, ++s)
+ if (e1 >= e)
+ goto nogood;
+ while(--delta >= 0)
+ PUT(' ');
+ if (signspace)
+ PUT(sign ? '-' : '+');
+ s = buf;
+ i = f__scale;
+ if (f__scale <= 0) {
+#ifdef WANT_LEAD_0
+ if (insert0)
+ PUT('0');
+#endif
+ PUT('.');
+ for(; i < 0; ++i)
+ PUT('0');
+ PUT(*s);
+ s += 2;
+ }
+ else if (f__scale > 1) {
+ PUT(*s);
+ s += 2;
+ while(--i > 0)
+ PUT(*s++);
+ PUT('.');
+ }
+ if (d1) {
+ se -= 2;
+ while(s < se) PUT(*s++);
+ se += 2;
+ do PUT('0'); while(--d1 > 0);
+ }
+ while(s < se)
+ PUT(*s++);
+ if (e < 2)
+ PUT(s[1]);
+ else {
+ while(++e1 <= e)
+ PUT('0');
+ while(*s)
+ PUT(*s++);
+ }
+ return 0;
+ }
+
+#ifdef KR_headers
+wrt_F(p,w,d,len) ufloat *p; ftnlen len;
+#else
+wrt_F(ufloat *p, int w, int d, ftnlen len)
+#endif
+{
+ int d1, sign, n;
+ double x;
+ char *b, buf[MAXINTDIGS+MAXFRACDIGS+4], *s;
+
+ x= (len==sizeof(real)?p->pf:p->pd);
+ if (d < MAXFRACDIGS)
+ d1 = 0;
+ else {
+ d1 = d - MAXFRACDIGS;
+ d = MAXFRACDIGS;
+ }
+ if (x < 0.)
+ { x = -x; sign = 1; }
+ else {
+ sign = 0;
+#ifndef VAX
+ if (!x)
+ x = 0.;
+#endif
+ }
+
+ if (n = f__scale)
+ if (n > 0)
+ do x *= 10.; while(--n > 0);
+ else
+ do x *= 0.1; while(++n < 0);
+
+#ifdef USE_STRLEN
+ sprintf(b = buf, "%#.*f", d, x);
+ n = strlen(b) + d1;
+#else
+ n = sprintf(b = buf, "%#.*f", d, x) + d1;
+#endif
+
+#ifndef WANT_LEAD_0
+ if (buf[0] == '0' && d)
+ { ++b; --n; }
+#endif
+ if (sign) {
+ /* check for all zeros */
+ for(s = b;;) {
+ while(*s == '0') s++;
+ switch(*s) {
+ case '.':
+ s++; continue;
+ case 0:
+ sign = 0;
+ }
+ break;
+ }
+ }
+ if (sign || f__cplus)
+ ++n;
+ if (n > w) {
+#ifdef WANT_LEAD_0
+ if (buf[0] == '0' && --n == w)
+ ++b;
+ else
+#endif
+ {
+ while(--w >= 0)
+ PUT('*');
+ return 0;
+ }
+ }
+ for(w -= n; --w >= 0; )
+ PUT(' ');
+ if (sign)
+ PUT('-');
+ else if (f__cplus)
+ PUT('+');
+ while(n = *b++)
+ PUT(n);
+ while(--d1 >= 0)
+ PUT('0');
+ return 0;
+ }
diff --git a/lib/libI77/wrtfmt.c b/lib/libI77/wrtfmt.c
new file mode 100644
index 0000000..f261ec3
--- /dev/null
+++ b/lib/libI77/wrtfmt.c
@@ -0,0 +1,387 @@
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+
+extern icilist *f__svic;
+extern char *f__icptr;
+
+ static int
+mv_cur(Void) /* shouldn't use fseek because it insists on calling fflush */
+ /* instead we know too much about stdio */
+{
+ int cursor = f__cursor;
+ f__cursor = 0;
+ if(f__external == 0) {
+ if(cursor < 0) {
+ if(f__hiwater < f__recpos)
+ f__hiwater = f__recpos;
+ f__recpos += cursor;
+ f__icptr += cursor;
+ if(f__recpos < 0)
+ err(f__elist->cierr, 110, "left off");
+ }
+ else if(cursor > 0) {
+ if(f__recpos + cursor >= f__svic->icirlen)
+ err(f__elist->cierr, 110, "recend");
+ if(f__hiwater <= f__recpos)
+ for(; cursor > 0; cursor--)
+ (*f__putn)(' ');
+ else if(f__hiwater <= f__recpos + cursor) {
+ cursor -= f__hiwater - f__recpos;
+ f__icptr += f__hiwater - f__recpos;
+ f__recpos = f__hiwater;
+ for(; cursor > 0; cursor--)
+ (*f__putn)(' ');
+ }
+ else {
+ f__icptr += cursor;
+ f__recpos += cursor;
+ }
+ }
+ return(0);
+ }
+ if(cursor > 0) {
+ if(f__hiwater <= f__recpos)
+ for(;cursor>0;cursor--) (*f__putn)(' ');
+ else if(f__hiwater <= f__recpos + cursor) {
+#ifndef NON_UNIX_STDIO
+ if(f__cf->_ptr + f__hiwater - f__recpos < buf_end(f__cf))
+ f__cf->_ptr += f__hiwater - f__recpos;
+ else
+#endif
+ (void) fseek(f__cf, (long) (f__hiwater - f__recpos), SEEK_CUR);
+ cursor -= f__hiwater - f__recpos;
+ f__recpos = f__hiwater;
+ for(; cursor > 0; cursor--)
+ (*f__putn)(' ');
+ }
+ else {
+#ifndef NON_UNIX_STDIO
+ if(f__cf->_ptr + cursor < buf_end(f__cf))
+ f__cf->_ptr += cursor;
+ else
+#endif
+ (void) fseek(f__cf, (long)cursor, SEEK_CUR);
+ f__recpos += cursor;
+ }
+ }
+ if(cursor<0)
+ {
+ if(cursor+f__recpos<0) err(f__elist->cierr,110,"left off");
+#ifndef NON_UNIX_STDIO
+ if(f__cf->_ptr + cursor >= f__cf->_base)
+ f__cf->_ptr += cursor;
+ else
+#endif
+ if(f__curunit && f__curunit->useek)
+ (void) fseek(f__cf,(long)cursor,SEEK_CUR);
+ else
+ err(f__elist->cierr,106,"fmt");
+ if(f__hiwater < f__recpos)
+ f__hiwater = f__recpos;
+ f__recpos += cursor;
+ }
+ return(0);
+}
+
+ static int
+#ifdef KR_headers
+wrt_Z(n,w,minlen,len) Uint *n; int w, minlen; ftnlen len;
+#else
+wrt_Z(Uint *n, int w, int minlen, ftnlen len)
+#endif
+{
+ register char *s, *se;
+ register int i, w1;
+ static int one = 1;
+ static char hex[] = "0123456789ABCDEF";
+ s = (char *)n;
+ --len;
+ if (*(char *)&one) {
+ /* little endian */
+ se = s;
+ s += len;
+ i = -1;
+ }
+ else {
+ se = s + len;
+ i = 1;
+ }
+ for(;; s += i)
+ if (s == se || *s)
+ break;
+ w1 = (i*(se-s) << 1) + 1;
+ if (*s & 0xf0)
+ w1++;
+ if (w1 > w)
+ for(i = 0; i < w; i++)
+ (*f__putn)('*');
+ else {
+ if ((minlen -= w1) > 0)
+ w1 += minlen;
+ while(--w >= w1)
+ (*f__putn)(' ');
+ while(--minlen >= 0)
+ (*f__putn)('0');
+ if (!(*s & 0xf0)) {
+ (*f__putn)(hex[*s & 0xf]);
+ if (s == se)
+ return 0;
+ s += i;
+ }
+ for(;; s += i) {
+ (*f__putn)(hex[*s >> 4 & 0xf]);
+ (*f__putn)(hex[*s & 0xf]);
+ if (s == se)
+ break;
+ }
+ }
+ return 0;
+ }
+
+ static int
+#ifdef KR_headers
+wrt_I(n,w,len, base) Uint *n; ftnlen len; register int base;
+#else
+wrt_I(Uint *n, int w, ftnlen len, register int base)
+#endif
+{ int ndigit,sign,spare,i;
+ longint x;
+ char *ans;
+ if(len==sizeof(integer)) x=n->il;
+ else if(len == sizeof(char)) x = n->ic;
+#ifdef Allow_TYQUAD
+ else if (len == sizeof(longint)) x = n->ili;
+#endif
+ else x=n->is;
+ ans=f__icvt(x,&ndigit,&sign, base);
+ spare=w-ndigit;
+ if(sign || f__cplus) spare--;
+ if(spare<0)
+ for(i=0;i<w;i++) (*f__putn)('*');
+ else
+ { for(i=0;i<spare;i++) (*f__putn)(' ');
+ if(sign) (*f__putn)('-');
+ else if(f__cplus) (*f__putn)('+');
+ for(i=0;i<ndigit;i++) (*f__putn)(*ans++);
+ }
+ return(0);
+}
+ static int
+#ifdef KR_headers
+wrt_IM(n,w,m,len,base) Uint *n; ftnlen len; int base;
+#else
+wrt_IM(Uint *n, int w, int m, ftnlen len, int base)
+#endif
+{ int ndigit,sign,spare,i,xsign;
+ longint x;
+ char *ans;
+ if(sizeof(integer)==len) x=n->il;
+ else if(len == sizeof(char)) x = n->ic;
+#ifdef Allow_TYQUAD
+ else if (len == sizeof(longint)) x = n->ili;
+#endif
+ else x=n->is;
+ ans=f__icvt(x,&ndigit,&sign, base);
+ if(sign || f__cplus) xsign=1;
+ else xsign=0;
+ if(ndigit+xsign>w || m+xsign>w)
+ { for(i=0;i<w;i++) (*f__putn)('*');
+ return(0);
+ }
+ if(x==0 && m==0)
+ { for(i=0;i<w;i++) (*f__putn)(' ');
+ return(0);
+ }
+ if(ndigit>=m)
+ spare=w-ndigit-xsign;
+ else
+ spare=w-m-xsign;
+ for(i=0;i<spare;i++) (*f__putn)(' ');
+ if(sign) (*f__putn)('-');
+ else if(f__cplus) (*f__putn)('+');
+ for(i=0;i<m-ndigit;i++) (*f__putn)('0');
+ for(i=0;i<ndigit;i++) (*f__putn)(*ans++);
+ return(0);
+}
+ static int
+#ifdef KR_headers
+wrt_AP(s) char *s;
+#else
+wrt_AP(char *s)
+#endif
+{ char quote;
+ int i;
+
+ if(f__cursor && (i = mv_cur()))
+ return i;
+ quote = *s++;
+ for(;*s;s++)
+ { if(*s!=quote) (*f__putn)(*s);
+ else if(*++s==quote) (*f__putn)(*s);
+ else return(1);
+ }
+ return(1);
+}
+ static int
+#ifdef KR_headers
+wrt_H(a,s) char *s;
+#else
+wrt_H(int a, char *s)
+#endif
+{
+ int i;
+
+ if(f__cursor && (i = mv_cur()))
+ return i;
+ while(a--) (*f__putn)(*s++);
+ return(1);
+}
+#ifdef KR_headers
+wrt_L(n,len, sz) Uint *n; ftnlen sz;
+#else
+wrt_L(Uint *n, int len, ftnlen sz)
+#endif
+{ int i;
+ long x;
+ if(sizeof(long)==sz) x=n->il;
+ else if(sz == sizeof(char)) x = n->ic;
+ else x=n->is;
+ for(i=0;i<len-1;i++)
+ (*f__putn)(' ');
+ if(x) (*f__putn)('T');
+ else (*f__putn)('F');
+ return(0);
+}
+ static int
+#ifdef KR_headers
+wrt_A(p,len) char *p; ftnlen len;
+#else
+wrt_A(char *p, ftnlen len)
+#endif
+{
+ while(len-- > 0) (*f__putn)(*p++);
+ return(0);
+}
+ static int
+#ifdef KR_headers
+wrt_AW(p,w,len) char * p; ftnlen len;
+#else
+wrt_AW(char * p, int w, ftnlen len)
+#endif
+{
+ while(w>len)
+ { w--;
+ (*f__putn)(' ');
+ }
+ while(w-- > 0)
+ (*f__putn)(*p++);
+ return(0);
+}
+
+ static int
+#ifdef KR_headers
+wrt_G(p,w,d,e,len) ufloat *p; ftnlen len;
+#else
+wrt_G(ufloat *p, int w, int d, int e, ftnlen len)
+#endif
+{ double up = 1,x;
+ int i=0,oldscale,n,j;
+ x = len==sizeof(real)?p->pf:p->pd;
+ if(x < 0 ) x = -x;
+ if(x<.1) {
+ if (x != 0.)
+ return(wrt_E(p,w,d,e,len));
+#ifdef WANT_LEAD_0
+ i = 1;
+#endif
+ goto have_i;
+ }
+ for(;i<=d;i++,up*=10)
+ { if(x>=up) continue;
+ have_i:
+ oldscale = f__scale;
+ f__scale = 0;
+ if(e==0) n=4;
+ else n=e+2;
+ i=wrt_F(p,w-n,d-i,len);
+ for(j=0;j<n;j++) (*f__putn)(' ');
+ f__scale=oldscale;
+ return(i);
+ }
+ return(wrt_E(p,w,d,e,len));
+}
+#ifdef KR_headers
+w_ed(p,ptr,len) struct syl *p; char *ptr; ftnlen len;
+#else
+w_ed(struct syl *p, char *ptr, ftnlen len)
+#endif
+{
+ int i;
+
+ if(f__cursor && (i = mv_cur()))
+ return i;
+ switch(p->op)
+ {
+ default:
+ fprintf(stderr,"w_ed, unexpected code: %d\n", p->op);
+ sig_die(f__fmtbuf, 1);
+ case I: return(wrt_I((Uint *)ptr,p->p1,len, 10));
+ case IM:
+ return(wrt_IM((Uint *)ptr,p->p1,p->p2,len,10));
+
+ /* O and OM don't work right for character, double, complex, */
+ /* or doublecomplex, and they differ from Fortran 90 in */
+ /* showing a minus sign for negative values. */
+
+ case O: return(wrt_I((Uint *)ptr, p->p1, len, 8));
+ case OM:
+ return(wrt_IM((Uint *)ptr,p->p1,p->p2,len,8));
+ case L: return(wrt_L((Uint *)ptr,p->p1, len));
+ case A: return(wrt_A(ptr,len));
+ case AW:
+ return(wrt_AW(ptr,p->p1,len));
+ case D:
+ case E:
+ case EE:
+ return(wrt_E((ufloat *)ptr,p->p1,p->p2,p->p3,len));
+ case G:
+ case GE:
+ return(wrt_G((ufloat *)ptr,p->p1,p->p2,p->p3,len));
+ case F: return(wrt_F((ufloat *)ptr,p->p1,p->p2,len));
+
+ /* Z and ZM assume 8-bit bytes. */
+
+ case Z: return(wrt_Z((Uint *)ptr,p->p1,0,len));
+ case ZM:
+ return(wrt_Z((Uint *)ptr,p->p1,p->p2,len));
+ }
+}
+#ifdef KR_headers
+w_ned(p) struct syl *p;
+#else
+w_ned(struct syl *p)
+#endif
+{
+ switch(p->op)
+ {
+ default: fprintf(stderr,"w_ned, unexpected code: %d\n", p->op);
+ sig_die(f__fmtbuf, 1);
+ case SLASH:
+ return((*f__donewrec)());
+ case T: f__cursor = p->p1-f__recpos - 1;
+ return(1);
+ case TL: f__cursor -= p->p1;
+ if(f__cursor < -f__recpos) /* TL1000, 1X */
+ f__cursor = -f__recpos;
+ return(1);
+ case TR:
+ case X:
+ f__cursor += p->p1;
+ return(1);
+ case APOS:
+ return(wrt_AP(*(char **)&p->p2));
+ case H:
+ return(wrt_H(p->p1,*(char **)&p->p2));
+ }
+}
diff --git a/lib/libI77/wsfe.c b/lib/libI77/wsfe.c
new file mode 100644
index 0000000..7c7f014
--- /dev/null
+++ b/lib/libI77/wsfe.c
@@ -0,0 +1,84 @@
+/*write sequential formatted external*/
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+extern int f__hiwater;
+
+#ifdef KR_headers
+x_putc(c)
+#else
+x_putc(int c)
+#endif
+{
+ /* this uses \n as an indicator of record-end */
+ if(c == '\n' && f__recpos < f__hiwater) { /* fseek calls fflush, a loss */
+#ifndef NON_UNIX_STDIO
+ if(f__cf->_ptr + f__hiwater - f__recpos < buf_end(f__cf))
+ f__cf->_ptr += f__hiwater - f__recpos;
+ else
+#endif
+ (void) fseek(f__cf, (long)(f__hiwater - f__recpos), SEEK_CUR);
+ }
+#ifdef OMIT_BLANK_CC
+ if (!f__recpos++ && c == ' ')
+ return c;
+#else
+ f__recpos++;
+#endif
+ return putc(c,f__cf);
+}
+x_wSL(Void)
+{
+ (*f__putn)('\n');
+ f__recpos=0;
+ f__cursor = 0;
+ f__hiwater = 0;
+ return(1);
+}
+xw_end(Void)
+{
+ if(f__nonl == 0)
+ (*f__putn)('\n');
+ f__hiwater = f__recpos = f__cursor = 0;
+ return(0);
+}
+xw_rev(Void)
+{
+ if(f__workdone) (*f__putn)('\n');
+ f__hiwater = f__recpos = f__cursor = 0;
+ return(f__workdone=0);
+}
+
+#ifdef KR_headers
+integer s_wsfe(a) cilist *a; /*start*/
+#else
+integer s_wsfe(cilist *a) /*start*/
+#endif
+{ int n;
+ if(!f__init) f_init();
+ if(n=c_sfe(a)) return(n);
+ f__reading=0;
+ f__sequential=1;
+ f__formatted=1;
+ f__external=1;
+ f__elist=a;
+ f__hiwater = f__cursor=f__recpos=0;
+ f__nonl = 0;
+ f__scale=0;
+ f__fmtbuf=a->cifmt;
+ f__curunit = &f__units[a->ciunit];
+ f__cf=f__curunit->ufd;
+ if(pars_f(f__fmtbuf)<0) err(a->cierr,100,"startio");
+ f__putn= x_putc;
+ f__doed= w_ed;
+ f__doned= w_ned;
+ f__doend=xw_end;
+ f__dorevert=xw_rev;
+ f__donewrec=x_wSL;
+ fmt_bg();
+ f__cplus=0;
+ f__cblank=f__curunit->ublnk;
+ if(f__curunit->uwrt != 1 && f__nowwriting(f__curunit))
+ err(a->cierr,errno,"write start");
+ return(0);
+}
diff --git a/lib/libI77/wsle.c b/lib/libI77/wsle.c
new file mode 100644
index 0000000..44b6972
--- /dev/null
+++ b/lib/libI77/wsle.c
@@ -0,0 +1,40 @@
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+#include "lio.h"
+
+#ifdef KR_headers
+integer s_wsle(a) cilist *a;
+#else
+integer s_wsle(cilist *a)
+#endif
+{
+ int n;
+ if(n=c_le(a)) return(n);
+ f__reading=0;
+ f__external=1;
+ f__formatted=1;
+ f__putn = t_putc;
+ f__lioproc = l_write;
+ L_len = LINE;
+ f__donewrec = x_wSL;
+ if(f__curunit->uwrt != 1 && f__nowwriting(f__curunit))
+ err(a->cierr, errno, "list output start");
+ return(0);
+ }
+
+integer e_wsle(Void)
+{
+ t_putc('\n');
+ f__recpos=0;
+#ifdef ALWAYS_FLUSH
+ if (fflush(f__cf))
+ err(f__elist->cierr, errno, "write end");
+#else
+ if (f__cf == stdout)
+ fflush(stdout);
+ else if (f__cf == stderr)
+ fflush(stderr);
+#endif
+ return(0);
+ }
diff --git a/lib/libI77/wsne.c b/lib/libI77/wsne.c
new file mode 100644
index 0000000..0febd52
--- /dev/null
+++ b/lib/libI77/wsne.c
@@ -0,0 +1,26 @@
+#include "f2c.h"
+#include "fio.h"
+#include "lio.h"
+
+ integer
+#ifdef KR_headers
+s_wsne(a) cilist *a;
+#else
+s_wsne(cilist *a)
+#endif
+{
+ int n;
+
+ if(n=c_le(a))
+ return(n);
+ f__reading=0;
+ f__external=1;
+ f__formatted=1;
+ f__putn = t_putc;
+ L_len = LINE;
+ f__donewrec = x_wSL;
+ if(f__curunit->uwrt != 1 && f__nowwriting(f__curunit))
+ err(a->cierr, errno, "namelist output start");
+ x_wsne(a);
+ return e_wsle();
+ }
diff --git a/lib/libI77/xwsne.c b/lib/libI77/xwsne.c
new file mode 100644
index 0000000..41c929b
--- /dev/null
+++ b/lib/libI77/xwsne.c
@@ -0,0 +1,72 @@
+#include "f2c.h"
+#include "fio.h"
+#include "lio.h"
+#include "fmt.h"
+
+extern int f__Aquote;
+
+ static VOID
+nl_donewrec(Void)
+{
+ (*f__donewrec)();
+ PUT(' ');
+ }
+
+#ifdef KR_headers
+x_wsne(a) cilist *a;
+#else
+#include "string.h"
+
+ VOID
+x_wsne(cilist *a)
+#endif
+{
+ Namelist *nl;
+ char *s;
+ Vardesc *v, **vd, **vde;
+ ftnint *number, type;
+ ftnlen *dims;
+ ftnlen size;
+ static ftnint one = 1;
+ extern ftnlen f__typesize[];
+
+ nl = (Namelist *)a->cifmt;
+ PUT('&');
+ for(s = nl->name; *s; s++)
+ PUT(*s);
+ PUT(' ');
+ f__Aquote = 1;
+ vd = nl->vars;
+ vde = vd + nl->nvars;
+ while(vd < vde) {
+ v = *vd++;
+ s = v->name;
+#ifdef No_Extra_Namelist_Newlines
+ if (f__recpos+strlen(s)+2 >= L_len)
+#endif
+ nl_donewrec();
+ while(*s)
+ PUT(*s++);
+ PUT(' ');
+ PUT('=');
+ number = (dims = v->dims) ? dims + 1 : &one;
+ type = v->type;
+ if (type < 0) {
+ size = -type;
+ type = TYCHAR;
+ }
+ else
+ size = f__typesize[type];
+ l_write(number, v->addr, size, type);
+ if (vd < vde) {
+ if (f__recpos+2 >= L_len)
+ nl_donewrec();
+ PUT(',');
+ PUT(' ');
+ }
+ else if (f__recpos+1 >= L_len)
+ nl_donewrec();
+ }
+ f__Aquote = 0;
+ PUT('/');
+ }
diff --git a/lib/libalias/Makefile b/lib/libalias/Makefile
new file mode 100644
index 0000000..6081e48
--- /dev/null
+++ b/lib/libalias/Makefile
@@ -0,0 +1,11 @@
+LIB= alias
+SHLIB_MAJOR= 2
+SHLIB_MINOR= 1
+CFLAGS+=-Wall -I${.CURDIR}
+SRCS= alias.c alias_db.c alias_ftp.c alias_irc.c alias_util.c
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/alias.h \
+ ${DESTDIR}/usr/include
+
+.include <bsd.lib.mk>
diff --git a/lib/libalias/alias.c b/lib/libalias/alias.c
new file mode 100644
index 0000000..1a9eb36
--- /dev/null
+++ b/lib/libalias/alias.c
@@ -0,0 +1,1142 @@
+/* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- */
+/*
+ Alias.c provides supervisory control for the functions of the
+ packet aliasing software. It consists of routines to monitor
+ TCP connection state, protocol-specific aliasing routines,
+ fragment handling and the following outside world functional
+ interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
+ PacketAliasIn and PacketAliasOut.
+
+ The other C program files are briefly described. The data
+ structure framework which holds information needed to translate
+ packets is encapsulated in alias_db.c. Data is accessed by
+ function calls, so other segments of the program need not know
+ about the underlying data structures. Alias_ftp.c contains
+ special code for modifying the ftp PORT command used to establish
+ data connections, while alias_irc.c do the same for IRC
+ DCC. Alias_util.c contains a few utility routines.
+
+ This software is placed into the public domain with no restrictions
+ on its distribution.
+
+ Version 1.0 August, 1996 (cjm)
+
+ Version 1.1 August 20, 1996 (cjm)
+ PPP host accepts incoming connections for ports 0 to 1023.
+ (Gary Roberts pointed out the need to handle incoming
+ connections.)
+
+ Version 1.2 September 7, 1996 (cjm)
+ Fragment handling error in alias_db.c corrected.
+ (Tom Torrance helped fix this problem.)
+
+ Version 1.4 September 16, 1996 (cjm)
+ - A more generalized method for handling incoming
+ connections, without the 0-1023 restriction, is
+ implemented in alias_db.c
+ - Improved ICMP support in alias.c. Traceroute
+ packet streams can now be correctly aliased.
+ - TCP connection closing logic simplified in
+ alias.c and now allows for additional 1 minute
+ "grace period" after FIN or RST is observed.
+
+ Version 1.5 September 17, 1996 (cjm)
+ Corrected error in handling incoming UDP packets with 0 checksum.
+ (Tom Torrance helped fix this problem.)
+
+ Version 1.6 September 18, 1996 (cjm)
+ Simplified ICMP aliasing scheme. Should now support
+ traceroute from Win95 as well as FreeBSD.
+
+ Version 1.7 January 9, 1997 (cjm)
+ - Out-of-order fragment handling.
+ - IP checksum error fixed for ftp transfers
+ from aliasing host.
+ - Integer return codes added to all
+ aliasing/de-aliasing functions.
+ - Some obsolete comments cleaned up.
+ - Differential checksum computations for
+ IP header (TCP, UDP and ICMP were already
+ differential).
+
+ Version 2.1 May 1997 (cjm)
+ - Added support for outgoing ICMP error
+ messages.
+ - Added two functions PacketAliasIn2()
+ and PacketAliasOut2() for dynamic address
+ control (e.g. round-robin allocation of
+ incoming packets).
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
+#include "alias_local.h"
+#include "alias.h"
+
+#define FTP_CONTROL_PORT_NUMBER 21
+#define IRC_CONTROL_PORT_NUMBER_1 6667
+#define IRC_CONTROL_PORT_NUMBER_2 6668
+
+/*
+ The following macro is used to update an
+ internet checksum. "delta" is a 32-bit
+ accumulation of all the changes to the
+ checksum (adding in new 16-bit words and
+ subtracting out old words), and "cksum"
+ is the checksum value to be updated.
+*/
+#define ADJUST_CHECKSUM(acc, cksum) { \
+ acc += cksum; \
+ if (acc < 0) \
+ { \
+ acc = -acc; \
+ acc = (acc >> 16) + (acc & 0xffff); \
+ acc += acc >> 16; \
+ cksum = (u_short) ~acc; \
+ } \
+ else \
+ { \
+ acc = (acc >> 16) + (acc & 0xffff); \
+ acc += acc >> 16; \
+ cksum = (u_short) acc; \
+ } \
+}
+
+
+
+
+/* TCP Handling Routines
+
+ TcpMonitorIn() -- These routines monitor TCP connections, and
+ TcpMonitorOut() -- delete a link node when a connection is closed.
+
+These routines look for SYN, ACK and RST flags to determine when TCP
+connections open and close. When a TCP connection closes, the data
+structure containing packet aliasing information is deleted after
+a timeout period.
+*/
+
+/* Local prototypes */
+static void TcpMonitorIn(struct ip *, struct alias_link *);
+
+static void TcpMonitorOut(struct ip *, struct alias_link *);
+
+
+static void
+TcpMonitorIn(struct ip *pip, struct alias_link *link)
+{
+ struct tcphdr *tc;
+
+ tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+ switch (GetStateIn(link))
+ {
+ case 0:
+ if (tc->th_flags & TH_SYN) SetStateIn(link, 1);
+ break;
+ case 1:
+ if (tc->th_flags & TH_FIN
+ || tc->th_flags & TH_RST) SetStateIn(link, 2);
+ }
+}
+
+static void
+TcpMonitorOut(struct ip *pip, struct alias_link *link)
+{
+ struct tcphdr *tc;
+
+ tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+ switch (GetStateOut(link))
+ {
+ case 0:
+ if (tc->th_flags & TH_SYN) SetStateOut(link, 1);
+ break;
+ case 1:
+ if (tc->th_flags & TH_FIN
+ || tc->th_flags & TH_RST) SetStateOut(link, 2);
+ }
+}
+
+
+
+
+
+/* Protocol Specific Packet Aliasing Routines
+
+ IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2(), IcmpAliasIn3()
+ IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2(), IcmpAliasOut3()
+ UdpAliasIn(), UdpAliasOut()
+ TcpAliasIn(), TcpAliasOut()
+
+These routines handle protocol specific details of packet aliasing.
+One may observe a certain amount of repetitive arithmetic in these
+functions, the purpose of which is to compute a revised checksum
+without actually summing over the entire data packet, which could be
+unnecessarily time consuming.
+
+The purpose of the packet aliasing routines is to replace the source
+address of the outgoing packet and then correctly put it back for
+any incoming packets. For TCP and UDP, ports are also re-mapped.
+
+For ICMP echo/timestamp requests and replies, the following scheme
+is used: the id number is replaced by an alias for the outgoing
+packet.
+
+ICMP error messages are handled by looking at the IP fragment
+in the data section of the message.
+
+For TCP and UDP protocols, a port number is chosen for an outgoing
+packet, and then incoming packets are identified by IP address and
+port numbers. For TCP packets, there is additional logic in the event
+that sequence and ack numbers have been altered (as is the case for
+FTP data port commands).
+
+The port numbers used by the packet aliasing module are not true
+ports in the Unix sense. No sockets are actually bound to ports.
+They are more correctly thought of as placeholders.
+
+All packets go through the aliasing mechanism, whether they come from
+the gateway machine or other machines on a local area network.
+*/
+
+
+/* Local prototypes */
+static int IcmpAliasIn1(struct ip *);
+static int IcmpAliasIn2(struct ip *);
+static int IcmpAliasIn3(struct ip *);
+static int IcmpAliasIn (struct ip *);
+
+static int IcmpAliasOut1(struct ip *);
+static int IcmpAliasOut2(struct ip *);
+static int IcmpAliasOut3(struct ip *);
+static int IcmpAliasOut (struct ip *);
+
+static int UdpAliasOut(struct ip *);
+static int UdpAliasIn (struct ip *);
+
+static int TcpAliasOut(struct ip *, int);
+static int TcpAliasIn (struct ip *);
+
+
+static int
+IcmpAliasIn1(struct ip *pip)
+{
+/*
+ De-alias incoming echo and timestamp replies
+*/
+ struct alias_link *link;
+ struct icmp *ic;
+
+ ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+
+/* Get source address from ICMP data field and restore original data */
+ link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id);
+ if (link != NULL)
+ {
+ u_short original_id;
+ int accumulate;
+
+ original_id = GetOriginalPort(link);
+
+/* Adjust ICMP checksum */
+ accumulate = ic->icmp_id;
+ accumulate -= original_id;
+ ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+
+/* Put original sequence number back in */
+ ic->icmp_id = original_id;
+
+/* Put original address back into IP header */
+ {
+ struct in_addr original_address;
+
+ original_address = GetOriginalAddress(link);
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &original_address,
+ (u_short *) &pip->ip_dst,
+ 2);
+ pip->ip_dst = original_address;
+ }
+
+ return(PKT_ALIAS_OK);
+ }
+ return(PKT_ALIAS_IGNORED);
+}
+
+static int
+IcmpAliasIn2(struct ip *pip)
+{
+/*
+ Alias incoming ICMP error messages containing
+ IP header and first 64 bits of datagram.
+*/
+ struct ip *ip;
+ struct icmp *ic, *ic2;
+ struct udphdr *ud;
+ struct tcphdr *tc;
+ struct alias_link *link;
+
+ ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+ ip = (struct ip *) ic->icmp_data;
+
+ ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
+ tc = (struct tcphdr *) ud;
+ ic2 = (struct icmp *) ud;
+
+ if (ip->ip_p == IPPROTO_UDP)
+ link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
+ ud->uh_dport, ud->uh_sport,
+ IPPROTO_UDP);
+ else if (ip->ip_p == IPPROTO_TCP)
+ link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
+ tc->th_dport, tc->th_sport,
+ IPPROTO_TCP);
+ else if (ip->ip_p == IPPROTO_ICMP)
+ if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
+ link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id);
+ else
+ link = NULL;
+ else
+ link = NULL;
+
+ if (link != NULL)
+ {
+ if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
+ {
+ u_short *sptr;
+ int accumulate;
+ struct in_addr original_address;
+ u_short original_port;
+
+ original_address = GetOriginalAddress(link);
+ original_port = GetOriginalPort(link);
+
+/* Adjust ICMP checksum */
+ sptr = (u_short *) &(ip->ip_src);
+ accumulate = *sptr++;
+ accumulate += *sptr;
+ sptr = (u_short *) &original_address;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+ accumulate += ud->uh_sport;
+ accumulate -= original_port;
+ ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+
+/* Un-alias address in IP header */
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &original_address,
+ (u_short *) &pip->ip_dst,
+ 2);
+ pip->ip_dst = original_address;
+
+/* Un-alias address and port number of original IP packet
+fragment contained in ICMP data section */
+ ip->ip_src = original_address;
+ ud->uh_sport = original_port;
+ }
+ else if (pip->ip_p == IPPROTO_ICMP)
+ {
+ u_short *sptr;
+ int accumulate;
+ struct in_addr original_address;
+ u_short original_id;
+
+ original_address = GetOriginalAddress(link);
+ original_id = GetOriginalPort(link);
+
+/* Adjust ICMP checksum */
+ sptr = (u_short *) &(ip->ip_src);
+ accumulate = *sptr++;
+ accumulate += *sptr;
+ sptr = (u_short *) &original_address;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+ accumulate += ic2->icmp_id;
+ accumulate -= original_id;
+ ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+
+/* Un-alias address in IP header */
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &original_address,
+ (u_short *) &pip->ip_dst,
+ 2);
+ pip->ip_dst = original_address;
+
+/* Un-alias address of original IP packet and seqence number of
+ embedded icmp datagram */
+ ip->ip_src = original_address;
+ ic2->icmp_id = original_id;
+ }
+ return(PKT_ALIAS_OK);
+ }
+ return(PKT_ALIAS_IGNORED);
+}
+
+
+static int
+IcmpAliasIn3(struct ip *pip)
+{
+ struct in_addr original_address;
+
+ original_address = FindOriginalAddress(pip->ip_dst);
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &original_address,
+ (u_short *) &pip->ip_dst,
+ 2);
+ pip->ip_dst = original_address;
+
+ return PKT_ALIAS_OK;
+}
+
+
+static int
+IcmpAliasIn(struct ip *pip)
+{
+ int iresult;
+ struct icmp *ic;
+
+ ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+
+ iresult = PKT_ALIAS_IGNORED;
+ switch (ic->icmp_type)
+ {
+ case ICMP_ECHOREPLY:
+ case ICMP_TSTAMPREPLY:
+ if (ic->icmp_code == 0)
+ {
+ iresult = IcmpAliasIn1(pip);
+ }
+ break;
+ case ICMP_UNREACH:
+ case ICMP_SOURCEQUENCH:
+ case ICMP_TIMXCEED:
+ case ICMP_PARAMPROB:
+ iresult = IcmpAliasIn2(pip);
+ break;
+ case ICMP_ECHO:
+ case ICMP_TSTAMP:
+ iresult = IcmpAliasIn3(pip);
+ break;
+ }
+ return(iresult);
+}
+
+
+static int
+IcmpAliasOut1(struct ip *pip)
+{
+/*
+ Alias ICMP echo and timestamp packets
+*/
+ struct alias_link *link;
+ struct icmp *ic;
+
+ ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+
+/* Save overwritten data for when echo packet returns */
+ link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id);
+ if (link != NULL)
+ {
+ u_short alias_id;
+ int accumulate;
+
+ alias_id = GetAliasPort(link);
+
+/* Since data field is being modified, adjust ICMP checksum */
+ accumulate = ic->icmp_id;
+ accumulate -= alias_id;
+ ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+
+/* Alias sequence number */
+ ic->icmp_id = alias_id;
+
+/* Change source address */
+ {
+ struct in_addr alias_address;
+
+ alias_address = GetAliasAddress(link);
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &alias_address,
+ (u_short *) &pip->ip_src,
+ 2);
+ pip->ip_src = alias_address;
+ }
+
+ return(PKT_ALIAS_OK);
+ }
+ return(PKT_ALIAS_IGNORED);
+}
+
+
+static int
+IcmpAliasOut2(struct ip *pip)
+{
+/*
+ Alias outgoing ICMP error messages containing
+ IP header and first 64 bits of datagram.
+*/
+ struct in_addr alias_addr;
+ struct ip *ip;
+ struct icmp *ic;
+
+ ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+ ip = (struct ip *) ic->icmp_data;
+
+ alias_addr = FindAliasAddress(ip->ip_src);
+
+/* Alias destination address in IP fragment */
+ DifferentialChecksum(&ic->icmp_cksum,
+ (u_short *) &alias_addr,
+ (u_short *) &ip->ip_dst,
+ 2);
+ ip->ip_dst = alias_addr;
+
+/* alias source address in IP header */
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &alias_addr,
+ (u_short *) &pip->ip_src,
+ 2);
+ pip->ip_src = alias_addr;
+
+ return PKT_ALIAS_OK;
+}
+
+
+static int
+IcmpAliasOut3(struct ip *pip)
+{
+/*
+ Handle outgoing echo and timestamp replies. The
+ only thing which is done in this case is to alias
+ the source IP address of the packet.
+*/
+ struct in_addr alias_addr;
+
+ alias_addr = FindAliasAddress(pip->ip_src);
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &alias_addr,
+ (u_short *) &pip->ip_src,
+ 2);
+ pip->ip_src = alias_addr;
+
+ return PKT_ALIAS_OK;
+}
+
+
+static int
+IcmpAliasOut(struct ip *pip)
+{
+ int iresult;
+ struct icmp *ic;
+
+ ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+
+ iresult = PKT_ALIAS_IGNORED;
+ switch (ic->icmp_type)
+ {
+ case ICMP_ECHO:
+ case ICMP_TSTAMP:
+ if (ic->icmp_code == 0)
+ {
+ iresult = IcmpAliasOut1(pip);
+ }
+ break;
+ case ICMP_UNREACH:
+ case ICMP_SOURCEQUENCH:
+ case ICMP_TIMXCEED:
+ case ICMP_PARAMPROB:
+ iresult = IcmpAliasOut2(pip);
+ break;
+ case ICMP_ECHOREPLY:
+ case ICMP_TSTAMPREPLY:
+ iresult = IcmpAliasOut3(pip);
+ }
+ return(iresult);
+}
+
+static int
+UdpAliasIn(struct ip *pip)
+{
+ struct udphdr *ud;
+ struct alias_link *link;
+
+ ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+ link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
+ ud->uh_sport, ud->uh_dport,
+ IPPROTO_UDP);
+ if (link != NULL)
+ {
+ struct in_addr alias_address;
+ struct in_addr original_address;
+ u_short alias_port;
+ int accumulate;
+ u_short *sptr;
+
+ alias_address = GetAliasAddress(link);
+ original_address = GetOriginalAddress(link);
+ alias_port = ud->uh_dport;
+ ud->uh_dport = GetOriginalPort(link);
+
+/* If UDP checksum is not zero, then adjust since destination port */
+/* is being unaliased and destination port is being altered. */
+ if (ud->uh_sum != 0)
+ {
+ accumulate = alias_port;
+ accumulate -= ud->uh_dport;
+ sptr = (u_short *) &alias_address;
+ accumulate += *sptr++;
+ accumulate += *sptr;
+ sptr = (u_short *) &original_address;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+ ADJUST_CHECKSUM(accumulate, ud->uh_sum)
+ }
+
+/* Restore original IP address */
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &original_address,
+ (u_short *) &pip->ip_dst,
+ 2);
+ pip->ip_dst = original_address;
+ return(PKT_ALIAS_OK);
+ }
+ return(PKT_ALIAS_IGNORED);
+}
+
+static int
+UdpAliasOut(struct ip *pip)
+{
+ struct udphdr *ud;
+ struct alias_link *link;
+
+ ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+ link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
+ ud->uh_sport, ud->uh_dport,
+ IPPROTO_UDP);
+ if (link != NULL)
+ {
+ u_short alias_port;
+ struct in_addr alias_address;
+
+ alias_address = GetAliasAddress(link);
+ alias_port = GetAliasPort(link);
+
+/* If UDP checksum is not zero, adjust since source port is */
+/* being aliased and source address is being altered */
+ if (ud->uh_sum != 0)
+ {
+ int accumulate;
+ u_short *sptr;
+
+ accumulate = ud->uh_sport;
+ accumulate -= alias_port;
+ sptr = (u_short *) &(pip->ip_src);
+ accumulate += *sptr++;
+ accumulate += *sptr;
+ sptr = (u_short *) &alias_address;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+ ADJUST_CHECKSUM(accumulate, ud->uh_sum)
+ }
+
+/* Put alias port in TCP header */
+ ud->uh_sport = alias_port;
+
+/* Change source address */
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &alias_address,
+ (u_short *) &pip->ip_src,
+ 2);
+ pip->ip_src = alias_address;
+
+ return(PKT_ALIAS_OK);
+ }
+ return(PKT_ALIAS_IGNORED);
+}
+
+
+
+static int
+TcpAliasIn(struct ip *pip)
+{
+ struct tcphdr *tc;
+ struct alias_link *link;
+
+ tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+ link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
+ tc->th_sport, tc->th_dport,
+ IPPROTO_TCP);
+ if (link != NULL)
+ {
+ struct in_addr alias_address;
+ struct in_addr original_address;
+ u_short alias_port;
+ int accumulate;
+ u_short *sptr;
+
+ alias_address = GetAliasAddress(link);
+ original_address = GetOriginalAddress(link);
+ alias_port = tc->th_dport;
+ tc->th_dport = GetOriginalPort(link);
+
+/* Adjust TCP checksum since destination port is being unaliased */
+/* and destination port is being altered. */
+ accumulate = alias_port;
+ accumulate -= tc->th_dport;
+ sptr = (u_short *) &alias_address;
+ accumulate += *sptr++;
+ accumulate += *sptr;
+ sptr = (u_short *) &original_address;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+
+/* See if ack number needs to be modified */
+ if (GetAckModified(link) == 1)
+ {
+ int delta;
+
+ delta = GetDeltaAckIn(pip, link);
+ if (delta != 0)
+ {
+ sptr = (u_short *) &tc->th_ack;
+ accumulate += *sptr++;
+ accumulate += *sptr;
+ tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
+ sptr = (u_short *) &tc->th_ack;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+ }
+ }
+
+ ADJUST_CHECKSUM(accumulate, tc->th_sum);
+
+/* Restore original IP address */
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &original_address,
+ (u_short *) &pip->ip_dst,
+ 2);
+ pip->ip_dst = original_address;
+
+/* Monitor TCP connection state */
+ TcpMonitorIn(pip, link);
+
+ return(PKT_ALIAS_OK);
+ }
+ return(PKT_ALIAS_IGNORED);
+}
+
+static int
+TcpAliasOut(struct ip *pip, int maxpacketsize)
+{
+ struct tcphdr *tc;
+ struct alias_link *link;
+
+ tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+ link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
+ tc->th_sport, tc->th_dport,
+ IPPROTO_TCP);
+ if (link !=NULL)
+ {
+ struct in_addr alias_address;
+ u_short alias_port;
+ int accumulate;
+ u_short *sptr;
+
+ alias_port = GetAliasPort(link);
+ alias_address = GetAliasAddress(link);
+
+/* Monitor tcp connection state */
+ TcpMonitorOut(pip, link);
+
+/* Special processing for ftp connection */
+ if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
+ || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
+ AliasHandleFtpOut(pip, link, maxpacketsize);
+ if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
+ || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
+ AliasHandleIrcOut(pip, link, maxpacketsize);
+
+/* Adjust TCP checksum since source port is being aliased */
+/* and source address is being altered */
+ accumulate = tc->th_sport;
+ accumulate -= alias_port;
+ sptr = (u_short *) &(pip->ip_src);
+ accumulate += *sptr++;
+ accumulate += *sptr;
+ sptr = (u_short *) &alias_address;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+
+/* Modify sequence number if necessary */
+ if (GetAckModified(link) == 1)
+ {
+ int delta;
+
+ delta = GetDeltaSeqOut(pip, link);
+ if (delta != 0)
+ {
+ sptr = (u_short *) &tc->th_seq;
+ accumulate += *sptr++;
+ accumulate += *sptr;
+ tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
+ sptr = (u_short *) &tc->th_seq;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+ }
+ }
+
+ ADJUST_CHECKSUM(accumulate, tc->th_sum)
+
+/* Put alias address in TCP header */
+ tc->th_sport = alias_port;
+
+/* Change source address */
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &alias_address,
+ (u_short *) &pip->ip_src,
+ 2);
+ pip->ip_src = alias_address;
+
+ return(PKT_ALIAS_OK);
+ }
+ return(PKT_ALIAS_IGNORED);
+}
+
+
+
+
+/* Fragment Handling
+
+ FragmentIn()
+ FragmentOut()
+
+The packet aliasing module has a limited ability for handling IP
+fragments. If the ICMP, TCP or UDP header is in the first fragment
+received, then the id number of the IP packet is saved, and other
+fragments are identified according to their ID number and IP address
+they were sent from. Pointers to unresolved fragments can also be
+saved and recalled when a header fragment is seen.
+*/
+
+/* Local prototypes */
+static int FragmentIn(struct ip *);
+static int FragmentOut(struct ip *);
+
+
+static int
+FragmentIn(struct ip *pip)
+{
+ struct alias_link *link;
+
+ link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
+ if (link != NULL)
+ {
+ struct in_addr original_address;
+
+ GetFragmentAddr(link, &original_address);
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &original_address,
+ (u_short *) &pip->ip_dst,
+ 2);
+ pip->ip_dst = original_address;
+
+ return(PKT_ALIAS_OK);
+ }
+ return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
+}
+
+
+static int
+FragmentOut(struct ip *pip)
+{
+ struct in_addr alias_address;
+
+ alias_address = FindAliasAddress(pip->ip_src);
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &alias_address,
+ (u_short *) &pip->ip_src,
+ 2);
+ pip->ip_src = alias_address;
+
+ return(PKT_ALIAS_OK);
+}
+
+
+
+
+
+
+/* Outside World Access
+
+ SaveFragmentPtr()
+ GetNextFragmentPtr()
+ FragmentAliasIn()
+ PacketAliasIn()
+ PacketAliasOut()
+ PacketAliasIn2()
+ PacketAliasOut2()
+
+(prototypes in alias.h)
+*/
+
+
+int
+SaveFragmentPtr(char *ptr)
+{
+ int iresult;
+ struct alias_link *link;
+ struct ip *pip;
+
+ pip = (struct ip *) ptr;
+ link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
+ iresult = PKT_ALIAS_ERROR;
+ if (link != NULL)
+ {
+ SetFragmentPtr(link, ptr);
+ iresult = PKT_ALIAS_OK;
+ }
+ return(iresult);
+}
+
+
+char *
+GetNextFragmentPtr(char *ptr)
+{
+ struct alias_link *link;
+ char *fptr;
+ struct ip *pip;
+
+ pip = (struct ip *) ptr;
+ link = FindFragmentPtr(pip->ip_src, pip->ip_id);
+ if (link != NULL)
+ {
+ GetFragmentPtr(link, &fptr);
+ SetExpire(link, 0); /* Deletes link */
+
+ return(fptr);
+ }
+ else
+ {
+ return(NULL);
+ }
+}
+
+
+void
+FragmentAliasIn(char *ptr, /* Points to correctly de-aliased
+ header fragment */
+ char *ptr_fragment /* Points to fragment which must
+ be de-aliased */
+ )
+{
+ struct ip *pip;
+ struct ip *fpip;
+
+ pip = (struct ip *) ptr;
+ fpip = (struct ip *) ptr_fragment;
+
+ DifferentialChecksum(&fpip->ip_sum,
+ (u_short *) &pip->ip_dst,
+ (u_short *) &fpip->ip_dst,
+ 2);
+ fpip->ip_dst = pip->ip_dst;
+}
+
+
+int
+PacketAliasIn(char *ptr, int maxpacketsize)
+{
+ struct in_addr alias_addr;
+ struct ip *pip;
+ int iresult;
+
+ HouseKeeping();
+ pip = (struct ip *) ptr;
+ alias_addr = pip->ip_dst;
+
+ iresult = PKT_ALIAS_IGNORED;
+ if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
+ {
+ switch (pip->ip_p)
+ {
+ case IPPROTO_ICMP:
+ iresult = IcmpAliasIn(pip);
+ break;
+ case IPPROTO_UDP:
+ iresult = UdpAliasIn(pip);
+ break;
+ case IPPROTO_TCP:
+ iresult = TcpAliasIn(pip);
+ break;
+ }
+
+ if (ntohs(pip->ip_off) & IP_MF)
+ {
+ struct alias_link *link;
+
+ link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
+ if (link != NULL)
+ {
+ iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
+ SetFragmentAddr(link, pip->ip_dst);
+ }
+ else
+ {
+ iresult = PKT_ALIAS_ERROR;
+ }
+ }
+ }
+ else
+ {
+ iresult = FragmentIn(pip);
+ }
+
+ return(iresult);
+}
+
+
+
+/* Unregistered address ranges */
+
+/* 10.0.0.0 -> 10.255.255.255 */
+#define UNREG_ADDR_A_LOWER 0x0a000000
+#define UNREG_ADDR_A_UPPER 0x0affffff
+
+/* 172.16.0.0 -> 172.31.255.255 */
+#define UNREG_ADDR_B_LOWER 0xac100000
+#define UNREG_ADDR_B_UPPER 0xac1fffff
+
+/* 192.168.0.0 -> 192.168.255.255 */
+#define UNREG_ADDR_C_LOWER 0xc0a80000
+#define UNREG_ADDR_C_UPPER 0xc0a8ffff
+
+
+
+int
+PacketAliasOut(char *ptr, /* valid IP packet */
+ int maxpacketsize /* How much the packet data may grow
+ (FTP and IRC inline changes) */
+ )
+{
+ int iresult;
+ struct in_addr addr_save;
+ struct ip *pip;
+
+ HouseKeeping();
+ pip = (struct ip *) ptr;
+
+ addr_save = GetDefaultAliasAddress();
+ if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
+ {
+ unsigned int addr;
+ int iclass;
+
+ iclass = 0;
+ addr = ntohl(pip->ip_src.s_addr);
+ if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
+ iclass = 3;
+ else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
+ iclass = 2;
+ else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
+ iclass = 1;
+
+ if (iclass == 0)
+ {
+ SetDefaultAliasAddress(pip->ip_src);
+ }
+ }
+
+ iresult = PKT_ALIAS_IGNORED;
+ if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
+ {
+ switch (pip->ip_p)
+ {
+ case IPPROTO_ICMP:
+ iresult = IcmpAliasOut(pip);
+ break;
+ case IPPROTO_UDP:
+ iresult = UdpAliasOut(pip);
+ break;
+ case IPPROTO_TCP:
+ iresult = TcpAliasOut(pip, maxpacketsize);
+ break;
+ }
+ }
+ else
+ {
+ iresult = FragmentOut(pip);
+ }
+
+ SetDefaultAliasAddress(addr_save);
+ return(iresult);
+}
+
+
+int
+PacketAliasIn2(char *ptr, /* valid IP packet */
+ struct in_addr addr, /* Default aliasing address */
+ int maxpacketsize /* How much the packet data may grow
+ (FTP and IRC inline changes) */
+ )
+{
+ int result_code;
+ struct in_addr addr_save;
+
+ ClearNewDefaultLink();
+ addr_save = GetDefaultAliasAddress();
+
+ SetDefaultTargetAddress(addr);
+ result_code = PacketAliasIn(ptr, maxpacketsize);
+ ClearDefaultTargetAddress();
+
+ if (result_code == PKT_ALIAS_OK)
+ {
+ if (CheckNewDefaultLink())
+ return PKT_ALIAS_NEW_LINK;
+ }
+
+ return result_code;
+}
+
+
+int
+PacketAliasOut2(char *ptr, /* valid IP packet */
+ struct in_addr addr, /* Default aliasing address */
+ int maxpacketsize /* How much the packet data may grow
+ (FTP and IRC inline changes) */
+ )
+{
+ int result_code;
+ struct in_addr addr_save;
+
+ ClearNewDefaultLink();
+ addr_save = GetDefaultAliasAddress();
+
+ SetDefaultAliasAddress(addr);
+ result_code = PacketAliasOut(ptr, maxpacketsize);
+ SetDefaultAliasAddress(addr_save);
+
+ if (result_code == PKT_ALIAS_OK)
+ {
+ if (CheckNewDefaultLink())
+ return PKT_ALIAS_NEW_LINK;
+ }
+
+ return result_code;
+}
diff --git a/lib/libalias/alias.h b/lib/libalias/alias.h
new file mode 100644
index 0000000..0063802
--- /dev/null
+++ b/lib/libalias/alias.h
@@ -0,0 +1,102 @@
+/*lint -save -library Flexelint comment for external headers */
+
+/*
+ Alias.h defines the outside world interfaces for the packet
+ aliasing software.
+
+ This software is placed into the public domain with no restrictions
+ on its distribution.
+*/
+
+
+#ifndef _ALIAS_H_
+#define _ALIAS_H_
+
+/* Alias link representativei (incomplete struct) */
+struct alias_link;
+
+/* External interfaces (API) to packet aliasing engine */
+extern int SaveFragmentPtr(char *);
+extern char *GetNextFragmentPtr(char *);
+extern void FragmentAliasIn(char *, char *);
+extern int PacketAliasIn(char *, int maxpacketsize);
+extern int PacketAliasOut(char *, int maxpacketsize);
+extern int PacketAliasIn2(char *, struct in_addr, int maxpacketsize);
+extern int PacketAliasOut2(char *, struct in_addr, int maxpacketsize);
+extern void SetPacketAliasAddress(struct in_addr);
+extern void InitPacketAlias(void);
+extern void InitPacketAliasLog(void);
+extern void UninitPacketAliasLog(void);
+extern unsigned int SetPacketAliasMode(unsigned int, unsigned int);
+extern struct alias_link *
+PacketAliasRedirectPort(struct in_addr, u_short,
+ struct in_addr, u_short,
+ struct in_addr, u_short,
+ u_char);
+extern int
+PacketAliasPermanentLink(struct in_addr, u_short,
+ struct in_addr, u_short,
+ u_short, u_char);
+extern struct alias_link *
+PacketAliasRedirectAddr(struct in_addr,
+ struct in_addr);
+void PacketAliasRedirectDelete(struct alias_link *);
+
+
+/* InternetChecksum() is not specifically part of the
+ packet aliasing API, but is sometimes needed outside
+ the module. (~for instance, natd uses it to create
+ an ICMP error message when interface size is
+ exceeded.) */
+
+extern u_short InternetChecksum(u_short *, int);
+
+
+/********************** Mode flags ********************/
+/* Set these flags using SetPacketAliasMode() */
+
+/* If PKT_ALIAS_LOG is set, a message will be printed to
+ /var/log/alias.log every time a link is created or deleted. This
+ is useful for debugging */
+#define PKT_ALIAS_LOG 1
+
+/* If PKT_ALIAS_DENY_INCOMING is set, then incoming connections (e.g.
+ to ftp, telnet or web servers will be prevented by the aliasing
+ mechanism. */
+#define PKT_ALIAS_DENY_INCOMING 2
+
+/* If PKT_ALIAS_SAME_PORTS is set, packets will be attempted sent from
+ the same port as they originated on. This allow eg rsh to work
+ *99% of the time*, but _not_ 100%. (It will be slightly flakey
+ instead of not working at all.) */
+#define PKT_ALIAS_SAME_PORTS 4
+
+/* If PKT_ALIAS_USE_SOCKETS is set, then when partially specified
+ links (e.g. destination port and/or address is zero), the packet
+ aliasing engine will attempt to allocate a socket for the aliasing
+ port it chooses. This will avoid interference with the host
+ machine. Fully specified links do not require this. */
+#define PKT_ALIAS_USE_SOCKETS 8
+
+/* If PKT_ALIAS_UNREGISTERED_ONLY is set, then only packets with with
+ unregistered source addresses will be aliased (along with those
+ of the ppp host maching itself. Private addresses are those
+ in the following ranges:
+
+ 10.0.0.0 -> 10.255.255.255
+ 172.16.0.0 -> 172.31.255.255
+ 192.168.0.0 -> 192.168.255.255 */
+#define PKT_ALIAS_UNREGISTERED_ONLY 16
+
+
+
+/* Return Codes */
+#define PKT_ALIAS_ERROR -1
+#define PKT_ALIAS_OK 1
+#define PKT_ALIAS_IGNORED 2
+#define PKT_ALIAS_UNRESOLVED_FRAGMENT 3
+#define PKT_ALIAS_FOUND_HEADER_FRAGMENT 4
+#define PKT_ALIAS_NEW_LINK 5
+
+#endif
+/*lint -restore */
diff --git a/lib/libalias/alias_db.c b/lib/libalias/alias_db.c
new file mode 100644
index 0000000..dafd9f8
--- /dev/null
+++ b/lib/libalias/alias_db.c
@@ -0,0 +1,1972 @@
+/* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*-
+ Alias_db.c encapsulates all data structures used for storing
+ packet aliasing data. Other parts of the aliasing software
+ access data through functions provided in this file.
+
+ Data storage is based on the notion of a "link", which is
+ established for ICMP echo/reply packets, UDP datagrams and
+ TCP stream connections. A link stores the original source
+ and destination addresses. For UDP and TCP, it also stores
+ source and destination port numbers, as well as an alias
+ port number. Links are also used to store information about
+ fragments.
+
+ There is a facility for sweeping through and deleting old
+ links as new packets are sent through. A simple timeout is
+ used for ICMP and UDP links. TCP links are left alone unless
+ there is an incomplete connection, in which case the link
+ can be deleted after a certain amount of time.
+
+
+ This software is placed into the public domain with no restrictions
+ on its distribution.
+
+ Initial version: August, 1996 (cjm)
+
+ Version 1.4: September 16, 1996 (cjm)
+ Facility for handling incoming links added.
+
+ Version 1.6: September 18, 1996 (cjm)
+ ICMP data handling simplified.
+
+ Version 1.7: January 9, 1997 (cjm)
+ Fragment handling simplified.
+ Saves pointers for unresolved fragments.
+ Permits links for unspecied remote ports
+ or unspecified remote addresses.
+ Fixed bug which did not properly zero port
+ table entries after a link was deleted.
+ Cleaned up some obsolete comments.
+
+ Version 1.8: January 14, 1997 (cjm)
+ Fixed data type error in StartPoint().
+ (This error did not exist prior to v1.7
+ and was discovered and fixed by Ari Suutari)
+
+ Version 1.9: February 1, 1997
+ Optionally, connections initiated from packet aliasing host
+ machine will will not have their port number aliased unless it
+ conflicts with an aliasing port already being used. (cjm)
+
+ All options earlier being #ifdef'ed now are available through
+ a new interface, SetPacketAliasMode(). This allow run time
+ control (which is now available in PPP+pktAlias through the
+ 'alias' keyword). (ee)
+
+ Added ability to create an alias port without
+ either destination address or port specified.
+ port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee)
+
+ Removed K&R style function headers
+ and general cleanup. (ee)
+
+ Added packetAliasMode to replace compiler #defines's (ee)
+
+ Allocates sockets for partially specified
+ ports if ALIAS_USE_SOCKETS defined. (cjm)
+
+ Version 2.0: March, 1997
+ SetAliasAddress() will now clean up alias links
+ if the aliasing address is changed. (cjm)
+
+ PacketAliasPermanentLink() function added to support permanent
+ links. (J. Fortes suggested the need for this.)
+ Examples:
+
+ (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
+
+ (192.168.0.2, port 21) <-> alias port 3604, known dest addr
+ unknown dest port
+
+ These permament links allow for incoming connections to
+ machines on the local network. They can be given with a
+ user-chosen amount of specificity, with increasing specificity
+ meaning more security. (cjm)
+
+ Quite a bit of rework to the basic engine. The portTable[]
+ array, which kept track of which ports were in use was replaced
+ by a table/linked list structure. (cjm)
+
+ SetExpire() function added. (cjm)
+
+ DeleteLink() no longer frees memory association with a pointer
+ to a fragment (this bug was first recognized by E. Eiklund in
+ v1.9).
+
+ Version 2.1: May, 1997 (cjm)
+ Packet aliasing engine reworked so that it can handle
+ multiple external addresses rather than just a single
+ host address.
+
+ PacketAliasRedirectPort() and PacketAliasRedirectAddr()
+ added to the API. The first function is a more generalized
+ version of PacketAliasPermanentLink(). The second function
+ implements static network address translation.
+*/
+
+
+/* System include files */
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+/* BSD network include files */
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include "alias.h"
+#include "alias_local.h"
+
+
+
+/*
+ Constants (note: constants are also defined
+ near relevant functions or structs)
+*/
+
+/* Sizes of input and output link tables */
+#define LINK_TABLE_OUT_SIZE 101
+#define LINK_TABLE_IN_SIZE 4001
+
+/* Parameters used for cleanup of expired links */
+#define ALIAS_CLEANUP_INTERVAL_SECS 60
+#define ALIAS_CLEANUP_MAX_SPOKES 30
+
+/* Timouts (in seconds) for different link types) */
+#define ICMP_EXPIRE_TIME 60
+#define UDP_EXPIRE_TIME 60
+#define TCP_EXPIRE_TIME 90
+#define FRAGMENT_ID_EXPIRE_TIME 10
+#define FRAGMENT_PTR_EXPIRE_TIME 30
+
+/* Dummy port number codes used for FindLinkIn/Out() and AddLink().
+ These constants can be anything except zero, which indicates an
+ unknown port numbea. */
+
+#define NO_DEST_PORT 1
+#define NO_SRC_PORT 1
+
+
+
+/* Data Structures
+
+ The fundamental data structure used in this program is
+ "struct alias_link". Whenever a TCP connection is made,
+ a UDP datagram is sent out, or an ICMP echo request is made,
+ a link record is made (if it has not already been created).
+ The link record is identified by the source address/port
+ and the destination address/port. In the case of an ICMP
+ echo request, the source port is treated as being equivalent
+ with the 16-bit id number of the ICMP packet.
+
+ The link record also can store some auxiliary data. For
+ TCP connections that have had sequence and acknowledgment
+ modifications, data space is available to track these changes.
+ A state field is used to keep track in changes to the tcp
+ connection state. Id numbers of fragments can also be
+ stored in the auxiliary space. Pointers to unresolved
+ framgents can also be stored.
+
+ The link records support two independent chainings. Lookup
+ tables for input and out tables hold the initial pointers
+ the link chains. On input, the lookup table indexes on alias
+ port and link type. On output, the lookup table indexes on
+ source addreess, destination address, source port, destination
+ port and link type.
+*/
+
+struct ack_data_record /* used to save changes to ack/seq numbers */
+{
+ u_long ack_old;
+ u_long ack_new;
+ int delta;
+ int active;
+};
+
+struct tcp_state /* Information about tcp connection */
+{
+ int in; /* State for outside -> inside */
+ int out; /* State for inside -> outside */
+ int index; /* Index to ack data array */
+ int ack_modified; /* Indicates whether ack and seq numbers */
+ /* been modified */
+};
+
+#define N_LINK_TCP_DATA 3 /* Number of distinct ack number changes
+ saved for a modified TCP stream */
+struct tcp_dat
+{
+ struct tcp_state state;
+ struct ack_data_record ack[N_LINK_TCP_DATA];
+};
+
+struct alias_link /* Main data structure */
+{
+ struct in_addr src_addr; /* Address and port information */
+ struct in_addr dst_addr; /* . */
+ struct in_addr alias_addr; /* . */
+ u_short src_port; /* . */
+ u_short dst_port; /* . */
+ u_short alias_port; /* . */
+
+ int link_type; /* Type of link: tcp, udp, icmp, frag */
+
+/* values for link_type */
+#define LINK_ICMP 1
+#define LINK_UDP 2
+#define LINK_TCP 3
+#define LINK_FRAGMENT_ID 4
+#define LINK_FRAGMENT_PTR 5
+#define LINK_ADDR 6
+
+ int flags; /* indicates special characteristics */
+
+/* flag bits */
+#define LINK_UNKNOWN_DEST_PORT 0x01
+#define LINK_UNKNOWN_DEST_ADDR 0x02
+#define LINK_PERMANENT 0x04
+#define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */
+
+ int timestamp; /* Time link was last accessed */
+ int expire_time; /* Expire time for link */
+
+ int sockfd; /* socket descriptor */
+
+ u_int start_point_out; /* Index number in output lookup table */
+ u_int start_point_in;
+ struct alias_link *next_out; /* Linked list pointers for input and */
+ struct alias_link *last_out; /* output tables */
+ struct alias_link *next_in; /* . */
+ struct alias_link *last_in; /* . */
+
+ union /* Auxiliary data */
+ {
+ struct in_addr frag_addr;
+ char *frag_ptr;
+ struct tcp_dat *tcp;
+ } data;
+};
+
+
+
+
+
+/* Global Variables
+
+ The global variables listed here are only accessed from
+ within alias_db.c and so are prefixed with the static
+ designation.
+*/
+
+int packetAliasMode; /* Mode flags */
+ /* - documented in alias.h */
+
+static struct in_addr aliasAddress; /* Address written onto source */
+ /* field of IP packet. */
+
+static struct in_addr targetAddress; /* IP address incoming packets */
+ /* are sent to if no aliasing */
+ /* link already exists */
+
+static struct in_addr nullAddress; /* Used as a dummy parameter for */
+ /* some function calls */
+static struct alias_link *
+linkTableOut[LINK_TABLE_OUT_SIZE]; /* Lookup table of pointers to */
+ /* chains of link records. Each */
+static struct alias_link * /* link record is doubly indexed */
+linkTableIn[LINK_TABLE_IN_SIZE]; /* into input and output lookup */
+ /* tables. */
+
+static int icmpLinkCount; /* Link statistics */
+static int udpLinkCount;
+static int tcpLinkCount;
+static int fragmentIdLinkCount;
+static int fragmentPtrLinkCount;
+static int sockCount;
+
+static int cleanupIndex; /* Index to chain of link table */
+ /* being inspected for old links */
+
+static int timeStamp; /* System time in seconds for */
+ /* current packet */
+
+static int lastCleanupTime; /* Last time IncrementalCleanup() */
+ /* was called */
+
+static int houseKeepingResidual; /* used by HouseKeeping() */
+
+static int deleteAllLinks; /* If equal to zero, DeleteLink() */
+ /* will not remove permanent links */
+
+static FILE *monitorFile; /* File descriptor for link */
+ /* statistics monitoring file */
+
+static int firstCall = 1; /* Needed by InitAlias() */
+
+static int newDefaultLink; /* Indicates if a new aliasing */
+ /* link has been created after a */
+ /* call to PacketAliasIn/Out(). */
+
+
+
+
+
+
+/* Internal utility routines (used only in alias_db.c)
+
+Lookup table starting points:
+ StartPointIn() -- link table initial search point for
+ outgoing packets
+ StartPointOut() -- port table initial search point for
+ incoming packets
+
+Miscellaneous:
+ SeqDiff() -- difference between two TCP sequences
+ ShowAliasStats() -- send alias statistics to a monitor file
+*/
+
+
+/* Local prototypes */
+static u_int StartPointIn(struct in_addr, u_short, int);
+
+static u_int StartPointOut(struct in_addr, struct in_addr,
+ u_short, u_short, int);
+
+static int SeqDiff(u_long, u_long);
+
+static void ShowAliasStats(void);
+
+
+static u_int
+StartPointIn(struct in_addr alias_addr,
+ u_short alias_port,
+ int link_type)
+{
+ u_int n;
+
+ n = alias_addr.s_addr;
+ n += alias_port;
+ n += link_type;
+ return(n % LINK_TABLE_IN_SIZE);
+}
+
+
+static u_int
+StartPointOut(struct in_addr src_addr, struct in_addr dst_addr,
+ u_short src_port, u_short dst_port, int link_type)
+{
+ u_int n;
+
+ n = src_addr.s_addr;
+ n += dst_addr.s_addr;
+ n += src_port;
+ n += dst_port;
+ n += link_type;
+
+ return(n % LINK_TABLE_OUT_SIZE);
+}
+
+
+static int
+SeqDiff(u_long x, u_long y)
+{
+/* Return the difference between two TCP sequence numbers */
+
+/*
+ This function is encapsulated in case there are any unusual
+ arithmetic conditions that need to be considered.
+*/
+
+ return (ntohl(y) - ntohl(x));
+}
+
+
+static void
+ShowAliasStats(void)
+{
+/* Used for debugging */
+
+ if (packetAliasMode & PKT_ALIAS_LOG)
+ {
+ fprintf(monitorFile, "icmp=%d, udp=%d, tcp=%d, frag_id=%d frag_ptr=%d",
+ icmpLinkCount,
+ udpLinkCount,
+ tcpLinkCount,
+ fragmentIdLinkCount,
+ fragmentPtrLinkCount);
+
+ fprintf(monitorFile, " / tot=%d (sock=%d)\n",
+ icmpLinkCount + udpLinkCount
+ + tcpLinkCount
+ + fragmentIdLinkCount
+ + fragmentPtrLinkCount,
+ sockCount);
+
+ fflush(monitorFile);
+ }
+}
+
+
+
+
+
+/* Internal routines for finding, deleting and adding links
+
+Port Allocation:
+ GetNewPort() -- find and reserve new alias port number
+ GetSocket() -- try to allocate a socket for a given port
+
+Link creation and deletion:
+ CleanupAliasData() - remove all link chains from lookup table
+ IncrementalCleanup() - look for stale links in a single chain
+ DeleteLink() - remove link
+ AddLink() - add link
+
+Link search:
+ FindLinkOut() - find link for outgoing packets
+ FindLinkIn() - find link for incoming packets
+*/
+
+/* Local prototypes */
+static int GetNewPort(struct alias_link *, int);
+
+static u_short GetSocket(u_short, int *, int);
+
+static void CleanupAliasData(void);
+
+static void IncrementalCleanup(void);
+
+static void DeleteLink(struct alias_link *);
+
+static struct alias_link *
+AddLink(struct in_addr, struct in_addr, struct in_addr,
+ u_short, u_short, int, int);
+
+static struct alias_link *
+FindLinkOut(struct in_addr, struct in_addr, u_short, u_short, int);
+
+static struct alias_link *
+FindLinkIn(struct in_addr, struct in_addr, u_short, u_short, int, int);
+
+
+#define ALIAS_PORT_BASE 0x08000
+#define ALIAS_PORT_MASK 0x07fff
+#define GET_NEW_PORT_MAX_ATTEMPTS 20
+
+#define GET_ALIAS_PORT -1
+#define GET_ALIAS_ID GET_ALIAS_PORT
+
+/* GetNewPort() allocates port numbers. Note that if a port number
+ is already in use, that does not mean that it cannot be used by
+ another link concurrently. This is because GetNewPort() looks for
+ unused triplets: (dest addr, dest port, alias port). */
+
+static int
+GetNewPort(struct alias_link *link, int alias_port_param)
+{
+ int i;
+ int max_trials;
+ u_short port_sys;
+ u_short port_net;
+
+/*
+ Description of alias_port_param for GetNewPort(). When
+ this parameter is zero or positive, it precisely specifies
+ the port number. GetNewPort() will return this number
+ without check that it is in use.
+
+ Whis this parameter is -1, it indicates to get a randomly
+ selected port number.
+*/
+
+ if (alias_port_param == GET_ALIAS_PORT)
+ {
+ /*
+ * The aliasing port is automatically selected
+ * by one of two methods below:
+ */
+ max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
+
+ if (packetAliasMode & PKT_ALIAS_SAME_PORTS)
+ {
+ /*
+ * When the ALIAS_SAME_PORTS option is
+ * chosen, the first try will be the
+ * actual source port. If this is already
+ * in use, the remainder of the trials
+ * will be random.
+ */
+ port_net = link->src_port;
+ port_sys = ntohs(port_net);
+ }
+ else
+ {
+ /* First trial and all subsequent are random. */
+ port_sys = random() & ALIAS_PORT_MASK;
+ port_sys += ALIAS_PORT_BASE;
+ port_net = htons(port_sys);
+ }
+ }
+ else if (alias_port_param >= 0 && alias_port_param < 0x10000)
+ {
+ link->alias_port = (u_short) alias_port_param;
+ return(0);
+ }
+ else
+ {
+ fprintf(stderr, "PacketAlias/GetNewPort(): ");
+ fprintf(stderr, "input parameter error\n");
+ return(-1);
+ }
+
+
+/* Port number search */
+ for (i=0; i<max_trials; i++)
+ {
+ int go_ahead;
+ struct alias_link *search_result;
+
+ search_result = FindLinkIn(link->dst_addr, link->alias_addr,
+ link->dst_port, port_net,
+ link->link_type, 0);
+
+ if (search_result == NULL)
+ go_ahead = 1;
+ else if (!(link->flags & LINK_PARTIALLY_SPECIFIED)
+ && (search_result->flags & LINK_PARTIALLY_SPECIFIED))
+ go_ahead = 1;
+ else
+ go_ahead = 0;
+
+ if (go_ahead)
+ {
+ if ((packetAliasMode && PKT_ALIAS_USE_SOCKETS)
+ && (link->flags & LINK_PARTIALLY_SPECIFIED))
+ {
+ if (GetSocket(port_net, &link->sockfd, link->link_type))
+ {
+ link->alias_port = port_net;
+ return(0);
+ }
+ }
+ else
+ {
+ link->alias_port = port_net;
+ return(0);
+ }
+ }
+
+ port_sys = random() & ALIAS_PORT_MASK;
+ port_sys += ALIAS_PORT_BASE;
+ port_net = htons(port_sys);
+ }
+
+ fprintf(stderr, "PacketAlias/GetnewPort(): ");
+ fprintf(stderr, "could not find free port\n");
+
+ return(-1);
+}
+
+
+static u_short
+GetSocket(u_short port_net, int *sockfd, int link_type)
+{
+ int err;
+ int sock;
+ struct sockaddr_in sock_addr;
+
+ if (link_type == LINK_TCP)
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ else if (link_type == LINK_UDP)
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ else
+ {
+ fprintf(stderr, "PacketAlias/GetSocket(): ");
+ fprintf(stderr, "incorrect link type\n");
+ return(0);
+ }
+
+ if (sock < 0)
+ {
+ fprintf(stderr, "PacketAlias/GetSocket(): ");
+ fprintf(stderr, "socket() error %d\n", *sockfd);
+ return(0);
+ }
+
+ sock_addr.sin_family = AF_INET;
+ sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ sock_addr.sin_port = port_net;
+
+ err = bind(sock,
+ (struct sockaddr *) &sock_addr,
+ sizeof(sock_addr));
+ if (err == 0)
+ {
+ sockCount++;
+ *sockfd = sock;
+ return(1);
+ }
+ else
+ {
+ return(0);
+ }
+}
+
+
+static void
+CleanupAliasData(void)
+{
+ struct alias_link *link;
+ int i, icount;
+
+ icount = 0;
+ for (i=0; i<LINK_TABLE_OUT_SIZE; i++)
+ {
+ link = linkTableOut[i];
+ linkTableOut[i] = NULL;
+ while (link != NULL)
+ {
+ struct alias_link *link_next;
+ link_next = link->next_out;
+ icount++;
+ DeleteLink(link);
+ link = link_next;
+ }
+ }
+
+ cleanupIndex =0;
+}
+
+
+static void
+IncrementalCleanup(void)
+{
+ int icount;
+ struct alias_link *link;
+
+ icount = 0;
+ link = linkTableOut[cleanupIndex++];
+ while (link != NULL)
+ {
+ int idelta;
+ struct alias_link *link_next;
+
+ link_next = link->next_out;
+ idelta = timeStamp - link->timestamp;
+ switch (link->link_type)
+ {
+ case LINK_ICMP:
+ case LINK_UDP:
+ case LINK_FRAGMENT_ID:
+ case LINK_FRAGMENT_PTR:
+ if (idelta > link->expire_time)
+ {
+ DeleteLink(link);
+ icount++;
+ }
+ break;
+ case LINK_TCP:
+ if (idelta > link->expire_time)
+ {
+ struct tcp_dat *tcp_aux;
+
+ tcp_aux = link->data.tcp;
+ if (tcp_aux->state.in != 1
+ || tcp_aux->state.out != 1)
+ {
+ DeleteLink(link);
+ icount++;
+ }
+ }
+ break;
+ }
+ link = link_next;
+ }
+
+ if (cleanupIndex == LINK_TABLE_OUT_SIZE)
+ cleanupIndex = 0;
+}
+
+void
+DeleteLink(struct alias_link *link)
+{
+ struct alias_link *link_last;
+ struct alias_link *link_next;
+
+/* Don't do anything if the link is marked permanent */
+ if (deleteAllLinks == 0 && link->flags & LINK_PERMANENT)
+ return;
+
+/* Adjust output table pointers */
+ link_last = link->last_out;
+ link_next = link->next_out;
+
+ if (link_last != NULL)
+ link_last->next_out = link_next;
+ else
+ linkTableOut[link->start_point_out] = link_next;
+
+ if (link_next != NULL)
+ link_next->last_out = link_last;
+
+/* Adjust input table pointers */
+ link_last = link->last_in;
+ link_next = link->next_in;
+
+ if (link_last != NULL)
+ link_last->next_in = link_next;
+ else
+ linkTableIn[link->start_point_in] = link_next;
+
+ if (link_next != NULL)
+ link_next->last_in = link_last;
+
+/* Close socket, if one has been allocated */
+ if (link->sockfd != -1)
+ {
+ sockCount--;
+ close(link->sockfd);
+ }
+
+/* Link-type dependent cleanup */
+ switch(link->link_type)
+ {
+ case LINK_ICMP:
+ icmpLinkCount--;
+ break;
+ case LINK_UDP:
+ udpLinkCount--;
+ break;
+ case LINK_TCP:
+ tcpLinkCount--;
+ if (link->data.tcp != NULL)
+ free(link->data.tcp);
+ break;
+ case LINK_FRAGMENT_ID:
+ fragmentIdLinkCount--;
+ break;
+ case LINK_FRAGMENT_PTR:
+ fragmentPtrLinkCount--;
+ break;
+ }
+
+/* Free memory */
+ free(link);
+
+/* Write statistics, if logging enabled */
+ if (packetAliasMode & PKT_ALIAS_LOG)
+ {
+ ShowAliasStats();
+ }
+}
+
+
+static struct alias_link *
+AddLink(struct in_addr src_addr,
+ struct in_addr dst_addr,
+ struct in_addr alias_addr,
+ u_short src_port,
+ u_short dst_port,
+ int alias_port_param, /* if less than zero, alias */
+ int link_type) /* port will be automatically */
+{ /* chosen. If greater than */
+ u_int start_point; /* zero, equal to alias port */
+ struct alias_link *link;
+ struct alias_link *first_link;
+
+ link = malloc(sizeof(struct alias_link));
+ if (link != NULL)
+ {
+ /* If either the aliasing address or source address are
+ equal to the default device address (equal to the
+ global variable aliasAddress), then set the alias
+ address field of the link record to zero */
+
+ if (src_addr.s_addr == aliasAddress.s_addr)
+ src_addr.s_addr = 0;
+
+ if (alias_addr.s_addr == aliasAddress.s_addr)
+ alias_addr.s_addr = 0;
+
+ /* Basic initialization */
+ link->src_addr = src_addr;
+ link->dst_addr = dst_addr;
+ link->src_port = src_port;
+ link->alias_addr = alias_addr;
+ link->dst_port = dst_port;
+ link->link_type = link_type;
+ link->sockfd = -1;
+ link->flags = 0;
+ link->timestamp = timeStamp;
+
+ /* Expiration time */
+ switch (link_type)
+ {
+ case LINK_ICMP:
+ link->expire_time = ICMP_EXPIRE_TIME;
+ break;
+ case LINK_UDP:
+ link->expire_time = UDP_EXPIRE_TIME;
+ break;
+ case LINK_TCP:
+ link->expire_time = TCP_EXPIRE_TIME;
+ break;
+ case LINK_FRAGMENT_ID:
+ link->expire_time = FRAGMENT_ID_EXPIRE_TIME;
+ break;
+ case LINK_FRAGMENT_PTR:
+ link->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
+ break;
+ }
+
+ /* Determine alias flags */
+ if (dst_addr.s_addr == 0)
+ link->flags |= LINK_UNKNOWN_DEST_ADDR;
+ if (dst_port == 0)
+ link->flags |= LINK_UNKNOWN_DEST_PORT;
+
+ /* Determine alias port */
+ if (GetNewPort(link, alias_port_param) != 0)
+ {
+ free(link);
+ return(NULL);
+ }
+
+ /* Set up pointers for output lookup table */
+ start_point = StartPointOut(src_addr, dst_addr,
+ src_port, dst_port, link_type);
+ first_link = linkTableOut[start_point];
+
+ link->last_out = NULL;
+ link->next_out = first_link;
+ link->start_point_out = start_point;
+
+ if (first_link != NULL)
+ first_link->last_out = link;
+
+ linkTableOut[start_point] = link;
+
+ /* Set up pointers for input lookup table */
+ start_point = StartPointIn(alias_addr, link->alias_port, link_type);
+ first_link = linkTableIn[start_point];
+
+ link->last_in = NULL;
+ link->next_in = first_link;
+ link->start_point_in = start_point;
+
+ if (first_link != NULL)
+ first_link->last_in = link;
+
+ linkTableIn[start_point] = link;
+
+ /* Link-type dependent initialization */
+ switch(link_type)
+ {
+ struct tcp_dat *aux_tcp;
+
+ case LINK_ICMP:
+ icmpLinkCount++;
+ break;
+ case LINK_UDP:
+ udpLinkCount++;
+ break;
+ case LINK_TCP:
+ aux_tcp = malloc(sizeof(struct tcp_dat));
+ link->data.tcp = aux_tcp;
+ if (aux_tcp != NULL)
+ {
+ int i;
+
+ tcpLinkCount++;
+ aux_tcp->state.in = 0;
+ aux_tcp->state.out = 0;
+ aux_tcp->state.index = 0;
+ aux_tcp->state.ack_modified = 0;
+ for (i=0; i<N_LINK_TCP_DATA; i++)
+ aux_tcp->ack[i].active = 0;
+ }
+ else
+ {
+ fprintf(stderr, "PacketAlias/AddLink: ");
+ fprintf(stderr, " cannot allocate auxiliary TCP data\n");
+ }
+ break;
+ case LINK_FRAGMENT_ID:
+ fragmentIdLinkCount++;
+ break;
+ case LINK_FRAGMENT_PTR:
+ fragmentPtrLinkCount++;
+ break;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "PacketAlias/AddLink(): ");
+ fprintf(stderr, "malloc() call failed.\n");
+ }
+
+ if (packetAliasMode & PKT_ALIAS_LOG)
+ {
+ ShowAliasStats();
+ }
+
+ return(link);
+}
+
+
+static struct alias_link *
+FindLinkOut(struct in_addr src_addr,
+ struct in_addr dst_addr,
+ u_short src_port,
+ u_short dst_port,
+ int link_type)
+{
+ u_int i;
+ struct alias_link *link;
+
+ if (src_addr.s_addr == aliasAddress.s_addr)
+ src_addr.s_addr = 0;
+
+ i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
+ link = linkTableOut[i];
+ while (link != NULL)
+ {
+ if (link->src_addr.s_addr == src_addr.s_addr
+ && link->dst_addr.s_addr == dst_addr.s_addr
+ && link->dst_port == dst_port
+ && link->src_port == src_port
+ && link->link_type == link_type)
+ {
+ link->timestamp = timeStamp;
+ break;
+ }
+ link = link->next_out;
+ }
+
+ return(link);
+}
+
+
+struct alias_link *
+FindLinkIn(struct in_addr dst_addr,
+ struct in_addr alias_addr,
+ u_short dst_port,
+ u_short alias_port,
+ int link_type,
+ int replace_partial_links)
+{
+ int flags_in;
+ u_int start_point;
+ struct alias_link *link;
+ struct alias_link *link_fully_specified;
+ struct alias_link *link_unknown_all;
+ struct alias_link *link_unknown_dst_addr;
+ struct alias_link *link_unknown_dst_port;
+
+/* Initialize pointers */
+ link_fully_specified = NULL;
+ link_unknown_all = NULL;
+ link_unknown_dst_addr = NULL;
+ link_unknown_dst_port = NULL;
+
+/* If either the dest addr or port is unknown, the search
+ loop will have to know about this. */
+
+ flags_in = 0;
+ if (dst_addr.s_addr == 0)
+ flags_in |= LINK_UNKNOWN_DEST_ADDR;
+ if (dst_port == 0)
+ flags_in |= LINK_UNKNOWN_DEST_PORT;
+
+/* The following allows permanent links to be
+ be specified as using the default aliasing address
+ (i.e. device interface address) without knowing
+ in advance what that address is. */
+
+ if (alias_addr.s_addr == aliasAddress.s_addr)
+ alias_addr.s_addr = 0;
+
+/* Search loop */
+ start_point = StartPointIn(alias_addr, alias_port, link_type);
+ link = linkTableIn[start_point];
+ while (link != NULL)
+ {
+ int flags;
+
+ flags = flags_in | link->flags;
+ if (!(flags & LINK_PARTIALLY_SPECIFIED))
+ {
+ if (link->alias_addr.s_addr == alias_addr.s_addr
+ && link->alias_port == alias_port
+ && link->dst_addr.s_addr == dst_addr.s_addr
+ && link->dst_port == dst_port
+ && link->link_type == link_type)
+ {
+ link_fully_specified = link;
+ break;
+ }
+ }
+ else if ((flags & LINK_UNKNOWN_DEST_ADDR)
+ && (flags & LINK_UNKNOWN_DEST_PORT))
+ {
+ if (link->alias_addr.s_addr == alias_addr.s_addr
+ && link->alias_port == alias_port
+ && link->link_type == link_type)
+ {
+ if (link_unknown_all == NULL)
+ link_unknown_all = link;
+ }
+ }
+ else if (flags & LINK_UNKNOWN_DEST_ADDR)
+ {
+ if (link->alias_addr.s_addr == alias_addr.s_addr
+ && link->alias_port == alias_port
+ && link->link_type == link_type
+ && link->dst_port == dst_port)
+ {
+ if (link_unknown_dst_addr == NULL)
+ link_unknown_dst_addr = link;
+ }
+ }
+ else if (flags & LINK_UNKNOWN_DEST_PORT)
+ {
+ if (link->alias_addr.s_addr == alias_addr.s_addr
+ && link->alias_port == alias_port
+ && link->link_type == link_type
+ && link->dst_addr.s_addr == dst_addr.s_addr)
+ {
+ if (link_unknown_dst_port == NULL)
+ link_unknown_dst_port = link;
+ }
+ }
+ link = link->next_in;
+ }
+
+
+
+ if (link_fully_specified != NULL)
+ {
+ return (link_fully_specified);
+ }
+ else if (link_unknown_dst_port != NULL)
+ {
+ if (replace_partial_links)
+ {
+ link = AddLink(link_unknown_dst_port->src_addr, dst_addr,
+ alias_addr,
+ link_unknown_dst_port->src_port, dst_port,
+ alias_port, link_type);
+ DeleteLink(link_unknown_dst_port);
+ return(link);
+ }
+ else
+ {
+ return(link_unknown_dst_port);
+ }
+ }
+ else if (link_unknown_dst_addr != NULL)
+ {
+ if (replace_partial_links)
+ {
+ link = AddLink(link_unknown_dst_addr->src_addr, dst_addr,
+ alias_addr,
+ link_unknown_dst_addr->src_port, dst_port,
+ alias_port, link_type);
+ DeleteLink(link_unknown_dst_addr);
+ return(link);
+ }
+ else
+ {
+ return(link_unknown_dst_addr);
+ }
+ }
+ else if (link_unknown_all != NULL)
+ {
+ if (replace_partial_links)
+ {
+ link = AddLink(link_unknown_all->src_addr, dst_addr,
+ alias_addr,
+ link_unknown_all->src_port, dst_port,
+ alias_port, link_type);
+ DeleteLink(link_unknown_all);
+ return(link);
+ }
+ else
+ {
+ return(link_unknown_all);
+ }
+ }
+ else
+ {
+ return(NULL);
+ }
+}
+
+
+
+
+/* External routines for finding/adding links
+
+-- "external" means outside alias_db.c, but within alias*.c --
+
+ FindIcmpIn(), FindIcmpOut()
+ FindFragmentIn1(), FindFragmentIn2()
+ AddFragmentPtrLink(), FindFragmentPtr()
+ FindUdpTcpIn(), FindUdpTcpOut()
+ FindOriginalAddress(), FindAliasAddress()
+
+(prototypes in alias_local.h)
+*/
+
+
+struct alias_link *
+FindIcmpIn(struct in_addr dst_addr,
+ struct in_addr alias_addr,
+ u_short id_alias)
+{
+ return FindLinkIn(dst_addr, alias_addr,
+ NO_DEST_PORT, id_alias,
+ LINK_ICMP, 0);
+}
+
+
+struct alias_link *
+FindIcmpOut(struct in_addr src_addr,
+ struct in_addr dst_addr,
+ u_short id)
+{
+ struct alias_link * link;
+
+ link = FindLinkOut(src_addr, dst_addr,
+ id, NO_DEST_PORT,
+ LINK_ICMP);
+ if (link == NULL)
+ {
+ struct in_addr alias_addr;
+
+ alias_addr = FindAliasAddress(src_addr);
+ link = AddLink(src_addr, dst_addr, alias_addr,
+ id, NO_DEST_PORT, GET_ALIAS_ID,
+ LINK_ICMP);
+ }
+
+ return(link);
+}
+
+
+struct alias_link *
+FindFragmentIn1(struct in_addr dst_addr,
+ struct in_addr alias_addr,
+ u_short ip_id)
+{
+ struct alias_link *link;
+
+ link = FindLinkIn(dst_addr, alias_addr,
+ NO_DEST_PORT, ip_id,
+ LINK_FRAGMENT_ID, 0);
+
+ if (link == NULL)
+ {
+ link = AddLink(nullAddress, dst_addr, alias_addr,
+ NO_SRC_PORT, NO_DEST_PORT, ip_id,
+ LINK_FRAGMENT_ID);
+ }
+
+ return(link);
+}
+
+
+struct alias_link *
+FindFragmentIn2(struct in_addr dst_addr, /* Doesn't add a link if one */
+ struct in_addr alias_addr, /* is not found. */
+ u_short ip_id)
+{
+ return FindLinkIn(dst_addr, alias_addr,
+ NO_DEST_PORT, ip_id,
+ LINK_FRAGMENT_ID, 0);
+}
+
+
+struct alias_link *
+AddFragmentPtrLink(struct in_addr dst_addr,
+ u_short ip_id)
+{
+ return AddLink(nullAddress, dst_addr, nullAddress,
+ NO_SRC_PORT, NO_DEST_PORT, ip_id,
+ LINK_FRAGMENT_PTR);
+}
+
+
+struct alias_link *
+FindFragmentPtr(struct in_addr dst_addr,
+ u_short ip_id)
+{
+ return FindLinkIn(dst_addr, nullAddress,
+ NO_DEST_PORT, ip_id,
+ LINK_FRAGMENT_PTR, 0);
+}
+
+
+struct alias_link *
+FindUdpTcpIn(struct in_addr dst_addr,
+ struct in_addr alias_addr,
+ u_short dst_port,
+ u_short alias_port,
+ u_char proto)
+{
+ int link_type;
+ struct alias_link *link;
+
+ switch (proto)
+ {
+ case IPPROTO_UDP:
+ link_type = LINK_UDP;
+ break;
+ case IPPROTO_TCP:
+ link_type = LINK_TCP;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+
+ link = FindLinkIn(dst_addr, alias_addr,
+ dst_port, alias_port,
+ link_type, 1);
+
+ if ( !(packetAliasMode & PKT_ALIAS_DENY_INCOMING) && link == NULL)
+ {
+ struct in_addr target_addr;
+
+ target_addr = FindOriginalAddress(alias_addr);
+ link = AddLink(target_addr, dst_addr, alias_addr,
+ alias_port, dst_port, alias_port,
+ link_type);
+ }
+
+ return(link);
+}
+
+
+struct alias_link *
+FindUdpTcpOut(struct in_addr src_addr,
+ struct in_addr dst_addr,
+ u_short src_port,
+ u_short dst_port,
+ u_char proto)
+{
+ int link_type;
+ struct alias_link *link;
+
+ switch (proto)
+ {
+ case IPPROTO_UDP:
+ link_type = LINK_UDP;
+ break;
+ case IPPROTO_TCP:
+ link_type = LINK_TCP;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+
+ link = FindLinkOut(src_addr, dst_addr, src_port, dst_port, link_type);
+
+ if (link == NULL)
+ {
+ struct in_addr alias_addr;
+
+ alias_addr = FindAliasAddress(src_addr);
+ link = AddLink(src_addr, dst_addr, alias_addr,
+ src_port, dst_port, GET_ALIAS_PORT,
+ link_type);
+ }
+
+ return(link);
+}
+
+
+struct in_addr
+FindOriginalAddress(struct in_addr alias_addr)
+{
+ struct alias_link *link;
+
+ link = FindLinkIn(nullAddress, alias_addr,
+ 0, 0, LINK_ADDR, 0);
+ if (link == NULL)
+ {
+ newDefaultLink = 1;
+ if (targetAddress.s_addr != 0)
+ return targetAddress;
+ else
+ return alias_addr;
+ }
+ else
+ {
+ if (link->src_addr.s_addr == 0)
+ return aliasAddress;
+ else
+ return link->src_addr;
+ }
+}
+
+
+struct in_addr
+FindAliasAddress(struct in_addr original_addr)
+{
+ struct alias_link *link;
+
+ link = FindLinkOut(original_addr, nullAddress,
+ 0, 0, LINK_ADDR);
+ if (link == NULL)
+ {
+ return aliasAddress;
+ }
+ else
+ {
+ if (link->alias_addr.s_addr == 0)
+ return aliasAddress;
+ else
+ return link->alias_addr;
+ }
+}
+
+
+/* External routines for getting or changing link data
+ (external to alias_db.c, but internal to alias*.c)
+
+ SetFragmentData(), GetFragmentData()
+ SetFragmentPtr(), GetFragmentPtr()
+ SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
+ GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
+ GetOriginalPort(), GetAliasPort()
+ SetAckModified(), GetAckModified()
+ GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
+ ClearNewLink()
+ CheckNewLink()
+*/
+
+
+void
+SetFragmentAddr(struct alias_link *link, struct in_addr src_addr)
+{
+ link->data.frag_addr = src_addr;
+}
+
+
+void
+GetFragmentAddr(struct alias_link *link, struct in_addr *src_addr)
+{
+ *src_addr = link->data.frag_addr;
+}
+
+
+void
+SetFragmentPtr(struct alias_link *link, char *fptr)
+{
+ link->data.frag_ptr = fptr;
+}
+
+
+void
+GetFragmentPtr(struct alias_link *link, char **fptr)
+{
+ *fptr = link->data.frag_ptr;
+}
+
+
+void
+SetStateIn(struct alias_link *link, int state)
+{
+ /* TCP input state */
+ (link->data.tcp)->state.in = state;
+}
+
+
+void
+SetStateOut(struct alias_link *link, int state)
+{
+ /* TCP output state */
+ (link->data.tcp)->state.out = state;
+}
+
+
+int
+GetStateIn(struct alias_link *link)
+{
+ /* TCP input state */
+ return( (link->data.tcp)->state.in);
+}
+
+
+int
+GetStateOut(struct alias_link *link)
+{
+ /* TCP output state */
+ return( (link->data.tcp)->state.out);
+}
+
+
+struct in_addr
+GetOriginalAddress(struct alias_link *link)
+{
+ if (link->src_addr.s_addr == 0)
+ return aliasAddress;
+ else
+ return(link->src_addr);
+}
+
+
+struct in_addr
+GetDestAddress(struct alias_link *link)
+{
+ return(link->dst_addr);
+}
+
+
+struct in_addr
+GetAliasAddress(struct alias_link *link)
+{
+ if (link->alias_addr.s_addr == 0)
+ return aliasAddress;
+ else
+ return link->alias_addr;
+}
+
+
+struct in_addr
+GetDefaultAliasAddress()
+{
+ return aliasAddress;
+}
+
+
+void
+SetDefaultAliasAddress(struct in_addr alias_addr)
+{
+ aliasAddress = alias_addr;
+}
+
+
+void
+SetDefaultTargetAddress(struct in_addr target_addr)
+{
+ targetAddress = target_addr;
+}
+
+
+void ClearDefaultTargetAddress(void)
+{
+ targetAddress.s_addr = 0;
+}
+
+
+u_short
+GetOriginalPort(struct alias_link *link)
+{
+ return(link->src_port);
+}
+
+
+u_short
+GetAliasPort(struct alias_link *link)
+{
+ return(link->alias_port);
+}
+
+
+void
+SetAckModified(struct alias_link *link)
+{
+/* Indicate that ack numbers have been modified in a TCP connection */
+ (link->data.tcp)->state.ack_modified = 1;
+}
+
+
+int
+GetAckModified(struct alias_link *link)
+{
+/* See if ack numbers have been modified */
+ return( (link->data.tcp)->state.ack_modified );
+}
+
+
+int
+GetDeltaAckIn(struct ip *pip, struct alias_link *link)
+{
+/*
+Find out how much the ack number has been altered for an incoming
+TCP packet. To do this, a circular list is ack numbers where the TCP
+packet size was altered is searched.
+*/
+
+ int i;
+ struct tcphdr *tc;
+ int delta, ack_diff_min;
+ u_long ack;
+
+ tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+ ack = tc->th_ack;
+
+ delta = 0;
+ ack_diff_min = -1;
+ for (i=0; i<N_LINK_TCP_DATA; i++)
+ {
+ struct ack_data_record x;
+
+ x = (link->data.tcp)->ack[i];
+ if (x.active == 1)
+ {
+ int ack_diff;
+
+ ack_diff = SeqDiff(x.ack_new, ack);
+ if (ack_diff >= 0)
+ {
+ if (ack_diff_min >= 0)
+ {
+ if (ack_diff < ack_diff_min)
+ {
+ delta = x.delta;
+ ack_diff_min = ack_diff;
+ }
+ }
+ else
+ {
+ delta = x.delta;
+ ack_diff_min = ack_diff;
+ }
+ }
+ }
+ }
+ return (delta);
+}
+
+
+int
+GetDeltaSeqOut(struct ip *pip, struct alias_link *link)
+{
+/*
+Find out how much the seq number has been altered for an outgoing
+TCP packet. To do this, a circular list is ack numbers where the TCP
+packet size was altered is searched.
+*/
+
+ int i;
+ struct tcphdr *tc;
+ int delta, seq_diff_min;
+ u_long seq;
+
+ tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+ seq = tc->th_seq;
+
+ delta = 0;
+ seq_diff_min = -1;
+ for (i=0; i<N_LINK_TCP_DATA; i++)
+ {
+ struct ack_data_record x;
+
+ x = (link->data.tcp)->ack[i];
+ if (x.active == 1)
+ {
+ int seq_diff;
+
+ seq_diff = SeqDiff(x.ack_old, seq);
+ if (seq_diff >= 0)
+ {
+ if (seq_diff_min >= 0)
+ {
+ if (seq_diff < seq_diff_min)
+ {
+ delta = x.delta;
+ seq_diff_min = seq_diff;
+ }
+ }
+ else
+ {
+ delta = x.delta;
+ seq_diff_min = seq_diff;
+ }
+ }
+ }
+ }
+ return (delta);
+}
+
+
+void
+AddSeq(struct ip *pip, struct alias_link *link, int delta)
+{
+/*
+When a TCP packet has been altered in length, save this
+information in a circular list. If enough packets have
+been altered, then this list will begin to overwrite itself.
+*/
+
+ struct tcphdr *tc;
+ struct ack_data_record x;
+ int hlen, tlen, dlen;
+ int i;
+
+ tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+ hlen = (pip->ip_hl + tc->th_off) << 2;
+ tlen = ntohs(pip->ip_len);
+ dlen = tlen - hlen;
+
+ x.ack_old = htonl(ntohl(tc->th_seq) + dlen);
+ x.ack_new = htonl(ntohl(tc->th_seq) + dlen + delta);
+ x.delta = delta;
+ x.active = 1;
+
+ i = (link->data.tcp)->state.index;
+ (link->data.tcp)->ack[i] = x;
+
+ i++;
+ if (i == N_LINK_TCP_DATA)
+ (link->data.tcp)->state.index = 0;
+ else
+ (link->data.tcp)->state.index = i;
+}
+
+void
+SetExpire(struct alias_link *link, int expire)
+{
+ if (expire == 0)
+ {
+ link->flags &= ~LINK_PERMANENT;
+ DeleteLink(link);
+ }
+ else if (expire == -1)
+ {
+ link->flags |= LINK_PERMANENT;
+ }
+ else if (expire > 0)
+ {
+ link->expire_time = expire;
+ }
+ else
+ {
+ fprintf(stderr, "PacketAlias/SetExpire(): ");
+ fprintf(stderr, "error in expire parameter\n");
+ }
+}
+
+void
+ClearNewDefaultLink(void)
+{
+ newDefaultLink = 0;
+}
+
+
+int
+CheckNewDefaultLink(void)
+{
+ return newDefaultLink;
+}
+
+
+
+/*
+ Whenever an outgoing or incoming packet is handled, HouseKeeping()
+ is called to find and remove timed-out aliasing links. Logic exists
+ to sweep through the entire table and linked list structure
+ every 60 seconds.
+
+ (prototype in alias_local.h)
+*/
+
+void
+HouseKeeping(void)
+{
+ int i, n, n100;
+ struct timeval tv;
+ struct timezone tz;
+
+ /*
+ * Save system time (seconds) in global variable timeStamp for
+ * use by other functions. This is done so as not to unnecessarily
+ * waste timeline by making system calls.
+ */
+ gettimeofday(&tv, &tz);
+ timeStamp = tv.tv_sec;
+
+ /* Compute number of spokes (output table link chains) to cover */
+ n100 = LINK_TABLE_OUT_SIZE * 100 + houseKeepingResidual;
+ n100 *= timeStamp - lastCleanupTime;
+ n100 /= ALIAS_CLEANUP_INTERVAL_SECS;
+
+ n = n100/100;
+
+ /* Handle different cases */
+ if (n > ALIAS_CLEANUP_MAX_SPOKES)
+ {
+ n = ALIAS_CLEANUP_MAX_SPOKES;
+ lastCleanupTime = timeStamp;
+ houseKeepingResidual = 0;
+
+ for (i=0; i<n; i++)
+ IncrementalCleanup();
+ }
+ else if (n > 0)
+ {
+ lastCleanupTime = timeStamp;
+ houseKeepingResidual = n100 - 100*n;
+
+ for (i=0; i<n; i++)
+ IncrementalCleanup();
+ }
+ else if (n < 0)
+ {
+ fprintf(stderr, "PacketAlias/HouseKeeping(): ");
+ fprintf(stderr, "something unexpected in time values\n");
+ lastCleanupTime = timeStamp;
+ houseKeepingResidual = 0;
+ }
+}
+
+
+
+
+
+/* Outside world interfaces
+
+-- "outside world" means other than alias*.c routines --
+
+ PacketAliasRedirectPort()
+ PacketAliasRedirectAddr()
+ SetPacketAliasAddress()
+ InitPacketAliasLog()
+ UninitPacketAliasLog()
+ InitPacketAlias()
+ SetPacketAliasMode()
+
+(prototypes in alias.h)
+*/
+
+/* Redirection from a specific public addr:port to a
+ a private addr:port */
+struct alias_link *
+PacketAliasRedirectPort(struct in_addr src_addr, u_short src_port,
+ struct in_addr dst_addr, u_short dst_port,
+ struct in_addr alias_addr, u_short alias_port,
+ u_char proto)
+{
+ int link_type;
+ struct alias_link *link;
+
+ switch(proto)
+ {
+ case IPPROTO_UDP:
+ link_type = LINK_UDP;
+ break;
+ case IPPROTO_TCP:
+ link_type = LINK_TCP;
+ break;
+ default:
+ fprintf(stderr, "PacketAliasRedirectPort(): ");
+ fprintf(stderr, "only TCP and UDP protocols allowed\n");
+ return NULL;
+ }
+
+ link = AddLink(src_addr, dst_addr, alias_addr,
+ src_port, dst_port, alias_port,
+ link_type);
+
+ if (link != NULL)
+ {
+ link->flags |= LINK_PERMANENT;
+ }
+ else
+ {
+ fprintf(stderr, "PacketAliasRedirectPort(): "
+ "call to AddLink() failed\n");
+ }
+
+ return link;
+}
+
+
+/* This function is slightly less generalized than
+ PacketAliasRedirectPort and is included for backwards
+ compatibility */
+int
+PacketAliasPermanentLink(struct in_addr src_addr, u_short src_port,
+ struct in_addr dst_addr, u_short dst_port,
+ u_short alias_port, u_char proto)
+{
+ struct alias_link *link;
+
+ link = PacketAliasRedirectPort(src_addr, src_port,
+ dst_addr, dst_port,
+ nullAddress, alias_port,
+ proto);
+
+ if (link == NULL)
+ return -1;
+ else
+ return 0;
+}
+
+
+/* Static address translation */
+struct alias_link *
+PacketAliasRedirectAddr(struct in_addr src_addr,
+ struct in_addr alias_addr)
+{
+ struct alias_link *link;
+
+ link = AddLink(src_addr, nullAddress, alias_addr,
+ 0, 0, 0,
+ LINK_ADDR);
+
+ if (link != NULL)
+ {
+ link->flags |= LINK_PERMANENT;
+ }
+ else
+ {
+ fprintf(stderr, "PacketAliasRedirectAddr(): "
+ "call to AddLink() failed\n");
+ }
+
+ return link;
+}
+
+
+void
+PacketAliasRedirectDelete(struct alias_link *link)
+{
+/* This is a very dangerous function to put in the API,
+ because an invalid pointer can crash the program. */
+
+ deleteAllLinks = 1;
+ DeleteLink(link);
+ deleteAllLinks = 0;
+}
+
+
+void
+SetPacketAliasAddress(struct in_addr addr)
+{
+ if (aliasAddress.s_addr != addr.s_addr)
+ {
+ CleanupAliasData();
+ aliasAddress = addr;
+ }
+}
+
+
+/* Init the log file and enable logging */
+void
+InitPacketAliasLog(void)
+{
+ if ((~packetAliasMode & PKT_ALIAS_LOG)
+ && (monitorFile = fopen("/var/log/alias.log", "w")))
+ {
+ packetAliasMode |= PKT_ALIAS_LOG;
+ fprintf(monitorFile,
+ "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
+ }
+}
+
+
+/* Close the log-file and disable logging. */
+void
+UninitPacketAliasLog(void)
+{
+ if( monitorFile )
+ fclose(monitorFile);
+ packetAliasMode &= ~PKT_ALIAS_LOG;
+}
+
+
+void
+InitPacketAlias(void)
+{
+ int i;
+ struct timeval tv;
+ struct timezone tz;
+
+ if (firstCall == 1)
+ {
+ gettimeofday(&tv, &tz);
+ timeStamp = tv.tv_sec;
+ lastCleanupTime = tv.tv_sec;
+ houseKeepingResidual = 0;
+
+ for (i=0; i<LINK_TABLE_OUT_SIZE; i++)
+ linkTableOut[i] = NULL;
+ for (i=0; i<LINK_TABLE_IN_SIZE; i++)
+ linkTableIn[i] = NULL;
+
+ firstCall = 0;
+ }
+ else
+ {
+ deleteAllLinks = 1;
+ CleanupAliasData();
+ deleteAllLinks = 0;
+ }
+
+ aliasAddress.s_addr = 0;
+
+ icmpLinkCount = 0;
+ udpLinkCount = 0;
+ tcpLinkCount = 0;
+ fragmentIdLinkCount = 0;
+ fragmentPtrLinkCount = 0;
+ sockCount = 0;
+
+ cleanupIndex =0;
+
+ packetAliasMode = PKT_ALIAS_SAME_PORTS
+ | PKT_ALIAS_USE_SOCKETS;
+
+ if (packetAliasMode & PKT_ALIAS_LOG)
+ {
+ InitPacketAliasLog();
+ fprintf(monitorFile, "Packet aliasing initialized.\n");
+ }
+}
+
+
+/* Change mode for some operations */
+unsigned int
+SetPacketAliasMode
+(
+ unsigned int flags, /* Which state to bring flags to */
+ unsigned int mask /* Mask of which flags to affect (use 0 to do a
+ probe for flag values) */
+)
+{
+/* Enable logging? */
+ if (flags & mask & PKT_ALIAS_LOG)
+ {
+ InitPacketAliasLog(); /* Do the enable */
+ }
+/* _Disable_ logging? */
+ if (~flags & mask & PKT_ALIAS_LOG) {
+ UninitPacketAliasLog();
+ }
+
+/* Other flags can be set/cleared without special action */
+ packetAliasMode = (flags & mask) | (packetAliasMode & ~mask);
+ return packetAliasMode;
+}
+
+
+/*
+ Clear all packet aliasing links, but leave mode
+ flags unchanged. Typically used when the interface
+ address changes and all existing links become
+ invalid.
+*/
diff --git a/lib/libalias/alias_ftp.c b/lib/libalias/alias_ftp.c
new file mode 100644
index 0000000..e03c04b
--- /dev/null
+++ b/lib/libalias/alias_ftp.c
@@ -0,0 +1,220 @@
+/*
+ Alias_ftp.c performs special processing for FTP sessions under
+ TCP. Specifically, when a PORT command from the client side
+ is sent, it is intercepted and modified. The address is changed
+ to the gateway machine and an aliasing port is used.
+
+ For this routine to work, the PORT command must fit entirely
+ into a single TCP packet. This is typically the case, but exceptions
+ can easily be envisioned under the actual specifications.
+
+ Probably the most troubling aspect of the approach taken here is
+ that the new PORT command will typically be a different length, and
+ this causes a certain amount of bookkeeping to keep track of the
+ changes of sequence and acknowledgment numbers, since the client
+ machine is totally unaware of the modification to the TCP stream.
+
+
+ This software is placed into the public domain with no restrictions
+ on its distribution.
+
+ Initial version: August, 1996 (cjm)
+
+ Version 1.6
+ Brian Somers and Martin Renters identified an IP checksum
+ error for modified IP packets.
+
+ Version 1.7: January 9, 1996 (cjm)
+ Differental checksum computation for change
+ in IP packet length.
+
+ Version 2.1: May, 1997 (cjm)
+ Very minor changes to conform with
+ local/global/function naming conventions
+ withing the packet alising module.
+*/
+
+/* Includes */
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include "alias_local.h"
+
+static void NewFtpPortCommand(struct ip *, struct alias_link *, struct in_addr, u_short, int);
+
+
+
+void
+AliasHandleFtpOut(
+struct ip *pip, /* IP packet to examine/patch */
+struct alias_link *link, /* The link to go through (aliased port) */
+int maxpacketsize /* The maximum size this packet can grow to (including headers) */)
+{
+ int hlen, tlen, dlen;
+ struct in_addr true_addr;
+ u_short true_port;
+ char *sptr;
+ struct tcphdr *tc;
+
+/* Calculate data length of TCP packet */
+ tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+ hlen = (pip->ip_hl + tc->th_off) << 2;
+ tlen = ntohs(pip->ip_len);
+ dlen = tlen - hlen;
+
+/* Return is data length is too long or too short */
+ if (dlen<10 || dlen>80)
+ return;
+
+/* Place string pointer and beginning of data */
+ sptr = (char *) pip;
+ sptr += hlen;
+
+/* Parse through string using state diagram method */
+ {
+ char ch, zero;
+ int i, state;
+ u_long a1, a2, a3, a4;
+ u_short p1, p2;
+
+ a1=0; a2=0; a3=0; a4=0; p1=0; p2=0;
+ zero = '0';
+ state=-4;
+ for (i=0; i<dlen; i++)
+ {
+ ch = sptr[i];
+ switch (state)
+ {
+ case -4: if (ch == 'P') state=-3; else return; break;
+ case -3: if (ch == 'O') state=-2; else return; break;
+ case -2: if (ch == 'R') state=-1; else return; break;
+ case -1: if (ch == 'T') state= 0; else return; break;
+
+ case 0 :
+ if (isdigit(ch)) {a1=ch-zero; state=1 ;} break;
+ case 1 :
+ if (isdigit(ch)) a1=10*a1+ch-zero; else state=2 ; break;
+ case 2 :
+ if (isdigit(ch)) {a2=ch-zero; state=3 ;} break;
+ case 3 :
+ if (isdigit(ch)) a2=10*a2+ch-zero; else state=4 ; break;
+ case 4 :
+ if (isdigit(ch)) {a3=ch-zero; state=5 ;} break;
+ case 5 :
+ if (isdigit(ch)) a3=10*a3+ch-zero; else state=6 ; break;
+ case 6 :
+ if (isdigit(ch)) {a4=ch-zero; state=7 ;} break;
+ case 7 :
+ if (isdigit(ch)) a4=10*a4+ch-zero; else state=8 ; break;
+ case 8 :
+ if (isdigit(ch)) {p1=ch-zero; state=9 ;} break;
+ case 9 :
+ if (isdigit(ch)) p1=10*p1+ch-zero; else state=10; break;
+ case 10:
+ if (isdigit(ch)) {p2=ch-zero; state=11;} break;
+ case 11:
+ if (isdigit(ch)) p2=10*p2+ch-zero; break;
+ }
+ }
+
+ if (state == 11)
+ {
+ true_port = htons((p1<<8) + p2);
+ true_addr.s_addr = htonl((a1<<24) + (a2<<16) +(a3<<8) + a4);
+ NewFtpPortCommand(pip, link, true_addr, true_port, maxpacketsize);
+ }
+ }
+}
+
+static void
+NewFtpPortCommand(struct ip *pip,
+ struct alias_link *link,
+ struct in_addr true_addr,
+ u_short true_port,
+ int maxpacketsize)
+{
+ struct alias_link *ftp_link;
+
+/* Establish link to address and port found in PORT command */
+ ftp_link = FindUdpTcpOut(true_addr, GetDestAddress(link),
+ true_port, 0, IPPROTO_TCP);
+
+ if (ftp_link != NULL)
+ {
+ int slen, hlen, tlen, dlen;
+ struct tcphdr *tc;
+
+/* Calculate data length of TCP packet */
+ tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+ hlen = (pip->ip_hl + tc->th_off) << 2;
+ tlen = ntohs(pip->ip_len);
+ dlen = tlen - hlen;
+
+/* Create new PORT command */
+ {
+ char stemp[80];
+ char *sptr;
+ u_short alias_port;
+ u_char *ptr;
+ int a1, a2, a3, a4, p1, p2;
+ struct in_addr alias_address;
+
+/* Decompose alias address into quad format */
+ alias_address = GetAliasAddress(link);
+ ptr = (char *) &alias_address;
+ a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr;
+
+/* Decompose alias port into pair format */
+ alias_port = GetAliasPort(ftp_link);
+ ptr = (char *) &alias_port;
+ p1 = *ptr++; p2=*ptr;
+
+/* Generate command string */
+ sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
+ a1,a2,a3,a4,p1,p2);
+
+/* Save string length for IP header modification */
+ slen = strlen(stemp);
+
+/* Copy into IP packet */
+ sptr = (char *) pip; sptr += hlen;
+ strncpy(sptr, stemp, maxpacketsize-hlen);
+ }
+
+/* Save information regarding modified seq and ack numbers */
+ {
+ int delta;
+
+ SetAckModified(link);
+ delta = GetDeltaSeqOut(pip, link);
+ AddSeq(pip, link, delta+slen-dlen);
+ }
+
+/* Revise IP header */
+ {
+ u_short new_len;
+
+ new_len = htons(hlen + slen);
+ DifferentialChecksum(&pip->ip_sum,
+ &new_len,
+ &pip->ip_len,
+ 1);
+ pip->ip_len = new_len;
+ }
+
+/* Compute TCP checksum for revised packet */
+ tc->th_sum = 0;
+ tc->th_sum = TcpChecksum(pip);
+ }
+ else
+ {
+ fprintf(stderr,
+ "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");
+ }
+}
diff --git a/lib/libalias/alias_irc.c b/lib/libalias/alias_irc.c
new file mode 100644
index 0000000..3657368
--- /dev/null
+++ b/lib/libalias/alias_irc.c
@@ -0,0 +1,311 @@
+/* Alias_irc.c intercepts packages contain IRC CTCP commands, and
+ changes DCC commands to export a port on the aliasing host instead
+ of an aliased host.
+
+ For this routine to work, the DCC command must fit entirely into a
+ single TCP packet. This will usually happen, but is not
+ guaranteed.
+
+ The interception is likely to change the length of the packet.
+ The handling of this is copied more-or-less verbatim from
+ ftp_alias.c
+
+ This software is placed into the public domain with no restrictions
+ on its distribution.
+
+ Initial version: Eivind Eklund <perhaps@yes.no> (ee) 97-01-29
+
+ Version 2.1: May, 1997 (cjm)
+ Very minor changes to conform with
+ local/global/function naming conventions
+ withing the packet alising module.
+*/
+
+/* Includes */
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <limits.h>
+
+#include "alias_local.h"
+
+/* Local defines */
+#define DBprintf(a)
+
+
+void
+AliasHandleIrcOut(struct ip *pip, /* IP packet to examine */
+ struct alias_link *link, /* Which link are we on? */
+ int maxsize /* Maximum size of IP packet including headers */
+ )
+{
+ int hlen, tlen, dlen;
+ struct in_addr true_addr;
+ u_short true_port;
+ char *sptr;
+ struct tcphdr *tc;
+ int i; /* Iterator through the source */
+
+/* Calculate data length of TCP packet */
+ tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+ hlen = (pip->ip_hl + tc->th_off) << 2;
+ tlen = ntohs(pip->ip_len);
+ dlen = tlen - hlen;
+
+ /* Return if data length is too short - assume an entire PRIVMSG in each packet. */
+ if (dlen<sizeof(":A!a@n.n PRIVMSG A :aDCC 1 1a")-1)
+ return;
+
+/* Place string pointer at beginning of data */
+ sptr = (char *) pip;
+ sptr += hlen;
+ maxsize -= hlen; /* We're interested in maximum size of data, not packet */
+
+ /* Search for a CTCP command [Note 1] */
+ for( i=0; i<dlen; i++ ) {
+ if(sptr[i]=='\001')
+ goto lFOUND_CTCP;
+ }
+ return; /* No CTCP commands in */
+ /* Handle CTCP commands - the buffer may have to be copied */
+lFOUND_CTCP:
+ {
+ char newpacket[65536]; /* Estimate of maximum packet size :) */
+ int copyat = i; /* Same */
+ int iCopy = 0; /* How much data have we written to copy-back string? */
+ unsigned long org_addr; /* Original IP address */
+ unsigned short org_port; /* Original source port address */
+ lCTCP_START:
+ if( i >= dlen || iCopy >= sizeof(newpacket) )
+ goto lPACKET_DONE;
+ newpacket[iCopy++] = sptr[i++]; /* Copy the CTCP start character */
+ /* Start of a CTCP */
+ if( i+4 >= dlen ) /* Too short for DCC */
+ goto lBAD_CTCP;
+ if( sptr[i+0] != 'D' )
+ goto lBAD_CTCP;
+ if( sptr[i+1] != 'C' )
+ goto lBAD_CTCP;
+ if( sptr[i+2] != 'C' )
+ goto lBAD_CTCP;
+ if( sptr[i+3] != ' ' )
+ goto lBAD_CTCP;
+ /* We have a DCC command - handle it! */
+ i+= 4; /* Skip "DCC " */
+ if( iCopy+4 > sizeof(newpacket) )
+ goto lPACKET_DONE;
+ newpacket[iCopy++] = 'D';
+ newpacket[iCopy++] = 'C';
+ newpacket[iCopy++] = 'C';
+ newpacket[iCopy++] = ' ';
+
+ DBprintf(("Found DCC\n"));
+ /* Skip any extra spaces (should not occur according to
+ protocol, but DCC breaks CTCP protocol anyway */
+ while(sptr[i] == ' ') {
+ if( ++i >= dlen) {
+ DBprintf(("DCC packet terminated in just spaces\n"));
+ goto lPACKET_DONE;
+ }
+ }
+
+ DBprintf(("Transferring command...\n"));
+ while(sptr[i] != ' ') {
+ newpacket[iCopy++] = sptr[i];
+ if( ++i >= dlen || iCopy >= sizeof(newpacket) ) {
+ DBprintf(("DCC packet terminated during command\n"));
+ goto lPACKET_DONE;
+ }
+ }
+ /* Copy _one_ space */
+ if( i+1 < dlen && iCopy < sizeof(newpacket) )
+ newpacket[iCopy++] = sptr[i++];
+
+ DBprintf(("Done command - removing spaces\n"));
+ /* Skip any extra spaces (should not occur according to
+ protocol, but DCC breaks CTCP protocol anyway */
+ while(sptr[i] == ' ') {
+ if( ++i >= dlen ) {
+ DBprintf(("DCC packet terminated in just spaces (post-command)\n"));
+ goto lPACKET_DONE;
+ }
+ }
+
+ DBprintf(("Transferring filename...\n"));
+ while(sptr[i] != ' ') {
+ newpacket[iCopy++] = sptr[i];
+ if( ++i >= dlen || iCopy >= sizeof(newpacket) ) {
+ DBprintf(("DCC packet terminated during filename\n"));
+ goto lPACKET_DONE;
+ }
+ }
+ /* Copy _one_ space */
+ if( i+1 < dlen && iCopy < sizeof(newpacket) )
+ newpacket[iCopy++] = sptr[i++];
+
+ DBprintf(("Done filename - removing spaces\n"));
+ /* Skip any extra spaces (should not occur according to
+ protocol, but DCC breaks CTCP protocol anyway */
+ while(sptr[i] == ' ') {
+ if( ++i >= dlen ) {
+ DBprintf(("DCC packet terminated in just spaces (post-filename)\n"));
+ goto lPACKET_DONE;
+ }
+ }
+
+ DBprintf(("Fetching IP address\n"));
+ /* Fetch IP address */
+ org_addr = 0;
+ while(i<dlen && isdigit(sptr[i])) {
+ if( org_addr > ULONG_MAX/10UL ) { /* Terminate on overflow */
+ DBprintf(("DCC Address overflow (org_addr == 0x%08lx, next char %c\n", org_addr, sptr[i]));
+ goto lBAD_CTCP;
+ }
+ org_addr *= 10;
+ org_addr += sptr[i++]-'0';
+ }
+ DBprintf(("Skipping space\n"));
+ if( i+1 >= dlen || sptr[i] != ' ' ) {
+ DBprintf(("Overflow (%d >= %d) or bad character (%02x) terminating IP address\n", i+1, dlen, sptr[i]));
+ goto lBAD_CTCP;
+ }
+ /* Skip any extra spaces (should not occur according to
+ protocol, but DCC breaks CTCP protocol anyway, so we might
+ as well play it safe */
+ while(sptr[i] == ' ') {
+ if( ++i >= dlen ) {
+ DBprintf(("Packet failure - space overflow.\n"));
+ goto lPACKET_DONE;
+ }
+ }
+ DBprintf(("Fetching port number\n"));
+ /* Fetch source port */
+ org_port = 0;
+ while(i<dlen && isdigit(sptr[i])) {
+ if( org_port > 6554 ) { /* Terminate on overflow (65536/10 rounded up*/
+ DBprintf(("DCC: port number overflow\n"));
+ goto lBAD_CTCP;
+ }
+ org_port *= 10;
+ org_port += sptr[i++]-'0';
+ }
+ /* Skip illegal addresses (or early termination) */
+ if( i >= dlen || (sptr[i] != '\001' && sptr[i] != ' ') ) {
+ DBprintf(("Bad port termination\n"));
+ goto lBAD_CTCP;
+ }
+ DBprintf(("Got IP %lu and port %u\n", org_addr, (unsigned)org_port));
+
+ /* We've got the address and port - now alias it */
+ {
+ struct alias_link *dcc_link;
+ struct in_addr destaddr;
+
+
+ true_port = htons(org_port);
+ true_addr.s_addr = htonl(org_addr);
+ destaddr.s_addr = 0;
+
+ /* Steal the FTP_DATA_PORT - it doesn't really matter, and this
+ would probably allow it through at least _some_
+ firewalls. */
+ dcc_link = FindUdpTcpOut (true_addr,
+ destaddr,
+ true_port,
+ 0, IPPROTO_TCP);
+ DBprintf(("Got a DCC link\n"));
+ if ( dcc_link ) {
+ struct in_addr alias_address; /* Address from aliasing */
+ u_short alias_port; /* Port given by aliasing */
+
+ alias_address = GetAliasAddress(link);
+ iCopy += snprintf(&newpacket[iCopy],
+ sizeof(newpacket)-iCopy,
+ "%lu ", htonl(alias_address.s_addr));
+ if( iCopy >= sizeof(newpacket) ) { /* Truncated/fit exactly - bad news */
+ DBprintf(("DCC constructed packet overflow.\n"));
+ goto lBAD_CTCP;
+ }
+ alias_port = GetAliasPort(dcc_link);
+ iCopy += snprintf(&newpacket[iCopy],
+ sizeof(newpacket)-iCopy,
+ "%u", htons(alias_port) );
+ /* Done - truncated cases will be taken care of by lBAD_CTCP */
+ DBprintf(("Aliased IP %lu and port %u\n", alias_address.s_addr, (unsigned)alias_port));
+ }
+ }
+ /* An uninteresting CTCP - state entered right after '\001' has
+ been pushed. Also used to copy the rest of a DCC, after IP
+ address and port has been handled */
+ lBAD_CTCP:
+ for(; i<dlen && iCopy<sizeof(newpacket); i++,iCopy++) {
+ newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
+ if(sptr[i] == '\001') {
+ goto lNORMAL_TEXT;
+ }
+ }
+ goto lPACKET_DONE;
+ /* Normal text */
+ lNORMAL_TEXT:
+ for(; i<dlen && iCopy<sizeof(newpacket); i++,iCopy++) {
+ newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
+ if(sptr[i] == '\001') {
+ goto lCTCP_START;
+ }
+ }
+ /* Handle the end of a packet */
+ lPACKET_DONE:
+ iCopy = iCopy > maxsize-copyat ? maxsize-copyat : iCopy;
+ memcpy(sptr+copyat, newpacket, iCopy);
+
+/* Save information regarding modified seq and ack numbers */
+ {
+ int delta;
+
+ SetAckModified(link);
+ delta = GetDeltaSeqOut(pip, link);
+ AddSeq(pip, link, delta+copyat+iCopy-dlen);
+ }
+
+ /* Revise IP header */
+ {
+ u_short new_len;
+
+ new_len = htons(hlen + iCopy + copyat);
+ DifferentialChecksum(&pip->ip_sum,
+ &new_len,
+ &pip->ip_len,
+ 1);
+ pip->ip_len = new_len;
+ }
+
+ /* Compute TCP checksum for revised packet */
+ tc->th_sum = 0;
+ tc->th_sum = TcpChecksum(pip);
+ return;
+ }
+}
+
+/* Notes:
+ [Note 1]
+ The initial search will most often fail; it could be replaced with a 32-bit specific search.
+ Such a search would be done for 32-bit unsigned value V:
+ V ^= 0x01010101; (Search is for null bytes)
+ if( ((V-0x01010101)^V) & 0x80808080 ) {
+ (found a null bytes which was a 01 byte)
+ }
+ To assert that the processor is 32-bits, do
+ extern int ircdccar[32]; (32 bits)
+ extern int ircdccar[CHAR_BIT*sizeof(unsigned int)];
+ which will generate a type-error on all but 32-bit machines.
+
+ [Note 2] This routine really ought to be replaced with one that
+ creates a transparent proxy on the aliasing host, to allow arbitary
+ changes in the TCP stream. This should not be too difficult given
+ this base; I (ee) will try to do this some time later.
+ */
diff --git a/lib/libalias/alias_local.h b/lib/libalias/alias_local.h
new file mode 100644
index 0000000..dd1a2f4
--- /dev/null
+++ b/lib/libalias/alias_local.h
@@ -0,0 +1,91 @@
+/* -*- mode: c; tab-width: 3; c-basic-offset: 3; -*-
+ Alias_local.h contains the function prototypes for alias.c,
+ alias_db.c, alias_util.c and alias_ftp.c, alias_irc.c (as well
+ as any future add-ons). It is intended to be used only within
+ the aliasing software. Outside world interfaces are defined
+ in alias.h
+
+ This software is placed into the public domain with no restrictions
+ on its distribution.
+
+ Initial version: August, 1996 (cjm)
+
+ <updated several times by original author and Eivind Eiklund>
+*/
+
+extern int packetAliasMode;
+
+struct alias_link;
+
+/* General utilities */
+u_short IpChecksum(struct ip *);
+u_short TcpChecksum(struct ip *);
+void DifferentialChecksum(u_short *, u_short *, u_short *, int);
+
+/* Internal data access */
+struct alias_link *
+FindIcmpIn(struct in_addr, struct in_addr, u_short);
+
+struct alias_link *
+FindIcmpOut(struct in_addr, struct in_addr, u_short);
+
+struct alias_link *
+FindFragmentIn1(struct in_addr, struct in_addr, u_short);
+
+struct alias_link *
+FindFragmentIn2(struct in_addr, struct in_addr, u_short);
+
+struct alias_link *
+AddFragmentPtrLink(struct in_addr, u_short);
+
+struct alias_link *
+FindFragmentPtr(struct in_addr, u_short);
+
+struct alias_link *
+FindUdpTcpIn (struct in_addr, struct in_addr, u_short, u_short, u_char);
+
+struct alias_link *
+FindUdpTcpOut(struct in_addr, struct in_addr, u_short, u_short, u_char);
+
+struct in_addr
+FindOriginalAddress(struct in_addr);
+
+struct in_addr
+FindAliasAddress(struct in_addr);
+
+
+/* External data access/modification */
+void GetFragmentAddr(struct alias_link *, struct in_addr *);
+void SetFragmentAddr(struct alias_link *, struct in_addr);
+void GetFragmentPtr(struct alias_link *, char **);
+void SetFragmentPtr(struct alias_link *, char *);
+void SetStateIn(struct alias_link *, int);
+void SetStateOut(struct alias_link *, int);
+int GetStateIn(struct alias_link *);
+int GetStateOut(struct alias_link *);
+struct in_addr GetOriginalAddress(struct alias_link *);
+struct in_addr GetDestAddress(struct alias_link *);
+struct in_addr GetAliasAddress(struct alias_link *);
+struct in_addr GetDefaultAliasAddress(void);
+void SetDefaultAliasAddress(struct in_addr);
+void SetDefaultTargetAddress(struct in_addr);
+void ClearDefaultTargetAddress(void);
+u_short GetOriginalPort(struct alias_link *);
+u_short GetAliasPort(struct alias_link *);
+void SetAckModified(struct alias_link *);
+int GetAckModified(struct alias_link *);
+int GetDeltaAckIn(struct ip *, struct alias_link *);
+int GetDeltaSeqOut(struct ip *, struct alias_link *);
+void AddSeq(struct ip *, struct alias_link *, int);
+void SetExpire(struct alias_link *, int);
+void ClearNewDefaultLink(void);
+int CheckNewDefaultLink(void);
+
+/* Housekeeping function */
+void HouseKeeping(void);
+
+/* Tcp specfic routines */
+/*lint -save -library Suppress flexelint warnings */
+void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
+void AliasHandleIrcOut(struct ip *pip, struct alias_link *link, int maxsize );
+/*lint -restore */
diff --git a/lib/libalias/alias_util.c b/lib/libalias/alias_util.c
new file mode 100644
index 0000000..e5906ca
--- /dev/null
+++ b/lib/libalias/alias_util.c
@@ -0,0 +1,135 @@
+/*
+ Alias_util.h contains general utilities used by other functions
+ in the packet aliasing module. At the moment, there are functions
+ for computing IP header and TCP packet checksums.
+
+ The checksum routines are based upon example code in a Unix networking
+ text written by Stevens (sorry, I can't remember the title -- but
+ at least this is a good author).
+
+ Initial Version: August, 1996 (cjm)
+
+ Version 1.7: January 9, 1997
+ Added differential checksum update function.
+*/
+
+/*
+Note: the checksum routines assume that the actual checksum word has
+been zeroed out. If the checksum workd is filled with the proper value,
+then these routines will give a result of zero (useful for testing
+purposes);
+*/
+
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include "alias_local.h"
+
+u_short
+InternetChecksum(u_short *ptr, int nbytes)
+{
+ int sum, oddbyte;
+
+ sum = 0;
+ while (nbytes > 1)
+ {
+ sum += *ptr++;
+ nbytes -= 2;
+ }
+ if (nbytes == 1)
+ {
+ oddbyte = 0;
+ *((u_char *) &oddbyte) = *(u_char *) ptr;
+ sum += oddbyte;
+ }
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+ return(~sum);
+}
+
+u_short
+IpChecksum(struct ip *pip)
+{
+ return( InternetChecksum((u_short *) pip, (pip->ip_hl << 2)) );
+
+}
+
+u_short
+TcpChecksum(struct ip *pip)
+{
+ u_short *ptr;
+ struct tcphdr *tc;
+ int nhdr, ntcp, nbytes;
+ int sum, oddbyte;
+
+ nhdr = pip->ip_hl << 2;
+ ntcp = ntohs(pip->ip_len) - nhdr;
+
+ tc = (struct tcphdr *) ((char *) pip + nhdr);
+ ptr = (u_short *) tc;
+
+/* Add up TCP header and data */
+ nbytes = ntcp;
+ sum = 0;
+ while (nbytes > 1)
+ {
+ sum += *ptr++;
+ nbytes -= 2;
+ }
+ if (nbytes == 1)
+ {
+ oddbyte = 0;
+ *((u_char *) &oddbyte) = *(u_char *) ptr;
+ sum += oddbyte;
+ }
+
+/* "Pseudo-header" data */
+ ptr = (u_short *) &(pip->ip_dst);
+ sum += *ptr++;
+ sum += *ptr;
+ ptr = (u_short *) &(pip->ip_src);
+ sum += *ptr++;
+ sum += *ptr;
+ sum += htons((u_short) ntcp);
+ sum += htons((u_short) pip->ip_p);
+
+/* Roll over carry bits */
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+
+/* Return checksum */
+ return((u_short) ~sum);
+}
+
+
+void
+DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n)
+{
+ int i;
+ int accumulate;
+
+ accumulate = *cksum;
+ for (i=0; i<n; i++)
+ {
+ accumulate -= *new++;
+ accumulate += *old++;
+ }
+
+ if (accumulate < 0)
+ {
+ accumulate = -accumulate;
+ accumulate = (accumulate >> 16) + (accumulate & 0xffff);
+ accumulate += accumulate >> 16;
+ *cksum = (u_short) ~accumulate;
+ }
+ else
+ {
+ accumulate = (accumulate >> 16) + (accumulate & 0xffff);
+ accumulate += accumulate >> 16;
+ *cksum = (u_short) accumulate;
+ }
+}
+
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index 043119e..ef476fa 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -1,27 +1,24 @@
# @(#)Makefile 8.2 (Berkeley) 2/3/94
+# $Id: Makefile,v 1.18 1997/05/03 03:49:51 jb Exp $
#
-# All library objects contain sccsid strings by default; they may be
+# All library objects contain rcsid strings by default; they may be
# excluded as a space-saving measure. To produce a library that does
-# not contain these strings, delete -DLIBC_SCCS and -DSYSLIBC_SCCS
+# not contain these strings, delete -DLIBC_RCS and -DSYSLIBC_RCS
# from CFLAGS below. To remove these strings from just the system call
-# stubs, remove just -DSYSLIBC_SCCS from CFLAGS.
+# stubs, remove just -DSYSLIBC_RCS from CFLAGS.
LIB=c
-CFLAGS+=-DLIBC_SCCS -DSYSLIBC_SCCS
+SHLIB_MAJOR= 3
+SHLIB_MINOR= 0
+CFLAGS+=-DLIBC_RCS -DSYSLIBC_RCS
AINC= -I${.CURDIR}/${MACHINE}
CLEANFILES+=tags
+INSTALL_PIC_ARCHIVE= yes
+PRECIOUSLIB= yes
-.include "${.CURDIR}/db/Makefile.inc"
-.include "${.CURDIR}/compat-43/Makefile.inc"
-.include "${.CURDIR}/gen/Makefile.inc"
-.include "${.CURDIR}/gmon/Makefile.inc"
-.include "${.CURDIR}/locale/Makefile.inc"
-.include "${.CURDIR}/net/Makefile.inc"
-.include "${.CURDIR}/quad/Makefile.inc"
-.include "${.CURDIR}/regex/Makefile.inc"
-.include "${.CURDIR}/stdio/Makefile.inc"
-.include "${.CURDIR}/stdlib/Makefile.inc"
-.include "${.CURDIR}/string/Makefile.inc"
-.include "${.CURDIR}/sys/Makefile.inc"
+#
+# Include make rules that are shared with libc_r.
+#
+.include "${.CURDIR}/Makefile.inc"
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 \
@@ -32,20 +29,11 @@ KSRCS= bcmp.c ffs.c index.c mcount.c rindex.c strcat.c strcmp.c strcpy.c \
libkern: libkern.gen libkern.${MACHINE}
libkern.gen: ${KQSRCS} ${KSRCS}
- cp -p ${.CURDIR}/quad/quad.h ${.ALLSRC} /sys/libkern
+ cp -p ${.CURDIR}/quad/quad.h ${.ALLSRC} ${DESTDIR}/sys/libkern
libkern.${MACHINE}:: ${KMSRCS}
.if defined(KMSRCS) && !empty(KMSRCS)
- cp -p ${.ALLSRC} /sys/libkern/${MACHINE}
+ cp -p ${.ALLSRC} ${DESTDIR}/sys/libkern/${MACHINE}
.endif
-beforeinstall: tags
- install -c -o bin -g bin -m 444 tags /var/db/libc.tags
-
-tags: ${SRCS}
- ctags ${.ALLSRC:M*.c}
- egrep -o "^ENTRY(.*)|^FUNC(.*)|^SYSCALL(.*)" ${.ALLSRC:M*.s} | \
- sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
- >> tags; sort -o tags tags
-
.include <bsd.lib.mk>
diff --git a/lib/libc/Makefile.inc b/lib/libc/Makefile.inc
new file mode 100644
index 0000000..1f51b57
--- /dev/null
+++ b/lib/libc/Makefile.inc
@@ -0,0 +1,25 @@
+# $Id$
+#
+# This file contains make rules that are shared by libc and libc_r.
+#
+.include "${.CURDIR}/../libc/db/Makefile.inc"
+.include "${.CURDIR}/../libc/compat-43/Makefile.inc"
+.include "${.CURDIR}/../libc/gen/Makefile.inc"
+.include "${.CURDIR}/../libc/gmon/Makefile.inc"
+.include "${.CURDIR}/../libc/locale/Makefile.inc"
+.include "${.CURDIR}/../libc/net/Makefile.inc"
+.include "${.CURDIR}/../libc/nls/Makefile.inc"
+.include "${.CURDIR}/../libc/quad/Makefile.inc"
+.include "${.CURDIR}/../libc/regex/Makefile.inc"
+.include "${.CURDIR}/../libc/stdio/Makefile.inc"
+.include "${.CURDIR}/../libc/stdlib/Makefile.inc"
+.include "${.CURDIR}/../libc/stdtime/Makefile.inc"
+.include "${.CURDIR}/../libc/string/Makefile.inc"
+.include "${.CURDIR}/../libc/sys/Makefile.inc"
+.include "${.CURDIR}/../libc/rpc/Makefile.inc"
+.include "${.CURDIR}/../libc/xdr/Makefile.inc"
+.if !defined(NO_YP_LIBC)
+CFLAGS+= -DYP
+.include "${.CURDIR}/../libc/yp/Makefile.inc"
+.endif
+.include "${.CURDIR}/../libc/${MACHINE}/sys/Makefile.inc"
diff --git a/lib/libc/amd64/SYS.h b/lib/libc/amd64/SYS.h
new file mode 100644
index 0000000..593b2ed
--- /dev/null
+++ b/lib/libc/amd64/SYS.h
@@ -0,0 +1,86 @@
+/*-
+ * 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. 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: @(#)SYS.h 5.5 (Berkeley) 5/7/91
+ *
+ * $Id: SYS.h,v 1.10 1997/02/22 14:58:30 peter Exp $
+ */
+
+#include <sys/syscall.h>
+#include "DEFS.h"
+
+#define SYSCALL(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \
+ ENTRY(x); lea __CONCAT(SYS_,x),%eax; KERNCALL; jb 2b
+#define RSYSCALL(x) SYSCALL(x); ret
+
+#define PSEUDO(x,y) ENTRY(x); lea __CONCAT(SYS_,y), %eax; KERNCALL; ret
+/* gas messes up offset -- although we don't currently need it, do for BCS */
+#define LCALL(x,y) .byte 0x9a ; .long y; .word x
+
+/*
+ * Design note:
+ *
+ * The macros PSYSCALL() and PRSYSCALL() are intended for use where a
+ * syscall needs to be renamed in the threaded library. When building
+ * a normal library, they default to the traditional SYSCALL() and
+ * RSYSCALL(). This avoids the need to #ifdef _THREAD_SAFE everywhere
+ * that the renamed function needs to be called.
+ */
+#ifdef _THREAD_SAFE
+/*
+ * For the thread_safe versions, we prepend _thread_sys_ to the function
+ * name so that the 'C' wrapper can go around the real name.
+ */
+#define PSYSCALL(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \
+ ENTRY(__CONCAT(_thread_sys_,x)); \
+ lea __CONCAT(SYS_,x),%eax; KERNCALL; jb 2b
+#define PRSYSCALL(x) PSYSCALL(x); ret
+#define PPSEUDO(x,y) ENTRY(__CONCAT(_thread_sys_,x)); \
+ lea __CONCAT(SYS_,y), %eax; KERNCALL; ret
+#else
+/*
+ * The non-threaded library defaults to traditional syscalls where
+ * the function name matches the syscall name.
+ */
+#define PSYSCALL(x) SYSCALL(x)
+#define PRSYSCALL(x) RSYSCALL(x)
+#define PPSEUDO(x,y) PSEUDO(x,y)
+#endif
+
+#ifdef __ELF__
+#define KERNCALL int $0x80 /* Faster */
+#else
+#define KERNCALL LCALL(7,0) /* The old way */
+#endif
diff --git a/lib/libc/amd64/gen/Makefile.inc b/lib/libc/amd64/gen/Makefile.inc
new file mode 100644
index 0000000..457d5c3
--- /dev/null
+++ b/lib/libc/amd64/gen/Makefile.inc
@@ -0,0 +1,5 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
+
+SRCS+= isinf.c infinity.c
+SRCS+= _setjmp.S alloca.S fabs.S ldexp.c modf.S setjmp.S sigsetjmp.S
diff --git a/lib/libc/amd64/gen/_setjmp.S b/lib/libc/amd64/gen/_setjmp.S
new file mode 100644
index 0000000..62259ce
--- /dev/null
+++ b/lib/libc/amd64/gen/_setjmp.S
@@ -0,0 +1,92 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS 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 environment 'a'.
+ * The previous signal state is NOT restored.
+ */
+
+#include "DEFS.h"
+
+#ifdef _THREAD_SAFE
+ENTRY(__thread_sys_setjmp)
+#else
+ENTRY(_setjmp)
+#endif
+ 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 28(%eax)
+ xorl %eax,%eax
+ ret
+
+#ifdef _THREAD_SAFE
+ENTRY(__thread_sys_longjmp)
+#else
+ENTRY(_longjmp)
+#endif
+ 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
+ fninit
+ fldcw 28(%edx)
+ testl %eax,%eax
+ jnz 1f
+ incl %eax
+1: movl %ecx,0(%esp)
+ ret
diff --git a/lib/libc/amd64/gen/frexp.c b/lib/libc/amd64/gen/frexp.c
new file mode 100644
index 0000000..aba4802
--- /dev/null
+++ b/lib/libc/amd64/gen/frexp.c
@@ -0,0 +1,67 @@
+/*-
+ * 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.
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
+
+#include <sys/types.h>
+#include <math.h>
+
+double
+frexp(value, eptr)
+ double value;
+ int *eptr;
+{
+ union {
+ double v;
+ struct {
+ u_int u_mant2 : 32;
+ u_int u_mant1 : 20;
+ u_int u_exp : 11;
+ u_int u_sign : 1;
+ } s;
+ } u;
+
+ if (value) {
+ u.v = value;
+ *eptr = u.s.u_exp - 1022;
+ u.s.u_exp = 1022;
+ return(u.v);
+ } else {
+ *eptr = 0;
+ return((double)0);
+ }
+}
diff --git a/lib/libc/amd64/gen/infinity.c b/lib/libc/amd64/gen/infinity.c
new file mode 100644
index 0000000..e46f676
--- /dev/null
+++ b/lib/libc/amd64/gen/infinity.c
@@ -0,0 +1,9 @@
+/*
+ * infinity.c
+ * $Id$
+ */
+
+#include <math.h>
+
+/* bytes for +Infinity on a 387 */
+char __infinity[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f };
diff --git a/lib/libc/amd64/gen/isinf.c b/lib/libc/amd64/gen/isinf.c
new file mode 100644
index 0000000..a796dcf
--- /dev/null
+++ b/lib/libc/amd64/gen/isinf.c
@@ -0,0 +1,68 @@
+/*-
+ * 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.
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
+
+#include <sys/types.h>
+
+int
+isnan(d)
+ double d;
+{
+ register struct IEEEdp {
+ u_int manl : 32;
+ u_int manh : 20;
+ u_int exp : 11;
+ u_int sign : 1;
+ } *p = (struct IEEEdp *)&d;
+
+ return(p->exp == 2047 && (p->manh || p->manl));
+}
+
+int
+isinf(d)
+ double d;
+{
+ register struct IEEEdp {
+ u_int manl : 32;
+ u_int manh : 20;
+ u_int exp : 11;
+ u_int sign : 1;
+ } *p = (struct IEEEdp *)&d;
+
+ return(p->exp == 2047 && !p->manh && !p->manl);
+}
diff --git a/lib/libc/amd64/gen/ldexp.c b/lib/libc/amd64/gen/ldexp.c
new file mode 100644
index 0000000..8b63f52
--- /dev/null
+++ b/lib/libc/amd64/gen/ldexp.c
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Sean Eric Fagan.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
+
+/*
+ * ldexp(value, exp): return value * (2 ** exp).
+ *
+ * Written by Sean Eric Fagan (sef@kithrup.COM)
+ * Sun Mar 11 20:27:09 PST 1990
+ */
+
+/*
+ * We do the conversion in C to let gcc optimize it away, if possible.
+ * The "fxch ; fstp" stuff is because value is still on the stack
+ * (stupid 8087!).
+ */
+double
+ldexp (double value, int exp)
+{
+ double temp, texp, temp2;
+ texp = exp;
+#ifdef __GNUC__
+#if __GNUC__ >= 2
+ asm ("fscale "
+ : "=u" (temp2), "=t" (temp)
+ : "0" (texp), "1" (value));
+#else
+ asm ("fscale ; fxch %%st(1) ; fstp%L1 %1 "
+ : "=f" (temp), "=0" (temp2)
+ : "0" (texp), "f" (value));
+#endif
+#else
+error unknown asm
+#endif
+ return (temp);
+}
diff --git a/lib/libc/amd64/gen/setjmp.S b/lib/libc/amd64/gen/setjmp.S
new file mode 100644
index 0000000..6525a16
--- /dev/null
+++ b/lib/libc/amd64/gen/setjmp.S
@@ -0,0 +1,113 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS 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 environment 'a'.
+ * The previous signal state is restored.
+ */
+
+#include "DEFS.h"
+#include "SYS.h"
+
+#ifdef _THREAD_SAFE
+ENTRY(_thread_sys_setjmp)
+#else
+ENTRY(setjmp)
+#endif
+ PIC_PROLOGUE
+ pushl $0
+#ifdef _THREAD_SAFE
+ call PIC_PLT(CNAME(_thread_sys_sigblock))
+#else
+ call PIC_PLT(CNAME(sigblock))
+#endif
+ popl %edx
+ 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)
+ movl %eax,24(%ecx)
+ fnstcw 28(%ecx)
+ xorl %eax,%eax
+ ret
+
+#ifdef _THREAD_SAFE
+ENTRY(_thread_sys_longjmp)
+#else
+ENTRY(longjmp)
+#endif
+ movl 4(%esp),%edx
+ PIC_PROLOGUE
+ pushl 24(%edx)
+#ifdef _THREAD_SAFE
+ call PIC_PLT(CNAME(_thread_sys_sigsetmask))
+#else
+ call PIC_PLT(CNAME(sigsetmask)) /* XXX this is not reentrant */
+#endif
+ popl %eax
+ 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
+ fninit
+ fldcw 28(%edx)
+ testl %eax,%eax
+ jnz 1f
+ incl %eax
+1: movl %ecx,0(%esp)
+ ret
diff --git a/lib/libc/amd64/gen/sigsetjmp.S b/lib/libc/amd64/gen/sigsetjmp.S
new file mode 100644
index 0000000..1220598
--- /dev/null
+++ b/lib/libc/amd64/gen/sigsetjmp.S
@@ -0,0 +1,125 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+#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).
+ *
+ * Use sigprocmask() instead of sigblock() and sigsetmask(), and
+ * check for and handle errors.
+ *
+ * Restore _all_ the registers and the signal mask atomically. Can
+ * use sigreturn() if sigreturn() works.
+ */
+
+#ifdef _THREAD_SAFE
+ENTRY(_thread_sys_sigsetjmp)
+#else
+ENTRY(sigsetjmp)
+#endif
+ movl 8(%esp),%eax
+ movl 4(%esp),%ecx
+ movl %eax,32(%ecx)
+ testl %eax,%eax
+ jz 2f
+ PIC_PROLOGUE
+ pushl $0
+#ifdef _THREAD_SAFE
+ call PIC_PLT(CNAME(_thread_sys_sigblock))
+#else
+ call PIC_PLT(CNAME(sigblock))
+#endif
+ addl $4,%esp
+ PIC_EPILOGUE
+ movl 4(%esp),%ecx
+ movl %eax,24(%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 28(%ecx)
+ xorl %eax,%eax
+ ret
+
+#ifdef _THREAD_SAFE
+ENTRY(_thread_sys_siglongjmp)
+#else
+ENTRY(siglongjmp)
+#endif
+ movl 4(%esp),%edx
+ cmpl $0,32(%edx)
+ jz 2f
+ PIC_PROLOGUE
+ pushl 24(%edx)
+#ifdef _THREAD_SAFE
+ call PIC_PLT(CNAME(_thread_sys_sigsetmask))
+#else
+ call PIC_PLT(CNAME(sigsetmask))
+#endif
+ addl $4,%esp
+ PIC_EPILOGUE
+2: 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
+ fninit
+ fldcw 28(%edx)
+ testl %eax,%eax
+ jnz 1f
+ incl %eax
+1: movl %ecx,0(%esp)
+ ret
diff --git a/lib/libc/amd64/net/Makefile.inc b/lib/libc/amd64/net/Makefile.inc
new file mode 100644
index 0000000..dff7fd1
--- /dev/null
+++ b/lib/libc/amd64/net/Makefile.inc
@@ -0,0 +1,4 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
+
+SRCS+= htonl.S htons.S ntohl.S ntohs.S
diff --git a/lib/libc/amd64/net/htonl.S b/lib/libc/amd64/net/htonl.S
new file mode 100644
index 0000000..095c40a
--- /dev/null
+++ b/lib/libc/amd64/net/htonl.S
@@ -0,0 +1,53 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+/* netorder = htonl(hostorder) */
+
+#include "DEFS.h"
+
+ENTRY(htonl)
+ movl 4(%esp),%eax
+ xchgb %al,%ah
+ roll $16,%eax
+ xchgb %al,%ah
+ ret
diff --git a/lib/libc/amd64/net/htons.S b/lib/libc/amd64/net/htons.S
new file mode 100644
index 0000000..238dfc2
--- /dev/null
+++ b/lib/libc/amd64/net/htons.S
@@ -0,0 +1,51 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+/* netorder = htons(hostorder) */
+
+#include "DEFS.h"
+
+ENTRY(htons)
+ movzwl 4(%esp),%eax
+ xchgb %al,%ah
+ ret
diff --git a/lib/libc/amd64/net/ntohl.S b/lib/libc/amd64/net/ntohl.S
new file mode 100644
index 0000000..5af5008
--- /dev/null
+++ b/lib/libc/amd64/net/ntohl.S
@@ -0,0 +1,53 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+/* hostorder = ntohl(netorder) */
+
+#include "DEFS.h"
+
+ENTRY(ntohl)
+ movl 4(%esp),%eax
+ xchgb %al,%ah
+ roll $16,%eax
+ xchgb %al,%ah
+ ret
diff --git a/lib/libc/amd64/net/ntohs.S b/lib/libc/amd64/net/ntohs.S
new file mode 100644
index 0000000..4bed4a2
--- /dev/null
+++ b/lib/libc/amd64/net/ntohs.S
@@ -0,0 +1,51 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+/* hostorder = ntohs(netorder) */
+
+#include "DEFS.h"
+
+ENTRY(ntohs)
+ movzwl 4(%esp),%eax
+ xchgb %al,%ah
+ ret
diff --git a/lib/libc/amd64/sys/Makefile.inc b/lib/libc/amd64/sys/Makefile.inc
new file mode 100644
index 0000000..0cf1aad
--- /dev/null
+++ b/lib/libc/amd64/sys/Makefile.inc
@@ -0,0 +1,13 @@
+# from: Makefile.inc,v 1.1 1993/09/03 19:04:23 jtc Exp
+# $Id: Makefile.inc,v 1.4 1997/02/22 14:59:27 peter Exp $
+
+.PATH: ${.CURDIR}/../libc/${MACHINE}/sys
+
+SRCS+= i386_get_ldt.c i386_set_ldt.c
+
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN2+= i386/sys/i386_get_ldt.2
+
+MLINKS+=i386_get_ldt.2 i386_set_ldt.2
+.endif
diff --git a/lib/libc/amd64/sys/brk.S b/lib/libc/amd64/sys/brk.S
new file mode 100644
index 0000000..4fdf0c6
--- /dev/null
+++ b/lib/libc/amd64/sys/brk.S
@@ -0,0 +1,91 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
+
+#include "SYS.h"
+
+ .globl HIDENAME(curbrk)
+ .globl HIDENAME(minbrk)
+ENTRY(_brk)
+ jmp ok
+
+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:
+ lea 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:
+ lea SYS_break,%eax
+ KERNCALL
+ jb err
+ movl 4(%esp),%eax
+ movl %eax,HIDENAME(curbrk)
+ movl $0,%eax
+ ret
+err:
+ jmp HIDENAME(cerror)
+#endif
diff --git a/lib/libc/amd64/sys/cerror.S b/lib/libc/amd64/sys/cerror.S
new file mode 100644
index 0000000..2d8f935
--- /dev/null
+++ b/lib/libc/amd64/sys/cerror.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.
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
+
+#include "SYS.h"
+
+ .globl HIDENAME(cerror)
+
+#ifdef _THREAD_SAFE
+ /*
+ * Threaded version using __error().
+ */
+ .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
+
+#else /* _THREAD_SAFE */
+ /*
+ * Non-threaded version using global errno.
+ */
+ .globl CNAME(errno)
+HIDENAME(cerror):
+#ifdef PIC
+ /* The caller must execute the PIC prologue before jumping to cerror. */
+ movl PIC_GOT(CNAME(errno)),%ecx
+ movl %eax,(%ecx)
+ PIC_EPILOGUE
+#else
+ movl %eax,CNAME(errno)
+#endif
+ movl $-1,%eax
+ movl $-1,%edx
+ ret
+#endif /* _THREAD_SAFE */
diff --git a/lib/libc/amd64/sys/exect.S b/lib/libc/amd64/sys/exect.S
new file mode 100644
index 0000000..af0d2ee
--- /dev/null
+++ b/lib/libc/amd64/sys/exect.S
@@ -0,0 +1,56 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
+
+#include "SYS.h"
+#include <machine/psl.h>
+
+ENTRY(exect)
+ lea 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); */
diff --git a/lib/libc/amd64/sys/pipe.S b/lib/libc/amd64/sys/pipe.S
new file mode 100644
index 0000000..637b86f
--- /dev/null
+++ b/lib/libc/amd64/sys/pipe.S
@@ -0,0 +1,51 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
+
+#include "SYS.h"
+
+PSYSCALL(pipe)
+ movl 4(%esp),%ecx
+ movl %eax,(%ecx)
+ movl %edx,4(%ecx)
+ movl $0,%eax
+ ret
diff --git a/lib/libc/amd64/sys/ptrace.S b/lib/libc/amd64/sys/ptrace.S
new file mode 100644
index 0000000..018a02c
--- /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.
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
+
+#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
+ lea SYS_ptrace,%eax
+ KERNCALL
+ jb err
+ ret
+err:
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
diff --git a/lib/libc/amd64/sys/reboot.S b/lib/libc/amd64/sys/reboot.S
new file mode 100644
index 0000000..70049b2
--- /dev/null
+++ b/lib/libc/amd64/sys/reboot.S
@@ -0,0 +1,47 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
+
+#include "SYS.h"
+
+SYSCALL(reboot)
+ iret
diff --git a/lib/libc/amd64/sys/sbrk.S b/lib/libc/amd64/sys/sbrk.S
new file mode 100644
index 0000000..a3afd89
--- /dev/null
+++ b/lib/libc/amd64/sys/sbrk.S
@@ -0,0 +1,95 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
+
+#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)
+ lea 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)
+ lea SYS_break,%eax
+ KERNCALL
+ jb err
+ movl HIDENAME(curbrk),%eax
+ addl %ecx,HIDENAME(curbrk)
+back:
+ ret
+err:
+ jmp HIDENAME(cerror)
+#endif /* PIC */
diff --git a/lib/libc/amd64/sys/setlogin.S b/lib/libc/amd64/sys/setlogin.S
new file mode 100644
index 0000000..7bcf3bd
--- /dev/null
+++ b/lib/libc/amd64/sys/setlogin.S
@@ -0,0 +1,59 @@
+/*-
+ * 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.
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#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) */
diff --git a/lib/libc/amd64/sys/sigreturn.S b/lib/libc/amd64/sys/sigreturn.S
new file mode 100644
index 0000000..65deb40
--- /dev/null
+++ b/lib/libc/amd64/sys/sigreturn.S
@@ -0,0 +1,52 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
+
+#include "SYS.h"
+
+/*
+ * NOTE: If the profiling ENTRY() code ever changes any registers, they
+ * must be saved. On FreeBSD, this is not the case.
+ */
+
+PSYSCALL(sigreturn)
+ ret
diff --git a/lib/libc/amd64/sys/vfork.S b/lib/libc/amd64/sys/vfork.S
new file mode 100644
index 0000000..e4ed257
--- /dev/null
+++ b/lib/libc/amd64/sys/vfork.S
@@ -0,0 +1,101 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
+
+#include "DEFS.h"
+#include "SYS.h"
+
+/*
+ * pid = vfork();
+ *
+ * %edx == 0 in parent process, %edx == 1 in child process.
+ * %eax == pid of child in parent, %eax == pid of parent in child.
+ *
+ */
+
+ENTRY(vfork)
+ popl %ecx /* my rta into ecx */
+ lea SYS_vfork,%eax
+ KERNCALL
+ jb verror
+vforkok:
+ cmpl $0,%edx /* child process? */
+ jne child /* yes */
+ jmp parent
+#ifdef _THREAD_SAFE
+ /*
+ * Threaded version using __error().
+ */
+ .globl CNAME(__error)
+ .type CNAME(__error),@function
+verror:
+ pushl %eax
+#ifdef PIC
+ call PIC_PLT(CNAME(__error))
+#else
+ call CNAME(__error)
+#endif
+ popl %ecx
+ movl %ecx,(%eax)
+ movl $-1,%eax
+ movl $-1,%edx
+#else /* !_THREAD_SAFE */
+ /*
+ * Non-threaded version using global errno.
+ */
+ .globl CNAME(errno)
+verror:
+#ifdef PIC
+ PIC_PROLOGUE
+ movl PIC_GOT(CNAME(errno)), %edx
+ movl %eax,(%edx)
+ PIC_EPILOGUE
+#else
+ movl %eax,CNAME(errno)
+#endif
+ movl $-1,%eax
+#endif /* !_THREAD_SAFE */
+ jmp %ecx
+child:
+ movl $0,%eax
+parent:
+ jmp %ecx
diff --git a/lib/libc/compat-43/Makefile.inc b/lib/libc/compat-43/Makefile.inc
index e4d66f5..25d7763 100644
--- a/lib/libc/compat-43/Makefile.inc
+++ b/lib/libc/compat-43/Makefile.inc
@@ -1,13 +1,20 @@
# @(#)Makefile.inc 8.1 (Berkeley) 6/2/93
+# $Id$
# compat-43 sources
-.PATH: ${.CURDIR}/${MACHINE}/compat-43 ${.CURDIR}/compat-43
+.PATH: ${.CURDIR}/../libc/${MACHINE}/compat-43 ${.CURDIR}/../libc/compat-43
SRCS+= creat.c gethostid.c getwd.c killpg.c sethostid.c setpgrp.c \
- setregid.c setreuid.c setrgid.c setruid.c sigcompat.c
+ setrgid.c setruid.c sigcompat.c
-MAN2+= creat.0 gethostid.0 killpg.0 setregid.0 setreuid.0 setruid.0 \
- sigblock.0 sigpause.0 sigsetmask.0 sigvec.0
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN2+= compat-43/creat.2 compat-43/killpg.2 \
+ compat-43/sigblock.2 \
+ compat-43/sigpause.2 compat-43/sigsetmask.2 compat-43/sigvec.2
-MLINKS+=setruid.2 setrgid.2
-MLINKS+=gethostid.2 sethostid.2
+MAN3+= compat-43/gethostid.3 compat-43/setruid.3
+
+MLINKS+=setruid.3 setrgid.3
+MLINKS+=gethostid.3 sethostid.3
+.endif
diff --git a/lib/libc/compat-43/creat.2 b/lib/libc/compat-43/creat.2
index 826909a..b4a035c 100644
--- a/lib/libc/compat-43/creat.2
+++ b/lib/libc/compat-43/creat.2
@@ -40,7 +40,7 @@
.Sh SYNOPSIS
.Fd #include <fcntl.h>
.Ft int
-.Fn creat "char *path" "mode_t mode"
+.Fn creat "const char *path" "mode_t mode"
.Sh DESCRIPTION
.Bf -symbolic
This interface is made obsolete by:
@@ -56,5 +56,6 @@ open(path, O_CREAT | O_TRUNC | O_WRONLY, mode);
.Xr open 2
.Sh HISTORY
The
-.Nm
-function call appeared in Version 6 AT&T UNIX.
+.Fn creat
+function call appeared in
+.At v6 .
diff --git a/lib/libc/compat-43/creat.c b/lib/libc/compat-43/creat.c
index 31d60b8..a4f1234 100644
--- a/lib/libc/compat-43/creat.c
+++ b/lib/libc/compat-43/creat.c
@@ -37,6 +37,7 @@ static char sccsid[] = "@(#)creat.c 8.1 (Berkeley) 6/2/93";
#include <fcntl.h>
+int
#if __STDC__
creat(const char *path, mode_t mode)
#else
diff --git a/lib/libc/compat-43/gethostid.3 b/lib/libc/compat-43/gethostid.3
index 8f56a28..b4f6b62 100644
--- a/lib/libc/compat-43/gethostid.3
+++ b/lib/libc/compat-43/gethostid.3
@@ -42,7 +42,7 @@
.Fd #include <unistd.h>
.Ft long
.Fn gethostid void
-.Ft int
+.Ft void
.Fn sethostid "long hostid"
.Sh DESCRIPTION
.Fn Sethostid
@@ -57,10 +57,10 @@ 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 2 .
+.Xr sysctl 3 .
.Sh SEE ALSO
-.Xr sysctl 2 ,
.Xr gethostname 3 ,
+.Xr sysctl 3 ,
.Xr sysctl 8 .
.Sh BUGS
32 bits for the identifier is too small.
diff --git a/lib/libc/compat-43/getwd.c b/lib/libc/compat-43/getwd.c
index f105150e..9f0e633 100644
--- a/lib/libc/compat-43/getwd.c
+++ b/lib/libc/compat-43/getwd.c
@@ -47,7 +47,7 @@ getwd(buf)
{
char *p;
- if (p = getcwd(buf, MAXPATHLEN))
+ if ( (p = getcwd(buf, MAXPATHLEN)) )
return(p);
(void)strcpy(buf, strerror(errno));
return((char *)NULL);
diff --git a/lib/libc/compat-43/killpg.2 b/lib/libc/compat-43/killpg.2
index b57e406..01e44f4 100644
--- a/lib/libc/compat-43/killpg.2
+++ b/lib/libc/compat-43/killpg.2
@@ -38,6 +38,7 @@
.Nm killpg
.Nd send signal to a process group
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
.Fd #include <signal.h>
.Ft int
.Fn killpg "pid_t pgrp" "int sig"
@@ -85,11 +86,11 @@ of the target processes has an effective user ID different from that
of the sending process.
.El
.Sh SEE ALSO
-.Xr kill 2 ,
.Xr getpgrp 2 ,
+.Xr kill 2 ,
.Xr sigaction 2
.Sh HISTORY
The
-.Nm
+.Fn killpg
function call appeared in
.Bx 4.0 .
diff --git a/lib/libc/compat-43/killpg.c b/lib/libc/compat-43/killpg.c
index f9b7901..ac3ba6e 100644
--- a/lib/libc/compat-43/killpg.c
+++ b/lib/libc/compat-43/killpg.c
@@ -42,6 +42,7 @@ static char sccsid[] = "@(#)killpg.c 8.1 (Berkeley) 6/2/93";
/*
* Backwards-compatible killpg().
*/
+int
#if __STDC__
killpg(pid_t pgid, int sig)
#else
diff --git a/lib/libc/compat-43/setpgrp.c b/lib/libc/compat-43/setpgrp.c
index df63ebd..dc0dd3f 100644
--- a/lib/libc/compat-43/setpgrp.c
+++ b/lib/libc/compat-43/setpgrp.c
@@ -38,6 +38,7 @@ static char sccsid[] = "@(#)setpgrp.c 8.1 (Berkeley) 6/2/93";
#include <sys/types.h>
#include <unistd.h>
+int
#if __STDC__
setpgrp(pid_t pid, pid_t pgid)
#else
diff --git a/lib/libc/compat-43/setruid.3 b/lib/libc/compat-43/setruid.3
index 7342b21..32245c1 100644
--- a/lib/libc/compat-43/setruid.3
+++ b/lib/libc/compat-43/setruid.3
@@ -39,7 +39,7 @@
.Nm setrgid
.Nd set user and group ID
.Sh SYNOPSIS
-.Fd #include <sys/types.h>
+.Fd #include <unistd.h>
.Ft int
.Fn setruid "uid_t ruid"
.Ft int
@@ -62,12 +62,12 @@ functions return \-1.
The use of these calls is not portable.
Their use is discouraged; they will be removed in the future.
.Sh SEE ALSO
-.Xr setuid 2 ,
-.Xr setgid 2 ,
-.Xr seteuid 2 ,
-.Xr setegid 2 ,
+.Xr getgid 2 ,
.Xr getuid 2 ,
-.Xr getgid 2
+.Xr setegid 2 ,
+.Xr seteuid 2 ,
+.Xr setgid 2 ,
+.Xr setuid 2
.Sh HISTORY
The
.Fn setruid
diff --git a/lib/libc/compat-43/sigblock.2 b/lib/libc/compat-43/sigblock.2
index 60e4251..bb61f61 100644
--- a/lib/libc/compat-43/sigblock.2
+++ b/lib/libc/compat-43/sigblock.2
@@ -72,13 +72,13 @@ imposed by the system.
The previous set of masked signals is returned.
.Sh SEE ALSO
.Xr kill 2 ,
-.Xr sigprocmask 2 ,
.Xr sigaction 2 ,
+.Xr sigprocmask 2 ,
.Xr sigsetmask 2 ,
.Xr sigsetops 3
.Sh HISTORY
The
-.Nm
+.Fn sigblock
function call appeared in
.Bx 4.2
and has been deprecated.
diff --git a/lib/libc/compat-43/sigcompat.c b/lib/libc/compat-43/sigcompat.c
index 69b1870..56550d2 100644
--- a/lib/libc/compat-43/sigcompat.c
+++ b/lib/libc/compat-43/sigcompat.c
@@ -38,6 +38,7 @@ static char sccsid[] = "@(#)sigcompat.c 8.1 (Berkeley) 6/2/93";
#include <sys/param.h>
#include <signal.h>
+int
sigvec(signo, sv, osv)
int signo;
struct sigvec *sv, *osv;
@@ -52,6 +53,7 @@ sigvec(signo, sv, osv)
return (ret);
}
+int
sigsetmask(mask)
int mask;
{
@@ -63,6 +65,7 @@ sigsetmask(mask)
return (omask);
}
+int
sigblock(mask)
int mask;
{
@@ -74,6 +77,7 @@ sigblock(mask)
return (omask);
}
+int
sigpause(mask)
int mask;
{
diff --git a/lib/libc/compat-43/sigpause.2 b/lib/libc/compat-43/sigpause.2
index 7c6c097..52230cc 100644
--- a/lib/libc/compat-43/sigpause.2
+++ b/lib/libc/compat-43/sigpause.2
@@ -60,15 +60,15 @@ always terminates by being interrupted, returning -1 with
set to
.Dv EINTR
.Sh SEE ALSO
-.Xr sigsuspend 2 ,
.Xr kill 2 ,
.Xr sigaction 2 ,
-.Xr sigprocmask 2 ,
.Xr sigblock 2 ,
+.Xr sigprocmask 2 ,
+.Xr sigsuspend 2 ,
.Xr sigvec 2
.Sh HISTORY
The
-.Nm
+.Fn sigpause
function call appeared in
.Bx 4.2
and has been deprecated.
diff --git a/lib/libc/compat-43/sigsetmask.2 b/lib/libc/compat-43/sigsetmask.2
index 13b7c1a..6131b0f 100644
--- a/lib/libc/compat-43/sigsetmask.2
+++ b/lib/libc/compat-43/sigsetmask.2
@@ -67,16 +67,16 @@ to be blocked.
.Sh RETURN VALUES
The previous set of masked signals is returned.
.Sh SEE ALSO
-.Xr sigprocmask 2 ,
.Xr kill 2 ,
.Xr sigaction 2 ,
+.Xr sigblock 2 ,
+.Xr sigprocmask 2 ,
.Xr sigsuspend 2 ,
.Xr sigvec 2 ,
-.Xr sigblock 2 ,
.Xr sigsetops 3
.Sh HISTORY
The
-.Nm
+.Fn sigsetmask
function call appeared in
.Bx 4.2
and has been deprecated.
diff --git a/lib/libc/compat-43/sigvec.2 b/lib/libc/compat-43/sigvec.2
index 1b5244f..de8d452 100644
--- a/lib/libc/compat-43/sigvec.2
+++ b/lib/libc/compat-43/sigvec.2
@@ -46,6 +46,7 @@ struct sigvec {
int sv_flags;
};
.Ed
+.Ft int
.Fn sigvec "int sig" "struct sigvec *vec" "struct sigvec *ovec"
.Sh DESCRIPTION
.Bf -symbolic
@@ -102,9 +103,9 @@ must arrange to restore the previous context itself.
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
+.Xr sigblock 2
or
-.Xr sigsetmask
+.Xr sigsetmask 2
call is made).
This mask is formed by taking the current signal mask,
adding the signal to be delivered, and
@@ -140,7 +141,7 @@ with names as in the include file
.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" Xr abort 2
+.It Dv SIGABRT No " create core image" Xr abort 3
call (formerly
.Dv SIGIOT )
.It Dv SIGEMT No " create core image" " emulate instruction executed"
@@ -148,7 +149,7 @@ call (formerly
.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" " system call given invalid argument"
+.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"
@@ -289,7 +290,7 @@ or
.Xr sigsuspend 2 ,
.Xr setjmp 3 ,
.Xr siginterrupt 3 ,
-.Xr signal 3,
+.Xr signal 3 ,
.Xr sigsetops 3 ,
.Xr tty 4
.Sh EXAMPLE
diff --git a/lib/libc/db/Makefile.inc b/lib/libc/db/Makefile.inc
index 77af9c5..518205c 100644
--- a/lib/libc/db/Makefile.inc
+++ b/lib/libc/db/Makefile.inc
@@ -1,10 +1,11 @@
-# @(#)Makefile.inc 8.2 (Berkeley) 2/21/94
+# from @(#)Makefile.inc 8.2 (Berkeley) 2/21/94
+# $Id$
#
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"
+.include "${.CURDIR}/../libc/db/btree/Makefile.inc"
+.include "${.CURDIR}/../libc/db/db/Makefile.inc"
+.include "${.CURDIR}/../libc/db/hash/Makefile.inc"
+.include "${.CURDIR}/../libc/db/man/Makefile.inc"
+.include "${.CURDIR}/../libc/db/mpool/Makefile.inc"
+.include "${.CURDIR}/../libc/db/recno/Makefile.inc"
diff --git a/lib/libc/db/README b/lib/libc/db/README
new file mode 100644
index 0000000..bed2c92
--- /dev/null
+++ b/lib/libc/db/README
@@ -0,0 +1,40 @@
+# @(#)README 8.27 (Berkeley) 9/1/94
+
+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.
+
+============================================
+Debugging:
+
+If you're running a memory checker (e.g. Purify) on DB, make sure that
+you recompile it with "-DPURIFY" in the CFLAGS, first. By default,
+allocated pages are not initialized by the DB code, and they will show
+up as reads of uninitialized memory in the buffer write routines.
diff --git a/lib/libc/db/btree/Makefile.inc b/lib/libc/db/btree/Makefile.inc
index 8ed7649..f373a21 100644
--- a/lib/libc/db/btree/Makefile.inc
+++ b/lib/libc/db/btree/Makefile.inc
@@ -1,6 +1,7 @@
-# @(#)Makefile.inc 8.2 (Berkeley) 7/14/94
+# from @(#)Makefile.inc 8.2 (Berkeley) 7/14/94
+# $Id$
-.PATH: ${.CURDIR}/db/btree
+.PATH: ${.CURDIR}/../libc/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 \
diff --git a/lib/libc/db/btree/bt_open.c b/lib/libc/db/btree/bt_open.c
index f052249..5fc3168 100644
--- a/lib/libc/db/btree/bt_open.c
+++ b/lib/libc/db/btree/bt_open.c
@@ -125,7 +125,7 @@ __bt_open(fname, flags, mode, openinfo, dflags)
*/
if (b.psize &&
(b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 ||
- b.psize & sizeof(indx_t) - 1))
+ b.psize & (sizeof(indx_t) - 1) ))
goto einval;
/* Minimum number of keys per page; absolute minimum is 2. */
@@ -245,7 +245,7 @@ __bt_open(fname, flags, mode, openinfo, dflags)
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)
+ m.psize & (sizeof(indx_t) - 1) )
goto eftype;
if (m.flags & ~SAVEMETA)
goto eftype;
@@ -278,8 +278,8 @@ __bt_open(fname, flags, mode, openinfo, dflags)
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.cachesize & (b.psize - 1) )
+ b.cachesize += (~b.cachesize & (b.psize - 1) ) + 1;
if (b.cachesize < b.psize * MINCACHE)
b.cachesize = b.psize * MINCACHE;
diff --git a/lib/libc/db/VERSION b/lib/libc/db/changelog
index be08b78..1540ca8 100644
--- a/lib/libc/db/VERSION
+++ b/lib/libc/db/changelog
@@ -1,39 +1,45 @@
-# @(#)VERSION 8.9 (Berkeley) 4/2/94
-
-This is version 1.74 of the Berkeley DB code.
-
-If your version of the DB code doesn't have a copy
-of this version file, it's really old, please update it!
-
-New versions of this software are periodically made
-available by anonymous ftp from ftp.cs.berkeley.edu,
-in the file ucb/4bsd/db.tar.Z, or from ftp.uu.net.
-If you'd like to get 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.
-VERSION This file.
-btree B+tree routines.
-db Dbopen(3) interface routine.
-doc USENIX papers, formatted manual pages.
-hash Extended linear hashing routines.
-man Unformatted manual pages.
-mpool Memory pool routines.
-recno Fixed/variable length record routines.
-test Test package.
-
-============================================
+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
@@ -52,7 +58,7 @@ test Test package.
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
diff --git a/lib/libc/db/db/Makefile.inc b/lib/libc/db/db/Makefile.inc
index 59478ba1..a10f0fc 100644
--- a/lib/libc/db/db/Makefile.inc
+++ b/lib/libc/db/db/Makefile.inc
@@ -1,5 +1,6 @@
-# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
-.PATH: ${.CURDIR}/db/db
+.PATH: ${.CURDIR}/../libc/db/db
SRCS+= db.c
diff --git a/lib/libc/db/doc/hash.usenix.ps b/lib/libc/db/doc/hash.usenix.ps
deleted file mode 100644
index c884778..0000000
--- a/lib/libc/db/doc/hash.usenix.ps
+++ /dev/null
@@ -1,12209 +0,0 @@
-%!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: $Header: psdit.pro,v 2.1 85/11/24 12:19:43 shore Rel $
-
-% 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/doc/libtp.usenix.ps b/lib/libc/db/doc/libtp.usenix.ps
deleted file mode 100644
index ea821a9..0000000
--- a/lib/libc/db/doc/libtp.usenix.ps
+++ /dev/null
@@ -1,12340 +0,0 @@
-%!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: $Header: psdit.pro,v 2.1 85/11/24 12:19:43 shore Rel $
-
-% 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
index cac96fe..080a1a2 100644
--- a/lib/libc/db/hash/Makefile.inc
+++ b/lib/libc/db/hash/Makefile.inc
@@ -1,6 +1,7 @@
-# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
-.PATH: ${.CURDIR}/db/hash
+.PATH: ${.CURDIR}/../libc/db/hash
SRCS+= hash.c hash_bigkey.c hash_buf.c hash_func.c hash_log2.c \
hash_page.c hsearch.c ndbm.c
diff --git a/lib/libc/db/hash/hash.c b/lib/libc/db/hash/hash.c
index 4b7b732..7d000dc 100644
--- a/lib/libc/db/hash/hash.c
+++ b/lib/libc/db/hash/hash.c
@@ -130,6 +130,13 @@ __hash_open(file, flags, mode, info, dflags)
if (file) {
if ((hashp->fp = open(file, flags, mode)) == -1)
RETURN_ERROR(errno, error0);
+
+ /* if the .db file is empty, and we had permission to create
+ a new .db file, then reinitialize the database */
+ if ((flags & O_CREAT) &&
+ fstat(hashp->fp, &statbuf) == 0 && statbuf.st_size == 0)
+ new_table = 1;
+
(void)fcntl(hashp->fp, F_SETFD, 1);
}
if (new_table) {
@@ -505,7 +512,7 @@ flush_meta(hashp)
else
if (wsize != sizeof(HASHHDR)) {
errno = EFTYPE;
- hashp->errno = errno;
+ hashp->error = errno;
return (-1);
}
for (i = 0; i < NCACHED; i++)
@@ -536,7 +543,7 @@ hash_get(dbp, key, data, flag)
hashp = (HTAB *)dbp->internal;
if (flag) {
- hashp->errno = errno = EINVAL;
+ hashp->error = errno = EINVAL;
return (ERROR);
}
return (hash_access(hashp, HASH_GET, (DBT *)key, data));
@@ -553,11 +560,11 @@ hash_put(dbp, key, data, flag)
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_NOOVERWRITE) {
- hashp->errno = errno = EINVAL;
+ hashp->error = errno = EINVAL;
return (ERROR);
}
if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
- hashp->errno = errno = EPERM;
+ hashp->error = errno = EPERM;
return (ERROR);
}
return (hash_access(hashp, flag == R_NOOVERWRITE ?
@@ -574,11 +581,11 @@ hash_delete(dbp, key, flag)
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_CURSOR) {
- hashp->errno = errno = EINVAL;
+ hashp->error = errno = EINVAL;
return (ERROR);
}
if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
- hashp->errno = errno = EPERM;
+ hashp->error = errno = EPERM;
return (ERROR);
}
return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
@@ -729,7 +736,7 @@ hash_seq(dbp, key, data, flag)
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_FIRST && flag != R_NEXT) {
- hashp->errno = errno = EINVAL;
+ hashp->error = errno = EINVAL;
return (ERROR);
}
#ifdef HASH_STATISTICS
@@ -868,7 +875,7 @@ hash_realloc(p_ptr, oldsize, newsize)
{
register void *p;
- if (p = malloc(newsize)) {
+ if ( (p = malloc(newsize)) ) {
memmove(p, *p_ptr, oldsize);
memset((char *)p + oldsize, 0, newsize - oldsize);
free(*p_ptr);
diff --git a/lib/libc/db/hash/hash.h b/lib/libc/db/hash/hash.h
index 913e82b..504a9b6 100644
--- a/lib/libc/db/hash/hash.h
+++ b/lib/libc/db/hash/hash.h
@@ -103,7 +103,7 @@ typedef struct htab { /* Memory resident data structure */
BUFHEAD *cpage; /* Current page */
int cbucket; /* Current bucket */
int cndx; /* Index of next item on cpage */
- int errno; /* Error Number -- for DBM
+ int error; /* Error Number -- for DBM
* compatability */
int new_file; /* Indicates if fd is backing store
* or no */
@@ -194,7 +194,7 @@ typedef struct htab { /* Memory resident data structure */
* 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
@@ -229,7 +229,7 @@ typedef struct htab { /* Memory resident data structure */
* OVFL_PAGENO - page number of the next overflow page
* OVFLPAGE -- 0
*
- * FULL_KEY_DATA
+ * FULL_KEY_DATA
* This must be the first key/data pair on the page.
* There are two cases:
*
diff --git a/lib/libc/db/hash/hash_bigkey.c b/lib/libc/db/hash/hash_bigkey.c
index 578314a..0cee07e 100644
--- a/lib/libc/db/hash/hash_bigkey.c
+++ b/lib/libc/db/hash/hash_bigkey.c
@@ -590,7 +590,7 @@ __big_split(hashp, op, np, big_keyp, addr, obucket, ret)
return (-1);
change = (__call_hash(hashp, key.data, key.size) != obucket);
- if (ret->next_addr = __find_last_page(hashp, &big_keyp)) {
+ if ( (ret->next_addr = __find_last_page(hashp, &big_keyp)) ) {
if (!(ret->nextp =
__get_buf(hashp, ret->next_addr, big_keyp, 0)))
return (-1);;
diff --git a/lib/libc/db/hash/hash_page.c b/lib/libc/db/hash/hash_page.c
index e1dfe6b..2c05090 100644
--- a/lib/libc/db/hash/hash_page.c
+++ b/lib/libc/db/hash/hash_page.c
@@ -688,7 +688,7 @@ overflow_page(hashp)
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);
diff --git a/lib/libc/db/hash/hsearch.c b/lib/libc/db/hash/hsearch.c
index cc8f7a4..6185330 100644
--- a/lib/libc/db/hash/hsearch.c
+++ b/lib/libc/db/hash/hsearch.c
@@ -62,7 +62,7 @@ hcreate(nel)
info.hash = NULL;
info.lorder = 0;
dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR, 0600, &info, 0);
- return ((int)dbp);
+ return (dbp != NULL);
}
extern ENTRY *
diff --git a/lib/libc/db/hash/ndbm.c b/lib/libc/db/hash/ndbm.c
index 2cbbe91..2e8165d 100644
--- a/lib/libc/db/hash/ndbm.c
+++ b/lib/libc/db/hash/ndbm.c
@@ -47,6 +47,7 @@ static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94";
#include <stdio.h>
#include <string.h>
+#include <errno.h>
#include <ndbm.h>
#include "hash.h"
@@ -70,6 +71,11 @@ dbm_open(file, flags, mode)
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));
@@ -92,15 +98,20 @@ dbm_fetch(db, key)
DBM *db;
datum key;
{
- datum retval;
+ datum retdata;
int status;
+ DBT dbtkey, dbtretdata;
- status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
+ dbtkey.data = key.dptr;
+ dbtkey.size = key.dsize;
+ status = (db->get)(db, &dbtkey, &dbtretdata, 0);
if (status) {
- retval.dptr = NULL;
- retval.dsize = 0;
+ dbtretdata.data = NULL;
+ dbtretdata.size = 0;
}
- return (retval);
+ retdata.dptr = dbtretdata.data;
+ retdata.dsize = dbtretdata.size;
+ return (retdata);
}
/*
@@ -113,11 +124,14 @@ dbm_firstkey(db)
DBM *db;
{
int status;
- datum retdata, retkey;
+ datum retkey;
+ DBT dbtretkey, dbtretdata;
- status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+ status = (db->seq)(db, &dbtretkey, &dbtretdata, R_FIRST);
if (status)
- retkey.dptr = NULL;
+ dbtretkey.data = NULL;
+ retkey.dptr = dbtretkey.data;
+ retkey.dsize = dbtretkey.size;
return (retkey);
}
@@ -131,13 +145,17 @@ dbm_nextkey(db)
DBM *db;
{
int status;
- datum retdata, retkey;
+ datum retkey;
+ DBT dbtretkey, dbtretdata;
- status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+ status = (db->seq)(db, &dbtretkey, &dbtretdata, R_NEXT);
if (status)
- retkey.dptr = NULL;
+ dbtretkey.data = NULL;
+ retkey.dptr = dbtretkey.data;
+ retkey.dsize = dbtretkey.size;
return (retkey);
}
+
/*
* Returns:
* 0 on success
@@ -149,8 +167,11 @@ dbm_delete(db, key)
datum key;
{
int status;
+ DBT dbtkey;
- status = (db->del)(db, (DBT *)&key, 0);
+ dbtkey.data = key.dptr;
+ dbtkey.size = key.dsize;
+ status = (db->del)(db, &dbtkey, 0);
if (status)
return (-1);
else
@@ -164,12 +185,18 @@ dbm_delete(db, key)
* 1 if DBM_INSERT and entry exists
*/
extern int
-dbm_store(db, key, content, flags)
+dbm_store(db, key, data, flags)
DBM *db;
- datum key, content;
+ datum key, data;
int flags;
{
- return ((db->put)(db, (DBT *)&key, (DBT *)&content,
+ 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));
}
@@ -180,7 +207,7 @@ dbm_error(db)
HTAB *hp;
hp = (HTAB *)db->internal;
- return (hp->errno);
+ return (hp->error);
}
extern int
@@ -190,7 +217,7 @@ dbm_clearerr(db)
HTAB *hp;
hp = (HTAB *)db->internal;
- hp->errno = 0;
+ hp->error = 0;
return (0);
}
diff --git a/lib/libc/db/man/Makefile.inc b/lib/libc/db/man/Makefile.inc
index d8d93f9..a1474b1 100644
--- a/lib/libc/db/man/Makefile.inc
+++ b/lib/libc/db/man/Makefile.inc
@@ -1,7 +1,12 @@
-# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# #Id$
-.PATH: ${.CURDIR}/db/man
+.PATH: ${.CURDIR}/../libc/db/man
+# Only build man pages with libc.
+.if ${LIB} == "c"
# mpool.3
-MAN3+= btree.0 dbopen.0 hash.0 recno.0
+MAN3+= db/man/btree.3 db/man/dbopen.3 db/man/hash.3 db/man/recno.3
+MAN3+= db/man/mpool.3
MLINKS+= dbopen.3 db.3
+.endif
diff --git a/lib/libc/db/man/hash.3 b/lib/libc/db/man/hash.3
index 4367031..d408b5d 100644
--- a/lib/libc/db/man/hash.3
+++ b/lib/libc/db/man/hash.3
@@ -131,11 +131,11 @@ If a hash function is specified,
will attempt to determine if the hash 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 routines described in
-.IR dbm (3),
+Backward compatible interfaces to the older
+.I dbm
and
-.IR ndbm (3)
-are provided, however these interfaces are not compatible with
+.I ndbm
+routines are provided, however these interfaces are not compatible with
previous file formats.
.SH ERRORS
The
diff --git a/lib/libc/db/man/mpool.3 b/lib/libc/db/man/mpool.3
index c17606e..e625dc4 100644
--- a/lib/libc/db/man/mpool.3
+++ b/lib/libc/db/man/mpool.3
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)mpool.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.TH MPOOL 3 "June 4, 1993"
.UC 7
@@ -115,7 +116,7 @@ If the
.I pgout
function is specified, it is called each time a buffer is written into the
backing file.
-Both functions are are called with the
+Both functions are called with the
.I pgcookie
pointer, the page number and a pointer to the page to being read or written.
.PP
diff --git a/lib/libc/db/man/recno.3 b/lib/libc/db/man/recno.3
index 516bef0..bb5f353 100644
--- a/lib/libc/db/man/recno.3
+++ b/lib/libc/db/man/recno.3
@@ -204,10 +204,10 @@ or the following:
An attempt was made to add a record to a fixed-length database that
was too large to fit.
.SH "SEE ALSO"
-.IR btree (3)
+.IR btree (3),
.IR dbopen (3),
.IR hash (3),
-.IR mpool (3),
+.IR mpool (3)
.sp
.IR "Document Processing in a Relational Database System" ,
Michael Stonebraker, Heidi Stettner, Joseph Kalash, Antonin Guttman,
diff --git a/lib/libc/db/mpool/Makefile.inc b/lib/libc/db/mpool/Makefile.inc
index 93210c8..c8f2949 100644
--- a/lib/libc/db/mpool/Makefile.inc
+++ b/lib/libc/db/mpool/Makefile.inc
@@ -1,5 +1,6 @@
-# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
-.PATH: ${.CURDIR}/db/mpool
+.PATH: ${.CURDIR}/../libc/db/mpool
SRCS+= mpool.c
diff --git a/lib/libc/db/mpool/mpool.libtp b/lib/libc/db/mpool/mpool.libtp
index 8c0fc27..dbb0469 100644
--- a/lib/libc/db/mpool/mpool.libtp
+++ b/lib/libc/db/mpool/mpool.libtp
@@ -1,6 +1,6 @@
/******************************************************************************
-VERSION $Id: buf.c,v 1.26 92/01/09 09:15:26 margo Exp $
+VERSION $Id$
PACKAGE: User Level Shared Memory Manager
DESCRIPTION:
diff --git a/lib/libc/db/recno/Makefile.inc b/lib/libc/db/recno/Makefile.inc
index e49e225..5241fa5 100644
--- a/lib/libc/db/recno/Makefile.inc
+++ b/lib/libc/db/recno/Makefile.inc
@@ -1,6 +1,7 @@
-# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
-.PATH: ${.CURDIR}/db/recno
+.PATH: ${.CURDIR}/../libc/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/rec_close.c b/lib/libc/db/recno/rec_close.c
index 16fb0b4..1c124de 100644
--- a/lib/libc/db/recno/rec_close.c
+++ b/lib/libc/db/recno/rec_close.c
@@ -155,7 +155,7 @@ __rec_sync(dbp, flags)
status = (dbp->seq)(dbp, &key, &data, R_NEXT);
}
} else {
- iov[1].iov_base = &t->bt_bval;
+ iov[1].iov_base = (char *)&t->bt_bval;
iov[1].iov_len = 1;
status = (dbp->seq)(dbp, &key, &data, R_FIRST);
diff --git a/lib/libc/db/recno/rec_open.c b/lib/libc/db/recno/rec_open.c
index 51d8a3c..8f8eff2 100644
--- a/lib/libc/db/recno/rec_open.c
+++ b/lib/libc/db/recno/rec_open.c
@@ -169,7 +169,7 @@ slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
t->bt_msize = sb.st_size;
if ((t->bt_smap = mmap(NULL, t->bt_msize,
PROT_READ, MAP_PRIVATE, rfd,
- (off_t)0)) == (caddr_t)-1)
+ (off_t)0)) == MAP_FAILED)
goto slow;
t->bt_cmap = t->bt_smap;
t->bt_emap = t->bt_smap + sb.st_size;
diff --git a/lib/libc/db/test/btree.tests/main.c b/lib/libc/db/test/btree.tests/main.c
index f26e193..39c1da0 100644
--- a/lib/libc/db/test/btree.tests/main.c
+++ b/lib/libc/db/test/btree.tests/main.c
@@ -629,7 +629,7 @@ load(db, argv)
key.size = sizeof(recno_t);
data.data = lp;
data.size = len + 1;
- } else {
+ } else {
key.data = lp;
key.size = len + 1;
for (p = lp + len - 1, t = buf; p >= lp; *t++ = *p--);
diff --git a/lib/libc/db/test/hash.tests/driver2.c b/lib/libc/db/test/hash.tests/driver2.c
index 2008a28..896820c 100644
--- a/lib/libc/db/test/hash.tests/driver2.c
+++ b/lib/libc/db/test/hash.tests/driver2.c
@@ -110,5 +110,5 @@ main(argc, argv)
exit(0);
}
-
+
diff --git a/lib/libc/db/test/hash.tests/tcreat3.c b/lib/libc/db/test/hash.tests/tcreat3.c
index bd125ac..31211c5 100644
--- a/lib/libc/db/test/hash.tests/tcreat3.c
+++ b/lib/libc/db/test/hash.tests/tcreat3.c
@@ -97,7 +97,7 @@ char **argv;
fprintf(stderr, "cannot enter: key %s\n",
item.data);
exit(1);
- }
+ }
}
(dbp->close)(dbp);
diff --git a/lib/libc/db/test/hash.tests/tdel.c b/lib/libc/db/test/hash.tests/tdel.c
index ed3f90a..fb99431 100644
--- a/lib/libc/db/test/hash.tests/tdel.c
+++ b/lib/libc/db/test/hash.tests/tdel.c
@@ -99,7 +99,7 @@ char **argv;
fprintf(stderr, "cannot enter: key %s\n",
item.data);
exit(1);
- }
+ }
}
if ( --argc ) {
@@ -113,7 +113,7 @@ char **argv;
if (stat) {
fprintf ( stderr, "Error retrieving %s\n", key.data );
exit(1);
- }
+ }
}
fclose(fp);
}
diff --git a/lib/libc/db/test/hash.tests/thash4.c b/lib/libc/db/test/hash.tests/thash4.c
index 9e344cb..952dccb 100644
--- a/lib/libc/db/test/hash.tests/thash4.c
+++ b/lib/libc/db/test/hash.tests/thash4.c
@@ -86,8 +86,8 @@ char **argv;
key.data = wp1;
item.data = wp2;
- while ( fgets(wp1, 8192, stdin) &&
- fgets(wp2, 8192, stdin) &&
+ while ( fgets(wp1, 8192, stdin) &&
+ fgets(wp2, 8192, stdin) &&
i++ < MAXWORDS) {
/*
* put info in structure, and structure in the item
@@ -103,14 +103,14 @@ char **argv;
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) &&
+ while ( fgets(wp1, 256, fp) &&
+ fgets(wp2, 8192, fp) &&
i++ < MAXWORDS) {
key.size = strlen(wp1);
diff --git a/lib/libc/db/test/hash.tests/tseq.c b/lib/libc/db/test/hash.tests/tseq.c
index f45700e..f41c172 100644
--- a/lib/libc/db/test/hash.tests/tseq.c
+++ b/lib/libc/db/test/hash.tests/tseq.c
@@ -72,7 +72,7 @@ char **argv;
/*
* put info in structure, and structure in the item
*/
- for ( stat = (dbp->seq) (dbp, &res, &item, 1 );
+ for ( stat = (dbp->seq) (dbp, &res, &item, 1 );
stat == 0;
stat = (dbp->seq) (dbp, &res, &item, 0 ) ) {
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index b24f7da..59ffcbb 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -1,56 +1,80 @@
# @(#)Makefile.inc 8.6 (Berkeley) 5/4/95
+# $Id: Makefile.inc,v 1.35 1997/06/14 01:15:41 ache Exp $
# machine-independent gen sources
-.PATH: ${.CURDIR}/${MACHINE}/gen ${.CURDIR}/gen
+.PATH: ${.CURDIR}/../libc/${MACHINE}/gen ${.CURDIR}/../libc/gen
-SRCS+= alarm.c assert.c clock.c closedir.c confstr.c crypt.c ctermid.c \
- ctime.c daemon.c devname.c difftime.c disklabel.c err.c errlst.c \
- exec.c fnmatch.c frexp.c fstab.c fts.c getbsize.c getcap.c getcwd.c \
- getgrent.c getgrouplist.c gethostname.c getloadavg.c getlogin.c \
- getmntinfo.c getnetgrent.c getpagesize.c getpass.c getpwent.c \
- getttyent.c getusershell.c getvfsbyname.c glob.c initgroups.c isatty.c \
- nice.c nlist.c opendir.c pause.c popen.c psignal.c pwcache.c raise.c \
- readdir.c rewinddir.c scandir.c seekdir.c sethostname.c setjmperr.c \
- setmode.c siginterrupt.c siglist.c signal.c \
- sigsetops.c sleep.c sysconf.c sysctl.c syslog.c telldir.c \
- termios.c time.c times.c timezone.c ttyname.c ttyslot.c ualarm.c \
- uname.c unvis.c usleep.c utime.c valloc.c vis.c wait.c wait3.c \
- waitpid.c
+SRCS+= alarm.c arc4random.c assert.c clock.c closedir.c config.c confstr.c \
+ crypt.c ctermid.c daemon.c devname.c disklabel.c err.c errlst.c \
+ exec.c fnmatch.c frexp.c fstab.c fts.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 getpass.c getpwent.c getttyent.c \
+ getusershell.c getvfsbyname.c getvfsent.c glob.c \
+ initgroups.c isatty.c msgctl.c \
+ msgget.c msgrcv.c msgsnd.c nice.c nlist.c ntp_gettime.c opendir.c \
+ pause.c popen.c psignal.c pwcache.c raise.c readdir.c rewinddir.c \
+ scandir.c seekdir.c semconfig.c semctl.c semget.c semop.c \
+ setdomainname.c sethostname.c setjmperr.c setmode.c shmat.c \
+ shmctl.c shmdt.c shmget.c siginterrupt.c siglist.c signal.c \
+ sigsetops.c sleep.c stringlist.c sysconf.c sysctl.c sysctlbyname.c \
+ syslog.c telldir.c termios.c time.c times.c timezone.c ttyname.c \
+ ttyslot.c ualarm.c uname.c unvis.c usleep.c utime.c valloc.c vis.c \
+ wait.c wait3.c waitpid.c
+
+# *rand48 family, from 1.1.5
+SRCS+= _rand48.c drand48.c erand48.c jrand48.c lcong48.c lrand48.c \
+ mrand48.c nrand48.c seed48.c srand48.c
# machine-dependent gen sources
-.include "${.CURDIR}/${MACHINE}/gen/Makefile.inc"
+.include "${.CURDIR}/../libc/${MACHINE}/gen/Makefile.inc"
.if (${MACHINE} == "tahoe" || ${MACHINE} == "vax")
errlst.o errlst.po:
${CC} -S ${CFLAGS} ${.IMPSRC}
- ed - < ${.CURDIR}/${MACHINE}/:errfix errlst.s
+ ed - < ${.CURDIR}/../libc/${MACHINE}/:errfix errlst.s
${AS} -o ${.TARGET} errlst.s
rm -f errlst.s
.endif
-MAN3+= alarm.0 clock.0 confstr.0 crypt.0 ctermid.0 ctime.0 daemon.0 \
- devname.0 directory.0 err.0 exec.0 fnmatch.0 frexp.0 fts.0 \
- getbsize.0 getcap.0 getcwd.0 getdiskbyname.0 getfsent.0 \
- getgrent.0 getgrouplist.0 gethostname.0 getloadavg.0 \
- getmntinfo.0 getnetgrent.0 getpagesize.0 getpass.0 getpwent.0 \
- getttyent.0 getusershell.0 getvfsbyname.0 glob.0 initgroups.0 isinf.0 \
- ldexp.0 modf.0 nice.0 nlist.0 pause.0 popen.0 psignal.0 pwcache.0 \
- raise.0 realpath.0 scandir.0 setjmp.0 setmode.0 siginterrupt.0 \
- signal.0 sigsetops.0 sleep.0 sysconf.0 sysctl.0 syslog.0 tcgetpgrp.0 \
- tcsendbreak.0 tcsetattr.0 tcsetpgrp.0 time.0 times.0 timezone.0 \
- ttyname.0 tzset.0 ualarm.0 uname.0 unvis.0 usleep.0 utime.0 \
- valloc.0 vis.0
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN3+= gen/alarm.3 gen/arc4random.3 gen/clock.3 gen/confstr.3 \
+ gen/config_open.3 gen/crypt.3 gen/ctermid.3 \
+ gen/daemon.3 gen/devname.3 gen/directory.3 gen/err.3 gen/exec.3 \
+ gen/fnmatch.3 gen/frexp.3 gen/fts.3 gen/getbsize.3 gen/getbootfile.3 \
+ gen/getcap.3 gen/getcwd.3 gen/getdiskbyname.3 gen/getdomainname.3 \
+ gen/getfsent.3 gen/getgrent.3 gen/getgrouplist.3 gen/gethostname.3 \
+ gen/getloadavg.3 \
+ gen/getmntinfo.3 gen/getnetgrent.3 gen/getpagesize.3 gen/getpass.3 \
+ gen/getpwent.3 gen/getttyent.3 gen/getusershell.3 gen/getvfsbyname.3 \
+ gen/getvfsent.3 gen/glob.3 \
+ gen/initgroups.3 gen/isinf.3 gen/ldexp.3 \
+ gen/msgctl.3 gen/msgget.3 gen/msgrcv.3 gen/msgsnd.3 \
+ gen/modf.3 gen/nice.3 \
+ gen/nlist.3 gen/pause.3 gen/popen.3 gen/psignal.3 gen/pwcache.3 \
+ gen/raise.3 gen/rand48.3 \
+ gen/scandir.3 gen/setjmp.3 gen/setmode.3 \
+ gen/siginterrupt.3 gen/signal.3 gen/sigsetops.3 gen/sleep.3 \
+ gen/stringlist.3 \
+ gen/sysconf.3 gen/sysctl.3 gen/syslog.3 gen/tcgetpgrp.3 \
+ gen/tcsendbreak.3 gen/tcsetattr.3 gen/tcsetpgrp.3 gen/time.3 \
+ gen/times.3 gen/timezone.3 gen/ttyname.3 gen/tzset.3 gen/ualarm.3 \
+ gen/uname.3 gen/unvis.3 gen/usleep.3 gen/utime.3 gen/valloc.3 gen/vis.3
-MLINKS+=crypt.3 encrypt.3 crypt.3 setkey.3
-MLINKS+=ctime.3 asctime.3 ctime.3 difftime.3 ctime.3 gmtime.3 \
- ctime.3 localtime.3 ctime.3 mktime.3
+MLINKS+=arc4random.3 arc4random_stir.3 arc4random.3 arc4random_addrandom.3
+MLINKS+=config_open.3 config_next.3 config_open.3 config_close.3 \
+ config_open.3 config_skip.3
+MLINKS+=crypt.3 encrypt.3 crypt.3 setkey.3 crypt.3 des_setkey.3 \
+ crypt.3 des_cipher.3
MLINKS+=directory.3 closedir.3 directory.3 dirfd.3 directory.3 opendir.3 \
directory.3 readdir.3 directory.3 rewinddir.3 directory.3 seekdir.3 \
directory.3 telldir.3
MLINKS+=exec.3 execl.3 exec.3 execle.3 exec.3 execlp.3 exec.3 execv.3 \
- exec.3 execvp.3
+ exec.3 execvp.3 exec.3 exect.3
MLINKS+=err.3 verr.3 err.3 errx.3 err.3 verrx.3 err.3 warn.3 err.3 vwarn.3 \
- err.3 warnx.3 err.3 vwarnx.3
+ err.3 warnx.3 err.3 vwarnx.3 err.3 err_set_file.3 \
+ err.3 err_set_exit.3
MLINKS+=isinf.3 isnan.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 \
@@ -60,18 +84,28 @@ MLINKS+=getcwd.3 getwd.3
MLINKS+=getfsent.3 endfsent.3 getfsent.3 getfsfile.3 getfsent.3 getfsspec.3 \
getfsent.3 getfstype.3 getfsent.3 setfsent.3
MLINKS+=getgrent.3 endgrent.3 getgrent.3 setgroupent.3 getgrent.3 getgrgid.3 \
- getgrent.3 getgrnam.3 getgrent.3 setgrent.3 getgrent.3 setgrfile.3
+ getgrent.3 getgrnam.3 getgrent.3 setgrent.3
MLINKS+=gethostname.3 sethostname.3
+MLINKS+=getdomainname.3 setdomainname.3
MLINKS+=getnetgrent.3 endnetgrent.3 getnetgrent.3 setnetgrent.3 \
getnetgrent.3 innetgr.3
MLINKS+=getpwent.3 endpwent.3 getpwent.3 setpassent.3 getpwent.3 getpwnam.3 \
getpwent.3 getpwuid.3 getpwent.3 setpwent.3 getpwent.3 setpwfile.3
-MLINKS+=getttyent.3 endttyent.3 getttyent.3 getttynam.3 getttyent.3 setttyent.3
+MLINKS+=getttyent.3 endttyent.3 getttyent.3 getttynam.3 \
+ getttyent.3 setttyent.3 getttyent.3 isdialuptty.3 \
+ getttyent.3 isnetworktty.3
+MLINKS+=getvfsent.3 getvfsbytype.3 \
+ getvfsent.3 setvfsent.3 getvfsent.3 endvfsent.3 \
+ getvfsent.3 vfsisloadable.3 getvfsent.3 vfsload.3
MLINKS+=getusershell.3 endusershell.3 getusershell.3 setusershell.3
MLINKS+=glob.3 globfree.3
MLINKS+=popen.3 pclose.3
-MLINKS+=psignal.3 sys_siglist.3
+MLINKS+=psignal.3 sys_siglist.3 psignal.3 sys_signame.3
MLINKS+=pwcache.3 user_from_uid.3 pwcache.3 group_from_gid.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+=setjmp.3 _longjmp.3 setjmp.3 _setjmp.3 setjmp.3 longjmp.3 \
setjmp.3 longjmperr.3 setjmp.3 longjmperror.3 \
@@ -90,3 +124,7 @@ MLINKS+=tcsetattr.3 tcgetattr.3 tcsetattr.3 cfsetospeed.3 \
MLINKS+=ttyname.3 isatty.3 ttyname.3 ttyslot.3
MLINKS+=tzset.3 tzsetwall.3
MLINKS+=vis.3 strvis.3 vis.3 strvisx.3
+MLINKS+=unvis.3 strunvis.3
+MLINKS+=fts.3 fts_open.3 fts.3 fts_read.3 fts.3 fts_children.3 \
+ fts.3 fts_close.3 fts.3 fts_set.3
+.endif
diff --git a/lib/libc/gen/__xuname.c b/lib/libc/gen/__xuname.c
new file mode 100644
index 0000000..25431d4
--- /dev/null
+++ b/lib/libc/gen/__xuname.c
@@ -0,0 +1,125 @@
+/*-
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char sccsid[] = "From: @(#)uname.c 8.1 (Berkeley) 1/4/94";*/
+static const char rcsid[] =
+ "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/utsname.h>
+#include <errno.h>
+
+int
+uname(name)
+ struct utsname *name;
+{
+ int mib[2], rval;
+ size_t len;
+ char *p;
+ int oerrno;
+
+ rval = 0;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_OSTYPE;
+ len = sizeof(name->sysname);
+ oerrno = errno;
+ if (sysctl(mib, 2, &name->sysname, &len, NULL, 0) == -1) {
+ if(errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ name->sysname[sizeof(name->sysname) - 1] = '\0';
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTNAME;
+ len = sizeof(name->nodename);
+ oerrno = errno;
+ if (sysctl(mib, 2, &name->nodename, &len, NULL, 0) == -1) {
+ if(errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ name->nodename[sizeof(name->nodename) - 1] = '\0';
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_OSRELEASE;
+ len = sizeof(name->release);
+ oerrno = errno;
+ if (sysctl(mib, 2, &name->release, &len, NULL, 0) == -1) {
+ if(errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ name->release[sizeof(name->release) - 1] = '\0';
+
+ /* The version may have newlines in it, turn them into spaces. */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_VERSION;
+ len = sizeof(name->version);
+ oerrno = errno;
+ if (sysctl(mib, 2, &name->version, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ name->version[sizeof(name->version) - 1] = '\0';
+ for (p = name->version; len--; ++p) {
+ if (*p == '\n' || *p == '\t') {
+ if (len > 1)
+ *p = ' ';
+ else
+ *p = '\0';
+ }
+ }
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_MACHINE;
+ len = sizeof(name->machine);
+ oerrno = errno;
+ if (sysctl(mib, 2, &name->machine, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ name->machine[sizeof(name->machine) - 1] = '\0';
+ return (rval);
+}
diff --git a/lib/libc/gen/_rand48.c b/lib/libc/gen/_rand48.c
new file mode 100644
index 0000000..990e2c8
--- /dev/null
+++ b/lib/libc/gen/_rand48.c
@@ -0,0 +1,46 @@
+/*
+ * 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"
+
+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/alarm.3 b/lib/libc/gen/alarm.3
index fb1893f..4d99fa1 100644
--- a/lib/libc/gen/alarm.3
+++ b/lib/libc/gen/alarm.3
@@ -39,8 +39,8 @@
.Nd set signal timer alarm
.Sh SYNOPSIS
.Fd #include <unistd.h>
-.Ft u_int
-.Fn alarm "u_int seconds"
+.Ft unsigned int
+.Fn alarm "unsigned int seconds"
.Sh DESCRIPTION
.Bf -symbolic
This interface is made obsolete by setitimer(2).
@@ -48,37 +48,42 @@ This interface is made obsolete by setitimer(2).
.Pp
The
.Fn alarm
-function
-waits a count of
-.Ar seconds
-before asserting the terminating signal
-.Dv SIGALRM .
-When the signal has successfully been caught,
+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
-returns the amount of time left on the clock.
-The maximum number of
+will supersede the prior call.
+The request
+.Fn alarm "0"
+voids the current
+alarm and the signal SIGALRM will not be delivered. The maximum number of
.Ar seconds
allowed
is 2147483647.
.Pp
-If an alarm has been set with
-.Fn alarm ,
-another call to
+The return value of
.Fn alarm
-will supersede the prior call.
-The request
-.Fn alarm "0"
-voids the current
-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 sigaction 2 ,
.Xr setitimer 2 ,
+.Xr sigaction 2 ,
.Xr sigpause 2 ,
.Xr sigvec 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
diff --git a/lib/libc/gen/arc4random.3 b/lib/libc/gen/arc4random.3
new file mode 100644
index 0000000..25c6d4d
--- /dev/null
+++ b/lib/libc/gen/arc4random.3
@@ -0,0 +1,83 @@
+.\" $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
+.\"
+.Dd April 15, 1997
+.Dt ARC4RANDOM 3
+.Os
+.Sh NAME
+.Nm arc4random,
+.Nm arc4random_stir,
+.Nm arc4random_addrandom
+.Nd arc4 random number generator.
+.Sh SYNOPSIS
+.Fd #include <stdlib.h>
+.Ft u_int32_t
+.Fn arc4random "void"
+.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.
+.Pp
+The
+.Fn arc4random_stir
+function reads data from
+.Pa /dev/urandom
+and uses it to permutate the S-Boxes via
+.Fn arc4random_addrandom .
+.Pp
+There is no need to call
+.Fn arc4random_stir
+before using
+.Fn arc4random ,
+since
+.Fn arc4random
+automatically initalizes itself.
+.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 refered to as
+.Pa ARC4 .
diff --git a/lib/libc/gen/arc4random.c b/lib/libc/gen/arc4random.c
new file mode 100644
index 0000000..b9f8a48
--- /dev/null
+++ b/lib/libc/gen/arc4random.c
@@ -0,0 +1,172 @@
+/* $Id: arc4random.c,v 1.1 1996/12/28 06:33:01 dm Exp $ */
+
+/*
+ * Arc4 random number generator for OpenBSD.
+ * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
+ *
+ * Modification and redistribution in source and binary forms is
+ * permitted provided that due credit is given to the author and the
+ * OpenBSD project (for instance by leaving this copyright notice
+ * intact).
+ */
+
+/*
+ * 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.
+ *
+ * Here the stream cipher has been modified always to include the time
+ * when initializing the state. That makes it impossible to
+ * regenerate the same random sequence twice, so this can't be used
+ * for encryption, but will generate good random numbers.
+ *
+ * RC4 is a registered trademark of RSA Laboratories.
+ */
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+struct arc4_stream {
+ u_int8_t i;
+ u_int8_t j;
+ u_int8_t s[256];
+};
+
+static int rs_initialized;
+static struct arc4_stream rs;
+
+static inline void
+arc4_init(as)
+ struct arc4_stream *as;
+{
+ int n;
+
+ for (n = 0; n < 256; n++)
+ as->s[n] = n;
+ as->i = 0;
+ as->j = 0;
+}
+
+static inline void
+arc4_addrandom(as, dat, datlen)
+ struct arc4_stream *as;
+ u_char *dat;
+ int datlen;
+{
+ int n;
+ u_int8_t si;
+
+ as->i--;
+ for (n = 0; n < 256; n++) {
+ as->i = (as->i + 1);
+ si = as->s[as->i];
+ as->j = (as->j + si + dat[n % datlen]);
+ as->s[as->i] = as->s[as->j];
+ as->s[as->j] = si;
+ }
+}
+
+static void
+arc4_stir(as)
+ struct arc4_stream *as;
+{
+ int fd;
+ struct {
+ struct timeval tv;
+ pid_t pid;
+ u_int8_t rnd[128 - sizeof(struct timeval) - sizeof(pid_t)];
+ } rdat;
+
+ gettimeofday(&rdat.tv, NULL);
+ rdat.pid = getpid();
+ fd = open("/dev/urandom", O_RDONLY, 0);
+ if (fd >= 0) {
+ (void) read(fd, rdat.rnd, sizeof(rdat.rnd));
+ close(fd);
+ }
+ /* fd < 0? Ah, what the heck. We'll just take whatever was on the
+ * stack... */
+
+ arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
+}
+
+static inline u_int8_t
+arc4_getbyte(as)
+ struct arc4_stream *as;
+{
+ u_int8_t si, sj;
+
+ as->i = (as->i + 1);
+ si = as->s[as->i];
+ as->j = (as->j + si);
+ sj = as->s[as->j];
+ as->s[as->i] = sj;
+ as->s[as->j] = si;
+ return (as->s[(si + sj) & 0xff]);
+}
+
+static inline u_int32_t
+arc4_getword(as)
+ struct arc4_stream *as;
+{
+ u_int32_t val;
+ val = arc4_getbyte(as) << 24;
+ val |= arc4_getbyte(as) << 16;
+ val |= arc4_getbyte(as) << 8;
+ val |= arc4_getbyte(as);
+ return val;
+}
+
+void
+arc4random_stir()
+{
+ if (!rs_initialized) {
+ arc4_init(&rs);
+ rs_initialized = 1;
+ }
+ arc4_stir(&rs);
+}
+
+void
+arc4random_addrandom(dat, datlen)
+ u_char *dat;
+ int datlen;
+{
+ if (!rs_initialized)
+ arc4random_stir();
+ arc4_addrandom(&rs, dat, datlen);
+}
+
+u_int32_t
+arc4random()
+{
+ if (!rs_initialized)
+ arc4random_stir();
+ return arc4_getword(&rs);
+}
+
+#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
index 4914aca..eb2748c 100644
--- a/lib/libc/gen/assert.c
+++ b/lib/libc/gen/assert.c
@@ -35,7 +35,6 @@
static char sccsid[] = "@(#)assert.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
-#include <sys/types.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/lib/libc/gen/clock.3 b/lib/libc/gen/clock.3
index f70184e..0e5ad06 100644
--- a/lib/libc/gen/clock.3
+++ b/lib/libc/gen/clock.3
@@ -42,7 +42,7 @@
.Nm clock
.Nd determine processor time used
.Sh SYNOPSIS
-.Fd #include <sys/types.h>
+.Fd #include <time.h>
.Ft clock_t
.Fn clock void
.Sh DESCRIPTION
@@ -51,14 +51,16 @@ The
function
determines the amount of processor time used since the invocation of the
calling process, measured in
-.Dv CLK_TCK Ns s.
+.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 getrusage 2 ,
+.Xr clocks 7
.Sh STANDARDS
The
.Fn clock
diff --git a/lib/libc/gen/clock.c b/lib/libc/gen/clock.c
index 12dc866..fe867c2 100644
--- a/lib/libc/gen/clock.c
+++ b/lib/libc/gen/clock.c
@@ -40,10 +40,11 @@ static char sccsid[] = "@(#)clock.c 8.1 (Berkeley) 6/4/93";
#include <sys/resource.h>
/*
- * Convert usec to clock ticks; could do (usec * CLK_TCK) / 1000000,
+ * 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 * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
+#define CONVTCK(r) ((r).tv_sec * CLOCKS_PER_SEC \
+ + (r).tv_usec / (1000000 / CLOCKS_PER_SEC))
clock_t
clock()
diff --git a/lib/libc/gen/closedir.c b/lib/libc/gen/closedir.c
index d3fc00b..6c46e70 100644
--- a/lib/libc/gen/closedir.c
+++ b/lib/libc/gen/closedir.c
@@ -40,6 +40,8 @@ static char sccsid[] = "@(#)closedir.c 8.1 (Berkeley) 6/10/93";
#include <stdlib.h>
#include <unistd.h>
+extern void _reclaim_telldir __P(( const DIR * ));
+
/*
* close a directory.
*/
@@ -53,7 +55,8 @@ closedir(dirp)
fd = dirp->dd_fd;
dirp->dd_fd = -1;
dirp->dd_loc = 0;
- (void)free((void *)dirp->dd_buf);
- (void)free((void *)dirp);
+ free((void *)dirp->dd_buf);
+ free((void *)dirp);
+ _reclaim_telldir(dirp);
return(close(fd));
}
diff --git a/lib/libc/gen/config.c b/lib/libc/gen/config.c
new file mode 100644
index 0000000..2d1ed44
--- /dev/null
+++ b/lib/libc/gen/config.c
@@ -0,0 +1,187 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * This file contains four procedures used to read config-files.
+ *
+ * char * config_open(const char *filename,int contlines)
+ * Will open the named file, read it into a private malloc'ed area,
+ * and close the file again.
+ * All lines where the first !isspace() char is '#' are deleted.
+ * If contlines are non-zero lines where the first char is isspace()
+ * will be joined to the preceeding line.
+ * In case of trouble the name of the offending system call will be
+ * returned. On success NULL is returned.
+ *
+ * void config_close()
+ * This will free the internal malloc'ed area.
+ *
+ * char * config_next()
+ * This will return a pointer to the next entry in the area. NULL is
+ * returned at "end of file". The return value is '\0' terminated, and
+ * can be modified, but the contents must be copied somewhere else for
+ * permanent use.
+ *
+ * char * config_skip(char **p)
+ * This will pick out the next word from the string. The return-value
+ * points to the word found, and *p is advanced past the word. NULL is
+ * returned at "end of string".
+ *
+ * Many programs have a n*100 bytes config-file and N*1000 bytes of source
+ * to read it. Doing pointer-aerobics on files that small is a waste of
+ * time, and bashing around with getchar/ungetc isn't much better. These
+ * routines implement a simple algorithm and syntax.
+ *
+ * config_skip consider a contiguous string of !isspace() chars a word.
+ *
+ * 13nov1994 Poul-Henning Kamp phk@login.dknet.dk
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+
+static char *file_buf;
+static char *ptr;
+
+char *
+config_open(const char *filename, int contlines)
+{
+ int fd;
+ struct stat st;
+ char *p, *q;
+
+ if ((fd = open(filename, O_RDONLY)) < 0)
+ return "open";
+ if (fstat(fd, &st) < 0) {
+ close(fd);
+ return "fstat";
+ }
+ if (file_buf)
+ free(file_buf);
+ file_buf = malloc(st.st_size + 2);
+ if (!file_buf) {
+ close(fd);
+ return "malloc";
+ }
+ if (st.st_size != read(fd, file_buf, st.st_size)) {
+ free(file_buf);
+ file_buf = (char *) 0;
+ close(fd);
+ return "read";
+ }
+ close(fd);
+ file_buf[st.st_size] = '\n';
+ file_buf[st.st_size + 1] = '\0';
+
+ /*
+ * /^[ \t]*#[^\n]*$/d
+ *
+ * Delete all lines where the first !isspace() char is '#'
+ */
+
+ ptr = file_buf;
+ for (p = ptr; *p;) {
+ for (q = p; *q != '\n' && isspace(*q); q++)
+ continue;
+ if (*q == '#') {
+ p = strchr(p, '\n');
+ if (p)
+ p++;
+ } else {
+ q = strchr(p, '\n');
+ q++;
+ memcpy(ptr, p, q - p);
+ ptr += q - p;
+ p = q;
+ }
+ }
+ *ptr = '\0';
+ ptr = file_buf;
+
+ if (!contlines)
+ return 0;
+
+ /* Join all lines starting with a isspace() char to the preceeding
+ * line */
+
+ for (p = ptr; *p;) {
+ q = strchr(p, '\n');
+ if (isspace(*(q + 1)))
+ *q = ' ';
+ p = q + 1;
+ }
+
+ return 0;
+}
+
+void
+config_close(void)
+{
+ if (file_buf)
+ free(file_buf);
+ ptr = file_buf = 0;
+}
+
+/*
+ * Get next entry. config_open did all the weird stuff, so just return
+ * the next line.
+ */
+
+char *
+config_next(void)
+{
+ char *p;
+
+ /* We might be done already ! */
+ if (!ptr || !*ptr)
+ return 0;
+
+ while (isspace(*ptr))
+ ptr++;
+ p = ptr;
+ ptr = strchr(p, '\n');
+ if (ptr) {
+ *ptr = '\0';
+ ptr++;
+ }
+ return p;
+}
+
+/*
+ * Return next word
+ */
+
+char *
+config_skip(char **p)
+{
+ char *q, *r;
+
+ if (!*p || !**p)
+ return 0;
+ for (q = *p; isspace(*q); q++);
+ if (!*q)
+ return 0;
+ for (r = q; *r && !isspace(*r); r++);
+ if (*r)
+ *r++ = '\0';
+ *p = r;
+ return q;
+}
diff --git a/lib/libc/gen/config_open.3 b/lib/libc/gen/config_open.3
new file mode 100644
index 0000000..a2ef707
--- /dev/null
+++ b/lib/libc/gen/config_open.3
@@ -0,0 +1,73 @@
+.\" ----------------------------------------------------------------------------
+.\" "THE BEER-WARE LICENSE" (Revision 42):
+.\" <phk@login.dknet.dk> 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
+.\" ----------------------------------------------------------------------------
+.\"
+.\" $Id$
+.\"
+.Dd November 13, 1994
+.Dt config_open 3
+.Os FreeBSD
+.Sh NAME
+.Nm config_open ,
+.Nm config_close ,
+.Nm config_next ,
+.Nm config_skip
+.Nd read config files
+.Sh SYNOPSIS
+.Ft char *
+.Fn config_open "const char *filename" "int contlines"
+.Ft void
+.Fn config_close
+.Ft char *
+.Fn config_next
+.Ft char *
+.Fn config_skip "char **string"
+.Sh DESCRIPTION
+These functions are used to read config files with the following syntax:
+.Bl -bullet -compact
+.It
+All lines where the first
+.Sq !isspace()
+is '#' are comments which are discarded.
+.It
+If continuation-lines are enabled, any line starting with a
+.Sq isspace()
+character is joined to the preceding line and blank lines are discarded.
+.It
+An entry starts at the first
+.Sq !isspace()
+character and ends at the first
+.Sq Li \en
+.Li .
+.El
+.Pp
+.Fn config_open
+will open the specified
+.Fa filename
+and read it into a private malloced area, and close the file again. If
+.Fa contlines
+is non-zero, continuation lines will be allowed.
+In case of trouble, the name of the system-call causing the trouble will
+be returned. If successful,
+.Fn config_open
+returns NULL.
+.Pp
+.Fn config_close
+will free the malloced area.
+.Pp
+.Fn config_next
+returns the next entry in the area. NULL is returned to indicate End-of-file.
+The returned string is null-terminated.
+.Pp
+.Fn config_skip
+returns the next word from the string
+.Fa *string
+.Li .
+.Fa *string
+will be advanced to point to the next word.
+NULL is returned to indicate the end of the string.
+.Sh AUTHOR
+Poul-Henning Kamp <phk@login.dknet.dk>
diff --git a/lib/libc/gen/confstr.3 b/lib/libc/gen/confstr.3
index 8714452..90115e3 100644
--- a/lib/libc/gen/confstr.3
+++ b/lib/libc/gen/confstr.3
@@ -43,7 +43,8 @@
.Fn confstr "int name" "char *buf" "size_t len"
.Sh DESCRIPTION
.Bf -symbolic
-This interface is obsoleted by sysctl(3).
+This interface is obsoleted by
+.Xr sysctl 3 .
.Ef
.Pp
The
@@ -84,7 +85,7 @@ environment variable that finds all the standard utilities.
.El
.Sh RETURN VALUES
If the call to
-.Nm confstr
+.Fn confstr
is not successful, \-1 is returned and
.Va errno
is set appropriately.
@@ -101,7 +102,7 @@ the string in
was truncated.
.Sh ERRORS
The
-.Nm confstr
+.Fn confstr
function may fail and set
.Va error
for any of the errors specified for the library functions
@@ -119,5 +120,6 @@ argument is invalid.
.Xr sysctl 3
.Sh HISTORY
The
-.Nm confstr
-function first appeared in 4.4BSD.
+.Fn confstr
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/confstr.c b/lib/libc/gen/confstr.c
index cc4df53..0a7078e 100644
--- a/lib/libc/gen/confstr.c
+++ b/lib/libc/gen/confstr.c
@@ -42,6 +42,7 @@ static char sccsid[] = "@(#)confstr.c 8.1 (Berkeley) 6/4/93";
#include <paths.h>
#include <stdlib.h>
#include <unistd.h>
+#include <string.h>
size_t
confstr(name, buf, len)
diff --git a/lib/libc/gen/crypt.3 b/lib/libc/gen/crypt.3
index 7ecf0cf..0f97a70 100644
--- a/lib/libc/gen/crypt.3
+++ b/lib/libc/gen/crypt.3
@@ -29,9 +29,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)crypt.3 8.1.1.1 (Berkeley) 8/18/93
+.\" @(#)crypt.3 8.2 (Berkeley) 12/11/93
.\"
-.Dd August 18, 1993
+.Dd December 11, 1993
.Dt CRYPT 3
.Os
.Sh NAME
@@ -42,10 +42,11 @@
.Nm des_cipher
.Nd DES encryption
.Sh SYNOPSIS
-.Ft char
-.Fn *crypt "const char *key" "const char *setting"
+.Fd #include <unistd.h>
+.Ft char *
+.Fn crypt "const char *key" "const char *setting"
.Ft int
-.Fn setkey "char *key"
+.Fn setkey "const char *key"
.Ft int
.Fn encrypt "char *block" "int flag"
.Ft int
@@ -54,7 +55,7 @@
.Fn des_cipher "const char *in" "char *out" "long salt" "int count"
.Sh DESCRIPTION
The
-.Xr crypt
+.Fn crypt
function
performs password encryption.
It is derived from the
@@ -161,8 +162,9 @@ If the value of
is 0,
the argument
.Fa block
-is encrypted, otherwise it fails.
-The encryption is returned in the original
+is encrypted, otherwise it
+is decrypted.
+The encryption or decryption is returned in the original
array
.Fa block
after using the
@@ -188,7 +190,9 @@ significant bit in each character is ignored and the next 7 bits of each
character are concatenated to yield a 56-bit key.
The function
.Fn des_cipher
-encrypts the 64-bits stored in the 8 characters at
+encrypts (or decrypts if
+.Fa count
+is negative) the 64-bits stored in the 8 characters at
.Fa in
using
.Xr abs 3
@@ -223,12 +227,27 @@ They have been provided return values primarily to distinguish
implementations where hardware support is provided but not
available or where the DES encryption is not available due to the
usual political silliness.
+.Pp
+Use of
+.Fn crypt
+requires linking with the
+.Nm libcrypt
+library. The
+.Fn setkey ,
+.Fn encrypt ,
+.Fn des_setkey
+and
+.Fn des_cipher
+can be found in the
+.Nm libcipher
+library (the standard C library,
+.Nm libc ,
+only contains stubs to these routines).
.Sh SEE ALSO
.Xr login 1 ,
.Xr passwd 1 ,
.Xr getpass 3 ,
.Xr passwd 5
-.sp
.Rs
.%T "Mathematical Cryptology for Computer Scientists and Mathematicians"
.%A Wayne Patterson
diff --git a/lib/libc/gen/crypt.c b/lib/libc/gen/crypt.c
index 1aad9c6..c1417b8 100644
--- a/lib/libc/gen/crypt.c
+++ b/lib/libc/gen/crypt.c
@@ -36,19 +36,24 @@
#if defined(LIBC_SCCS) && !defined(lint)
/* from static char sccsid[] = "@(#)crypt.c 5.11 (Berkeley) 6/25/91"; */
-static char rcsid[] = "$Header: /a/cvs/386BSD/src/lib/libc/gen/crypt.c,v 1.6 1993/08/29 22:03:56 nate Exp $";
+static char rcsid[] = "$Header: /home/ncvs/src/lib/libc/gen/crypt.c,v 1.3 1995/05/30 05:40:10 rgrimes Exp $";
#endif /* LIBC_SCCS and not lint */
#include <unistd.h>
#include <stdio.h>
+#include <string.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!");
+
+int
des_setkey(key)
register const char *key;
{
@@ -56,6 +61,10 @@ des_setkey(key)
return (0);
}
+__warn_references(des_cipher,
+ "WARNING! des_cipher(3) not present in the system!");
+
+int
des_cipher(in, out, salt, num_iter)
const char *in;
char *out;
@@ -67,6 +76,10 @@ des_cipher(in, out, salt, num_iter)
return (0);
}
+__warn_references(setkey,
+ "WARNING! setkey(3) not present in the system!");
+
+int
setkey(key)
register const char *key;
{
@@ -74,6 +87,10 @@ setkey(key)
return (0);
}
+__warn_references(encrypt,
+ "WARNING! encrypt(3) not present in the system!");
+
+int
encrypt(block, flag)
register char *block;
int flag;
diff --git a/lib/libc/gen/ctermid.3 b/lib/libc/gen/ctermid.3
index ff92420..2e3e9e6 100644
--- a/lib/libc/gen/ctermid.3
+++ b/lib/libc/gen/ctermid.3
@@ -80,7 +80,7 @@ The current implementation detects no error conditions.
.Xr ttyname 3
.Sh STANDARDS
The
-.Xr ctermid
+.Fn ctermid
function conforms to
.St -p1003.1-88 .
.Sh BUGS
diff --git a/lib/libc/gen/daemon.3 b/lib/libc/gen/daemon.3
index 1905923..afbbee2 100644
--- a/lib/libc/gen/daemon.3
+++ b/lib/libc/gen/daemon.3
@@ -37,6 +37,8 @@
.Nm daemon
.Nd run in the background
.Sh SYNOPSIS
+.Fd #include <stdlib.h>
+.Ft int
.Fn daemon "int nochdir" "int noclose"
.Sh DESCRIPTION
.Pp
@@ -58,17 +60,19 @@ is non-zero,
will redirect standard input, standard output and standard error
to ``/dev/null''.
.Sh ERRORS
-The function
+If an error occurs,
.Fn daemon
-may fail and set
+returns -1 and sets the global variable
.Va errno
-for any of the errors specified for the library functions
+to 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
.Sh HISTORY
The
.Fn daemon
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/devname.3 b/lib/libc/gen/devname.3
index 49fcc78..8f9ad92 100644
--- a/lib/libc/gen/devname.3
+++ b/lib/libc/gen/devname.3
@@ -63,6 +63,6 @@ found is the string
.Xr dev_mkdb 8
.Sh HISTORY
The
-.Nm devname
+.Fn devname
function call appeared in
.Bx 4.4 .
diff --git a/lib/libc/gen/directory.3 b/lib/libc/gen/directory.3
index 0503989..0abbe5f 100644
--- a/lib/libc/gen/directory.3
+++ b/lib/libc/gen/directory.3
@@ -151,7 +151,7 @@ returns the integer file descriptor associated with the named
see
.Xr open 2 .
.Pp
-Sample code which searchs a directory for entry ``name'' is:
+Sample code which searches a directory for entry ``name'' is:
.Bd -literal -offset indent
len = strlen(name);
dirp = opendir(".");
@@ -164,10 +164,10 @@ while ((dp = readdir(dirp)) != NULL)
return NOT_FOUND;
.Ed
.Sh SEE ALSO
-.Xr open 2 ,
.Xr close 2 ,
-.Xr read 2 ,
.Xr lseek 2 ,
+.Xr open 2 ,
+.Xr read 2 ,
.Xr dir 5
.Sh HISTORY
The
diff --git a/lib/libc/gen/disklabel.c b/lib/libc/gen/disklabel.c
index eaefbab..b5cef89 100644
--- a/lib/libc/gen/disklabel.c
+++ b/lib/libc/gen/disklabel.c
@@ -32,7 +32,11 @@
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 5/3/95";
+#endif
+static const char rcsid[] =
+ "$Id: disklabel.c,v 1.5 1997/02/22 14:58:01 peter Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -47,8 +51,8 @@ static char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 5/3/95";
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <ctype.h>
-static int error __P((int));
static int gettype __P((char *, char **));
struct disklabel *
@@ -168,17 +172,3 @@ gettype(t, names)
return (atoi(t));
return (0);
}
-
-static int
-error(err)
- int err;
-{
- char *p;
-
- (void)write(STDERR_FILENO, "disktab: ", 9);
- (void)write(STDERR_FILENO, _PATH_DISKTAB, sizeof(_PATH_DISKTAB) - 1);
- (void)write(STDERR_FILENO, ": ", 2);
- p = strerror(err);
- (void)write(STDERR_FILENO, p, strlen(p));
- (void)write(STDERR_FILENO, "\n", 1);
-}
diff --git a/lib/libc/gen/drand48.c b/lib/libc/gen/drand48.c
new file mode 100644
index 0000000..cec04a6
--- /dev/null
+++ b/lib/libc/gen/drand48.c
@@ -0,0 +1,22 @@
+/*
+ * 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];
+
+double
+drand48(void)
+{
+ return erand48(_rand48_seed);
+}
diff --git a/lib/libc/gen/erand48.c b/lib/libc/gen/erand48.c
new file mode 100644
index 0000000..286904c
--- /dev/null
+++ b/lib/libc/gen/erand48.c
@@ -0,0 +1,23 @@
+/*
+ * 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"
+
+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
index 2a3f4c3..aa340f6 100644
--- a/lib/libc/gen/err.3
+++ b/lib/libc/gen/err.3
@@ -29,9 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)err.3 8.1 (Berkeley) 6/9/93
+.\" From: @(#)err.3 8.1 (Berkeley) 6/9/93
+.\" $Id: err.3,v 1.6 1997/02/22 14:58:02 peter Exp $
.\"
-.Dd "June 9, 1993"
+.Dd April 13, 1995
.Dt ERR 3
.Os BSD 4
.Sh NAME
@@ -42,25 +43,32 @@
.Nm warn ,
.Nm vwarn ,
.Nm warnx ,
-.Nm vwarnx
+.Nm vwarnx ,
+.Nm err_set_file ,
+.Nm err_set_exit
.Nd formatted error messages
.Sh SYNOPSIS
.Fd #include <err.h>
.Ft void
.Fn err "int eval" "const char *fmt" "..."
.Ft void
-.Fn verr "int eval" "const char *fmt" "va_list args"
-.Ft void
.Fn errx "int eval" "const char *fmt" "..."
.Ft void
-.Fn verrx "int eval" "const char *fmt" "va_list args"
-.Ft void
.Fn warn "const char *fmt" "..."
.Ft void
-.Fn vwarn "const char *fmt" "va_list args"
-.Ft void
.Fn warnx "const char *fmt" "..."
.Ft void
+.Fn err_set_file "void *fp"
+.Ft void
+.Fn err_set_exit "void (*exitf)(int)"
+.Fd #include <stdarg.h>
+.Ft void
+.Fn verr "int eval" "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 vwarnx "const char *fmt" "va_list args"
.Sh DESCRIPTION
The
@@ -68,7 +76,9 @@ The
and
.Fn warn
family of functions display a formatted error message on the standard
-error output.
+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
@@ -95,6 +105,13 @@ and
.Fn verrx
functions do not return, but exit with the value of the argument
.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.
.Sh EXAMPLES
Display the current errno information string and exit:
.Bd -literal -offset indent
@@ -119,10 +136,12 @@ if ((fd = open(block_device, O_RDONLY, 0)) == -1)
err(1, "%s", block_device);
.Ed
.Sh SEE ALSO
+.Xr exit 3 ,
.Xr strerror 3
.Sh HISTORY
The
.Fn err
and
.Fn warn
-functions first appeared in 4.4BSD.
+functions first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/err.c b/lib/libc/gen/err.c
index 71cd1d9..bf7d347 100644
--- a/lib/libc/gen/err.c
+++ b/lib/libc/gen/err.c
@@ -49,7 +49,25 @@ static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
extern char *__progname; /* Program name, from crt0. */
-__dead void
+static FILE *err_file; /* file to use for error output */
+static void (*err_exit)(int);
+
+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;
+}
+
+void
#ifdef __STDC__
err(int eval, const char *fmt, ...)
#else
@@ -69,7 +87,7 @@ err(eval, fmt, va_alist)
va_end(ap);
}
-__dead void
+void
verr(eval, fmt, ap)
int eval;
const char *fmt;
@@ -78,16 +96,20 @@ verr(eval, fmt, ap)
int sverrno;
sverrno = errno;
- (void)fprintf(stderr, "%s: ", __progname);
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", __progname);
if (fmt != NULL) {
- (void)vfprintf(stderr, fmt, ap);
- (void)fprintf(stderr, ": ");
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, ": ");
}
- (void)fprintf(stderr, "%s\n", strerror(sverrno));
+ (void)fprintf(err_file, "%s\n", strerror(sverrno));
+ if(err_exit)
+ err_exit(eval);
exit(eval);
}
-__dead void
+void
#if __STDC__
errx(int eval, const char *fmt, ...)
#else
@@ -107,16 +129,20 @@ errx(eval, fmt, va_alist)
va_end(ap);
}
-__dead void
+void
verrx(eval, fmt, ap)
int eval;
const char *fmt;
va_list ap;
{
- (void)fprintf(stderr, "%s: ", __progname);
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", __progname);
if (fmt != NULL)
- (void)vfprintf(stderr, fmt, ap);
- (void)fprintf(stderr, "\n");
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, "\n");
+ if (err_exit)
+ err_exit(eval);
exit(eval);
}
@@ -147,12 +173,14 @@ vwarn(fmt, ap)
int sverrno;
sverrno = errno;
- (void)fprintf(stderr, "%s: ", __progname);
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", __progname);
if (fmt != NULL) {
- (void)vfprintf(stderr, fmt, ap);
- (void)fprintf(stderr, ": ");
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, ": ");
}
- (void)fprintf(stderr, "%s\n", strerror(sverrno));
+ (void)fprintf(err_file, "%s\n", strerror(sverrno));
}
void
@@ -179,8 +207,10 @@ vwarnx(fmt, ap)
const char *fmt;
va_list ap;
{
- (void)fprintf(stderr, "%s: ", __progname);
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", __progname);
if (fmt != NULL)
- (void)vfprintf(stderr, fmt, ap);
- (void)fprintf(stderr, "\n");
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, "\n");
}
diff --git a/lib/libc/gen/exec.3 b/lib/libc/gen/exec.3
index 3438bec..367d71a 100644
--- a/lib/libc/gen/exec.3
+++ b/lib/libc/gen/exec.3
@@ -65,7 +65,7 @@ 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
+.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
@@ -148,7 +148,7 @@ used.
In addition, certain errors are treated specially.
.Pp
If permission is denied for a file (the attempted
-.Xr execve
+.Fn execve
returned
.Er EACCES ) ,
these functions will continue searching the rest of
@@ -159,7 +159,7 @@ set to
.Er EACCES .
.Pp
If the header of a file isn't recognized (the attempted
-.Xr execve
+.Fn execve
returned
.Er ENOEXEC ) ,
these functions will execute the shell with the path of
@@ -167,7 +167,7 @@ the file as its first argument.
(If this attempt fails, no further searching is done.)
.Pp
If the file is currently busy (the attempted
-.Xr execve
+.Fn execve
returned
.Er ETXTBUSY ) ,
these functions will sleep for several seconds,
@@ -179,13 +179,13 @@ executes a file with the program tracing facilities enabled (see
.Xr ptrace 2 ) .
.Sh RETURN VALUES
If any of the
-.Xr exec
+.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
+.Bl -tag -width /bin/sh -compact
.It Pa /bin/sh
The shell.
.El
@@ -213,10 +213,9 @@ for any of the errors specified for the library function
.Xr sh 1 ,
.Xr execve 2 ,
.Xr fork 2 ,
-.Xr trace 2 ,
-.Xr environ 7 ,
+.Xr ktrace 2 ,
.Xr ptrace 2 ,
-.Xr environ 7 ,
+.Xr environ 7 .
.Sh COMPATIBILITY
Historically, the default path for the
.Fn execlp
diff --git a/lib/libc/gen/exec.c b/lib/libc/gen/exec.c
index 2f7eadd..72b6db4 100644
--- a/lib/libc/gen/exec.c
+++ b/lib/libc/gen/exec.c
@@ -58,19 +58,20 @@ buildargv(ap, arg, envpp)
const char *arg;
char ***envpp;
{
- static int memsize;
- static char **argv;
- register int off;
+ register char **argv, **nargv;
+ register int memsize, off;
argv = NULL;
- for (off = 0;; ++off) {
+ for (off = memsize = 0;; ++off) {
if (off >= memsize) {
memsize += 50; /* Starts out at 0. */
memsize *= 2; /* Ramp up fast. */
- if (!(argv = realloc(argv, memsize * sizeof(char *)))) {
- memsize = 0;
+ nargv = realloc(argv, memsize * sizeof(char *));
+ if (nargv == NULL) {
+ free(argv);
return (NULL);
}
+ argv = nargv;
if (off == 0) {
argv[0] = (char *)arg;
off = 1;
@@ -104,7 +105,7 @@ execl(name, arg, va_alist)
#else
va_start(ap);
#endif
- if (argv = buildargv(ap, arg, NULL))
+ if ( (argv = buildargv(ap, arg, NULL)) )
(void)execve(name, argv, environ);
va_end(ap);
sverrno = errno;
@@ -132,7 +133,7 @@ execle(name, arg, va_alist)
#else
va_start(ap);
#endif
- if (argv = buildargv(ap, arg, &envp))
+ if ( (argv = buildargv(ap, arg, &envp)) )
(void)execve(name, argv, envp);
va_end(ap);
sverrno = errno;
@@ -160,7 +161,7 @@ execlp(name, arg, va_alist)
#else
va_start(ap);
#endif
- if (argv = buildargv(ap, arg, NULL))
+ if ( (argv = buildargv(ap, arg, NULL)) )
(void)execvp(name, argv);
va_end(ap);
sverrno = errno;
@@ -183,13 +184,14 @@ execvp(name, argv)
const char *name;
char * const *argv;
{
- static int memsize;
- static char **memp;
+ char **memp;
register int cnt, lp, ln;
register char *p;
int eacces, etxtbsy;
char *bp, *cur, *path, buf[MAXPATHLEN];
+ eacces = etxtbsy = 0;
+
/* If it's an absolute or relative path name, it's easy. */
if (index(name, '/')) {
bp = (char *)name;
@@ -198,13 +200,18 @@ execvp(name, argv)
}
bp = buf;
+ /* If it's an empty path name, fail in the usual POSIX way. */
+ if (*name == '\0') {
+ errno = ENOENT;
+ return (-1);
+ }
+
/* Get the path we're searching. */
if (!(path = getenv("PATH")))
path = _PATH_DEFPATH;
cur = path = strdup(path);
- eacces = etxtbsy = 0;
- while (p = strsep(&cur, ":")) {
+ while ( (p = strsep(&cur, ":")) ) {
/*
* It's a SHELL path -- double, leading and trailing colons
* mean the current directory.
@@ -240,18 +247,16 @@ retry: (void)execve(bp, argv, environ);
case ENOENT:
break;
case ENOEXEC:
- for (cnt = 0; argv[cnt]; ++cnt);
- if ((cnt + 2) * sizeof(char *) > memsize) {
- memsize = (cnt + 2) * sizeof(char *);
- if ((memp = realloc(memp, memsize)) == NULL) {
- memsize = 0;
- goto done;
- }
- }
+ for (cnt = 0; argv[cnt]; ++cnt)
+ ;
+ memp = malloc((cnt + 2) * sizeof(char *));
+ if (memp == NULL)
+ goto done;
memp[0] = "sh";
memp[1] = bp;
bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
(void)execve(_PATH_BSHELL, memp, environ);
+ free(memp);
goto done;
case ETXTBSY:
if (etxtbsy < 3)
diff --git a/lib/libc/gen/fnmatch.3 b/lib/libc/gen/fnmatch.3
index 3b87da1..1da91a8 100644
--- a/lib/libc/gen/fnmatch.3
+++ b/lib/libc/gen/fnmatch.3
@@ -85,7 +85,12 @@ 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 strings match periods in patterns.
+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 ``leading'' is related to the specification of
.Dv FNM_PATHNAME.
A period is always ``leading'' if it is the first character in
@@ -94,6 +99,17 @@ Additionally, if
.Dv FNM_PATHNAME
is set,
a period is ``leading'' if it immediately follows a slash.
+.It Dv FNM_LEADING_DIR
+Ignore
+.Nm /*
+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
diff --git a/lib/libc/gen/fnmatch.c b/lib/libc/gen/fnmatch.c
index dc7f151..c3312b4 100644
--- a/lib/libc/gen/fnmatch.c
+++ b/lib/libc/gen/fnmatch.c
@@ -43,12 +43,20 @@ static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
* Compares a filename or pathname to a pattern.
*/
+#include <ctype.h>
#include <fnmatch.h>
#include <string.h>
+#include <stdio.h>
+
+#include "collate.h"
#define EOS '\0'
-static const char *rangematch __P((const char *, int, int));
+#define RANGE_MATCH 1
+#define RANGE_NOMATCH 0
+#define RANGE_ERROR (-1)
+
+static int rangematch __P((const char *, char, int, char **));
int
fnmatch(pattern, string, flags)
@@ -56,11 +64,14 @@ fnmatch(pattern, string, flags)
int flags;
{
const char *stringstart;
+ char *newp;
char c, test;
for (stringstart = string;;)
switch (c = *pattern++) {
case EOS:
+ if ((flags & FNM_LEADING_DIR) && *string == '/')
+ return (0);
return (*string == EOS ? 0 : FNM_NOMATCH);
case '?':
if (*string == EOS)
@@ -87,7 +98,8 @@ fnmatch(pattern, string, flags)
/* Optimize for pattern with * at end or before /. */
if (c == EOS)
if (flags & FNM_PATHNAME)
- return (strchr(string, '/') == NULL ?
+ return ((flags & FNM_LEADING_DIR) ||
+ strchr(string, '/') == NULL ?
0 : FNM_NOMATCH);
else
return (0);
@@ -109,11 +121,22 @@ fnmatch(pattern, string, flags)
case '[':
if (*string == EOS)
return (FNM_NOMATCH);
- if (*string == '/' && flags & FNM_PATHNAME)
+ if (*string == '/' && (flags & FNM_PATHNAME))
return (FNM_NOMATCH);
- if ((pattern =
- rangematch(pattern, *string, flags)) == NULL)
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
+
+ switch (rangematch(pattern, *string, flags, &newp)) {
+ case RANGE_ERROR:
+ goto norm;
+ case RANGE_MATCH:
+ pattern = newp;
+ break;
+ case RANGE_NOMATCH:
+ return (FNM_NOMATCH);
+ }
++string;
break;
case '\\':
@@ -125,17 +148,27 @@ fnmatch(pattern, string, flags)
}
/* FALLTHROUGH */
default:
- if (c != *string++)
+ norm:
+ if (c == *string)
+ ;
+ else if ((flags & FNM_CASEFOLD) &&
+ (tolower((unsigned char)c) ==
+ tolower((unsigned char)*string)))
+ ;
+ else
return (FNM_NOMATCH);
+ string++;
break;
}
/* NOTREACHED */
}
-static const char *
-rangematch(pattern, test, flags)
+static int
+rangematch(pattern, test, flags, newp)
const char *pattern;
- int test, flags;
+ char test;
+ int flags;
+ char **newp;
{
int negate, ok;
char c, c2;
@@ -147,25 +180,52 @@ rangematch(pattern, test, flags)
* consistency with the regular expression syntax.
* J.T. Conklin (conklin@ngai.kaleida.com)
*/
- if (negate = (*pattern == '!' || *pattern == '^'))
+ if ( (negate = (*pattern == '!' || *pattern == '^')) )
++pattern;
-
- for (ok = 0; (c = *pattern++) != ']';) {
+
+ if (flags & FNM_CASEFOLD)
+ test = tolower((unsigned char)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;
+ c = *pattern++;
+ do {
if (c == '\\' && !(flags & FNM_NOESCAPE))
c = *pattern++;
if (c == EOS)
- return (NULL);
- if (*pattern == '-'
+ return (RANGE_ERROR);
+
+ if (c == '/' && (flags & FNM_PATHNAME))
+ return (RANGE_NOMATCH);
+
+ if (flags & FNM_CASEFOLD)
+ c = tolower((unsigned char)c);
+
+ if (*pattern == '-'
&& (c2 = *(pattern+1)) != EOS && c2 != ']') {
pattern += 2;
if (c2 == '\\' && !(flags & FNM_NOESCAPE))
c2 = *pattern++;
if (c2 == EOS)
- return (NULL);
- if (c <= test && test <= c2)
+ return (RANGE_ERROR);
+
+ if (flags & FNM_CASEFOLD)
+ c2 = tolower((unsigned char)c2);
+
+ if (__collate_load_error ?
+ c <= test && test <= c2 :
+ __collate_range_cmp(c, test) <= 0
+ && __collate_range_cmp(test, c2) <= 0
+ )
ok = 1;
} else if (c == test)
ok = 1;
- }
- return (ok == negate ? NULL : pattern);
+ } while ((c = *pattern++) != ']');
+
+ *newp = (char *)pattern;
+ return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
}
diff --git a/lib/libc/gen/frexp.3 b/lib/libc/gen/frexp.3
index 574efa3..58c25fc 100644
--- a/lib/libc/gen/frexp.3
+++ b/lib/libc/gen/frexp.3
@@ -76,8 +76,8 @@ If
is zero, both parts of the result are zero.
.Sh SEE ALSO
.Xr ldexp 3 ,
-.Xr modf 3 ,
-.Xr math 3
+.Xr math 3 ,
+.Xr modf 3
.Sh STANDARDS
The
.Fn frexp
diff --git a/lib/libc/gen/fstab.c b/lib/libc/gen/fstab.c
index 48e5352..a526068 100644
--- a/lib/libc/gen/fstab.c
+++ b/lib/libc/gen/fstab.c
@@ -44,27 +44,32 @@ static char sccsid[] = "@(#)fstab.c 8.1 (Berkeley) 6/4/93";
static FILE *_fs_fp;
static struct fstab _fs_fstab;
+static int LineNo = 0;
-static error __P((int));
-static fstabscan __P((void));
+static void error __P((int));
+static int fstabscan __P((void));
-static
+static int
fstabscan()
{
- register char *cp;
+ char *cp, *p;
#define MAXLINELENGTH 1024
static char line[MAXLINELENGTH];
char subline[MAXLINELENGTH];
int typexx;
for (;;) {
- if (!(cp = fgets(line, sizeof(line), _fs_fp)))
+
+ if (!(p = fgets(line, sizeof(line), _fs_fp)))
return(0);
/* OLD_STYLE_FSTAB */
- if (!strpbrk(cp, " \t")) {
- _fs_fstab.fs_spec = strtok(cp, ":\n");
- _fs_fstab.fs_file = strtok((char *)NULL, ":\n");
- _fs_fstab.fs_type = strtok((char *)NULL, ":\n");
+ ++LineNo;
+ if (*line == '#' || *line == '\n')
+ continue;
+ if (!strpbrk(p, " \t")) {
+ _fs_fstab.fs_spec = strsep(&p, ":\n");
+ _fs_fstab.fs_file = strsep(&p, ":\n");
+ _fs_fstab.fs_type = strsep(&p, ":\n");
if (_fs_fstab.fs_type) {
if (!strcmp(_fs_fstab.fs_type, FSTAB_XX))
continue;
@@ -72,9 +77,9 @@ fstabscan()
_fs_fstab.fs_vfstype =
strcmp(_fs_fstab.fs_type, FSTAB_SW) ?
"ufs" : "swap";
- if (cp = strtok((char *)NULL, ":\n")) {
+ if ((cp = strsep(&p, ":\n")) != NULL) {
_fs_fstab.fs_freq = atoi(cp);
- if (cp = strtok((char *)NULL, ":\n")) {
+ if ((cp = strsep(&p, ":\n")) != NULL) {
_fs_fstab.fs_passno = atoi(cp);
return(1);
}
@@ -83,24 +88,37 @@ fstabscan()
goto bad;
}
/* OLD_STYLE_FSTAB */
- _fs_fstab.fs_spec = strtok(cp, " \t\n");
+ while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+ ;
+ _fs_fstab.fs_spec = cp;
if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
continue;
- _fs_fstab.fs_file = strtok((char *)NULL, " \t\n");
- _fs_fstab.fs_vfstype = strtok((char *)NULL, " \t\n");
- _fs_fstab.fs_mntops = strtok((char *)NULL, " \t\n");
+ while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+ ;
+ _fs_fstab.fs_file = cp;
+ 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;
- if ((cp = strtok((char *)NULL, " \t\n")) != NULL) {
+ while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+ ;
+ if (cp != NULL) {
_fs_fstab.fs_freq = atoi(cp);
- if ((cp = strtok((char *)NULL, " \t\n")) != NULL)
+ while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+ ;
+ if (cp != NULL)
_fs_fstab.fs_passno = atoi(cp);
}
strcpy(subline, _fs_fstab.fs_mntops);
- for (typexx = 0, cp = strtok(subline, ","); cp;
- cp = strtok((char *)NULL, ",")) {
+ p = subline;
+ for (typexx = 0, cp = strsep(&p, ","); cp;
+ cp = strsep(&p, ",")) {
if (strlen(cp) != 2)
continue;
if (!strcmp(cp, FSTAB_RW)) {
@@ -139,7 +157,7 @@ bad: /* no way to distinguish between EOF and syntax error */
struct fstab *
getfsent()
{
- if (!_fs_fp && !setfsent() || !fstabscan())
+ if ((!_fs_fp && !setfsent()) || !fstabscan())
return((struct fstab *)NULL);
return(&_fs_fstab);
}
@@ -166,14 +184,18 @@ getfsfile(name)
return((struct fstab *)NULL);
}
+int
setfsent()
{
if (_fs_fp) {
rewind(_fs_fp);
+ LineNo = 0;
return(1);
}
- if (_fs_fp = fopen(_PATH_FSTAB, "r"))
+ if ((_fs_fp = fopen(_PATH_FSTAB, "r")) != NULL) {
+ LineNo = 0;
return(1);
+ }
error(errno);
return(0);
}
@@ -187,15 +209,18 @@ endfsent()
}
}
-static
+static void
error(err)
int err;
{
char *p;
+ char num[30];
(void)write(STDERR_FILENO, "fstab: ", 7);
(void)write(STDERR_FILENO, _PATH_FSTAB, sizeof(_PATH_FSTAB) - 1);
- (void)write(STDERR_FILENO, ": ", 1);
+ (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..03b586d
--- /dev/null
+++ b/lib/libc/gen/ftok.3
@@ -0,0 +1,85 @@
+.\" 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.
+.\"
+.\" $Id: ftok.3,v 1.7 1997/02/22 15:06:08 peter Exp $
+.Dd June 24, 1994
+.Os
+.Dt ftok 3
+.Sh NAME
+.Nm ftok
+.Nd create IPC identifier from path name
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Ft key_t
+.Fn ftok "const char *path" "int id"
+.Sh DESCRIPTION
+.Bf -symbolic
+This function is available from the compatibility library, libcompat.
+.Ef
+The
+.Fn ftok
+function attempts to create a unique key suitable for use with the
+.Xr msgget 3 ,
+.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 3
+.Sh HISTORY
+The
+.Fn ftok
+function originates with System V and is typically used by programs
+that use the System V IPC routines.
+.Sh AUTHOR
+.Bl -tag
+Thorsten Lockert <tholo@sigmasoft.com>
+.El
+.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..4f59725
--- /dev/null
+++ b/lib/libc/gen/ftok.c
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ipc.h>
+
+key_t
+ftok(path, id)
+ const char *path;
+ char 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..e532707
--- /dev/null
+++ b/lib/libc/gen/fts-compat.c
@@ -0,0 +1,995 @@
+/*-
+ * 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.
+ * 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[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.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>
+
+static FTSENT *fts_alloc __P((FTS *, char *, int));
+static FTSENT *fts_build __P((FTS *, int));
+static void fts_lfree __P((FTSENT *));
+static void fts_load __P((FTS *, FTSENT *));
+static size_t fts_maxarglen __P((char * const *));
+static void fts_padjust __P((FTS *, void *));
+static int fts_palloc __P((FTS *, size_t));
+static FTSENT *fts_sort __P((FTS *, FTSENT *, int));
+static u_short fts_stat __P((FTS *, FTSENT *, int));
+
+#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])) )
+
+#define ISSET(opt) (sp->fts_options & opt)
+#define SET(opt) (sp->fts_options |= opt)
+
+#define CHDIR(sp, path) (!ISSET(FTS_NOCHDIR) && chdir(path))
+#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 */
+
+FTS *
+fts_open(argv, options, compar)
+ char * const *argv;
+ register int options;
+ int (*compar)();
+{
+ register FTS *sp;
+ register FTSENT *p, *root;
+ register int nitems;
+ FTSENT *parent, *tmp;
+ int len;
+
+ /* Options check. */
+ if (options & ~FTS_OPTIONMASK) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Allocate/initialize the stream */
+ if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
+ return (NULL);
+ memset(sp, 0, sizeof(FTS));
+ sp->fts_compar = compar;
+ sp->fts_options = options;
+
+ /* 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; ++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 insure
+ * 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;
+ register FTSENT *p;
+{
+ register int len;
+ register 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(sp)
+ FTS *sp;
+{
+ register 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 ? 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);
+ }
+
+ /* Free up the stream pointer. */
+ free(sp);
+
+ /* Set errno and return. */
+ if (!ISSET(FTS_NOCHDIR) && saved_errno) {
+ errno = saved_errno;
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Special case a root of "/" so that slashes aren't appended which would
+ * cause paths to be written as "//foo".
+ */
+#define NAPPEND(p) \
+ (p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \
+ p->fts_path[0] == '/' ? 0 : p->fts_pathlen)
+
+FTSENT *
+fts_read(sp)
+ register FTS *sp;
+{
+ register FTSENT *p, *tmp;
+ register int instr;
+ register 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 && sp->fts_options & FTS_NAMEONLY) {
+ sp->fts_options &= ~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) {
+ if (CHDIR(sp, p->fts_accpath)) {
+ p->fts_errno = errno;
+ p->fts_flags |= FTS_DONTCHDIR;
+ for (p = sp->fts_child; p; 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) ) {
+ free(tmp);
+
+ /*
+ * If reached the top, return to the original directory, and
+ * load the paths for the next root.
+ */
+ if (p->fts_level == FTS_ROOTLEVEL) {
+ if (!ISSET(FTS_NOCHDIR) && 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 (!ISSET(FTS_NOCHDIR) && 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)) {
+ if (CHDIR(sp, "..")) {
+ 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(sp, p, instr)
+ FTS *sp;
+ FTSENT *p;
+ int instr;
+{
+ if (instr && 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(sp, instr)
+ register FTS *sp;
+ int instr;
+{
+ register FTSENT *p;
+ int fd;
+
+ if (instr && 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)
+ fts_lfree(sp->fts_child);
+
+ if (instr == FTS_NAMEONLY) {
+ sp->fts_options |= 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);
+}
+
+/*
+ * 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)
+ register FTS *sp;
+ int type;
+{
+ register struct dirent *dp;
+ register FTSENT *p, *head;
+ register int nitems;
+ FTSENT *cur, *tail;
+ DIR *dirp;
+ void *adjaddr;
+ int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno;
+ 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;
+ else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL))
+ nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
+ else
+ nlinks = -1;
+
+#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 (FCHDIR(sp, dirfd(dirp))) {
+ 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.
+ */
+ maxlen = sp->fts_pathlen - cur->fts_pathlen - 1;
+ len = NAPPEND(cur);
+ if (ISSET(FTS_NOCHDIR)) {
+ cp = sp->fts_path + len;
+ *cp++ = '/';
+ }
+
+ level = cur->fts_level + 1;
+
+ /* Read the directory, attaching each entry to the `link' pointer. */
+ adjaddr = NULL;
+ for (head = tail = NULL, nitems = 0; (dp = readdir(dirp)); ) {
+ if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+ continue;
+
+ if ((p = fts_alloc(sp, dp->d_name, (int)dp->d_namlen)) == NULL)
+ goto mem1;
+ if (dp->d_namlen > maxlen) {
+ if (fts_palloc(sp, (size_t)dp->d_namlen)) {
+ /*
+ * 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);
+ errno = saved_errno;
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ adjaddr = sp->fts_path;
+ maxlen = sp->fts_pathlen - sp->fts_cur->fts_pathlen - 1;
+ }
+
+ p->fts_pathlen = len + dp->d_namlen + 1;
+ p->fts_parent = sp->fts_cur;
+ p->fts_level = level;
+
+#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
+ || (nlinks > 0 &&
+ 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;
+ }
+ (void)closedir(dirp);
+
+ /*
+ * If had to realloc the path, adjust the addresses for the rest
+ * of the tree.
+ */
+ if (adjaddr)
+ fts_padjust(sp, adjaddr);
+
+ /*
+ * If not changing directories, reset the path back to original
+ * state.
+ */
+ if (ISSET(FTS_NOCHDIR)) {
+ if (cp - 1 > sp->fts_path)
+ --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) : CHDIR(sp, ".."))) {
+ 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;
+ register FTSENT *p;
+ int follow;
+{
+ register FTSENT *t;
+ register dev_t dev;
+ register 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);
+}
+
+static FTSENT *
+fts_sort(sp, head, nitems)
+ FTS *sp;
+ FTSENT *head;
+ register int nitems;
+{
+ register 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 = realloc(sp->fts_array,
+ (size_t)(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((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->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;
+ register int namelen;
+{
+ register FTSENT *p;
+ size_t len;
+
+ /*
+ * 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. Since the
+ * fts_name field is declared to be of size 1, the fts_name pointer is
+ * namelen + 2 before the first possible address of the stat structure.
+ */
+ len = sizeof(FTSENT) + namelen;
+ if (!ISSET(FTS_NOSTAT))
+ len += sizeof(struct stat) + ALIGNBYTES;
+ if ((p = malloc(len)) == NULL)
+ return (NULL);
+
+ /* Copy the name plus the trailing NULL. */
+ memmove(p->fts_name, name, namelen + 1);
+
+ if (!ISSET(FTS_NOSTAT))
+ p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
+ 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;
+ return (p);
+}
+
+static void
+fts_lfree(head)
+ register FTSENT *head;
+{
+ register 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;
+ sp->fts_path = realloc(sp->fts_path, (size_t)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, addr)
+ FTS *sp;
+ void *addr;
+{
+ FTSENT *p;
+
+#define ADJUST(p) { \
+ (p)->fts_accpath = \
+ (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
+ (p)->fts_path = addr; \
+}
+ /* Adjust the current set of children. */
+ for (p = sp->fts_child; p; p = p->fts_link)
+ ADJUST(p);
+
+ /* Adjust the rest of the tree. */
+ for (p = sp->fts_cur; 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);
+}
diff --git a/lib/libc/gen/fts-compat.h b/lib/libc/gen/fts-compat.h
new file mode 100644
index 0000000..4fa4a3a
--- /dev/null
+++ b/lib/libc/gen/fts-compat.h
@@ -0,0 +1,128 @@
+/*
+ * 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
+ */
+
+#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 */
+
+#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 */
+} FTS;
+
+typedef struct _ftsent {
+ struct _ftsent *fts_cycle; /* cycle node */
+ struct _ftsent *fts_parent; /* parent directory */
+ struct _ftsent *fts_link; /* next file in directory */
+ long fts_number; /* local numeric value */
+ void *fts_pointer; /* local address value */
+ 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[1]; /* file name */
+} FTSENT;
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+FTSENT *fts_children __P((FTS *, int));
+int fts_close __P((FTS *));
+FTS *fts_open __P((char * const *, int,
+ int (*)(const FTSENT **, const FTSENT **)));
+FTSENT *fts_read __P((FTS *));
+int fts_set __P((FTS *, FTSENT *, int));
+__END_DECLS
+
+#endif /* !_FTS_H_ */
diff --git a/lib/libc/gen/fts.3 b/lib/libc/gen/fts.3
index dde076d..7813665 100644
--- a/lib/libc/gen/fts.3
+++ b/lib/libc/gen/fts.3
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)fts.3 8.5 (Berkeley) 4/16/94
+.\" $Id$
.\"
.Dd April 16, 1994
.Dt FTS 3
@@ -42,13 +43,13 @@
.Fd #include <sys/stat.h>
.Fd #include <fts.h>
.Ft FTS *
-.Fn fts_open "char * const *path_argv" "int options" "int *compar(const FTSENT **, const FTSENT **)"
+.Fn fts_open "char * const *path_argv" "int options" "int (*compar)(const FTSENT **, const FTSENT **)"
.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"
+.Fn fts_set "FTS *ftsp" "FTSENT *f" "int options"
.Ft int
.Fn fts_close "FTS *ftsp"
.Sh DESCRIPTION
@@ -122,7 +123,7 @@ typedef struct _ftsent {
These fields are defined as follows:
.Bl -tag -width "fts_namelen"
.It Fa fts_info
-One of the following flags describing the returned
+One of the following values describing the returned
.Fa FTSENT
structure and
the file it represents.
diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c
new file mode 100644
index 0000000..e532707
--- /dev/null
+++ b/lib/libc/gen/fts.c
@@ -0,0 +1,995 @@
+/*-
+ * 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.
+ * 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[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.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>
+
+static FTSENT *fts_alloc __P((FTS *, char *, int));
+static FTSENT *fts_build __P((FTS *, int));
+static void fts_lfree __P((FTSENT *));
+static void fts_load __P((FTS *, FTSENT *));
+static size_t fts_maxarglen __P((char * const *));
+static void fts_padjust __P((FTS *, void *));
+static int fts_palloc __P((FTS *, size_t));
+static FTSENT *fts_sort __P((FTS *, FTSENT *, int));
+static u_short fts_stat __P((FTS *, FTSENT *, int));
+
+#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])) )
+
+#define ISSET(opt) (sp->fts_options & opt)
+#define SET(opt) (sp->fts_options |= opt)
+
+#define CHDIR(sp, path) (!ISSET(FTS_NOCHDIR) && chdir(path))
+#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 */
+
+FTS *
+fts_open(argv, options, compar)
+ char * const *argv;
+ register int options;
+ int (*compar)();
+{
+ register FTS *sp;
+ register FTSENT *p, *root;
+ register int nitems;
+ FTSENT *parent, *tmp;
+ int len;
+
+ /* Options check. */
+ if (options & ~FTS_OPTIONMASK) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Allocate/initialize the stream */
+ if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
+ return (NULL);
+ memset(sp, 0, sizeof(FTS));
+ sp->fts_compar = compar;
+ sp->fts_options = options;
+
+ /* 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; ++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 insure
+ * 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;
+ register FTSENT *p;
+{
+ register int len;
+ register 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(sp)
+ FTS *sp;
+{
+ register 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 ? 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);
+ }
+
+ /* Free up the stream pointer. */
+ free(sp);
+
+ /* Set errno and return. */
+ if (!ISSET(FTS_NOCHDIR) && saved_errno) {
+ errno = saved_errno;
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Special case a root of "/" so that slashes aren't appended which would
+ * cause paths to be written as "//foo".
+ */
+#define NAPPEND(p) \
+ (p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \
+ p->fts_path[0] == '/' ? 0 : p->fts_pathlen)
+
+FTSENT *
+fts_read(sp)
+ register FTS *sp;
+{
+ register FTSENT *p, *tmp;
+ register int instr;
+ register 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 && sp->fts_options & FTS_NAMEONLY) {
+ sp->fts_options &= ~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) {
+ if (CHDIR(sp, p->fts_accpath)) {
+ p->fts_errno = errno;
+ p->fts_flags |= FTS_DONTCHDIR;
+ for (p = sp->fts_child; p; 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) ) {
+ free(tmp);
+
+ /*
+ * If reached the top, return to the original directory, and
+ * load the paths for the next root.
+ */
+ if (p->fts_level == FTS_ROOTLEVEL) {
+ if (!ISSET(FTS_NOCHDIR) && 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 (!ISSET(FTS_NOCHDIR) && 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)) {
+ if (CHDIR(sp, "..")) {
+ 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(sp, p, instr)
+ FTS *sp;
+ FTSENT *p;
+ int instr;
+{
+ if (instr && 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(sp, instr)
+ register FTS *sp;
+ int instr;
+{
+ register FTSENT *p;
+ int fd;
+
+ if (instr && 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)
+ fts_lfree(sp->fts_child);
+
+ if (instr == FTS_NAMEONLY) {
+ sp->fts_options |= 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);
+}
+
+/*
+ * 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)
+ register FTS *sp;
+ int type;
+{
+ register struct dirent *dp;
+ register FTSENT *p, *head;
+ register int nitems;
+ FTSENT *cur, *tail;
+ DIR *dirp;
+ void *adjaddr;
+ int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno;
+ 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;
+ else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL))
+ nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
+ else
+ nlinks = -1;
+
+#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 (FCHDIR(sp, dirfd(dirp))) {
+ 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.
+ */
+ maxlen = sp->fts_pathlen - cur->fts_pathlen - 1;
+ len = NAPPEND(cur);
+ if (ISSET(FTS_NOCHDIR)) {
+ cp = sp->fts_path + len;
+ *cp++ = '/';
+ }
+
+ level = cur->fts_level + 1;
+
+ /* Read the directory, attaching each entry to the `link' pointer. */
+ adjaddr = NULL;
+ for (head = tail = NULL, nitems = 0; (dp = readdir(dirp)); ) {
+ if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+ continue;
+
+ if ((p = fts_alloc(sp, dp->d_name, (int)dp->d_namlen)) == NULL)
+ goto mem1;
+ if (dp->d_namlen > maxlen) {
+ if (fts_palloc(sp, (size_t)dp->d_namlen)) {
+ /*
+ * 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);
+ errno = saved_errno;
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ adjaddr = sp->fts_path;
+ maxlen = sp->fts_pathlen - sp->fts_cur->fts_pathlen - 1;
+ }
+
+ p->fts_pathlen = len + dp->d_namlen + 1;
+ p->fts_parent = sp->fts_cur;
+ p->fts_level = level;
+
+#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
+ || (nlinks > 0 &&
+ 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;
+ }
+ (void)closedir(dirp);
+
+ /*
+ * If had to realloc the path, adjust the addresses for the rest
+ * of the tree.
+ */
+ if (adjaddr)
+ fts_padjust(sp, adjaddr);
+
+ /*
+ * If not changing directories, reset the path back to original
+ * state.
+ */
+ if (ISSET(FTS_NOCHDIR)) {
+ if (cp - 1 > sp->fts_path)
+ --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) : CHDIR(sp, ".."))) {
+ 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;
+ register FTSENT *p;
+ int follow;
+{
+ register FTSENT *t;
+ register dev_t dev;
+ register 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);
+}
+
+static FTSENT *
+fts_sort(sp, head, nitems)
+ FTS *sp;
+ FTSENT *head;
+ register int nitems;
+{
+ register 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 = realloc(sp->fts_array,
+ (size_t)(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((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->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;
+ register int namelen;
+{
+ register FTSENT *p;
+ size_t len;
+
+ /*
+ * 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. Since the
+ * fts_name field is declared to be of size 1, the fts_name pointer is
+ * namelen + 2 before the first possible address of the stat structure.
+ */
+ len = sizeof(FTSENT) + namelen;
+ if (!ISSET(FTS_NOSTAT))
+ len += sizeof(struct stat) + ALIGNBYTES;
+ if ((p = malloc(len)) == NULL)
+ return (NULL);
+
+ /* Copy the name plus the trailing NULL. */
+ memmove(p->fts_name, name, namelen + 1);
+
+ if (!ISSET(FTS_NOSTAT))
+ p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
+ 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;
+ return (p);
+}
+
+static void
+fts_lfree(head)
+ register FTSENT *head;
+{
+ register 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;
+ sp->fts_path = realloc(sp->fts_path, (size_t)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, addr)
+ FTS *sp;
+ void *addr;
+{
+ FTSENT *p;
+
+#define ADJUST(p) { \
+ (p)->fts_accpath = \
+ (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
+ (p)->fts_path = addr; \
+}
+ /* Adjust the current set of children. */
+ for (p = sp->fts_child; p; p = p->fts_link)
+ ADJUST(p);
+
+ /* Adjust the rest of the tree. */
+ for (p = sp->fts_cur; 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);
+}
diff --git a/lib/libc/gen/getbootfile.3 b/lib/libc/gen/getbootfile.3
new file mode 100644
index 0000000..3c2e783
--- /dev/null
+++ b/lib/libc/gen/getbootfile.3
@@ -0,0 +1,70 @@
+.\" 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: @(#)gethostname.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
+.\"
+.Dd September 23, 1994
+.Dt GETBOOTFILE 3
+.Os
+.Sh NAME
+.Nm getbootfile
+.Nd get kernel boot file name
+.Sh SYNOPSIS
+.Fd #include <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 a null pointer is returned and an error code is
+placed in the global location
+.Va errno .
+.Sh SEE ALSO
+.Xr sysctl 3
+.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 /kernel
+is returned instead of the real boot file.
+.Sh HISTORY
+The
+.Fn getbootfile
+function call appeared in
+.Fx 2.0 .
diff --git a/lib/libc/gen/getbootfile.c b/lib/libc/gen/getbootfile.c
new file mode 100644
index 0000000..5b293a7
--- /dev/null
+++ b/lib/libc/gen/getbootfile.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.
+ * 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[] = "From: @(#)gethostname.c 8.1 (Berkeley) 6/4/93";*/
+static const char rcsid[] =
+ "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/sysctl.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 ("/kernel");
+ return (name);
+}
diff --git a/lib/libc/gen/getbsize.3 b/lib/libc/gen/getbsize.3
index 0455573..48ef7ac 100644
--- a/lib/libc/gen/getbsize.3
+++ b/lib/libc/gen/getbsize.3
@@ -43,7 +43,7 @@
.Fn getbsize "int *headerlenp" "long *blocksizep"
.Sh DESCRIPTION
The
-.Nm getbsize
+.Fn getbsize
function determines the user's preferred block size based on the value of the
.Dq BLOCKSIZE
environment variable; see
@@ -51,7 +51,7 @@ environment variable; see
for details on its use and format.
.Pp
The
-.Nm getbsize
+.Fn getbsize
function returns a pointer to a null-terminated string describing
the block size, something like
.Dq 1K-blocks .
@@ -74,6 +74,6 @@ a block size of 512 bytes.
.Xr environ 7
.Sh HISTORY
The
-.Nm getbsize
-function call appeared in
+.Fn getbsize
+function first appeared in
.Bx 4.4 .
diff --git a/lib/libc/gen/getcap.3 b/lib/libc/gen/getcap.3
index f8fcc81..55507a4 100644
--- a/lib/libc/gen/getcap.3
+++ b/lib/libc/gen/getcap.3
@@ -34,7 +34,7 @@
.\"
.\" @(#)getcap.3 8.4 (Berkeley) 5/13/94
.\"
-.Dd "May 13, 1994"
+.Dd May 13, 1994
.Dt GETCAP 3
.Os
.Sh NAME
@@ -58,7 +58,7 @@
.Ft int
.Fn cgetmatch "char *buf" "char *name"
.Ft char *
-.Fn cgetcap "char *buf" "char *cap" "char type"
+.Fn cgetcap "char *buf" "char *cap" "int type"
.Ft int
.Fn cgetnum "char *buf" "char *cap" "long *num"
.Ft int
@@ -83,8 +83,9 @@ and returns a pointer to a
.Xr malloc Ns \&'d
copy of it in
.Fa buf .
-.Nm Cgetent
-will first look for files ending in
+The
+.Fn cgetent
+function will first look for files ending in
.Nm .db
(see
.Xr cap_mkdb 1)
@@ -98,7 +99,7 @@ must be retained through all subsequent calls to
and
.Fn cgetustr ,
but may then be
-.Xr free Ns \&'d.
+.Xr free 3 Ns \&'d.
On success 0 is returned, 1 if the returned
record contains an unresolved
.Nm tc
@@ -111,13 +112,14 @@ and \-3 if a potential reference loop is detected (see
.Ic tc=
comments below).
.Pp
-.Nm Cgetset
-enables the addition of a character buffer containing a single capability
+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
-.Nm cgetent .
+.Fn cgetent .
The entry is passed in
.Fa ent .
If
@@ -125,29 +127,32 @@ If
is
.Dv NULL ,
the current entry is removed from the database.
-.Nm Cgetset
+A call to
+.Fn cgetset
must precede the database traversal. It must be called before the
-.Nm cgetent
+.Fn cgetent
call. If a sequential access is being performed (see below), it must be called
before the first sequential access call (
-.Nm cgetfirst
+.Fn cgetfirst
or
-.Nm cgetnext
+.Fn cgetnext
), or be directly preceded by a
-.Nm cgetclose
+.Fn cgetclose
call.
On success 0 is returned and \-1 on failure.
.Pp
-.Nm Cgetmatch
-will return 0 if
+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
-.Nm Cgetcap
-searches the capability record
+The
+.Fn cgetcap
+function searches the capability record
.Fa buf
for the capability
.Fa cap
@@ -169,8 +174,9 @@ found. The end of the capability value is signaled by a `:' or
.Dv NUL
(see below for capability database syntax).
.Pp
-.Nm Cgetnum
-retrieves the value of the numeric capability
+The
+.Fn cgetnum
+function retrieves the value of the numeric capability
.Fa cap
from the capability record pointed to by
.Fa buf .
@@ -181,8 +187,9 @@ pointed to by
0 is returned on success, \-1 if the requested numeric capability couldn't
be found.
.Pp
-.Nm Cgetstr
-retrieves the value of the string capability
+The
+.Fn cgetstr
+function retrieves the value of the string capability
.Fa cap
from the capability record pointed to by
.Fa buf .
@@ -200,28 +207,33 @@ is returned on success, \-1 if the requested string capability couldn't
be found, \-2 if a system error was encountered (storage allocation
failure).
.Pp
-.Nm Cgetustr
-is identical to
-.Nm cgetstr
+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
-.Nm Cgetfirst ,
-.Nm cgetnext ,
-comprise a function group that provides for sequential
+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 .
-.Nm Cgetfirst
-returns the first record in the database and resets the access
+The
+.Fn cgetfirst
+function returns the first record in the database and resets the access
to the first record.
-.Nm Cgetnext
-returns the next record in the database with respect to the
+The
+.Fn cgetnext
+function returns the next record in the database with respect to the
record returned by the previous
-.Nm cgetfirst
+.Fn cgetfirst
or
-.Nm cgetnext
+.Fn cgetnext
call. If there is no such previous call, the first record in the database is
returned.
Each record is returned in a
@@ -242,10 +254,11 @@ is returned if a potential reference loop is detected (see
comments below).
Upon completion of database (0 return) the database is closed.
.Pp
-.Nm Cgetclose
-closes the sequential access and frees any memory and file descriptors
+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
-.Nm cgetset .
+.Fn cgetset .
.Sh CAPABILITY DATABASE SYNTAX
Capability databases are normally
.Tn ASCII
@@ -301,16 +314,17 @@ 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 .
-.Nm Cgetcap
-will return a pointer to a value of a name given the capability name and
-the type of the value.
+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
-.Nm cgetnum
+.Fn cgetnum
and
-.Nm cgetstr
+.Fn cgetstr
can be used to implement the traditional syntax and semantics of `#'
and `='.
Typeless capabilities are typically used to denote boolean objects with
@@ -380,7 +394,7 @@ file2:
.Ed
.Pp
The records are extracted by calling
-.Nm cgetent
+.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,
@@ -392,9 +406,9 @@ 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
-.Nm cgetnum
+.Fn cgetnum
and
-.Nm cgetstr :
+.Fn cgetstr :
.Bl -column "nameXnumber"
.Sm off
.It Em name No \&# Em number Ta numeric
@@ -431,7 +445,7 @@ String capability values may contain any character. Non-printable
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 ('\fIX\fP' & 037) control-\fIX\fP
+^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)
@@ -441,7 +455,7 @@ of escape sequences:
\e\|c, \e\|C (:) colon
\e\|\e (\e\|) back slash
\e\|^ (^) caret
-\e\|\fInnn\fP (ASCII octal \fInnn\fP)
+\e\|nnn (ASCII octal nnn)
.El
.Pp
A `\|\e' may be followed by up to three octal digits directly specifies
@@ -455,26 +469,28 @@ are typically used to denote the end of strings; many applications
use `\e\|200' to represent a
.Dv NUL .
.Sh DIAGNOSTICS
-.Nm Cgetent ,
-.Nm cgetset ,
-.Nm cgetmatch ,
-.Nm cgetnum ,
-.Nm cgetstr ,
-.Nm cgetustr ,
-.Nm cgetfirst ,
+.Fn Cgetent ,
+.Fn cgetset ,
+.Fn cgetmatch ,
+.Fn cgetnum ,
+.Fn cgetstr ,
+.Fn cgetustr ,
+.Fn cgetfirst ,
and
-.Nm cgetnext
+.Fn cgetnext
return a value greater than or equal to 0 on success and a value less
than 0 on failure.
-.Nm Cgetcap
-returns a character pointer on success and a
+The
+.Fn cgetcap
+function returns a character pointer on success and a
.Dv NULL
on failure.
.Pp
-.Nm Cgetent ,
+The
+.Fn cgetent ,
and
-.Nm cgetseq
-may fail and set
+.Fn cgetseq
+functions may fail and set
.Va errno
for any of the errors specified for the library functions:
.Xr fopen 2 ,
@@ -483,11 +499,12 @@ for any of the errors specified for the library functions:
and
.Xr close 2 .
.Pp
-.Nm Cgetent ,
-.Nm cgetset ,
-.Nm cgetstr ,
+The
+.Fn cgetent ,
+.Fn cgetset ,
+.Fn cgetstr ,
and
-.Nm cgetustr
+.Fn cgetustr
may fail and set
.Va errno
as follows:
@@ -504,8 +521,8 @@ Colons (`:') can't be used in names, types, or values.
There are no checks for
.Ic tc= name
loops in
-.Nm cgetent .
+.Fn cgetent .
.Pp
The buffer added to the database by a call to
-.Nm cgetset
+.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
index 2a81a35..93d1952 100644
--- a/lib/libc/gen/getcap.c
+++ b/lib/libc/gen/getcap.c
@@ -42,7 +42,7 @@ static char sccsid[] = "@(#)getcap.c 8.3 (Berkeley) 3/25/94";
#include <ctype.h>
#include <db.h>
-#include <errno.h>
+#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
@@ -192,13 +192,12 @@ getent(cap, len, db_array, fd, name, depth, nfield)
int fd, depth;
{
DB *capdbp;
- DBT key, data;
register char *r_end, *rp, **db_p;
int myfd, eof, foundit, retval, clen;
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.
@@ -306,7 +305,7 @@ getent(cap, len, db_array, fd, name, depth, nfield)
for (;;) {
if (bp >= b_end) {
int n;
-
+
n = read(fd, buf, sizeof(buf));
if (n <= 0) {
if (myfd)
@@ -323,7 +322,7 @@ getent(cap, len, db_array, fd, name, depth, nfield)
b_end = buf+n;
bp = buf;
}
-
+
c = *bp++;
if (c == '\n') {
if (rp > record && *(rp-1) == '\\') {
@@ -335,7 +334,7 @@ getent(cap, len, db_array, fd, name, depth, nfield)
*rp++ = c;
/*
- * Enforce loop invariant: if no room
+ * Enforce loop invariant: if no room
* left in record buffer, try to get
* some more.
*/
@@ -364,13 +363,13 @@ getent(cap, len, db_array, fd, name, depth, nfield)
*/
if (eof)
break;
-
+
/*
* Toss blank lines and comments.
*/
if (*record == '\0' || *record == '#')
continue;
-
+
/*
* See if this is the record we want ...
*/
@@ -431,7 +430,7 @@ tc_exp: {
tclen = s - tcstart;
tcend = s;
- iret = getent(&icap, &ilen, db_p, fd, tc, depth+1,
+ iret = getent(&icap, &ilen, db_p, fd, tc, depth+1,
NULL);
newicap = icap; /* Put into a register. */
newilen = ilen;
@@ -447,11 +446,11 @@ tc_exp: {
tc_not_resolved = 1;
/* couldn't resolve tc */
if (iret == -1) {
- *(s - 1) = ':';
+ *(s - 1) = ':';
scan = s - 1;
tc_not_resolved = 1;
continue;
-
+
}
}
/* not interested in name field of tc'ed record */
@@ -514,7 +513,7 @@ tc_exp: {
*/
scan = s-1;
}
-
+
}
/*
* Close file (if we opened it), give back any extra memory, and
@@ -524,17 +523,17 @@ tc_exp: {
(void)close(fd);
*len = rp - record - 1; /* don't count NUL */
if (r_end > rp)
- if ((record =
+ if ((record =
realloc(record, (size_t)(rp - record))) == NULL) {
errno = ENOMEM;
return (-2);
}
-
+
*cap = record;
if (tc_not_resolved)
return (1);
return (0);
-}
+}
static int
cdbget(capdbp, bp, name)
@@ -542,8 +541,6 @@ cdbget(capdbp, bp, name)
char **bp, *name;
{
DBT key, data;
- char *buf;
- int st;
key.data = name;
key.size = strlen(name);
@@ -564,7 +561,7 @@ cdbget(capdbp, bp, name)
key.data = (char *)data.data + 1;
key.size = data.size - 1;
}
-
+
*bp = (char *)data.data + 1;
return (((char *)(data.data))[0] == TCERR ? 1 : 0);
}
@@ -641,7 +638,7 @@ cgetclose()
}
/*
- * Cgetnext() gets either the first or next entry in the logical database
+ * 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.
*/
@@ -702,10 +699,10 @@ cgetnext(bp, db_array)
slash = 1;
else
slash = 0;
- }
+ }
- /*
+ /*
* Line points to a name line.
*/
i = 0;
@@ -745,12 +742,12 @@ cgetnext(bp, db_array)
*rp++ = *cp;
*rp = '\0';
- /*
- * XXX
+ /*
+ * XXX
* Last argument of getent here should be nbuf if we want true
- * sequential access in the case of duplicates.
+ * 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
+ * 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);
@@ -810,7 +807,11 @@ cgetstr(buf, cap, str)
bp++;
if (*bp == ':' || *bp == '\0')
break; /* drop unfinished escape */
- *mp++ = *bp++ & 037;
+ if (*bp == '?') {
+ *mp++ = '\177';
+ bp++;
+ } else
+ *mp++ = *bp++ & 037;
} else if (*bp == '\\') {
bp++;
if (*bp == ':' || *bp == '\0')
@@ -890,10 +891,10 @@ cgetstr(buf, cap, str)
* 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
+ * 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
+ * -1 if the requested string capability couldn't be found, -2 if a system
* error was encountered (storage allocation failure).
*/
int
@@ -1035,10 +1036,10 @@ nfcmp(nf, rec)
{
char *cp, tmp;
int ret;
-
+
for (cp = rec; *cp != ':'; cp++)
;
-
+
tmp = *(cp + 1);
*(cp + 1) = '\0';
ret = strcmp(nf, rec);
diff --git a/lib/libc/gen/getcwd.3 b/lib/libc/gen/getcwd.3
index b66aa1c..8b385be 100644
--- a/lib/libc/gen/getcwd.3
+++ b/lib/libc/gen/getcwd.3
@@ -35,10 +35,11 @@
.Dt GETCWD 3
.Os BSD 4.2
.Sh NAME
-.Nm getcwd
+.Nm getcwd ,
+.Nm getwd
.Nd get working directory pathname
.Sh SYNOPSIS
-.Fd #include <stdio.h>
+.Fd #include <unistd.h>
.Ft char *
.Fn getcwd "char *buf" "size_t size"
.Ft char *
diff --git a/lib/libc/gen/getcwd.c b/lib/libc/gen/getcwd.c
index 90ecfd7..42ca336 100644
--- a/lib/libc/gen/getcwd.c
+++ b/lib/libc/gen/getcwd.c
@@ -2,9 +2,6 @@
* Copyright (c) 1989, 1991, 1993, 1995
* 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:
@@ -49,165 +46,15 @@ static char sccsid[] = "@(#)getcwd.c 8.5 (Berkeley) 2/7/95";
#include <string.h>
#include <unistd.h>
-static char *getcwd_physical __P((char *, size_t));
-
#define ISDOT(dp) \
(dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
- dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
char *
getcwd(pt, size)
char *pt;
size_t size;
{
- char *pwd;
- size_t pwdlen;
- dev_t dev;
- ino_t ino;
- struct stat s;
-
- /* Check $PWD -- if it's right, it's fast. */
- if ((pwd = getenv("PWD")) != NULL && pwd[0] == '/' && !stat(pwd, &s)) {
- dev = s.st_dev;
- ino = s.st_ino;
- if (!stat(".", &s) && dev == s.st_dev && ino == s.st_ino) {
- pwdlen = strlen(pwd);
- if (size != 0) {
- if (pwdlen + 1 > size) {
- errno = ERANGE;
- return (NULL);
- }
- } else if ((pt = malloc(pwdlen + 1)) == NULL)
- return (NULL);
- memmove(pt, pwd, pwdlen);
- pt[pwdlen] = '\0';
- return (pt);
- }
- }
-
- return (getcwd_physical(pt, size));
-}
-
-/*
- * char *realpath(const char *path, char resolved_path[MAXPATHLEN]);
- *
- * 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(path, resolved)
- const char *path;
- char *resolved;
-{
- struct stat sb;
- int fd, n, rootd, serrno;
- char *p, *q, wbuf[MAXPATHLEN];
-
- /* Save the starting point. */
- if ((fd = open(".", O_RDONLY)) < 0) {
- (void)strcpy(resolved, ".");
- return (NULL);
- }
-
- /*
- * Find the dirname and basename from the path to be resolved.
- * Change directory to the dirname component.
- * lstat the basename part.
- * if it is a symlink, read in the value and loop.
- * if it is a directory, then change to that directory.
- * get the current directory name and append the basename.
- */
- (void)strncpy(resolved, path, MAXPATHLEN - 1);
- resolved[MAXPATHLEN - 1] = '\0';
-loop:
- q = strrchr(resolved, '/');
- if (q != NULL) {
- p = q + 1;
- if (q == resolved)
- q = "/";
- else {
- do {
- --q;
- } while (q > resolved && *q == '/');
- q[1] = '\0';
- q = resolved;
- }
- if (chdir(q) < 0)
- goto err1;
- } else
- p = resolved;
-
- /* Deal with the last component. */
- if (lstat(p, &sb) == 0) {
- if (S_ISLNK(sb.st_mode)) {
- n = readlink(p, resolved, MAXPATHLEN);
- if (n < 0)
- goto err1;
- resolved[n] = '\0';
- goto loop;
- }
- if (S_ISDIR(sb.st_mode)) {
- if (chdir(p) < 0)
- goto err1;
- p = "";
- }
- }
-
- /*
- * Save the last component name and get the full pathname of
- * the current directory.
- */
- (void)strcpy(wbuf, p);
-
- /*
- * Call the inernal internal version of getcwd which
- * does a physical search rather than using the $PWD short-cut
- */
- if (getcwd_physical(resolved, MAXPATHLEN) == 0)
- goto err1;
-
- /*
- * Join the two strings together, ensuring that the right thing
- * happens if the last component is empty, or the dirname is root.
- */
- if (resolved[0] == '/' && resolved[1] == '\0')
- rootd = 1;
- else
- rootd = 0;
-
- if (*wbuf) {
- if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) {
- errno = ENAMETOOLONG;
- goto err1;
- }
- if (rootd == 0)
- (void)strcat(resolved, "/");
- (void)strcat(resolved, wbuf);
- }
-
- /* Go back to where we came from. */
- if (fchdir(fd) < 0) {
- serrno = errno;
- goto err2;
- }
-
- /* It's okay if the close fails, what's an fd more or less? */
- (void)close(fd);
- return (resolved);
-
-err1: serrno = errno;
- (void)fchdir(fd);
-err2: (void)close(fd);
- errno = serrno;
- return (NULL);
-}
-
-static char *
-getcwd_physical(pt, size)
- char *pt;
- size_t size;
-{
register struct dirent *dp;
register DIR *dir;
register dev_t dev;
@@ -232,6 +79,10 @@ getcwd_physical(pt, size)
errno = EINVAL;
return (NULL);
}
+ if (size == 1) {
+ errno = ERANGE;
+ return (NULL);
+ }
ept = pt + size;
} else {
if ((pt = malloc(ptsize = 1024 - 4)) == NULL)
@@ -278,7 +129,7 @@ getcwd_physical(pt, size)
* path to the beginning of the buffer, but it's always
* been that way and stuff would probably break.
*/
- (void)bcopy(bpt, pt, ept - bpt);
+ bcopy(bpt, pt, ept - bpt);
free(up);
return (pt);
}
@@ -304,6 +155,7 @@ getcwd_physical(pt, size)
/* Add trailing slash for next directory. */
*bup++ = '/';
+ *bup = '\0';
/*
* If it's a mount point, have to stat each element because
@@ -341,7 +193,7 @@ getcwd_physical(pt, size)
* Check for length of the current name, preceding slash,
* leading slash.
*/
- if (bpt - pt <= dp->d_namlen + (first ? 1 : 2)) {
+ if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
size_t len, off;
if (!ptsize) {
@@ -354,7 +206,7 @@ getcwd_physical(pt, size)
goto err;
bpt = pt + off;
ept = pt + ptsize;
- (void)bcopy(bpt, ept - len, len);
+ bcopy(bpt, ept - len, len);
bpt = ept - len;
}
if (!first)
diff --git a/lib/libc/gen/getdomainname.3 b/lib/libc/gen/getdomainname.3
new file mode 100644
index 0000000..75214d2
--- /dev/null
+++ b/lib/libc/gen/getdomainname.3
@@ -0,0 +1,99 @@
+.\" 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.
+.\"
+.\" @(#)gethostname.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
+.\"
+.Dd May 6, 1994
+.Dt GETDOMAINNAME 3
+.Os BSD 4.2
+.Sh NAME
+.Nm getdomainname ,
+.Nm setdomainname
+.Nd get/set domain name of current host
+.Sh SYNOPSIS
+.Fd #include <unistd.h>
+.Ft int
+.Fn getdomainname "char *name" "int namelen"
+.Ft int
+.Fn setdomainname "const char *name" "int namelen"
+.Sh DESCRIPTION
+.Fn Getdomainname
+returns the standard domain name for the current processor, as
+previously set by
+.Fn setdomainname .
+The parameter
+.Fa namelen
+specifies the size of the
+.Fa name
+array. The returned name is null-terminated unless insufficient
+space is provided.
+.Pp
+.Fn Setdomainname
+sets the 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
+If the call succeeds a value of 0 is returned. If the call
+fails, a value of -1 is returned and an error code is
+placed in the global location
+.Va errno .
+.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
+parameter 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 BUGS
+Domain names are limited to
+.Dv MAXHOSTNAMELEN
+(from
+.Ao Pa sys/param.h Ac )
+characters, currently 256.
+.Sh HISTORY
+The
+.Fn getdomainname
+function call appeared in
+.Bx 4.2 .
diff --git a/lib/libc/gen/getdomainname.c b/lib/libc/gen/getdomainname.c
new file mode 100644
index 0000000..ba04803
--- /dev/null
+++ b/lib/libc/gen/getdomainname.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.
+ * 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[] = "From: @(#)gethostname.c 8.1 (Berkeley) 6/4/93";
+*/
+static const char rcsid[] =
+ "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#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
index 1051837..17f3d77 100644
--- a/lib/libc/gen/getfsent.3
+++ b/lib/libc/gen/getfsent.3
@@ -43,7 +43,7 @@
.Nd get file system descriptor file entry
.Sh SYNOPSIS
.Fd #include <fstab.h>
-.Ft fstab *
+.Ft struct fstab *
.Fn getfsent void
.Ft struct fstab *
.Fn getfsspec "const char *spec"
@@ -68,11 +68,11 @@ description file,
struct fstab {
char *fs_spec; /* block special device name */
char *fs_file; /* file system path prefix */
- char *fs_vfstype; /* type of file system */
- char *fs_mntops; /* comma separated mount options */
- char *fs_type; /* rw, ro, sw, or xx */
+ 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 dump */
+ int fs_passno; /* pass number on parallel fsck */
};
.Ed
.Pp
@@ -112,7 +112,9 @@ The
and
.Fn getfsfile
functions
-return a null pointer (0) on
+return a
+.Dv NULL
+pointer on
.Dv EOF
or error.
The
diff --git a/lib/libc/gen/getgrent.3 b/lib/libc/gen/getgrent.3
index e0e2782..a9f226a 100644
--- a/lib/libc/gen/getgrent.3
+++ b/lib/libc/gen/getgrent.3
@@ -29,9 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)getgrent.3 8.2 (Berkeley) 4/19/94
+.\" From: @(#)getgrent.3 8.2 (Berkeley) 4/19/94
+.\" $Id: getgrent.3,v 1.9 1997/02/22 14:58:07 peter Exp $
.\"
-.Dd April 19, 1994
+.Dd September 29, 1994
.Dt GETGRENT 3
.Os
.Sh NAME
@@ -44,6 +45,7 @@
.Nm endgrent
.Nd group database operations
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
.Fd #include <grp.h>
.Ft struct group *
.Fn getgrent void
@@ -51,7 +53,7 @@
.Fn getgrnam "const char *name"
.Ft struct group *
.Fn getgrgid "gid_t gid"
-.Ft struct group *
+.Ft int
.Fn setgroupent "int stayopen"
.\" .Ft void
.\" .Fn setgrfile "const char *name"
@@ -74,7 +76,7 @@ file
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
- gid_t gr_gid; /* group id */
+ int gr_gid; /* group id */
char **gr_mem; /* group members */
};
.Ed
@@ -121,6 +123,25 @@ The
.Fn endgrent
function
closes any open files.
+.Sh YP/NIS INTERACTION
+When the
+.Xr yp 4
+group database is enabled, the
+.Fn getgrnam
+and
+.Fn getgrgid
+functions use the YP maps
+.Dq Li group.byname
+and
+.Dq Li group.bygid ,
+respectively, if the requested group is not found in the local
+.Pa /etc/group
+file. The
+.Fn getgrent
+function will step through the YP map
+.Dq Li group.byname
+if the entire map is enabled as described in
+.Xr group 5 .
.Sh RETURN VALUES
The functions
.Fn getgrent ,
@@ -146,8 +167,9 @@ have no return value.
group database file
.El
.Sh SEE ALSO
-.Fn getpwent 3 ,
-.Fn group 5
+.Xr getpwent 3 ,
+.Xr yp 4 ,
+.Xr group 5
.Sh HISTORY
The functions
.Fn endgrent ,
@@ -181,12 +203,3 @@ 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 endgrent ,
-.Fn setgroupent ,
-and
-.Fn setgrent
-are fairly useless in a networked environment and should be
-avoided, if possible.
diff --git a/lib/libc/gen/getgrent.c b/lib/libc/gen/getgrent.c
index 102546a..26069c6 100644
--- a/lib/libc/gen/getgrent.c
+++ b/lib/libc/gen/getgrent.c
@@ -38,23 +38,68 @@ static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94";
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <grp.h>
static FILE *_gr_fp;
static struct group _gr_group;
static int _gr_stayopen;
static int grscan(), start_gr();
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+static int _gr_stepping_yp;
+static int _gr_yp_enabled;
+static int _getypgroup(struct group *, const char *, char *);
+static int _nextypgroup(struct group *);
+#endif
+
+/* initial size for malloc and increase steps for realloc */
+#define MAXGRP 64
+#define MAXLINELENGTH 256
-#define MAXGRP 200
-static char *members[MAXGRP];
-#define MAXLINELENGTH 1024
-static char line[MAXLINELENGTH];
+static char **members; /* list of group members */
+static int maxgrp; /* current length of **mebers */
+static char *line; /* temp buffer for group line */
+static int maxlinelength; /* current length of *line */
+
+/*
+ * Lines longer than MAXLINELENGTHLIMIT will be count as an error.
+ * <= 0 disable check for maximum line length
+ * 256K is enough for 64,000 uids
+ */
+#define MAXLINELENGTHLIMIT (256 * 1024)
+#define GROUP_IGNORE_COMMENTS 1 /* allow comments in /etc/group */
struct group *
getgrent()
{
- if (!_gr_fp && !start_gr() || !grscan(0, 0, NULL))
+ if (!_gr_fp && !start_gr()) {
+ return NULL;
+ }
+
+#ifdef YP
+ if (_gr_stepping_yp) {
+ if (_nextypgroup(&_gr_group))
+ return(&_gr_group);
+ }
+tryagain:
+#endif
+
+ if (!grscan(0, 0, NULL))
return(NULL);
+#ifdef YP
+ if(_gr_group.gr_name[0] == '+' && _gr_group.gr_name[1]) {
+ _getypgroup(&_gr_group, &_gr_group.gr_name[1],
+ "group.byname");
+ } else if(_gr_group.gr_name[0] == '+') {
+ if (!_nextypgroup(&_gr_group))
+ goto tryagain;
+ else
+ return(&_gr_group);
+ }
+#endif
return(&_gr_group);
}
@@ -66,7 +111,17 @@ getgrnam(name)
if (!start_gr())
return(NULL);
+#ifdef YP
+ tryagain:
+#endif
rval = grscan(1, 0, name);
+#ifdef YP
+ if(rval == -1 && (_gr_yp_enabled < 0 || (_gr_yp_enabled &&
+ _gr_group.gr_name[0] == '+'))) {
+ if (!(rval = _getypgroup(&_gr_group, name, "group.byname")))
+ goto tryagain;
+ }
+#endif
if (!_gr_stayopen)
endgrent();
return(rval ? &_gr_group : NULL);
@@ -84,20 +139,71 @@ getgrgid(gid)
if (!start_gr())
return(NULL);
+#ifdef YP
+ tryagain:
+#endif
rval = grscan(1, gid, NULL);
+#ifdef YP
+ if(rval == -1 && _gr_yp_enabled) {
+ char buf[16];
+ snprintf(buf, sizeof buf, "%d", (unsigned)gid);
+ if (!(rval = _getypgroup(&_gr_group, buf, "group.bygid")))
+ goto tryagain;
+ }
+#endif
if (!_gr_stayopen)
endgrent();
return(rval ? &_gr_group : NULL);
}
-static
+static int
start_gr()
{
if (_gr_fp) {
rewind(_gr_fp);
return(1);
}
- return((_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0);
+ _gr_fp = fopen(_PATH_GROUP, "r");
+ if(!_gr_fp) return 0;
+#ifdef YP
+ /*
+ * This is a disgusting hack, used to determine when YP is enabled.
+ * This would be easier if we had a group database to go along with
+ * the password database.
+ */
+ {
+ char *line;
+ size_t linelen;
+ _gr_yp_enabled = 0;
+ while((line = fgetln(_gr_fp, &linelen)) != NULL) {
+ if(line[0] == '+') {
+ if(line[1] && line[1] != ':' && !_gr_yp_enabled) {
+ _gr_yp_enabled = 1;
+ } else {
+ _gr_yp_enabled = -1;
+ break;
+ }
+ }
+ }
+ rewind(_gr_fp);
+ }
+#endif
+
+ if (maxlinelength == 0) {
+ if ((line = (char *)malloc(sizeof(char) *
+ MAXLINELENGTH)) == NULL)
+ return(0);
+ maxlinelength += MAXLINELENGTH;
+ }
+
+ if (maxgrp == 0) {
+ if ((members = (char **)malloc(sizeof(char **) *
+ MAXGRP)) == NULL)
+ return(0);
+ maxgrp += MAXGRP;
+ }
+
+ return 1;
}
int
@@ -113,52 +219,175 @@ setgroupent(stayopen)
if (!start_gr())
return(0);
_gr_stayopen = stayopen;
+#ifdef YP
+ _gr_stepping_yp = 0;
+#endif
return(1);
}
void
endgrent()
{
+#ifdef YP
+ _gr_stepping_yp = 0;
+#endif
if (_gr_fp) {
(void)fclose(_gr_fp);
_gr_fp = NULL;
}
}
-static
+static int
grscan(search, gid, name)
register int search, gid;
register char *name;
{
register char *cp, **m;
char *bp;
- char *fgets(), *strsep(), *index();
+
+#ifdef YP
+ int _ypfound;
+#endif
for (;;) {
- if (!fgets(line, sizeof(line), _gr_fp))
+#ifdef YP
+ _ypfound = 0;
+#endif
+ if (fgets(line, maxlinelength, _gr_fp) == NULL)
return(0);
- bp = line;
- /* skip lines that are too big */
+
if (!index(line, '\n')) {
- int ch;
+ do {
+ if (feof(_gr_fp))
+ return(0);
+
+ /* don't allocate infinite memory */
+ if (MAXLINELENGTHLIMIT > 0 &&
+ maxlinelength >= MAXLINELENGTHLIMIT)
+ return(0);
+
+ if ((line = (char *)realloc(line,
+ sizeof(char) *
+ (maxlinelength + MAXLINELENGTH))) == NULL)
+ return(0);
+
+ if (fgets(line + maxlinelength - 1,
+ MAXLINELENGTH + 1, _gr_fp) == NULL)
+ return(0);
- while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
- ;
+ maxlinelength += MAXLINELENGTH;
+ } while (!index(line + maxlinelength -
+ MAXLINELENGTH - 1, '\n'));
+ }
+
+#ifdef GROUP_IGNORE_COMMENTS
+ /*
+ * Ignore comments: ^[ \t]*#
+ */
+ for (cp = line; *cp != '\0'; cp++)
+ if (*cp != ' ' && *cp != '\t')
+ break;
+ if (*cp == '#' || *cp == '\0')
continue;
+#endif
+
+ bp = line;
+
+ if ((_gr_group.gr_name = strsep(&bp, ":\n")) == NULL)
+ break;
+#ifdef YP
+ /*
+ * XXX We need to be careful to avoid proceeding
+ * past this point under certain circumstances or
+ * we risk dereferencing null pointers down below.
+ */
+ if (_gr_group.gr_name[0] == '+') {
+ if (strlen(_gr_group.gr_name) == 1) {
+ switch(search) {
+ case 0:
+ return(1);
+ case 1:
+ return(-1);
+ default:
+ return(0);
+ }
+ } else {
+ cp = &_gr_group.gr_name[1];
+ if (search && name != NULL)
+ if (strcmp(cp, name))
+ continue;
+ if (!_getypgroup(&_gr_group, cp,
+ "group.byname"))
+ continue;
+ if (search && name == NULL)
+ if (gid != _gr_group.gr_gid)
+ continue;
+ /* We're going to override -- tell the world. */
+ _ypfound++;
+ }
}
- _gr_group.gr_name = strsep(&bp, ":\n");
- if (search && name && strcmp(_gr_group.gr_name, name))
+#else
+ if (_gr_group.gr_name[0] == '+')
continue;
- _gr_group.gr_passwd = strsep(&bp, ":\n");
+#endif /* YP */
+ if (search && name) {
+ if(strcmp(_gr_group.gr_name, name)) {
+ continue;
+ }
+ }
+#ifdef YP
+ if ((cp = strsep(&bp, ":\n")) == NULL)
+ if (_ypfound)
+ return(1);
+ else
+ break;
+ if (strlen(cp) || !_ypfound)
+ _gr_group.gr_passwd = cp;
+#else
+ if ((_gr_group.gr_passwd = strsep(&bp, ":\n")) == NULL)
+ break;
+#endif
if (!(cp = strsep(&bp, ":\n")))
- continue;
+#ifdef YP
+ if (_ypfound)
+ return(1);
+ else
+#endif
+ continue;
+#ifdef YP
+ /*
+ * Hurm. Should we be doing this? We allow UIDs to
+ * be overridden -- what about GIDs?
+ */
+ if (!_ypfound)
+#endif
_gr_group.gr_gid = atoi(cp);
if (search && name == NULL && _gr_group.gr_gid != gid)
continue;
cp = NULL;
- for (m = _gr_group.gr_mem = members;; bp++) {
- if (m == &members[MAXGRP - 1])
- break;
+ if (bp == NULL) /* !!! Must check for this! */
+ break;
+#ifdef YP
+ if ((cp = strsep(&bp, ":\n")) == NULL)
+ break;
+
+ if (!strlen(cp) && _ypfound)
+ return(1);
+ else
+ members[0] = NULL;
+ bp = cp;
+ cp = NULL;
+#endif
+ for (m = members; ; bp++) {
+ if (m == (members + maxgrp - 1)) {
+ if ((members = (char **)
+ realloc(members,
+ sizeof(char **) *
+ (maxgrp + MAXGRP))) == NULL)
+ return(0);
+ m = members + maxgrp - 1;
+ maxgrp += MAXGRP;
+ }
if (*bp == ',') {
if (cp) {
*bp = '\0';
@@ -169,13 +398,156 @@ grscan(search, gid, name)
if (cp) {
*bp = '\0';
*m++ = cp;
- }
+ }
break;
} else if (cp == NULL)
cp = bp;
+
}
+ _gr_group.gr_mem = members;
*m = NULL;
return(1);
}
/* NOTREACHED */
+ return (0);
}
+
+#ifdef YP
+
+static int
+_gr_breakout_yp(struct group *gr, char *result)
+{
+ char *s, *cp;
+ char **m;
+
+ /*
+ * XXX If 's' ends up being a NULL pointer, punt on this group.
+ * It means the NIS group entry is badly formatted and should
+ * be skipped.
+ */
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* name */
+ gr->gr_name = s;
+
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* password */
+ gr->gr_passwd = s;
+
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */
+ gr->gr_gid = atoi(s);
+
+ if ((s = result) == NULL) return 0;
+ cp = 0;
+
+ for (m = members; ; s++) {
+ if (m == members + maxgrp - 1) {
+ if ((members = (char **)realloc(members,
+ sizeof(char **) * (maxgrp + MAXGRP))) == NULL)
+ return(0);
+ m = members + maxgrp - 1;
+ maxgrp += MAXGRP;
+ }
+ if (*s == ',') {
+ if (cp) {
+ *s = '\0';
+ *m++ = cp;
+ cp = NULL;
+ }
+ } else if (*s == '\0' || *s == '\n' || *s == ' ') {
+ if (cp) {
+ *s = '\0';
+ *m++ = cp;
+ }
+ break;
+ } else if (cp == NULL) {
+ cp = s;
+ }
+ }
+ _gr_group.gr_mem = members;
+ *m = NULL;
+
+ return 1;
+}
+
+static char *_gr_yp_domain;
+
+static int
+_getypgroup(struct group *gr, const char *name, char *map)
+{
+ char *result, *s;
+ static char resultbuf[YPMAXRECORD + 2];
+ int resultlen;
+
+ if(!_gr_yp_domain) {
+ if(yp_get_default_domain(&_gr_yp_domain))
+ return 0;
+ }
+
+ if(yp_match(_gr_yp_domain, map, name, strlen(name),
+ &result, &resultlen))
+ return 0;
+
+ s = strchr(result, '\n');
+ if(s) *s = '\0';
+
+ if(resultlen >= sizeof resultbuf) return 0;
+ strncpy(resultbuf, result, resultlen);
+ resultbuf[resultlen] = '\0';
+ free(result);
+ return(_gr_breakout_yp(gr, resultbuf));
+
+}
+
+
+static int
+_nextypgroup(struct group *gr)
+{
+ static char *key;
+ static int keylen;
+ char *lastkey, *result;
+ static char resultbuf[YPMAXRECORD + 2];
+ int resultlen;
+ int rv;
+
+ if(!_gr_yp_domain) {
+ if(yp_get_default_domain(&_gr_yp_domain))
+ return 0;
+ }
+
+ if(!_gr_stepping_yp) {
+ if(key) free(key);
+ rv = yp_first(_gr_yp_domain, "group.byname",
+ &key, &keylen, &result, &resultlen);
+ if(rv) {
+ return 0;
+ }
+ _gr_stepping_yp = 1;
+ goto unpack;
+ } else {
+tryagain:
+ lastkey = key;
+ rv = yp_next(_gr_yp_domain, "group.byname", key, keylen,
+ &key, &keylen, &result, &resultlen);
+ free(lastkey);
+unpack:
+ if(rv) {
+ _gr_stepping_yp = 0;
+ return 0;
+ }
+
+ if(resultlen > sizeof(resultbuf)) {
+ free(result);
+ goto tryagain;
+ }
+
+ strncpy(resultbuf, result, resultlen);
+ resultbuf[resultlen] = '\0';
+ free(result);
+ if((result = strchr(resultbuf, '\n')) != NULL)
+ *result = '\0';
+ if (_gr_breakout_yp(gr, resultbuf))
+ return(1);
+ else
+ goto tryagain;
+ }
+}
+
+#endif /* YP */
diff --git a/lib/libc/gen/getgrouplist.3 b/lib/libc/gen/getgrouplist.3
index 7878574..0d04a27 100644
--- a/lib/libc/gen/getgrouplist.3
+++ b/lib/libc/gen/getgrouplist.3
@@ -79,7 +79,8 @@ group membership list
.Sh HISTORY
The
.Fn getgrouplist
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
.Sh BUGS
The
.Fn getgrouplist
diff --git a/lib/libc/gen/getgrouplist.c b/lib/libc/gen/getgrouplist.c
index daab7f5..31f90b4 100644
--- a/lib/libc/gen/getgrouplist.c
+++ b/lib/libc/gen/getgrouplist.c
@@ -50,7 +50,6 @@ getgrouplist(uname, agroup, groups, grpcnt)
int *grpcnt;
{
register struct group *grp;
- register struct passwd *pw;
register int i, ngroups;
int ret, maxgroups;
@@ -70,8 +69,10 @@ getgrouplist(uname, agroup, groups, grpcnt)
*/
setgrent();
while (grp = getgrent()) {
- if (grp->gr_gid == agroup)
- continue;
+ for (i = 0; i < ngroups; i++) {
+ if (grp->gr_gid == groups[i])
+ goto skip;
+ }
for (i = 0; grp->gr_mem[i]; i++) {
if (!strcmp(grp->gr_mem[i], uname)) {
if (ngroups >= maxgroups) {
@@ -82,6 +83,7 @@ getgrouplist(uname, agroup, groups, grpcnt)
break;
}
}
+skip:
}
endgrent();
*grpcnt = ngroups;
diff --git a/lib/libc/gen/gethostname.3 b/lib/libc/gen/gethostname.3
index fcb0303..84241f0 100644
--- a/lib/libc/gen/gethostname.3
+++ b/lib/libc/gen/gethostname.3
@@ -82,8 +82,8 @@ invalid address.
The caller tried to set the hostname and was not the super-user.
.El
.Sh SEE ALSO
-.Xr sysctl 2
-.Xr gethostid 3
+.Xr gethostid 3 ,
+.Xr sysctl 3
.Sh BUGS
Host names are limited to
.Dv MAXHOSTNAMELEN
@@ -92,6 +92,6 @@ Host names are limited to
characters, currently 256.
.Sh HISTORY
The
-.Nm
+.Fn gethostname
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/gen/gethostname.c b/lib/libc/gen/gethostname.c
index 058e4b6..64bd64d 100644
--- a/lib/libc/gen/gethostname.c
+++ b/lib/libc/gen/gethostname.c
@@ -38,7 +38,7 @@ static char sccsid[] = "@(#)gethostname.c 8.1 (Berkeley) 6/4/93";
#include <sys/param.h>
#include <sys/sysctl.h>
-long
+int
gethostname(name, namelen)
char *name;
int namelen;
diff --git a/lib/libc/gen/getloadavg.3 b/lib/libc/gen/getloadavg.3
index 2eafd5b..fa5b571 100644
--- a/lib/libc/gen/getloadavg.3
+++ b/lib/libc/gen/getloadavg.3
@@ -38,6 +38,7 @@
.Nm getloadavg
.Nd get system load averages
.Sh SYNOPSIS
+.Ft int
.Fn getloadavg "double loadavg[]" "int nelem"
.Sh DESCRIPTION
The
@@ -55,8 +56,8 @@ 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 sysctl 2 ,
-.Xr kvm_getloadavg 3
+.Xr kvm_getloadavg 3 ,
+.Xr sysctl 3
.Sh HISTORY
The
.Fn getloadavg
diff --git a/lib/libc/gen/getlogin.c b/lib/libc/gen/getlogin.c
index b6f55a4..5829539 100644
--- a/lib/libc/gen/getlogin.c
+++ b/lib/libc/gen/getlogin.c
@@ -47,10 +47,10 @@ int _logname_valid; /* known to setlogin() */
char *
getlogin()
{
- static char logname[MAXLOGNAME + 1];
+ static char logname[MAXLOGNAME];
if (_logname_valid == 0) {
- if (_getlogin(logname, sizeof(logname) - 1) < 0)
+ if (_getlogin(logname, sizeof(logname)) < 0)
return ((char *)NULL);
_logname_valid = 1;
}
diff --git a/lib/libc/gen/getmntinfo.3 b/lib/libc/gen/getmntinfo.3
index f0e83ea3..e92755b 100644
--- a/lib/libc/gen/getmntinfo.3
+++ b/lib/libc/gen/getmntinfo.3
@@ -48,7 +48,7 @@ The
.Fn getmntinfo
function
returns an array of
-.Xr statfs
+.Fn statfs
structures describing each currently mounted file system (see
.Xr statfs 2 ) .
.Pp
@@ -85,13 +85,14 @@ or
.Xr malloc 3 .
.Sh SEE ALSO
.Xr getfsstat 2 ,
-.Xr statfs 2 ,
.Xr mount 2 ,
+.Xr statfs 2 ,
.Xr mount 8
.Sh HISTORY
The
.Fn getmntinfo
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
.Sh BUGS
The
.Fn getmntinfo
@@ -104,5 +105,5 @@ will modify the same object.
The memory allocated by
.Fn getmntinfo
cannot be
-.Xr free 2 Ns 'd
+.Xr free 3 Ns 'd
by the application.
diff --git a/lib/libc/gen/getnetgrent.3 b/lib/libc/gen/getnetgrent.3
index 1e38538..38da3c0 100644
--- a/lib/libc/gen/getnetgrent.3
+++ b/lib/libc/gen/getnetgrent.3
@@ -42,9 +42,9 @@
.Nd netgroup database operations
.Sh SYNOPSIS
.Ft int
-.Fn getnetgrent "char **host, char **user, char **domain"
+.Fn getnetgrent "char **host" "char **user" "char **domain"
.Ft int
-.Fn innetgr "const char *netgroup, const char *host, const char *user, const char *domain"
+.Fn innetgr "const char *netgroup" "const char *host" "const char *user" "const char *domain"
.Ft void
.Fn setnetgrent "const char *netgroup"
.Ft void
@@ -113,7 +113,7 @@ have no return value.
netgroup database file
.El
.Sh SEE ALSO
-.Fn netgroup 5
+.Xr netgroup 5
.Sh COMPATIBILITY
The netgroup members have three string fields to maintain compatibility
with other vendor implementations, however it is not obvious what use the
@@ -122,7 +122,7 @@ string has within BSD.
.Sh BUGS
The function
.Fn getnetgrent
-returns pointers to dynamically allocated data areas that are free'd when
+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
index b34b78b..662958a 100644
--- a/lib/libc/gen/getnetgrent.c
+++ b/lib/libc/gen/getnetgrent.c
@@ -40,8 +40,64 @@ static char sccsid[] = "@(#)getnetgrent.c 8.2 (Berkeley) 4/27/95";
#include <stdio.h>
#include <strings.h>
+#include <stdlib.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
@@ -93,11 +149,55 @@ void
setnetgrent(group)
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 {
@@ -105,7 +205,8 @@ setnetgrent(group)
malloc(strlen(group) + 1);
strcpy(grouphead.grname, group);
}
- fclose(netf);
+ if (netf)
+ fclose(netf);
}
}
nextgrp = grouphead.gr;
@@ -118,6 +219,9 @@ int
getnetgrent(hostp, userp, domp)
char **hostp, **userp, **domp;
{
+#ifdef YP
+ _yp_innetgr = 0;
+#endif
if (nextgrp) {
*hostp = nextgrp->ng_str[NG_HOST];
@@ -164,22 +268,112 @@ endnetgrent()
free((char *)ogp);
}
grouphead.gr = (struct netgrp *)0;
+#ifdef YP
+ _netgr_yp_enabled = 0;
+#endif
}
+#ifdef YP
+static int _listmatch(list, group, len)
+char *list, *group;
+int len;
+{
+ char *ptr = list;
+
+ while ( (ptr = strstr(ptr, group)) ) {
+
+ ptr += strlen(group);
+
+ if (*ptr == ',' || *ptr == '\0')
+ return(1);
+ }
+
+ return(0);
+}
+
+static int _buildkey(key, str, dom, rotation)
+char *key, *str, *dom;
+int *rotation;
+{
+ (*rotation)++;
+ if (*rotation > 4)
+ return(0);
+ switch(*rotation) {
+ case(1): sprintf((char *)key, "%s.%s", str, dom ? dom : "*");
+ break;
+ case(2): sprintf((char *)key, "%s.*", str);
+ break;
+ case(3): sprintf((char *)key, "*.%s", dom ? dom : "*");
+ break;
+ case(4): sprintf((char *)key, "*.*");
+ break;
+ }
+ return(1);
+}
+#endif
+
/*
* Search for a match in a netgroup.
*/
int
innetgr(group, host, user, dom)
- char *group, *host, *user, *dom;
+ const char *group, *host, *user, *dom;
{
char *hst, *usr, *dm;
+#ifdef YP
+ char *result;
+ int resultlen;
+ int rv;
+#endif
+ /* 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.
+ */
+ if (_use_only_yp) {
+ char _key[MAXHOSTNAMELEN];
+ int rot = 0;
+
+ if(yp_get_default_domain(&_netgr_yp_domain))
+ return(0);
+ while(_buildkey(_key, user ? user : host, dom, &rot)) {
+ if (!yp_match(_netgr_yp_domain, user? "netgroup.byuser":
+ "netgroup.byhost", _key, strlen(_key), &result,
+ &resultlen)) {
+ rv = _listmatch(result, group, resultlen);
+ free(result);
+ if (rv)
+ return(1);
+ else
+ return(0);
+ }
+ }
+#ifdef CHARITABLE
+ }
+ /*
+ * Couldn't match using NIS-exclusive mode -- try
+ * standard mode.
+ */
+ setnetgrent(group);
+#else
+ return(0);
+ }
+#endif /* CHARITABLE */
+#endif /* YP */
while (getnetgrent(&hst, &usr, &dm))
- if ((host == (char *)0 || !strcmp(host, hst)) &&
- (user == (char *)0 || !strcmp(user, usr)) &&
- (dom == (char *)0 || !strcmp(dom, 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);
}
@@ -196,6 +390,9 @@ parse_netgrp(group)
{
register char *spos, *epos;
register int len, strpos;
+#ifdef DEBUG
+ register int fields;
+#endif
char *pos, *gpos;
struct netgrp *grp;
struct linelist *lp = linehead;
@@ -212,12 +409,21 @@ parse_netgrp(group)
(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;
- while (*pos != '\0') {
+ /* 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));
@@ -225,11 +431,17 @@ parse_netgrp(group)
grouphead.gr = grp;
pos++;
gpos = strsep(&pos, ")");
+#ifdef DEBUG
+ fields = 0;
+#endif
for (strpos = 0; strpos < 3; strpos++) {
- if (spos = strsep(&gpos, ",")) {
+ if ((spos = strsep(&gpos, ","))) {
+#ifdef DEBUG
+ fields++;
+#endif
while (*spos == ' ' || *spos == '\t')
spos++;
- if (epos = strpbrk(spos, " \t")) {
+ if ((epos = strpbrk(spos, " \t"))) {
*epos = '\0';
len = epos - spos;
} else
@@ -240,13 +452,36 @@ parse_netgrp(group)
bcopy(spos, grp->ng_str[strpos],
len + 1);
}
- } else
- goto errout;
+ } 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))
- return (1);
+ continue;
}
if (pos == NULL)
break;
@@ -254,10 +489,6 @@ parse_netgrp(group)
pos++;
}
return (0);
-errout:
- fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname,
- spos);
- return (1);
}
/*
@@ -272,10 +503,39 @@ read_for_group(group)
register int len, olen;
int cont;
struct linelist *lp;
- char line[LINSIZ + 1];
+ 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) {
- pos = line;
+#endif
+ pos = (char *)&line;
+#ifdef YP
+ if (*pos == '+') {
+ _netgr_yp_enabled = 1;
+ continue;
+ }
+#endif
if (*pos == '#')
continue;
while (*pos == ' ' || *pos == '\t')
@@ -337,5 +597,15 @@ read_for_group(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.c b/lib/libc/gen/getosreldate.c
new file mode 100644
index 0000000..808e16b
--- /dev/null
+++ b/lib/libc/gen/getosreldate.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.
+ * 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)
+/* From:
+static char sccsid[] = "@(#)gethostid.c 8.1 (Berkeley) 6/2/93";
+*/
+static const char rcsid[] =
+ "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#if __STDC__
+int
+getosreldate(void)
+#else
+int
+getosreldate()
+#endif
+{
+ int mib[2];
+ size_t size;
+ int 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
index 1a26297..51dbcd1 100644
--- a/lib/libc/gen/getpagesize.3
+++ b/lib/libc/gen/getpagesize.3
@@ -47,15 +47,14 @@ 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
-.Xr system
+The page size is a system
page size and may not be the same as the underlying
hardware page size.
.Sh SEE ALSO
-.Xr sbrk 2 ,
-.Xr pagesize 1
+.Xr pagesize 1 ,
+.Xr sbrk 2
.Sh HISTORY
The
-.Nm
+.Fn getpagesze
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/gen/getpagesize.c b/lib/libc/gen/getpagesize.c
index d586cf6..556ff9e 100644
--- a/lib/libc/gen/getpagesize.c
+++ b/lib/libc/gen/getpagesize.c
@@ -38,16 +38,24 @@ static char sccsid[] = "@(#)getpagesize.c 8.1 (Berkeley) 6/4/93";
#include <sys/param.h>
#include <sys/sysctl.h>
+/*
+ * This is unlikely to change over the running time of any
+ * program, so we cache the result to save some syscalls.
+ */
+
int
getpagesize()
{
- int mib[2], value;
+ int mib[2];
+ static int value;
size_t size;
- mib[0] = CTL_HW;
- mib[1] = HW_PAGESIZE;
- size = sizeof value;
- if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
- return (-1);
+ if (!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/getpass.3 b/lib/libc/gen/getpass.3
index 34e91cb..c1fb0e6 100644
--- a/lib/libc/gen/getpass.3
+++ b/lib/libc/gen/getpass.3
@@ -48,7 +48,7 @@ The
function displays a prompt to, and reads in a password from,
.Pa /dev/tty .
If this file is not accessible,
-.Nm getpass
+.Fn getpass
displays the prompt on the standard error output and reads from the standard
input.
.Pp
@@ -57,32 +57,38 @@ characters in length.
Any additional
characters and the terminating newline character are discarded.
.Pp
-.Nm Getpass
-turns off character echoing while reading the password.
+The
+.Fn getpass
+function turns off character echoing while reading the password.
.Pp
.Sh RETURN VALUES
-.Nm Getpass
-returns a pointer to the null terminated password.
+The
+.Fn getpass
+function returns a pointer to the null terminated password.
.Sh FILES
-.Bl -tag -width /dev/tty - compact
+.Bl -tag -width /dev/tty -compact
.It Pa /dev/tty
.El
.Sh SEE ALSO
.Xr crypt 3
.Sh HISTORY
A
-.Nm getpass
+.Fn getpass
function appeared in
.At v7 .
.Sh BUGS
The
-.Nm getpass
+.Fn getpass
function leaves its result in an internal static object and returns
a pointer to that object.
Subsequent calls to
-.Nm getpass
+.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/getpass.c b/lib/libc/gen/getpass.c
index f6391a1..b053d34 100644
--- a/lib/libc/gen/getpass.c
+++ b/lib/libc/gen/getpass.c
@@ -36,23 +36,53 @@ static char sccsid[] = "@(#)getpass.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/termios.h>
-#include <sys/signal.h>
+#include <signal.h>
#include <paths.h>
#include <pwd.h>
#include <stdio.h>
#include <unistd.h>
+static struct termios oterm, term;
+static sig_t ointhandler, oquithandler, otstphandler, oconthandler;
+static FILE *fp;
+
+static void
+sighandler(int signo)
+{
+ /* restore tty state */
+ (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &oterm);
+
+ /* restore old sig handlers */
+ (void)signal(SIGINT, ointhandler);
+ (void)signal(SIGQUIT, oquithandler);
+ (void)signal(SIGTSTP, otstphandler);
+
+ /* resend us this signal */
+ (void)kill(getpid(), signo);
+}
+
+/* ARGSUSED */
+static void
+sigconthandler(int signo)
+{
+ /* re-install our signal handlers */
+ ointhandler = signal(SIGINT, sighandler);
+ oquithandler = signal(SIGQUIT, sighandler);
+ otstphandler = signal(SIGTSTP, sighandler);
+
+ /* turn off echo again */
+ (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
+}
+
+
char *
getpass(prompt)
const char *prompt;
{
- struct termios term;
register int ch;
register char *p;
- FILE *fp, *outfp;
- long omask;
- int echo;
+ FILE *outfp;
static char buf[_PASSWORD_LEN + 1];
/*
@@ -63,16 +93,16 @@ getpass(prompt)
outfp = stderr;
fp = stdin;
}
- /*
- * note - blocking signals isn't necessarily the
- * right thing, but we leave it for now.
- */
- omask = sigblock(sigmask(SIGINT)|sigmask(SIGTSTP));
- (void)tcgetattr(fileno(fp), &term);
- if (echo = (term.c_lflag & ECHO)) {
- term.c_lflag &= ~ECHO;
- (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
- }
+
+ ointhandler = signal(SIGINT, sighandler);
+ oquithandler = signal(SIGQUIT, sighandler);
+ otstphandler = signal(SIGTSTP, sighandler);
+ oconthandler = signal(SIGCONT, sigconthandler);
+
+ (void)tcgetattr(fileno(fp), &oterm);
+ term = oterm;
+ term.c_lflag &= ~ECHO;
+ (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
(void)fputs(prompt, outfp);
rewind(outfp); /* implied flush */
for (p = buf; (ch = getc(fp)) != EOF && ch != '\n';)
@@ -80,11 +110,14 @@ getpass(prompt)
*p++ = ch;
*p = '\0';
(void)write(fileno(outfp), "\n", 1);
- if (echo) {
- term.c_lflag |= ECHO;
- (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
- }
- (void)sigsetmask(omask);
+ (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &oterm);
+
+ /* restore old sig handlers */
+ (void)signal(SIGINT, ointhandler);
+ (void)signal(SIGQUIT, oquithandler);
+ (void)signal(SIGTSTP, otstphandler);
+ (void)signal(SIGCONT, oconthandler);
+
if (fp != stdin)
(void)fclose(fp);
return(buf);
diff --git a/lib/libc/gen/getpwent.3 b/lib/libc/gen/getpwent.3
index 1208f53..6badc19 100644
--- a/lib/libc/gen/getpwent.3
+++ b/lib/libc/gen/getpwent.3
@@ -29,9 +29,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)getpwent.3 8.2 (Berkeley) 12/11/93
+.\" From: @(#)getpwent.3 8.2 (Berkeley) 12/11/93
.\"
-.Dd December 11, 1993
+.Dd September 20, 1994
.Dt GETPWENT 3
.Os
.Sh NAME
@@ -72,14 +72,15 @@ file
struct passwd {
char *pw_name; /* user name */
char *pw_passwd; /* encrypted password */
- uid_t pw_uid; /* user uid */
- gid_t pw_gid; /* user gid */
+ int pw_uid; /* user uid */
+ int 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
@@ -133,6 +134,24 @@ 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 YP/NIS INTERACTION
+When the
+.Xr yp 4
+password database is enabled, the
+.Fn getpwnam
+and
+.Fn getpwuid
+functions use the YP maps
+.Dq Li passwd.byname
+and
+.Dq Li passwd.byuid ,
+respectively, if the requested password entry is not found in the
+local database. The
+.Fn getpwent
+function will step through the YP map
+.Dq Li passwd.byname
+if the entire map is enabled as described in
+.Xr passwd 5 .
.Sh RETURN VALUES
The functions
.Fn getpwent ,
@@ -152,9 +171,9 @@ function
has no return value.
.Sh FILES
.Bl -tag -width /etc/master.passwd -compact
-.It Pa /var/db/pwd.db
+.It Pa /etc/pwd.db
The insecure password database file
-.It Pa /var/db/spwd.db
+.It Pa /etc/spwd.db
The secure password database file
.It Pa /etc/master.passwd
The current password file
@@ -162,25 +181,31 @@ The current password file
A Version 7 format password file
.El
.Sh SEE ALSO
-.Xr getlogin 3 ,
+.Xr getlogin 2 ,
.Xr getgrent 3 ,
+.Xr yp 4 ,
.Xr passwd 5 ,
.Xr pwd_mkdb 8 ,
.Xr vipw 8
.Sh HISTORY
The
-.Nm getpwent ,
-.Nm getpwnam ,
-.Nm getpwuid ,
-.Nm setpwent,
+.Fn getpwent ,
+.Fn getpwnam ,
+.Fn getpwuid ,
+.Fn setpwent,
and
-.Nm endpwent
+.Fn endpwent
functions appeared in
.At v7 .
The
-.Nm setpassent
+.Fn setpassent
function appeared in
.Bx 4.3 Reno .
+.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 BUGS
The functions
.Fn getpwent ,
@@ -191,17 +216,3 @@ 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 routines
-.Fn getpwent ,
-.Fn endpwent ,
-.Fn setpassent ,
-and
-.Fn setpwent
-are fairly useless in a networked environment and should be
-avoided, if possible.
-.Sh COMPATIBILITY
-The historic function
-.Xr setpwfile 3 ,
-which allowed the specification of alternate password databases,
-has been deprecated and is no longer available.
diff --git a/lib/libc/gen/getpwent.c b/lib/libc/gen/getpwent.c
index 155ba56..d1cec3e 100644
--- a/lib/libc/gen/getpwent.c
+++ b/lib/libc/gen/getpwent.c
@@ -35,6 +35,7 @@
static char sccsid[] = "@(#)getpwent.c 8.2 (Berkeley) 4/27/95";
#endif /* LIBC_SCCS and not lint */
+#include <stdio.h>
#include <sys/param.h>
#include <fcntl.h>
#include <db.h>
@@ -46,6 +47,11 @@ static char sccsid[] = "@(#)getpwent.c 8.2 (Berkeley) 4/27/95";
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <grp.h>
+
+extern void setnetgrent __P(( char * ));
+extern int getnetgrent __P(( char **, char **, char ** ));
+extern int innetgr __P(( const char *, const char *, const char *, const char * ));
/*
* The lookup techniques and data extraction code here must be kept
@@ -56,6 +62,29 @@ static struct passwd _pw_passwd; /* password structure */
static DB *_pw_db; /* password database */
static int _pw_keynum; /* key counter */
static int _pw_stayopen; /* keep fd's open */
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+static struct passwd _pw_copy;
+static DBT empty = { NULL, 0 };
+static DB *_ypcache = (DB *)NULL;
+static int _yp_exclusions = 0;
+static int _yp_enabled; /* set true when yp enabled */
+static int _pw_stepping_yp; /* set true when stepping thru map */
+static char _ypnam[YPMAXRECORD];
+#define YP_HAVE_MASTER 2
+#define YP_HAVE_ADJUNCT 1
+#define YP_HAVE_NONE 0
+static int _gotmaster;
+static char *_pw_yp_domain;
+static inline int unwind __P(( char * ));
+static inline void _ypinitdb __P(( void ));
+static int _havemaster __P((char *));
+static int _getyppass __P((struct passwd *, const char *, const char * ));
+static int _nextyppass __P((struct passwd *));
+#endif
static int __hashpw(), __initdb();
struct passwd *
@@ -63,16 +92,45 @@ getpwent()
{
DBT key;
char bf[sizeof(_pw_keynum) + 1];
+ int rv;
if (!_pw_db && !__initdb())
return((struct passwd *)NULL);
+#ifdef YP
+ if(_pw_stepping_yp) {
+ _pw_passwd = _pw_copy;
+ if (unwind((char *)&_ypnam))
+ return(&_pw_passwd);
+ }
+#endif
+tryagain:
+
++_pw_keynum;
bf[0] = _PW_KEYBYNUM;
bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
key.data = (u_char *)bf;
key.size = sizeof(_pw_keynum) + 1;
- return(__hashpw(&key) ? &_pw_passwd : (struct passwd *)NULL);
+ rv = __hashpw(&key);
+ if(!rv) return (struct passwd *)NULL;
+#ifdef YP
+ if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {
+ bzero((char *)&_ypnam, sizeof(_ypnam));
+ bcopy(_pw_passwd.pw_name, _ypnam,
+ strlen(_pw_passwd.pw_name));
+ _pw_copy = _pw_passwd;
+ if (unwind((char *)&_ypnam) == 0)
+ goto tryagain;
+ else
+ return(&_pw_passwd);
+ }
+#else
+ /* Ignore YP password file entries when YP is disabled. */
+ if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {
+ goto tryagain;
+ }
+#endif
+ return(&_pw_passwd);
}
struct passwd *
@@ -81,7 +139,7 @@ getpwnam(name)
{
DBT key;
int len, rval;
- char bf[UT_NAMESIZE + 1];
+ char bf[UT_NAMESIZE + 2];
if (!_pw_db && !__initdb())
return((struct passwd *)NULL);
@@ -93,10 +151,18 @@ getpwnam(name)
key.size = len + 1;
rval = __hashpw(&key);
- if (!_pw_stayopen) {
- (void)(_pw_db->close)(_pw_db);
- _pw_db = (DB *)NULL;
- }
+#ifdef YP
+ if (!rval && _yp_enabled)
+ rval = _getyppass(&_pw_passwd, name, "passwd.byname");
+#endif
+ /*
+ * Prevent login attempts when YP is not enabled but YP entries
+ * are in /etc/master.passwd.
+ */
+ if (rval && (_pw_passwd.pw_name[0] == '+'||
+ _pw_passwd.pw_name[0] == '-')) rval = 0;
+
+ endpwent();
return(rval ? &_pw_passwd : (struct passwd *)NULL);
}
@@ -118,10 +184,21 @@ getpwuid(uid)
key.size = sizeof(keyuid) + 1;
rval = __hashpw(&key);
- if (!_pw_stayopen) {
- (void)(_pw_db->close)(_pw_db);
- _pw_db = (DB *)NULL;
+#ifdef YP
+ if (!rval && _yp_enabled) {
+ char ypbuf[16]; /* big enough for 32-bit uids and then some */
+ snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid);
+ rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid");
}
+#endif
+ /*
+ * Prevent login attempts when YP is not enabled but YP entries
+ * are in /etc/master.passwd.
+ */
+ if (rval && (_pw_passwd.pw_name[0] == '+'||
+ _pw_passwd.pw_name[0] == '-')) rval = 0;
+
+ endpwent();
return(rval ? &_pw_passwd : (struct passwd *)NULL);
}
@@ -130,6 +207,9 @@ setpassent(stayopen)
int stayopen;
{
_pw_keynum = 0;
+#ifdef YP
+ _pw_stepping_yp = 0;
+#endif
_pw_stayopen = stayopen;
return(1);
}
@@ -138,6 +218,9 @@ int
setpwent()
{
_pw_keynum = 0;
+#ifdef YP
+ _pw_stepping_yp = 0;
+#endif
_pw_stayopen = 0;
return(1);
}
@@ -146,13 +229,23 @@ void
endpwent()
{
_pw_keynum = 0;
+#ifdef YP
+ _pw_stepping_yp = 0;
+#endif
if (_pw_db) {
(void)(_pw_db->close)(_pw_db);
_pw_db = (DB *)NULL;
}
+#ifdef YP
+ if (_ypcache) {
+ (void)(_ypcache->close)(_ypcache);
+ _ypcache = (DB *)NULL;
+ _yp_exclusions = 0;
+ }
+#endif
}
-static
+static int
__initdb()
{
static int warned;
@@ -160,14 +253,35 @@ __initdb()
p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB;
_pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL);
- if (_pw_db)
+ if (_pw_db) {
+#ifdef YP
+ DBT key, data;
+ char buf[] = { _PW_KEYYPENABLED };
+ key.data = buf;
+ key.size = 1;
+ if ((_pw_db->get)(_pw_db, &key, &data, 0)) {
+ _yp_enabled = 0;
+ } else {
+ _yp_enabled = (int)*((char *)data.data) - 2;
+ /* Don't even bother with this if we aren't root. */
+ if (!geteuid()) {
+ if (!_pw_yp_domain)
+ if (yp_get_default_domain(&_pw_yp_domain))
+ return(1);
+ _gotmaster = _havemaster(_pw_yp_domain);
+ } else _gotmaster = YP_HAVE_NONE;
+ if (!_ypcache)
+ _ypinitdb();
+ }
+#endif
return(1);
- if (!warned)
+ }
+ if (!warned++)
syslog(LOG_ERR, "%s: %m", p);
return(0);
}
-static
+static int
__hashpw(key)
DBT *key;
{
@@ -184,7 +298,7 @@ __hashpw(key)
/* THIS CODE MUST MATCH THAT IN pwd_mkdb. */
t = line;
-#define EXPAND(e) e = t; while (*t++ = *p++);
+#define EXPAND(e) e = t; while ( (*t++ = *p++) );
#define SCALAR(v) memmove(&(v), p, sizeof v); p += sizeof v
EXPAND(_pw_passwd.pw_name);
EXPAND(_pw_passwd.pw_passwd);
@@ -196,5 +310,521 @@ __hashpw(key)
EXPAND(_pw_passwd.pw_dir);
EXPAND(_pw_passwd.pw_shell);
SCALAR(_pw_passwd.pw_expire);
+ bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields);
+ p += sizeof _pw_passwd.pw_fields;
+ return(1);
+}
+
+#ifdef YP
+
+/*
+ * Create a DB hash database in memory. Bet you didn't know you
+ * could do a dbopen() will a NULL filename, did you.
+ */
+static inline void _ypinitdb()
+{
+ if (_ypcache == (DB *)NULL)
+ _ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL);
+ return;
+}
+
+/*
+ * See if a user is in the blackballed list.
+ */
+static inline int lookup(name)
+ char *name;
+{
+ DBT key;
+
+ if (!_yp_exclusions)
+ return(0);
+
+ key.data = name;
+ key.size = strlen(name);
+
+ if ((_ypcache->get)(_ypcache, &key, &empty, 0)) {
+ return(0);
+ }
+
return(1);
}
+
+/*
+ * Store a blackballed user in an in-core hash database.
+ */
+static inline void store(key)
+ char *key;
+{
+ DBT lkey;
+/*
+ if (lookup(key))
+ return;
+*/
+
+ _yp_exclusions = 1;
+
+ lkey.data = key;
+ lkey.size = strlen(key);
+
+ (void)(_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE);
+}
+
+/*
+ * Parse the + entries in the password database and do appropriate
+ * NIS lookups. While ugly to look at, this is optimized to do only
+ * as many lookups as are absolutely necessary in any given case.
+ * Basically, the getpwent() function will feed us + and - lines
+ * as they appear in the database. For + lines, we do netgroup/group
+ * and user lookups to find all usernames that match the rule and
+ * extract them from the NIS passwd maps. For - lines, we save the
+ * matching names in a database and a) exlude them, and b) make sure
+ * we don't consider them when processing other + lines that appear
+ * later.
+ */
+static inline int unwind(grp)
+ char *grp;
+{
+ char *user, *host, *domain;
+ static int latch = 0;
+ static struct group *gr = NULL;
+ int rv = 0;
+
+ if (grp[0] == '+') {
+ if (strlen(grp) == 1) {
+ return(_nextyppass(&_pw_passwd));
+ }
+ if (grp[1] == '@') {
+ _pw_stepping_yp = 1;
+grpagain:
+ if (gr != NULL) {
+ if (*gr->gr_mem != NULL) {
+ if (lookup(*gr->gr_mem)) {
+ gr->gr_mem++;
+ goto grpagain;
+ }
+ rv = _getyppass(&_pw_passwd,
+ *gr->gr_mem,
+ "passwd.byname");
+ gr->gr_mem++;
+ return(rv);
+ } else {
+ endgrent();
+ latch = 0;
+ gr = NULL;
+ return(0);
+ }
+ }
+ if (!latch) {
+ setnetgrent(grp+2);
+ latch++;
+ }
+again:
+ if (getnetgrent(&host, &user, &domain) == NULL) {
+ if ((gr = getgrnam(grp+2)) != NULL)
+ goto grpagain;
+ latch = 0;
+ _pw_stepping_yp = 0;
+ return(0);
+ } else {
+ if (lookup(user))
+ goto again;
+ if (_getyppass(&_pw_passwd, user,
+ "passwd.byname"))
+ return(1);
+ else
+ goto again;
+ }
+ } else {
+ if (lookup(grp+1))
+ return(0);
+ return(_getyppass(&_pw_passwd, grp+1, "passwd.byname"));
+ }
+ } else {
+ if (grp[1] == '@') {
+ setnetgrent(grp+2);
+ rv = 0;
+ while(getnetgrent(&host, &user, &domain) != NULL) {
+ store(user);
+ rv++;
+ }
+ if (!rv && (gr = getgrnam(grp+2)) != NULL) {
+ while(gr->gr_mem) {
+ store(gr->gr_mem);
+ gr->gr_mem++;
+ }
+ }
+ } else {
+ store(grp+1);
+ }
+ }
+ return(0);
+}
+
+/*
+ * See if a user is a member of a particular group.
+ */
+static inline int ingr(grp, name)
+ char *grp;
+ char *name;
+{
+ register struct group *gr;
+
+ if ((gr = getgrnam(grp)) == NULL)
+ return(0);
+
+ while(*gr->gr_mem) {
+ if (!strcmp(*gr->gr_mem, name)) {
+ endgrent();
+ return(1);
+ }
+ gr->gr_mem++;
+ }
+
+ endgrent();
+ return(0);
+}
+
+/*
+ * Check a user against the +@netgroup/-@netgroup lines listed in
+ * the local password database. Also checks +user/-user lines.
+ * If no netgroup exists that matches +@netgroup/-@netgroup,
+ * try searching regular groups with the same name.
+ */
+static inline int verf(name)
+ char *name;
+{
+ DBT key;
+ char bf[sizeof(_pw_keynum) + 1];
+ int keynum = 0;
+
+again:
+ ++keynum;
+ bf[0] = _PW_KEYYPBYNUM;
+ bcopy((char *)&keynum, bf + 1, sizeof(keynum));
+ key.data = (u_char *)bf;
+ key.size = sizeof(keynum) + 1;
+ if (!__hashpw(&key)) {
+ /* Try again using old format */
+ bf[0] = _PW_KEYBYNUM;
+ bcopy((char *)&keynum, bf + 1, sizeof(keynum));
+ key.data = (u_char *)bf;
+ if (!__hashpw(&key))
+ return(0);
+ }
+ if (_pw_passwd.pw_name[0] != '+' && (_pw_passwd.pw_name[0] != '-'))
+ goto again;
+ if (_pw_passwd.pw_name[0] == '+') {
+ if (strlen(_pw_passwd.pw_name) == 1) /* Wildcard */
+ return(1);
+ if (_pw_passwd.pw_name[1] == '@') {
+ if ((innetgr(_pw_passwd.pw_name+2, NULL, name,
+ _pw_yp_domain) ||
+ ingr(_pw_passwd.pw_name+2, name)) && !lookup(name))
+ return(1);
+ else
+ goto again;
+ } else {
+ if (!strcmp(name, _pw_passwd.pw_name+1) &&
+ !lookup(name))
+ return(1);
+ else
+ goto again;
+ }
+ }
+ if (_pw_passwd.pw_name[0] == '-') {
+ /* Note that a minus wildcard is a no-op. */
+ if (_pw_passwd.pw_name[1] == '@') {
+ if (innetgr(_pw_passwd.pw_name+2, NULL, name,
+ _pw_yp_domain) ||
+ ingr(_pw_passwd.pw_name+2, name)) {
+ store(name);
+ return(0);
+ } else
+ goto again;
+ } else {
+ if (!strcmp(name, _pw_passwd.pw_name+1)) {
+ store(name);
+ return(0);
+ } else
+ goto again;
+ }
+
+ }
+ return(0);
+}
+
+static char * _get_adjunct_pw(name)
+ char *name;
+{
+ static char adjunctbuf[YPMAXRECORD+2];
+ int rval;
+ char *result;
+ int resultlen;
+ char *map = "passwd.adjunct.byname";
+ char *s;
+
+ if ((rval = yp_match(_pw_yp_domain, map, name, strlen(name),
+ &result, &resultlen)))
+ return(NULL);
+
+ strncpy(adjunctbuf, result, resultlen);
+ adjunctbuf[resultlen] = '\0';
+ free(result);
+ result = (char *)&adjunctbuf;
+
+ /* Don't care about the name. */
+ if ((s = strsep(&result, ":")) == NULL)
+ return (NULL); /* name */
+ if ((s = strsep(&result, ":")) == NULL)
+ return (NULL); /* password */
+
+ return(s);
+}
+
+static int
+_pw_breakout_yp(struct passwd *pw, char *res, int resultlen, int master)
+{
+ char *s, *result;
+ static char resbuf[YPMAXRECORD+2];
+
+ /*
+ * Be triple, ultra super-duper paranoid: reject entries
+ * that start with a + or -. yp_mkdb and /var/yp/Makefile
+ * are _both_ supposed to strip these out, but you never
+ * know.
+ */
+ if (*res == '+' || *res == '-')
+ return 0;
+
+ /*
+ * The NIS protocol definition limits the size of an NIS
+ * record to YPMAXRECORD bytes. We need to do a copy to
+ * a static buffer here since the memory pointed to by
+ * res will be free()ed when this function returns.
+ */
+ strncpy((char *)&resbuf, res, resultlen);
+ resbuf[resultlen] = '\0';
+ result = (char *)&resbuf;
+
+ /*
+ * XXX Sanity check: make sure all fields are valid (no NULLs).
+ * If we find a badly formatted entry, we punt.
+ */
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* name */
+ /*
+ * We don't care what pw_fields says: we _always_ want the
+ * username returned to us by NIS.
+ */
+ pw->pw_name = s;
+ pw->pw_fields |= _PWF_NAME;
+
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* password */
+ if(!(pw->pw_fields & _PWF_PASSWD)) {
+ /* SunOS passwd.adjunct hack */
+ if (master == YP_HAVE_ADJUNCT && strstr(s, "##") != NULL) {
+ char *realpw;
+ realpw = _get_adjunct_pw(pw->pw_name);
+ if (realpw == NULL)
+ pw->pw_passwd = s;
+ else
+ pw->pw_passwd = realpw;
+ } else {
+ pw->pw_passwd = s;
+ }
+ pw->pw_fields |= _PWF_PASSWD;
+ }
+
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* uid */
+ if(!(pw->pw_fields & _PWF_UID)) {
+ pw->pw_uid = atoi(s);
+ pw->pw_fields |= _PWF_UID;
+ }
+
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */
+ if(!(pw->pw_fields & _PWF_GID)) {
+ pw->pw_gid = atoi(s);
+ pw->pw_fields |= _PWF_GID;
+ }
+
+ if (master == YP_HAVE_MASTER) {
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* class */
+ if(!(pw->pw_fields & _PWF_CLASS)) {
+ pw->pw_class = s;
+ pw->pw_fields |= _PWF_CLASS;
+ }
+
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* change */
+ if(!(pw->pw_fields & _PWF_CHANGE)) {
+ pw->pw_change = atol(s);
+ pw->pw_fields |= _PWF_CHANGE;
+ }
+
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* expire */
+ if(!(pw->pw_fields & _PWF_EXPIRE)) {
+ pw->pw_expire = atol(s);
+ pw->pw_fields |= _PWF_EXPIRE;
+ }
+ }
+
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* gecos */
+ if(!(pw->pw_fields & _PWF_GECOS)) {
+ pw->pw_gecos = s;
+ pw->pw_fields |= _PWF_GECOS;
+ }
+
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* dir */
+ if(!(pw->pw_fields & _PWF_DIR)) {
+ pw->pw_dir = s;
+ pw->pw_fields |= _PWF_DIR;
+ }
+
+ if ((s = strsep(&result, ":")) == NULL) return 0; /* shell */
+ if(!(pw->pw_fields & _PWF_SHELL)) {
+ pw->pw_shell = s;
+ pw->pw_fields |= _PWF_SHELL;
+ }
+
+ /* Be consistent. */
+ if ((s = strchr(pw->pw_shell, '\n'))) *s = '\0';
+
+ return 1;
+}
+
+static int
+_havemaster(char *_yp_domain)
+{
+ int order;
+ int rval;
+
+ if (!(rval = yp_order(_yp_domain, "master.passwd.byname", &order)))
+ return(YP_HAVE_MASTER);
+
+ /*
+ * NIS+ in YP compat mode doesn't support
+ * YPPROC_ORDER -- no point in continuing.
+ */
+ if (rval == YPERR_YPERR)
+ return(YP_HAVE_NONE);
+
+ /* master.passwd doesn't exist -- try passwd.adjunct */
+ if (rval == YPERR_MAP) {
+ rval = yp_order(_yp_domain, "passwd.adjunct.byname", &order);
+ if (!rval)
+ return(YP_HAVE_ADJUNCT);
+ }
+
+ return (YP_HAVE_NONE);
+}
+
+static int
+_getyppass(struct passwd *pw, const char *name, const char *map)
+{
+ char *result, *s;
+ int resultlen;
+ int rv;
+ char mastermap[YPMAXRECORD];
+
+ if(!_pw_yp_domain) {
+ if(yp_get_default_domain(&_pw_yp_domain))
+ return 0;
+ }
+
+ sprintf(mastermap,"%s",map);
+
+ if (_gotmaster == YP_HAVE_MASTER)
+ sprintf(mastermap,"master.%s", map);
+
+ if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name),
+ &result, &resultlen))
+ return 0;
+
+ if (!_pw_stepping_yp) {
+ s = strchr(result, ':');
+ if (s) {
+ *s = '\0';
+ } else {
+ /* Must be a malformed entry if no colons. */
+ free(result);
+ return(0);
+ }
+
+ if (!verf(result)) {
+ *s = ':';
+ free(result);
+ return(0);
+ }
+
+ *s = ':'; /* Put back the colon we previously replaced with a NUL. */
+ }
+
+ rv = _pw_breakout_yp(pw, result, resultlen, _gotmaster);
+ free(result);
+ return(rv);
+}
+
+static int
+_nextyppass(struct passwd *pw)
+{
+ static char *key;
+ static int keylen;
+ char *lastkey, *result, *s;
+ int resultlen;
+ int rv;
+ char *map = "passwd.byname";
+
+ if(!_pw_yp_domain) {
+ if(yp_get_default_domain(&_pw_yp_domain))
+ return 0;
+ }
+
+ if (_gotmaster == YP_HAVE_MASTER)
+ map = "master.passwd.byname";
+
+ if(!_pw_stepping_yp) {
+ if(key) free(key);
+ rv = yp_first(_pw_yp_domain, map,
+ &key, &keylen, &result, &resultlen);
+ if(rv) {
+ return 0;
+ }
+ _pw_stepping_yp = 1;
+ goto unpack;
+ } else {
+tryagain:
+ lastkey = key;
+ rv = yp_next(_pw_yp_domain, map, key, keylen,
+ &key, &keylen, &result, &resultlen);
+ free(lastkey);
+unpack:
+ if(rv) {
+ _pw_stepping_yp = 0;
+ return 0;
+ }
+
+ s = strchr(result, ':');
+ if (s) {
+ *s = '\0';
+ } else {
+ /* Must be a malformed entry if no colons. */
+ free(result);
+ goto tryagain;
+ }
+
+ if (lookup(result)) {
+ *s = ':';
+ free(result);
+ goto tryagain;
+ }
+
+ *s = ':'; /* Put back the colon we previously replaced with a NUL. */
+ if (_pw_breakout_yp(pw, result, resultlen, _gotmaster)) {
+ free(result);
+ return(1);
+ } else {
+ free(result);
+ goto tryagain;
+ }
+ }
+}
+
+#endif /* YP */
diff --git a/lib/libc/gen/getttyent.3 b/lib/libc/gen/getttyent.3
index 7ee453d..7d2e7ba 100644
--- a/lib/libc/gen/getttyent.3
+++ b/lib/libc/gen/getttyent.3
@@ -31,7 +31,7 @@
.\"
.\" @(#)getttyent.3 8.1 (Berkeley) 6/4/93
.\"
-.Dd June 4, 1993
+.Dd November 17, 1996
.Dt GETTTYENT 3
.Os BSD 4.3
.Sh NAME
@@ -40,16 +40,23 @@
.Nm setttyent ,
.Nm endttyent
.Nd get ttys file entry
+.Nm isdialuptty ,
+.Nm isnetworktty
+.Nd determine tty type from ttys file entry
.Sh SYNOPSIS
.Fd #include <ttyent.h>
.Ft struct ttyent *
-.Fn getttyent
+.Fn getttyent void
.Ft struct ttyent *
-.Fn getttynam "char *name"
+.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 isnetworktty "const char *name"
.Sh DESCRIPTION
The
.Fn getttyent ,
@@ -62,13 +69,16 @@ file.
.Bd -literal
struct ttyent {
char *ty_name; /* terminal device name */
- char *ty_getty; /* command to execute */
- char *ty_type; /* terminal type */
-#define TTY_ON 0x01 /* enable logins */
+ 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 */
- int ty_status; /* flag values */
- char *ty_window; /* command for window manager */
+#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
@@ -86,7 +96,7 @@ The name of the default terminal type connected to this tty line.
A mask of bit fields which indicate various actions allowed on this
tty line.
The possible flags are as follows:
-.Bl -tag -width TTY_SECURE
+.Bl -tag -width TTY_NETWORK
.It Dv TTY_ON
Enables logins (i.e.,
.Xr init 8
@@ -95,9 +105,23 @@ will start the command referenced by
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 isnetworktty
+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.
@@ -150,6 +174,14 @@ function
and
.Fn endttyent
return 0 on failure and 1 on success.
+.Pp
+The routines
+.Fn isdialuptty
+and
+.Fn isnetworktty
+return non-zero if the dialup or network flag is set for the
+tty entry relating to the tty named by the parameter, and
+zero otherwise.
.Sh FILES
.Bl -tag -width /etc/ttys -compact
.It Pa /etc/ttys
diff --git a/lib/libc/gen/getttyent.c b/lib/libc/gen/getttyent.c
index f9b1e0d..ac3e138 100644
--- a/lib/libc/gen/getttyent.c
+++ b/lib/libc/gen/getttyent.c
@@ -37,11 +37,19 @@ static char sccsid[] = "@(#)getttyent.c 8.1 (Berkeley) 6/4/93";
#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 __P((char *));
+static char *value __P((char *));
struct ttyent *
getttynam(tty)
@@ -49,8 +57,10 @@ getttynam(tty)
{
register struct ttyent *t;
+ if (strncmp(tty, "/dev/", 5) == 0)
+ tty += 5;
setttyent();
- while (t = getttyent())
+ while ( (t = getttyent()) )
if (!strcmp(tty, t->ty_name))
break;
endttyent();
@@ -61,22 +71,26 @@ struct ttyent *
getttyent()
{
static struct ttyent tty;
- register int c;
register char *p;
-#define MAXLINELENGTH 100
- static char line[MAXLINELENGTH];
- static char *skip(), *value();
+ register int c;
+ size_t i;
if (!tf && !setttyent())
return (NULL);
for (;;) {
- if (!fgets(p = line, sizeof(line), tf))
+ if (!fgets(p = line, lbsize, tf))
return (NULL);
- /* skip lines that are too big */
- if (!index(p, '\n')) {
- while ((c = getc(tf)) != '\n' && c != EOF)
- ;
- continue;
+ /* extend buffer if line was too big, and retry */
+ while (!index(p, '\n')) {
+ 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(*p))
++p;
@@ -84,6 +98,9 @@ getttyent()
break;
}
+#define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace(p[sizeof(e) - 1])
+#define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '='
+
zapchar = 0;
tty.ty_name = p;
p = skip(p);
@@ -93,14 +110,19 @@ getttyent()
p = skip(p);
if (!*(tty.ty_type = p))
tty.ty_type = NULL;
- else
+ 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);
+ }
}
tty.ty_status = 0;
tty.ty_window = NULL;
+ tty.ty_group = _TTYS_NOGROUP;
-#define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace(p[sizeof(e) - 1])
-#define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '='
for (; *p; p = skip(p)) {
if (scmp(_TTYS_OFF))
tty.ty_status &= ~TTY_ON;
@@ -108,8 +130,16 @@ getttyent()
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;
}
@@ -120,7 +150,7 @@ getttyent()
tty.ty_comment = p;
if (*p == 0)
tty.ty_comment = 0;
- if (p = index(p, '\n'))
+ if ( (p = index(p, '\n')) )
*p = '\0';
return (&tty);
}
@@ -177,10 +207,15 @@ int
setttyent()
{
+ if (line == NULL) {
+ if ((line = malloc(MALLOCCHUNK)) == NULL)
+ return (0);
+ lbsize = MALLOCCHUNK;
+ }
if (tf) {
- (void)rewind(tf);
+ rewind(tf);
return (1);
- } else if (tf = fopen(_PATH_TTYS, "r"))
+ } else if ( (tf = fopen(_PATH_TTYS, "r")) )
return (1);
return (0);
}
@@ -190,10 +225,40 @@ endttyent()
{
int rval;
+ /*
+ * NB: Don't free `line' because getttynam()
+ * may still be referencing it
+ */
if (tf) {
- rval = !(fclose(tf) == EOF);
+ rval = (fclose(tf) != EOF);
tf = NULL;
return (rval);
}
return (1);
}
+
+static int
+isttystat(tty, flag)
+ const char *tty;
+ int flag;
+{
+ register struct ttyent *t;
+
+ return ((t = getttynam(tty)) == NULL) ? 0 : !!(t->ty_status & flag);
+}
+
+
+int
+isdialuptty(tty)
+ const char *tty;
+{
+
+ return isttystat(tty, TTY_DIALUP);
+}
+
+int isnettty(tty)
+ const char *tty;
+{
+
+ return isttystat(tty, TTY_NETWORK);
+}
diff --git a/lib/libc/gen/getusershell.3 b/lib/libc/gen/getusershell.3
index 48aa859..223caef 100644
--- a/lib/libc/gen/getusershell.3
+++ b/lib/libc/gen/getusershell.3
@@ -40,6 +40,7 @@
.Nm endusershell
.Nd get legal user shells
.Sh SYNOPSIS
+.Fd #include <unistd.h>
.Ft char *
.Fn getusershell void
.Ft void
diff --git a/lib/libc/gen/getusershell.c b/lib/libc/gen/getusershell.c
index 2bcdaf7..408f9f3 100644
--- a/lib/libc/gen/getusershell.c
+++ b/lib/libc/gen/getusershell.c
@@ -72,7 +72,7 @@ getusershell()
void
endusershell()
{
-
+
if (shells != NULL)
free(shells);
shells = NULL;
diff --git a/lib/libc/gen/getvfsbyname.3 b/lib/libc/gen/getvfsbyname.3
index 746d4df..db6152f 100644
--- a/lib/libc/gen/getvfsbyname.3
+++ b/lib/libc/gen/getvfsbyname.3
@@ -38,10 +38,8 @@
.Nm getvfsbyname
.Nd get information about a filesystem
.Sh SYNOPSIS
-.Fd #include <sys/types.h>
+.Fd #include <sys/param.h>
.Fd #include <sys/mount.h>
-.Fd #include <kvm.h>
-.br
.Ft int
.Fn getvfsbyname "const char *name" "struct vfsconf *vfc"
.Sh DESCRIPTION
@@ -53,7 +51,7 @@ If successful,
the requested filesystem
.Fa vfsconf
is returned in the location pointed to by
-.Nm vfc .
+.Fa vfc .
The fields in a
.Dq Li struct vfsconf
are defined as follows:
@@ -95,4 +93,5 @@ specifies a filesystem that is unknown or not configured in the kernel.
.Sh HISTORY
A variant of the
.Fn getvfsbyname
-function first appeared in FreeBSD 2.0.
+function first appeared in
+.Fx 2.0 .
diff --git a/lib/libc/gen/getvfsbyname.c b/lib/libc/gen/getvfsbyname.c
index 9818bae..ae63bfe 100644
--- a/lib/libc/gen/getvfsbyname.c
+++ b/lib/libc/gen/getvfsbyname.c
@@ -32,17 +32,20 @@
*/
#ifndef lint
+#if 0
static char sccsid[] = "@(#)kvm_getvfsbyname.c 8.1 (Berkeley) 4/3/95";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
+#define _NEW_VFSCONF
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/sysctl.h>
#include <errno.h>
#include <kvm.h>
-int getvfsbyname __P((const char *, struct vfsconf *));
-
/*
* Given a filesystem name, determine if it is resident in the kernel,
* and if it is resident, return its vfsconf structure.
diff --git a/lib/libc/gen/getvfsent.3 b/lib/libc/gen/getvfsent.3
new file mode 100644
index 0000000..756fec4
--- /dev/null
+++ b/lib/libc/gen/getvfsent.3
@@ -0,0 +1,228 @@
+.\" $Id: getvfsent.3,v 1.8 1997/02/28 06:22:28 mpp Exp $
+.\" Written by Garrett A. Wollman, September 1994.
+.\" This manual page is in the public domain.
+.\"
+.Dd September 24, 1994
+.Dt GETVFSBYNAME 3
+.Os
+.Sh NAME
+.Nm getvfsbyname ,
+.Nm getvfsbytype ,
+.Nm getvfsent ,
+.Nm setvfsent ,
+.Nm endvfsent ,
+.Nm vfsisloadable ,
+.Nm vfsload
+.Nd manage virtual filesystem modules
+.Sh SYNOPSIS
+.Fd #include <sys/param.h>
+.Fd #include <sys/mount.h>
+.Ft struct vfsconf *
+.Fn getvfsbyname "const char *name"
+.Ft struct vfsconf *
+.Fn getvfsbytype "int type"
+.Ft struct vfsconf *
+.Fn getvfsent "void"
+.Ft void
+.Fn setvfsent "int cachelist"
+.Ft void
+.Fn endvfsent "void"
+.Ft int
+.Fn vfsisloadable "const char *name"
+.Ft int
+.Fn vfsload "const char *name"
+.Sh DESCRIPTION
+The
+.Fn getvfsbyname ,
+.Fn getvfsbytype ,
+and
+.Fn getvfsent
+functions provide convenient access to a list of installed virtual
+filesystem modules managed by the kernel.
+.Fn getvfsbyname
+and
+.Fn getvfsbytype
+provide direct access to a single filesystem's information;
+.Fn getvfsent
+steps through the list of filesystems one at a time. All three
+functions return a null pointer when no data is available. The fields
+in a
+.Dq Li struct vfsconf
+are as follows:
+.Pp
+.Bl -tag -compact -width vfc_refcount
+.It vfc_name
+the name of the filesystem
+.It vfc_index
+the filesystem type number assigned by the kernel and used in calls to
+.Xr mount 2
+.It vfc_refcount
+the number of references to this filesystem
+(usually the number of mounts, but one greater for filesystems which
+cannot be unloaded or which are statically linked into the kernel)
+.It vfc_flags
+flag bits, of which none are currently defined
+.El
+.Pp
+The
+.Fn setvfsent
+and
+.Fn endvfsent
+functions are used to control caching of the filesystem list, which is
+obtained in toto from the kernel via
+.Xr sysctl 3 .
+If the
+.Fa cachelist
+parameter to
+.Fn setvfsent
+is non-zero, the list will be retrieved only once, upon the first call
+to one of the retrieval functions, until
+.Fn endvfsent
+is called to clear the cache. In general,
+.Fn setvfsent 1
+should be called by programs using the
+.Fn getvfsent
+function, and
+.Fn setvfsent 0
+(which is also the default state)
+should be called by programs using the
+.Fn vfsload
+function.
+.Pp
+The
+.Fn vfsisloadable
+function returns a non-zero value if a later call to
+.Fn vfsload name
+is likely to succeed. We say ``likely'' because the conditions
+checked by
+.Fn vfsisloadable
+are only a small subset of the conditions necessary for
+.Fn vfsload
+to succeed. In particular,
+.Fn vfsisloadable
+checks that
+.Pa /dev/lkm
+is present and can be opened for writing, and that
+.Pa Ns Fa name Ns _mod.o
+can be found in one of the directories designated for LKMs.
+.Pp
+The
+.Fn vfsload
+function attempts to load a kernel module implementing filesystem
+.Fa name .
+It returns zero if the filesystem module was successfully located and
+loaded, or non-zero otherwise. It should only be called in the
+following circumstances:
+.Bl -enum
+.It
+.Fn getvfsbyname name
+has been called and returned a null pointer.
+.It
+.Fn vfsisloadable name
+has been called and returned a non-zero value.
+.It
+sufficient temporary file space is available
+.Em and writable
+in one of
+.No Ns \&${ Ns Ev TMPDIR Ns \&} ,
+.Pa /var/tmp ,
+or
+.Pa /tmp .
+.El
+.Pp
+Here is an example, taken from the source to
+.Xr mount_cd9660 8 :
+.Bd -literal -offset indent
+
+struct vfsconf *vfc;
+
+/* setup code here */
+
+vfc = getvfsbyname("cd9660");
+if(!vfc && vfsisloadable("cd9660")) {
+ if(vfsload("cd9660"))
+ err(1, "vfsload(cd9660)");
+ endvfsent(); /* flush cache */
+ vfc = getvfsbyname("cd9660");
+}
+
+mount(vfc ? vfc->vfc_index : MOUNT_CD9660, /* more arguments */
+
+.Ed
+The odd conditional in the call to
+.Xr mount 2
+is present for compatibility with old, non-LKM cognizant kernels, and
+will be removed (along with all vestiges of
+.Dv MOUNT_* )
+in a future release.
+.Sh RETURN VALUES
+The
+.Fn getvfsbyname ,
+.Fn getvfsbytype ,
+and
+.Fn getvfsent
+routines all return a pointer to the same static data structure when
+they succeed, and return a null pointer when they fail. On failure,
+.Va errno
+may be set to one of the values documented for
+.Xr sysctl 3
+or
+.Xr malloc 3 ,
+if a failure of that function was the cause; otherwise
+.Va errno
+will be unmodified.
+.Pp
+The
+.Fn vfsload
+function returns a non-zero value on failure, or zero on success. If
+.Fn vfsload
+fails,
+.Va errno
+may be set to one of the values documented for
+.Xr fork 2 ,
+.Xr waitpid 2 ,
+.Xr chdir 2 ,
+or
+.Xr execlp 3 ,
+or the return status of the
+.Xr modload 8
+program, which is not currently particularly useful but eventually
+will be. In addition, if
+.Xr modload 8
+exits on a signal,
+.Fn vfsload
+will fail and set
+.Va errno
+to
+.Er EINVAL .
+.Sh ENVIRONMENT
+.Bl -tag -compact -width TMPDIRx
+.It Ev TMPDIR
+location for temporary file created by
+.Xr modload 8
+on behalf of
+.Fn vfsload .
+.It Ev LKMDIR
+alternate directory for
+.Fn vfsisloadable
+and
+.Fn vfsload
+to search for loadable modules.
+.Sh SEE ALSO
+.Xr mount 2 ,
+.Xr modload 8 ,
+.Xr mount 8
+.Sh BUGS
+The return value of the
+.Xr modload 8
+command isn't particularly useful when interpreted as an
+.Va errno
+value (or anything else, for that matter).
+.Sh AUTHOR
+The loadable filesystem support was written by Garrett A. Wollman,
+based on generic loadable kernel module support by Terry Lambert.
+.Sh HISTORY
+The
+.Fn getvfsbyname
+family of functions first appeared in
+.Fx 2.0 .
diff --git a/lib/libc/gen/getvfsent.c b/lib/libc/gen/getvfsent.c
new file mode 100644
index 0000000..c4ce2cc
--- /dev/null
+++ b/lib/libc/gen/getvfsent.c
@@ -0,0 +1,248 @@
+/*
+ * getvfsent.c - get a listing of installed filesystems
+ * Written September 1994 by Garrett A. Wollman
+ * This file is in the public domain.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/sysctl.h>
+#include <unistd.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <paths.h>
+
+#define _PATH_MODLOAD "/sbin/modload" /* XXX should be in header file */
+
+static struct vfsconf *_vfslist = 0;
+static struct vfsconf _vfsconf;
+static size_t _vfslistlen = 0;
+static int _vfs_keeplist = 0;
+static int _vfs_index = 0;
+
+static int
+initvfs(void)
+{
+ int mib[2] = { CTL_VFS, VFS_VFSCONF };
+ size_t size = 0;
+ int rv;
+
+ rv = sysctl(mib, 2, (void *)0, &size, (void *)0, (size_t)0);
+ if(rv < 0)
+ return 0;
+
+ if(_vfslist)
+ free(_vfslist);
+ _vfslist = malloc(size);
+ if(!_vfslist)
+ return 0;
+
+ rv = sysctl(mib, 2, _vfslist, &size, (void *)0, (size_t)0);
+ if(rv < 0) {
+ free(_vfslist);
+ _vfslist = 0;
+ return 0;
+ }
+
+ _vfslistlen = size / sizeof _vfslist[0];
+ return 1;
+}
+
+struct vfsconf *
+getvfsent(void)
+{
+ if(!_vfslist && !initvfs()) {
+ return 0;
+ }
+
+ do {
+ if(_vfs_index >= _vfslistlen) {
+ return 0;
+ }
+
+ _vfsconf = _vfslist[_vfs_index++];
+ } while(!_vfsconf.vfc_vfsops);
+
+ if(!_vfs_keeplist) {
+ free(_vfslist);
+ _vfslist = 0;
+ }
+ return &_vfsconf;
+}
+
+struct vfsconf *
+getvfsbyname(const char *name)
+{
+ int i;
+
+ if(!_vfslist && !initvfs()) {
+ return 0;
+ }
+
+ for(i = 0; i < _vfslistlen; i++) {
+ if( ! strcmp(_vfslist[i].vfc_name, name) )
+ break;
+ }
+
+ if(i < _vfslistlen) {
+ _vfsconf = _vfslist[i];
+ }
+
+ if(!_vfs_keeplist) {
+ free(_vfslist);
+ _vfslist = 0;
+ }
+
+ if(i < _vfslistlen) {
+ return &_vfsconf;
+ } else {
+ return 0;
+ }
+}
+
+struct vfsconf *
+getvfsbytype(int type)
+{
+ int i;
+
+ if(!_vfslist && !initvfs()) {
+ return 0;
+ }
+
+ for(i = 0; i < _vfslistlen; i++) {
+ if(_vfslist[i].vfc_index == type)
+ break;
+ }
+
+ if(i < _vfslistlen) {
+ _vfsconf = _vfslist[i];
+ }
+
+ if(!_vfs_keeplist) {
+ free(_vfslist);
+ _vfslist = 0;
+ }
+
+ if(i < _vfslistlen) {
+ return &_vfsconf;
+ } else {
+ return 0;
+ }
+}
+
+void
+setvfsent(int keep)
+{
+ if(_vfslist && !keep) {
+ free(_vfslist);
+ _vfslist = 0;
+ }
+
+ _vfs_keeplist = keep;
+ _vfs_index = 0;
+}
+
+void
+endvfsent(void)
+{
+ if(_vfslist) {
+ free(_vfslist);
+ _vfslist = 0;
+ }
+
+ _vfs_index = 0;
+}
+
+static const char *vfs_lkmdirs[] = {
+ "/lkm",
+ "/usr/lkm",
+ 0,
+ 0
+};
+#define NLKMDIRS ((sizeof vfs_lkmdirs) / (sizeof vfs_lkmdirs[0]))
+
+static const char *
+vfspath(const char *name)
+{
+ static char pnbuf[MAXPATHLEN];
+ char *userdir = getenv("LKMDIR");
+ int i;
+
+ if(userdir && getuid() == geteuid() && getuid() == 0) {
+ vfs_lkmdirs[NLKMDIRS - 2] = userdir;
+ }
+
+ for(i = 0; vfs_lkmdirs[i]; i++) {
+ snprintf(pnbuf, sizeof pnbuf, "%s/%s_mod.o", vfs_lkmdirs[i], name);
+ if( ! access(pnbuf, R_OK) )
+ return pnbuf;
+ }
+
+ return 0;
+}
+
+int
+vfsisloadable(const char *name)
+{
+ int fd;
+
+ fd = open("/dev/lkm", O_RDWR, 0);
+ if(fd < 0) {
+ return 0;
+ }
+ close(fd);
+
+ return !!vfspath(name);
+}
+
+int
+vfsload(const char *name)
+{
+ const char *path = vfspath(name);
+ char name_mod[sizeof("_mod") + strlen(name)];
+ pid_t pid;
+ int status;
+
+ if(!path) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ pid = fork();
+ if(pid < 0)
+ return -1;
+
+ if(pid > 0) {
+ waitpid(pid, &status, 0);
+ if(WIFEXITED(status)) {
+ errno = WEXITSTATUS(status);
+ return errno ? -1 : 0;
+ }
+ errno = EINVAL; /* not enough errno values, >sigh< */
+ return -1;
+ }
+
+ status = -1;
+ unsetenv("TMPDIR");
+ if(status) {
+ status = chdir(_PATH_VARTMP);
+ }
+ if(status) {
+ status = chdir(_PATH_TMP);
+ }
+ if(status) {
+ exit(errno);
+ }
+
+ snprintf(name_mod, sizeof name_mod, "%s%s", name, "_mod");
+ status = execl(_PATH_MODLOAD, "modload", "-e", name_mod, "-o",
+ name_mod, "-u", "-q", path, (const char *)0);
+
+ exit(status ? errno : 0);
+}
+
diff --git a/lib/libc/gen/glob.3 b/lib/libc/gen/glob.3
index f28bc2a..50fd91a 100644
--- a/lib/libc/gen/glob.3
+++ b/lib/libc/gen/glob.3
@@ -43,7 +43,7 @@
.Sh SYNOPSIS
.Fd #include <glob.h>
.Ft int
-.Fn glob "const char *pattern" "int flags" "const int (*errfunc)(const char *, int)" "glob_t *pglob"
+.Fn glob "const char *pattern" "int flags" "int (*errfunc)(const char *, int)" "glob_t *pglob"
.Ft void
.Fn globfree "glob_t *pglob"
.Sh DESCRIPTION
@@ -220,10 +220,11 @@ to provide globbing from directories stored on tape.
Pre-process the pattern string to expand
.Ql {pat,pat,...}
strings like
-.Xr csh 1. The pattern
+.Xr csh 1 .
+The pattern
.Ql {}
-is left unexpanded for historical reasons
-.Xr (Csh 1
+is left unexpanded for historical reasons (and
+.Xr csh 1
does the same thing to
ease typing
of
@@ -424,7 +425,8 @@ The
.Fn glob
and
.Fn globfree
-functions first appeared in 4.4BSD.
+functions first appeared in
+.Bx 4.4 .
.Sh BUGS
Patterns longer than
.Dv MAXPATHLEN
diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c
index 8c8e162..f58fd8d 100644
--- a/lib/libc/gen/glob.c
+++ b/lib/libc/gen/glob.c
@@ -58,7 +58,7 @@ static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
* GLOB_TILDE:
* expand ~user/foo to the /home/dir/of/user/foo
* GLOB_BRACE:
- * expand {1,2}{a,b} to 1a 1b 2a 2b
+ * expand {1,2}{a,b} to 1a 1b 2a 2b
* gl_matchc:
* Number of matches in the current invocation of glob.
*/
@@ -76,6 +76,8 @@ static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
#include <string.h>
#include <unistd.h>
+#include "collate.h"
+
#define DOLLAR '$'
#define DOT '.'
#define EOS '\0'
@@ -140,7 +142,7 @@ static int glob1 __P((Char *, glob_t *));
static int glob2 __P((Char *, Char *, Char *, glob_t *));
static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *));
static int globextend __P((const Char *, glob_t *));
-static const Char * globtilde __P((const Char *, Char *, glob_t *));
+static const Char * globtilde __P((const Char *, Char *, size_t, glob_t *));
static int globexp1 __P((const Char *, glob_t *));
static int globexp2 __P((const Char *, const Char *, glob_t *, int *));
static int match __P((Char *, Char *, Char *));
@@ -173,7 +175,7 @@ glob(pattern, flags, errfunc, pglob)
bufend = bufnext + MAXPATHLEN;
if (flags & GLOB_QUOTE) {
/* Protect the quoted characters. */
- while (bufnext < bufend && (c = *patnext++) != EOS)
+ while (bufnext < bufend && (c = *patnext++) != EOS)
if (c == QUOTE) {
if ((c = *patnext++) == EOS) {
c = QUOTE;
@@ -184,8 +186,8 @@ glob(pattern, flags, errfunc, pglob)
else
*bufnext++ = c;
}
- else
- while (bufnext < bufend && (c = *patnext++) != EOS)
+ else
+ while (bufnext < bufend && (c = *patnext++) != EOS)
*bufnext++ = c;
*bufnext = EOS;
@@ -246,7 +248,7 @@ static int globexp2(ptr, pattern, pglob, rv)
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
*/
@@ -274,7 +276,7 @@ static int globexp2(ptr, pattern, pglob, rv)
for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
continue;
if (*pm == EOS) {
- /*
+ /*
* We could not find a matching RBRACKET.
* Ignore and just look for RBRACE
*/
@@ -299,7 +301,7 @@ static int globexp2(ptr, pattern, pglob, rv)
/* Append the current string */
for (lm = ls; (pl < pm); *lm++ = *pl++)
continue;
- /*
+ /*
* Append the rest of the pattern after the
* closing brace
*/
@@ -330,29 +332,33 @@ static int globexp2(ptr, pattern, pglob, rv)
* expand tilde from the passwd file.
*/
static const Char *
-globtilde(pattern, patbuf, pglob)
+globtilde(pattern, patbuf, patbuf_len, pglob)
const Char *pattern;
Char *patbuf;
+ size_t patbuf_len;
glob_t *pglob;
{
struct passwd *pwd;
char *h;
const Char *p;
- Char *b;
+ Char *b, *eb;
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
return pattern;
- /* Copy up to the end of the string or / */
- for (p = pattern + 1, h = (char *) patbuf; *p && *p != SLASH;
- *h++ = *p++)
+ /*
+ * 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
+ /*
+ * handle a plain ~ or ~/ by expanding $HOME
* first and then trying the password file
*/
if ((h = getenv("HOME")) == NULL) {
@@ -373,16 +379,17 @@ globtilde(pattern, patbuf, pglob)
}
/* Copy the home directory */
- for (b = patbuf; *h; *b++ = *h++)
+ for (b = patbuf; b < eb && *h; *b++ = *h++)
continue;
-
+
/* Append the rest of the pattern */
- while ((*b++ = *p++) != EOS)
+ while (b < eb && (*b++ = *p++) != EOS)
continue;
+ *b = EOS;
return patbuf;
}
-
+
/*
* The main glob() routine: compiles the pattern (optionally processing
@@ -400,7 +407,8 @@ glob0(pattern, pglob)
int c, err, oldpathc;
Char *bufnext, patbuf[MAXPATHLEN+1];
- qpatnext = globtilde(pattern, patbuf, pglob);
+ qpatnext = globtilde(pattern, patbuf, sizeof(patbuf) / sizeof(Char),
+ pglob);
oldpathc = pglob->gl_pathc;
bufnext = patbuf;
@@ -440,7 +448,7 @@ glob0(pattern, pglob)
break;
case STAR:
pglob->gl_flags |= GLOB_MAGCHAR;
- /* collapse adjacent stars to one,
+ /* collapse adjacent stars to one,
* to avoid exponential behavior
*/
if (bufnext == patbuf || bufnext[-1] != M_ALL)
@@ -460,17 +468,17 @@ glob0(pattern, pglob)
return(err);
/*
- * If there was no match we are going to append the pattern
+ * 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 &&
- ((pglob->gl_flags & GLOB_NOCHECK) ||
+ if (pglob->gl_pathc == oldpathc &&
+ ((pglob->gl_flags & GLOB_NOCHECK) ||
((pglob->gl_flags & GLOB_NOMAGIC) &&
!(pglob->gl_flags & GLOB_MAGCHAR))))
return(globextend(pattern, pglob));
- else if (!(pglob->gl_flags & GLOB_NOSORT))
+ else if (!(pglob->gl_flags & GLOB_NOSORT))
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
return(0);
@@ -519,7 +527,7 @@ glob2(pathbuf, pathend, pattern, pglob)
*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) &&
@@ -572,7 +580,7 @@ glob3(pathbuf, pathend, pattern, restpattern, pglob)
*pathend = EOS;
errno = 0;
-
+
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
/* TODO: don't call for ENOENT or ENOTDIR? */
if (pglob->gl_errfunc) {
@@ -598,7 +606,7 @@ glob3(pathbuf, pathend, pattern, restpattern, pglob)
/* Initial DOT must be matched literally. */
if (dp->d_name[0] == DOT && *pattern != DOT)
continue;
- for (sc = (u_char *) dp->d_name, dc = pathend;
+ for (sc = (u_char *) dp->d_name, dc = pathend;
(*dc++ = *sc++) != EOS;)
continue;
if (!match(pathend, pattern, restpattern)) {
@@ -644,7 +652,7 @@ globextend(path, pglob)
const Char *p;
newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
- pathv = pglob->gl_pathv ?
+ pathv = pglob->gl_pathv ?
realloc((char *)pglob->gl_pathv, newsize) :
malloc(newsize);
if (pathv == NULL)
@@ -668,7 +676,6 @@ globextend(path, pglob)
return(copy == NULL ? GLOB_NOSPACE : 0);
}
-
/*
* pattern matching function for filenames. Each occurrence of the *
* pattern causes a recursion level.
@@ -686,7 +693,7 @@ match(name, pat, patend)
case M_ALL:
if (pat == patend)
return(1);
- do
+ do
if (match(name, pat, patend))
return(1);
while (*name++ != EOS);
@@ -703,7 +710,11 @@ match(name, pat, patend)
++pat;
while (((c = *pat++) & M_MASK) != M_END)
if ((*pat & M_MASK) == M_RNG) {
- if (c <= k && k <= pat[1])
+ if (__collate_load_error ?
+ CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) :
+ __collate_range_cmp(CHAR(c), CHAR(k)) <= 0
+ && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0
+ )
ok = 1;
pat += 2;
} else if (c == k)
@@ -825,7 +836,7 @@ g_Ctoc(str, buf)
}
#ifdef DEBUG
-static void
+static void
qprintf(str, s)
const char *str;
register Char *s;
diff --git a/lib/libc/gen/initgroups.3 b/lib/libc/gen/initgroups.3
index a0b1c4f..474265d 100644
--- a/lib/libc/gen/initgroups.3
+++ b/lib/libc/gen/initgroups.3
@@ -67,14 +67,14 @@ returns \-1 if it was not invoked by the super-user.
.Xr getgrouplist 3
.Sh HISTORY
The
-.Nm
+.Fn initgroups
function appeared in
.Bx 4.2 .
.Sh BUGS
The
.Fn getgrouplist
function called by
-.Nm
+.Fn initgroups
uses the routines based on
.Xr getgrent 3 .
If the invoking program uses any of these routines,
diff --git a/lib/libc/gen/initgroups.c b/lib/libc/gen/initgroups.c
index d427539..b1ddd86 100644
--- a/lib/libc/gen/initgroups.c
+++ b/lib/libc/gen/initgroups.c
@@ -38,6 +38,8 @@ static char sccsid[] = "@(#)initgroups.c 8.1 (Berkeley) 6/4/93";
#include <sys/param.h>
#include <stdio.h>
+#include <err.h>
+#include <unistd.h>
int
initgroups(uname, agroup)
diff --git a/lib/libc/gen/isatty.c b/lib/libc/gen/isatty.c
index f6bb04b..c8356c7 100644
--- a/lib/libc/gen/isatty.c
+++ b/lib/libc/gen/isatty.c
@@ -37,12 +37,27 @@ static char sccsid[] = "@(#)isatty.c 8.1 (Berkeley) 6/4/93";
#include <termios.h>
#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
int
isatty(fd)
int fd;
{
+ int retval;
struct termios t;
- return(tcgetattr(fd, &t) != -1);
+#ifdef _THREAD_SAFE
+ if (_thread_fd_lock(fd, FD_READ, NULL,__FILE__,__LINE__) == 0) {
+#endif
+ retval = (tcgetattr(fd, &t) != -1);
+#ifdef _THREAD_SAFE
+ _thread_fd_unlock(fd, FD_READ);
+ } else {
+ retval = 0;
+ }
+#endif
+ return(retval);
}
diff --git a/lib/libc/gen/jrand48.c b/lib/libc/gen/jrand48.c
new file mode 100644
index 0000000..051d5a6
--- /dev/null
+++ b/lib/libc/gen/jrand48.c
@@ -0,0 +1,21 @@
+/*
+ * 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"
+
+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..f13826b
--- /dev/null
+++ b/lib/libc/gen/lcong48.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
+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
index bffcacf..0307ad1 100644
--- a/lib/libc/gen/ldexp.3
+++ b/lib/libc/gen/ldexp.3
@@ -68,10 +68,10 @@ and the value
is returned.
.Sh SEE ALSO
.Xr frexp 3 ,
-.Xr modf 3 ,
-.Xr math 3
+.Xr math 3 ,
+.Xr modf 3
.Sh STANDARDS
The
.Fn ldexp
-function conforms
+function conforms to
.St -ansiC .
diff --git a/lib/libc/gen/lrand48.c b/lib/libc/gen/lrand48.c
new file mode 100644
index 0000000..a3d0111
--- /dev/null
+++ b/lib/libc/gen/lrand48.c
@@ -0,0 +1,23 @@
+/*
+ * 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];
+
+long
+lrand48(void)
+{
+ _dorand48(_rand48_seed);
+ return ((long) _rand48_seed[2] << 15) + ((long) _rand48_seed[1] >> 1);
+}
diff --git a/lib/libc/gen/mrand48.c b/lib/libc/gen/mrand48.c
new file mode 100644
index 0000000..b23db51
--- /dev/null
+++ b/lib/libc/gen/mrand48.c
@@ -0,0 +1,23 @@
+/*
+ * 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];
+
+long
+mrand48(void)
+{
+ _dorand48(_rand48_seed);
+ return ((long) _rand48_seed[2] << 16) + (long) _rand48_seed[1];
+}
diff --git a/lib/libc/gen/msgctl.3 b/lib/libc/gen/msgctl.3
new file mode 100644
index 0000000..c505e7d
--- /dev/null
+++ b/lib/libc/gen/msgctl.3
@@ -0,0 +1,207 @@
+.\" $NetBSD: msgctl.2,v 1.1 1995/10/16 23:49:15 jtc Exp $
+.\"
+.\" Copyright (c) 1995 Frank van der Linden
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 Frank van der Linden
+.\" 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.
+.\"/
+.Dd August 17, 1995
+.Dt MSGCTL 3
+.Os FreeBSD
+.Sh NAME
+.Nm msgctl
+.Nd message control operations
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Fd #include <sys/msg.h>
+.Ft int
+.Fn msgctl "int msqid" "int cmd" "struct msqid_ds *buf"
+.Sh DESCRIPTION
+The
+.Fn msgctl
+system call performs some control operations on the message queue specified
+by
+.Fa msqid .
+
+Each message queue has a data structure associated with it, parts of which
+may be altered by
+.Fn msgctl
+and parts of which determine the actions of
+.Fn msgctl .
+The data structure is defined in
+.Aq Pa sys/msg.h
+and contains (amongst others) the following members:
+.Bd -literal
+struct msqid_ds {
+ struct ipc_perm msg_perm; /* msg queue permission bits */
+ struct msg *msg_first; /* first message in the queue */
+ struct msg *msg_last; /* last message in the queue */
+ u_long msg_cbytes; /* number of bytes in use on the queue */
+ u_long msg_qnum; /* number of msgs in the queue */
+ u_long msg_qbytes; /* max # of bytes on the queue */
+ pid_t msg_lspid; /* pid of last msgsnd() */
+ pid_t msg_lrpid; /* pid of last msgrcv() */
+ time_t msg_stime; /* time of last msgsnd() */
+ long msg_pad1;
+ time_t msg_rtime; /* time of last msgrcv() */
+ long msg_pad2;
+ time_t msg_ctime; /* time of last msgctl() */
+ long msg_pad3;
+ long msg_pad4[4];
+};
+.Ed
+.Pp
+The
+.Bf -literal
+ipc_perm
+.Ef
+structure used inside the
+.Bf -literal
+shmid_ds
+.Ef
+structure is defined in
+.Aq Pa sys/ipc.h
+and looks like this:
+.Bd -literal
+struct ipc_perm {
+ ushort cuid; /* creator user id */
+ ushort cgid; /* creator group id */
+ ushort uid; /* user id */
+ ushort gid; /* group id */
+ ushort mode; /* r/w permission */
+ ushort seq; /* sequence # (to generate unique msg/sem/shm id) */
+ key_t key; /* user specified msg/sem/shm key */
+};
+.Ed
+.Pp
+The operation to be performed by
+.Fn msgctl
+is specified in
+.Fa cmd
+and is one of:
+.Bl -tag -width IPC_RMIDX
+.It Dv IPC_STAT
+Gather information about the message queue and place it in the
+structure pointed to by
+.Fa buf .
+.It Dv IPC_SET
+Set the value of the
+.Va msg_perm.uid ,
+.Va msg_perm.gid ,
+.Va msg_perm.mode
+and
+.Va msg_qbytes
+fields in the structure associated with
+.Fa msqid .
+The values are taken from the corresponding fields in the structure
+pointed to by
+.Fa buf .
+This operation can only be executed by the super-user, or a process that
+has an effective user id equal to either
+.Va msg_perm.cuid
+or
+.Va msg_perm.uid
+in the data structure associated with the message queue.
+The value of
+.Va msg_qbytes
+can only be increased by the super-user. Values for
+.Va msg_qbytes
+that exceed the system limit (MSGMNB from
+.Aq Pa sys/msg.h )
+are silently truncated to that limit.
+
+.It Dv IPC_RMID
+Remove the message queue specified by
+.Fa msqid
+and destroy the data associated with it. Only the super-user or a process
+with an effective uid equal to the
+.Va msg_perm.cuid
+or
+.Va msg_perm.uid
+values in the data structure associated with the queue can do this.
+.El
+
+The permission to read from or write to a message queue (see
+.Xr msgsnd 3
+and
+.Xr msgrcv 3 )
+is determined by the
+.Va msg_perm.mode
+field in the same way as is
+done with files (see
+.Xr chmod 2 ),
+but the effective uid can match either the
+.Va msg_perm.cuid
+field or the
+.Va msg_perm.uid
+field, and the
+effective gid can match either
+.Va msg_perm.cgid
+or
+.Va msg_perm.gid .
+.Sh RETURN VALUES
+Upon successful completion, a value of 0 is returned. Otherwise, -1 is
+returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Fn msgctl
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EPERM
+.Fa cmd
+is equal to IPC_SET or IPC_RMID and the caller is not the super-user, nor does
+the effective uid match either the
+.Va msg_perm.uid
+or
+.Va msg_perm.cuid
+fields of the data structure associated with the message queue.
+
+An attempt is made to increase the value of
+.Va msg_qbytes
+through IPC_SET
+but the caller is not the super-user.
+.It Bq Er EACCESS
+The command is IPC_STAT
+and the caller has no read permission for this message queue.
+.It Bq Er EINVAL
+.Fa msqid
+is not a valid message queue identifier.
+
+.Va cmd
+is not a valid command.
+.It Bq Er EFAULT
+.Fa buf
+specifies an invalid address.
+.El
+.Sh SEE ALSO
+.Xr msgget 3 ,
+.Xr msgrcv 3 ,
+.Xr msgsnd 3
+.Sh HISTORY
+Message queues appeared in the first release of AT&T Unix System V.
diff --git a/lib/libc/gen/msgctl.c b/lib/libc/gen/msgctl.c
new file mode 100644
index 0000000..7b74c51e
--- /dev/null
+++ b/lib/libc/gen/msgctl.c
@@ -0,0 +1,15 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+
+#if __STDC__
+int msgctl(int msqid, int cmd, struct msqid_ds *buf)
+#else
+int msgctl(msqid,cmd,buf)
+ int msqid;
+ int cmd;
+ caddr_t buf;
+#endif
+{
+ return (msgsys(0, msqid, cmd, buf));
+}
diff --git a/lib/libc/gen/msgget.3 b/lib/libc/gen/msgget.3
new file mode 100644
index 0000000..72a07e4
--- /dev/null
+++ b/lib/libc/gen/msgget.3
@@ -0,0 +1,134 @@
+.\" $NetBSD: msgget.2,v 1.1 1995/10/16 23:49:19 jtc Exp $
+.\"
+.\" Copyright (c) 1995 Frank van der Linden
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 Frank van der Linden
+.\" 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.
+.\"/
+.Dd August 17, 1995
+.Dt MSGGET 3
+.Os FreeBSD
+.Sh NAME
+.Nm msgget
+.Nd get message queue
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Fd #include <sys/msg.h>
+.Ft int
+.Fn msgget "key_t key" "int msgflg"
+.Sh DESCRIPTION
+.Fn msgget
+returns the message queue identifier associated with
+.Fa key .
+A message queue identifier is a unique integer greater than zero.
+.Pp
+A message queue is created if either
+.Fa key
+is equal to
+.Dv IPC_PRIVATE ,
+or
+.Fa key
+does not have a message queue identifier associated with it, and the
+.Dv IPC_CREAT
+bit is set in
+.Fa msgflg.
+.Pp
+If a new message queue is created, the data structure associated with it (the
+.Va msqid_ds
+structure, see
+.Xr msgctl 3 )
+is initialized as follows:
+.Bl -bullet
+.It
+.Va msg_perm.cuid
+and
+.Va msg_perm.uid
+are set to the effective uid of the calling process.
+.It
+.Va msg_perm.gid
+and
+.Va msg_perm.cgid
+are set to the effective gid of the calling process.
+.It
+.Va msg_perm.mode
+is set to the lower 9 bits of
+.Fa msgflg .
+.It
+.Va msg_cbytes ,
+.Va msg_qnum ,
+.Va msg_lspid ,
+.Va msg_lrpid ,
+.Va msg_rtime ,
+and
+.Va msg_stime
+are set to 0.
+.It
+.Va msg_qbytes
+is set to the system wide maximum value for the number of bytes in a queue
+.Pf ( Dv MSGMNB ) .
+.It
+.Va msg_ctime
+is set to the current time.
+.El
+.Sh RETURN VALUES
+Upon successful completion a positive message queue identifier is returned.
+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 EACESS
+A message queue is already associated with
+.Fa key
+and the caller has no permission to access it.
+.It Bq Er EEXIST
+Both
+.Dv IPC_CREAT
+and
+.Dv IPC_EXCL
+are set in
+.Fa msgflg ,
+and a message queue is already associated with
+.Fa key .
+.It Bq Er ENOSPC
+A new message queue could not be created because the system limit for
+the number of message queues has been reached.
+.It Bq Er ENOENT
+.Dv IPC_CREAT
+was not set in
+.Fa msgflg
+and no message queue associated with
+.Fa key
+was found.
+.El
+.Sh SEE ALSO
+.Xr msgctl 3 ,
+.Xr msgrcv 3 ,
+.Xr msgsnd 3
+.Sh HISTORY
+Message queues appeared in the first release of AT&T Unix System V.
diff --git a/lib/libc/gen/msgget.c b/lib/libc/gen/msgget.c
new file mode 100644
index 0000000..3e146b0
--- /dev/null
+++ b/lib/libc/gen/msgget.c
@@ -0,0 +1,14 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+
+#if __STDC__
+int msgget(key_t key, int msgflg)
+#else
+int msgget(key,msgflg)
+ key_t key;
+ int msgflg;
+#endif
+{
+ return (msgsys(1, key, msgflg));
+}
diff --git a/lib/libc/gen/msgrcv.3 b/lib/libc/gen/msgrcv.3
new file mode 100644
index 0000000..11099ca
--- /dev/null
+++ b/lib/libc/gen/msgrcv.3
@@ -0,0 +1,207 @@
+.\" $NetBSD: msgrcv.2,v 1.1 1995/10/16 23:49:20 jtc Exp $
+.\"
+.\" Copyright (c) 1995 Frank van der Linden
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 Frank van der Linden
+.\" 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.
+.\"/
+.Dd August 17, 1995
+.Dt MSGRCV 3
+.Os FreeBSD
+.Sh NAME
+.Nm msgrcv
+.Nd receive a message from a message queue
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Fd #include <sys/msg.h>
+.Ft int
+.Fn msgrcv "int msqid" "void *msgp" "size_t msgsz" "long msgtyp" "int msgflg"
+.Sh DESCRIPTION
+The
+.Fn msgrcv
+function receives a message from the message queue specified in
+.Fa msqid ,
+and places it into the structure pointed to by
+.Fa msgp .
+This structure should consist of the following members:
+.Bd -literal
+ long mtype; /* message type */
+ char mtext[1]; /* body of message */
+.Ed
+.Pp
+.Va mtype
+is an integer greater than 0 that can be used for selecting messages,
+.Va mtext
+is an array of bytes, with a size up to that of the system limit
+.Pf ( Dv MSGMAX ) .
+.Pp
+The value of
+.Fa msgtyp
+has one of the following meanings:
+.Bl -bullet
+.It
+.Fa msgtyp
+is greater than 0. The first message of type
+.Fa msgtyp
+will be received.
+.It
+.Fa msgtyp
+is equal to 0. The first message on the queue will be received.
+.It
+.Fa msgtyp
+is less than 0. The first message of the lowest message type that is
+less than or equal to the absolute value of
+.Fa msgtyp
+will be received.
+.El
+.Pp
+.Fa msgsz
+specifies the maximum length of the requested message. If the received
+message has a length greater than
+.Fa msgsz
+it will be silently truncated if the
+.Dv MSG_NOERROR
+flag is set in
+.Fa msgflg ,
+otherwise an error will be returned.
+.Pp
+If no matching message is present on the message queue specified by
+.Fa msqid ,
+the behavior of
+.Fn msgrcv
+depends on whether the
+.Dv IPC_NOWAIT
+flag is set in
+.Fa msgflg
+or not. If
+.Dv IPC_NOWAIT
+is set,
+.Fn msgrcv
+will immediately return a value of -1, and set
+.Va errno
+to
+.Er EAGAIN .
+If
+.Dv IPC_NOWAIT
+is not set, the calling process will be blocked
+until:
+.Bl -bullet
+.It
+A message of the requested type becomes available on the message queue.
+.It
+The message queue is removed, in which case -1 will be returned, and
+.Va errno
+set to
+.Er EINVAL .
+.It
+A signal is received and caught. -1 is returned, and
+.Va errno
+set to
+.Er EINTR .
+.El
+.Pp
+If a message is successfully received, the data structure associated with
+.Fa msqid
+is updated as follows:
+.Bl -bullet
+.It
+.Va msg_cbytes
+is decremented by the size of the message.
+.It
+.Va msg_lrpid
+is set to the pid of the caller.
+.It
+.Va msg_lrtime
+is set to the current time.
+.It
+.Va msg_qnum
+is decremented by 1.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn msgrcv
+returns the number of bytes received into the
+.Va mtext
+field of the structure pointed to by
+.Fa msgp .
+Otherwise, -1 is returned, and
+.Va errno
+set to indicate the error.
+.Sh ERRORS
+.Fn msgrcv
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+.Fa msqid
+is not a valid message queue identifier.
+.Pp
+The message queue was removed while
+.Fn msgrcv
+was waiting for a message of the requested type to become available on it.
+.Pp
+.Fa msgsz
+is less than 0.
+.It Bq Er E2BIG
+A matching message was received, but its size was greater than
+.Fa msgsz
+and the
+.Dv MSG_NOERROR
+flag was not set in
+.Fa msgflg .
+.It Bq Er EACCESS
+The calling process does not have read access to the message queue.
+.It Bq Er EFAULT
+.Fa msgp
+points to an invalid address.
+.It Bq Er EINTR
+The system call was interrupted by the delivery of a signal.
+.It Bq Er EAGAIN
+There is no message of the requested type available on the message queue,
+and
+.Dv IPC_NOWAIT
+is set in
+.Fa msgflg .
+.Sh SEE ALSO
+.Xr msgctl 3 ,
+.Xr msgget 3 ,
+.Xr msgsnd 3
+.Sh BUGS
+.Tn NetBSD
+and
+.Tn FreeBSD
+do not define the
+.Er EIDRM
+error value, which should be used in
+the case of a removed message queue, nor the
+.Er ENOMSG
+value, which
+should be used when no suitable message is available and
+.Dv IPC_NOWAIT
+is set.
+.Sh HISTORY
+Message queues appeared in the first release of
+AT&T Unix System V.
diff --git a/lib/libc/gen/msgrcv.c b/lib/libc/gen/msgrcv.c
new file mode 100644
index 0000000..5c1e387
--- /dev/null
+++ b/lib/libc/gen/msgrcv.c
@@ -0,0 +1,17 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+
+#if __STDC__
+int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
+#else
+int msgrcv(msqid, msgp, msgsz, msgtyp, msgflg)
+ int msqid;
+ void *msgp;
+ size_t msgsz;
+ long msgtyp;
+ int msgflg;
+#endif
+{
+ return (msgsys(3, msqid, msgp, msgsz, msgtyp, msgflg));
+}
diff --git a/lib/libc/gen/msgsnd.3 b/lib/libc/gen/msgsnd.3
new file mode 100644
index 0000000..5a3c80c
--- /dev/null
+++ b/lib/libc/gen/msgsnd.3
@@ -0,0 +1,159 @@
+.\" $NetBSD: msgsnd.2,v 1.1 1995/10/16 23:49:24 jtc Exp $
+.\"
+.\" Copyright (c) 1995 Frank van der Linden
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 Frank van der Linden
+.\" 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.
+.\"/
+.Dd August 17, 1995
+.Dt MSGSND 3
+.Os FreeBSD
+.Sh NAME
+.Nm msgsnd
+.Nd send a message to a message queue
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Fd #include <sys/msg.h>
+.Ft int
+.Fn msgsnd "int msqid" "void *msgp" "size_t msgsz" "int msgflg"
+.Sh DESCRIPTION
+The
+.Fn msgsnd
+function sends a message from the message queue specified in
+.Fa msqid .
+.Fa msgp
+points to a structure containing the message. This structure should
+consist of the following members:
+.Bd -literal
+ long mtype; /* message type */
+ char mtext[1]; /* body of message */
+.Ed
+.Pp
+.Va mtype
+is an integer greater than 0 that can be used for selecting messages (see
+.Xr msgrcv 3 ) ,
+.Va mtext
+is an array of bytes, with a size up to that of the system limit
+.Pf ( Dv MSGMAX ) .
+.Pp
+If the number of bytes already on the message queue plus
+.Fa msgsz
+is bigger than the maximum number of bytes on the message queue
+.Pf ( Va msg_qbytes ,
+see
+.Xr msgctl 3 ) ,
+or the number of messages on all queues system-wide is already equal to
+the system limit,
+.Fa msgflg
+determines the action of
+.Fn msgsnd .
+If
+.Fa msgflg
+has
+.Dv IPC_NOWAIT
+mask set in it, the call will return immediately. If
+.Fa msgflg
+does not have
+.Dv IPC_NOWAIT
+set in it, the call will block until:
+.Bl -bullet
+.It
+The condition which caused the call to block does no longer exist.
+The message will be sent.
+.It
+The message queue is removed, in which case -1 will be returned, and
+.Va errno
+is set to
+.Er EINVAL .
+.It
+The caller catches a signal. The call returns with
+.Va errno
+set to
+.Er EINTR .
+.El
+.Pp
+After a successful call, the data structure associated with the message
+queue is updated in the following way:
+.Bl -bullet
+.It
+.Va msg_cbytes
+is incremented by the size of the message.
+.It
+.Va msg_qnum
+is incremented by 1.
+.It
+.Va msg_lspid
+is set to the pid of the calling process.
+.It
+.Va msg_stime
+is set to the current time.
+.El
+.Sh RETURN VALUES
+Upon successful completion, 0 is returned. Otherwise, -1 is returned and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Fn msgsnd
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+.Fa msqid
+is not a valid message queue identifier
+.Pp
+The message queue was removed while
+.Fn msgsnd
+was waiting for a resource to become available in order to deliver the
+message.
+.Pp
+.Fa msgsz
+is less than 0, or greater than
+.Va msg_qbytes .
+.It Bq Er EACCESS
+The calling process does not have write access to the message queue.
+.It Bq Er EAGAIN
+There was no space for this message either on the queue, or in the whole
+system, and
+.Dv IPC_NOWAIT
+was set in
+.Fa msgflg .
+.It Bq Er EFAULT
+.Fa msgp
+points to an invalid address.
+.It Bq Er EINTR
+The system call was interrupted by the delivery of a signal.
+.El
+.Sh BUGS
+.Tn NetBSD
+and
+.Tn FreeBSD
+do not define the
+.Er EIDRM
+error value, which should be used
+in the case of a removed message queue.
+.Sh HISTORY
+Message queues appeared in the first release of AT&T Unix System V.
diff --git a/lib/libc/gen/msgsnd.c b/lib/libc/gen/msgsnd.c
new file mode 100644
index 0000000..a620915
--- /dev/null
+++ b/lib/libc/gen/msgsnd.c
@@ -0,0 +1,16 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+
+#if __STDC__
+int msgsnd(int msqid, void *msgp, size_t msgsz, int msgflg)
+#else
+int msgsnd(msqid, msgp, msgsz, msgflg)
+ int msqid;
+ void *msgp;
+ size_t msgsz;
+ int msgflg;
+#endif
+{
+ return (msgsys(2, msqid, msgp, msgsz, msgflg));
+}
diff --git a/lib/libc/gen/nice.3 b/lib/libc/gen/nice.3
index 64a87c6..8179250 100644
--- a/lib/libc/gen/nice.3
+++ b/lib/libc/gen/nice.3
@@ -38,6 +38,7 @@
.Nm nice
.Nd set program scheduling priority
.Sh SYNOPSIS
+.Ft int
.Fn nice "int incr"
.Sh DESCRIPTION
.Bf -symbolic
@@ -57,8 +58,8 @@ Children inherit the priority of their parent processes via
.Xr fork 2 .
.Sh SEE ALSO
.Xr nice 1 ,
-.Xr setpriority 2 ,
.Xr fork 2 ,
+.Xr setpriority 2 ,
.Xr renice 8
.Sh HISTORY
A
diff --git a/lib/libc/gen/nlist.3 b/lib/libc/gen/nlist.3
index 11c9ee4..981a4c8 100644
--- a/lib/libc/gen/nlist.3
+++ b/lib/libc/gen/nlist.3
@@ -46,8 +46,8 @@ The
.Fn nlist
function
retrieves name list entries from the symbol table of an
-executable file. (See
-.Xr a.out 5 . )
+executable file (see
+.Xr a.out 5 ) .
The argument
.Fa \&nl
is set to reference the
diff --git a/lib/libc/gen/nlist.c b/lib/libc/gen/nlist.c
index 874f26e..7415cbe 100644
--- a/lib/libc/gen/nlist.c
+++ b/lib/libc/gen/nlist.c
@@ -46,6 +46,8 @@ static char sccsid[] = "@(#)nlist.c 8.1 (Berkeley) 6/4/93";
#include <string.h>
#include <unistd.h>
+int __fdnlist __P(( int, struct nlist * ));
+
int
nlist(name, list)
const char *name;
@@ -68,40 +70,53 @@ __fdnlist(fd, list)
register int fd;
register struct nlist *list;
{
- register struct nlist *p, *s;
- register caddr_t strtab;
+ register struct nlist *p, *symtab;
+ register caddr_t strtab, a_out_mmap;
register off_t stroff, symoff;
register u_long symsize;
- register int nent, cc;
- size_t strsize;
- struct nlist nbuf[1024];
- struct exec exec;
+ register int nent;
+ struct exec * exec;
struct stat st;
- if (lseek(fd, (off_t)0, SEEK_SET) == -1 ||
- read(fd, &exec, sizeof(exec)) != sizeof(exec) ||
- N_BADMAG(exec) || fstat(fd, &st) < 0)
+ /* check that file is at least as large as struct exec! */
+ if ((fstat(fd, &st) < 0) || (st.st_size < sizeof(struct exec)))
return (-1);
- symoff = N_SYMOFF(exec);
- symsize = exec.a_syms;
- stroff = symoff + symsize;
-
/* Check for files too large to mmap. */
- if (st.st_size - stroff > SIZE_T_MAX) {
+ if (st.st_size > SIZE_T_MAX) {
errno = EFBIG;
return (-1);
}
+
/*
- * 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).
+ * 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).
*/
- strsize = st.st_size - stroff;
- strtab = mmap(NULL, (size_t)strsize, PROT_READ, 0, fd, stroff);
- if (strtab == (char *)-1)
+ 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
@@ -120,30 +135,26 @@ __fdnlist(fd, list)
p->n_value = 0;
++nent;
}
- if (lseek(fd, symoff, SEEK_SET) == -1)
- return (-1);
while (symsize > 0) {
- cc = MIN(symsize, sizeof(nbuf));
- if (read(fd, nbuf, cc) != cc)
- break;
- symsize -= cc;
- for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) {
- register int soff = s->n_un.n_strx;
-
- if (soff == 0 || (s->n_type & N_STAB) != 0)
- continue;
+ register 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 = s->n_value;
- p->n_type = s->n_type;
- p->n_desc = s->n_desc;
- p->n_other = s->n_other;
+ 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(strtab, strsize);
+ munmap(a_out_mmap, (size_t)st.st_size);
return (nent);
}
diff --git a/lib/libc/gen/nrand48.c b/lib/libc/gen/nrand48.c
new file mode 100644
index 0000000..6c54065
--- /dev/null
+++ b/lib/libc/gen/nrand48.c
@@ -0,0 +1,21 @@
+/*
+ * 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"
+
+long
+nrand48(unsigned short xseed[3])
+{
+ _dorand48(xseed);
+ return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1);
+}
diff --git a/lib/libc/gen/ntp_gettime.c b/lib/libc/gen/ntp_gettime.c
new file mode 100644
index 0000000..1f18337
--- /dev/null
+++ b/lib/libc/gen/ntp_gettime.c
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] =
+ "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+
+int
+ntp_gettime(struct ntptimeval *ntv)
+{
+ int mib[3];
+ struct ntptimeval tv;
+ size_t size = sizeof tv;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_NTP_PLL;
+ mib[2] = NTP_PLL_GETTIME;
+ if (sysctl(mib, 3, &tv, &size, NULL, 0) == -1)
+ return TIME_ERROR;
+ if(ntv) *ntv = tv;
+ return tv.time_state;
+}
+
diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c
index 9c2b0ad..119791f 100644
--- a/lib/libc/gen/opendir.c
+++ b/lib/libc/gen/opendir.c
@@ -64,31 +64,40 @@ __opendir2(name, flags)
DIR *dirp;
int fd;
int incr;
+ int saved_errno;
int unionstack;
struct stat statb;
- if ((fd = open(name, O_RDONLY)) == -1)
+ /*
+ * stat() before open() because opening of special files may be
+ * harmful. fstat() after open because the file may have changed.
+ */
+ if (stat(name, &statb) != 0)
return (NULL);
- if (fstat(fd, &statb) || !S_ISDIR(statb.st_mode)) {
+ if (!S_ISDIR(statb.st_mode)) {
errno = ENOTDIR;
- close(fd);
return (NULL);
}
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 ||
- (dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
- close(fd);
+ if ((fd = open(name, O_RDONLY | O_NONBLOCK)) == -1)
return (NULL);
+ dirp = NULL;
+ if (fstat(fd, &statb) != 0)
+ goto fail;
+ if (!S_ISDIR(statb.st_mode)) {
+ errno = ENOTDIR;
+ goto fail;
}
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 ||
+ (dirp = malloc(sizeof(DIR))) == NULL)
+ goto fail;
/*
- * If CLBYTES is an exact multiple of DIRBLKSIZ, use a CLBYTES
- * buffer that it cluster boundary aligned.
+ * 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()
+ * trades to user space to be done by getdirentries().
*/
- if ((CLBYTES % DIRBLKSIZ) == 0)
- incr = CLBYTES;
- else
+ incr = getpagesize();
+ if ((incr % DIRBLKSIZ) != 0)
incr = DIRBLKSIZ;
/*
@@ -97,11 +106,8 @@ __opendir2(name, flags)
if (flags & DTF_NODUP) {
struct statfs sfb;
- if (fstatfs(fd, &sfb) < 0) {
- free(dirp);
- close(fd);
- return (NULL);
- }
+ if (fstatfs(fd, &sfb) < 0)
+ goto fail;
unionstack = !strcmp(sfb.f_fstypename, "union");
} else {
unionstack = 0;
@@ -132,11 +138,8 @@ __opendir2(name, flags)
space += incr;
len += incr;
buf = realloc(buf, len);
- if (buf == NULL) {
- free(dirp);
- close(fd);
- return (NULL);
- }
+ if (buf == NULL)
+ goto fail;
ddptr = buf + (len - space);
}
@@ -160,8 +163,10 @@ __opendir2(name, flags)
if (flags & DTF_REWIND) {
(void) close(fd);
if ((fd = open(name, O_RDONLY)) == -1) {
+ saved_errno = errno;
free(buf);
free(dirp);
+ errno = saved_errno;
return (NULL);
}
}
@@ -243,11 +248,8 @@ __opendir2(name, flags)
} else {
dirp->dd_len = incr;
dirp->dd_buf = malloc(dirp->dd_len);
- if (dirp->dd_buf == NULL) {
- free(dirp);
- close (fd);
- return (NULL);
- }
+ if (dirp->dd_buf == NULL)
+ goto fail;
dirp->dd_seek = 0;
flags &= ~DTF_REWIND;
}
@@ -262,4 +264,11 @@ __opendir2(name, flags)
dirp->dd_rewind = telldir(dirp);
return (dirp);
+
+fail:
+ saved_errno = errno;
+ free(dirp);
+ (void) close(fd);
+ errno = saved_errno;
+ return (NULL);
}
diff --git a/lib/libc/gen/pause.3 b/lib/libc/gen/pause.3
index b5fd207..962c6cb 100644
--- a/lib/libc/gen/pause.3
+++ b/lib/libc/gen/pause.3
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)pause.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt PAUSE 3
@@ -42,9 +43,8 @@
.Ft int
.Fn pause void
.Sh DESCRIPTION
-.Bf -symbolic
-Pause is made obsolete by sigpause(3).
-.Ef
+.Sy Pause is made obsolete by
+.Xr sigsuspend 2 .
.Pp
The
.Fn pause
@@ -75,7 +75,7 @@ The call was interrupted.
.Sh SEE ALSO
.Xr kill 2 ,
.Xr select 2 ,
-.Xr sigpause 2
+.Xr sigsuspend 2
.Sh HISTORY
A
.Fn pause
diff --git a/lib/libc/gen/popen.3 b/lib/libc/gen/popen.3
index 9ca1bb3..2d2856b 100644
--- a/lib/libc/gen/popen.3
+++ b/lib/libc/gen/popen.3
@@ -50,7 +50,7 @@ The
.Fn popen
function
.Dq opens
-a process by creating an IPC connection,
+a process by creating a bidirectional pipe
forking,
and invoking the shell.
Historically,
@@ -63,9 +63,9 @@ only allow the
argument to specify reading or writing, not both.
Since
.Nm popen
-is now implemented using sockets, the
+is now implemented using a bidirectional pipe, the
.Fa type
-may request a bidirectional data flow.
+argument may request a bidirectional data flow.
The
.Fa type
argument is a pointer to a null-terminated string
@@ -123,10 +123,9 @@ The
function returns
.Dv NULL
if the
-.Xr fork 2 ,
-.Xr pipe 2 ,
+.Xr fork 2
or
-.Xr socketpair 2
+.Xr pipe 2
calls fail,
or if it cannot allocate memory.
.Pp
@@ -150,13 +149,12 @@ The
function does not reliably set
.Va errno .
.Sh SEE ALSO
-.Xr fork 2 ,
.Xr sh 1 ,
+.Xr fork 2 ,
.Xr pipe 2 ,
-.Xr socketpair 2 ,
.Xr wait4 2 ,
-.Xr fflush 3 ,
.Xr fclose 3 ,
+.Xr fflush 3 ,
.Xr fopen 3 ,
.Xr stdio 3 ,
.Xr system 3
@@ -182,9 +180,9 @@ The
.Fn popen
argument
always calls
-.Xr sh ,
+.Xr sh 1 ,
never calls
-.Xr csh .
+.Xr csh 1 .
.Sh HISTORY
A
.Fn popen
diff --git a/lib/libc/gen/popen.c b/lib/libc/gen/popen.c
index 3c3bd6f..8cb7950 100644
--- a/lib/libc/gen/popen.c
+++ b/lib/libc/gen/popen.c
@@ -40,7 +40,6 @@ static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 5/3/95";
#include <sys/param.h>
#include <sys/wait.h>
-#include <sys/socket.h>
#include <signal.h>
#include <errno.h>
@@ -54,8 +53,8 @@ static struct pid {
struct pid *next;
FILE *fp;
pid_t pid;
-} *pidlist;
-
+} *pidlist;
+
FILE *
popen(command, type)
const char *command, *type;
@@ -64,37 +63,51 @@ popen(command, type)
FILE *iop;
int pdes[2], pid, twoway;
+ /*
+ * Lite2 introduced two-way popen() pipes using socketpair().
+ * FreeBSD's pipe() is bidirectional, so we use that.
+ */
if (strchr(type, '+')) {
twoway = 1;
type = "r+";
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
- return (NULL);
} else {
twoway = 0;
- if (*type != 'r' && *type != 'w' || type[1] ||
- (pipe(pdes) < 0))
+ if ((*type != 'r' && *type != 'w') || type[1])
return (NULL);
}
+ if (pipe(pdes) < 0)
+ return (NULL);
- if ((cur = malloc(sizeof(struct pid))) == NULL)
+ if ((cur = malloc(sizeof(struct pid))) == NULL) {
+ (void)close(pdes[0]);
+ (void)close(pdes[1]);
return (NULL);
+ }
switch (pid = vfork()) {
case -1: /* Error. */
(void)close(pdes[0]);
(void)close(pdes[1]);
- (void)free(cur);
+ 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]);
- pdes[1] = STDOUT_FILENO;
- }
- (void) close(pdes[0]);
- if (twoway && (pdes[1] != STDIN_FILENO))
+ 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) {
@@ -159,6 +172,6 @@ pclose(iop)
else
last->next = cur->next;
free(cur);
-
+
return (pid == -1 ? -1 : pstat);
}
diff --git a/lib/libc/gen/psignal.3 b/lib/libc/gen/psignal.3
index 1fdcbad..773759c 100644
--- a/lib/libc/gen/psignal.3
+++ b/lib/libc/gen/psignal.3
@@ -40,11 +40,11 @@
.Nm sys_signame
.Nd system signal messages
.Sh SYNOPSIS
-.Fd #include <sys/signal.h>
+.Fd #include <signal.h>
.Ft void
.Fn psignal "unsigned sig" "const char *s"
-.Vt extern char *sys_siglist[];
-.Vt extern char *sys_signame[];
+.Vt extern const char * const sys_siglist[];
+.Vt extern const char * const sys_signame[];
.Sh DESCRIPTION
The
.Fn psignal
diff --git a/lib/libc/gen/psignal.c b/lib/libc/gen/psignal.c
index 51491b4..b7e7ab6 100644
--- a/lib/libc/gen/psignal.c
+++ b/lib/libc/gen/psignal.c
@@ -39,7 +39,7 @@ static char sccsid[] = "@(#)psignal.c 8.1 (Berkeley) 6/4/93";
* Print the name of the signal indicated
* along with the supplied message.
*/
-#include <sys/signal.h>
+#include <signal.h>
#include <string.h>
#include <unistd.h>
diff --git a/lib/libc/gen/pw_scan.c b/lib/libc/gen/pw_scan.c
new file mode 100644
index 0000000..00f640b
--- /dev/null
+++ b/lib/libc/gen/pw_scan.c
@@ -0,0 +1,141 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)pw_scan.c 8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+
+/*
+ * This module is used to "verify" password entries by chpass(1) and
+ * pwd_mkdb(8).
+ */
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "pw_scan.h"
+
+int
+pw_scan(bp, pw)
+ char *bp;
+ struct passwd *pw;
+{
+ long id;
+ int root;
+ char *p, *sh;
+
+ 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;
+ id = atol(p);
+ if (root && id) {
+ warnx("root uid should be 0");
+ return (0);
+ }
+ if (id > USHRT_MAX) {
+ warnx("%s > max uid value (%d)", 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;
+ id = atol(p);
+ if (id > USHRT_MAX) {
+ warnx("%s > max gid value (%d)", p, USHRT_MAX);
+ /* return (0); This should not be fatal! */
+ }
+ pw->pw_gid = id;
+
+ pw->pw_class = strsep(&bp, ":"); /* class */
+ 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())) {
+ warnx("warning, unknown root shell");
+ break;
+ }
+ if (!strcmp(p, sh))
+ break;
+ }
+ if(p[0]) pw->pw_fields |= _PWF_SHELL;
+
+ if (p = strsep(&bp, ":")) { /* too many */
+fmt: 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..d1d4bc1
--- /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.
+ * 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.
+ *
+ * @(#)pw_scan.h 8.1 (Berkeley) 4/1/94
+ */
+
+extern int pw_scan __P((char *, struct passwd *));
diff --git a/lib/libc/gen/pwcache.3 b/lib/libc/gen/pwcache.3
index 74afa74..e44b5ef 100644
--- a/lib/libc/gen/pwcache.3
+++ b/lib/libc/gen/pwcache.3
@@ -38,8 +38,11 @@
.Nm pwcache
.Nd cache password and group entries
.Sh SYNOPSIS
-.Fn user_from_uid "uid_t uid" "int nouser"
-.Fn group_from_gid "gid_t gid" "int nogroup"
+.Fd #include <stdlib.h>
+.Ft char *
+.Fn user_from_uid "unsigned long uid" "int nouser"
+.Ft char *
+.Fn group_from_gid "unsigned long gid" "int nogroup"
.Sh DESCRIPTION
.Pp
The
@@ -84,7 +87,8 @@ pointer is returned.
.Xr getpwuid 3
.Sh HISTORY
The
-.Fn user_from_id
+.Fn user_from_uid
and
-.Fn group_from_id
-functions first appeared in 4.4BSD.
+.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
index 1dcbf5d..aea7f55 100644
--- a/lib/libc/gen/pwcache.c
+++ b/lib/libc/gen/pwcache.c
@@ -38,12 +38,13 @@ static char sccsid[] = "@(#)pwcache.c 8.1 (Berkeley) 6/4/93";
#include <sys/types.h>
#include <grp.h>
+#include <string.h>
#include <pwd.h>
#include <stdio.h>
#include <utmp.h>
#define NCACHE 64 /* power of 2 */
-#define MASK NCACHE - 1 /* bits to store with */
+#define MASK (NCACHE - 1) /* bits to store with */
char *
user_from_uid(uid, nouser)
@@ -52,10 +53,10 @@ user_from_uid(uid, nouser)
{
static struct ncache {
uid_t uid;
+ int found;
char name[UT_NAMESIZE + 1];
} c_uid[NCACHE];
static int pwopen;
- static char nbuf[15]; /* 32 bits == 10 digits */
register struct passwd *pw;
register struct ncache *cp;
@@ -65,17 +66,20 @@ user_from_uid(uid, nouser)
setpassent(1);
pwopen = 1;
}
- if ((pw = getpwuid(uid)) == NULL) {
+ pw = getpwuid(uid);
+ cp->uid = uid;
+ if (pw != NULL) {
+ cp->found = 1;
+ (void)strncpy(cp->name, pw->pw_name, UT_NAMESIZE);
+ cp->name[UT_NAMESIZE] = '\0';
+ } else {
+ cp->found = 0;
+ (void)snprintf(cp->name, UT_NAMESIZE, "%u", uid);
if (nouser)
return (NULL);
- (void)snprintf(nbuf, sizeof(nbuf), "%u", uid);
- return (nbuf);
}
- cp->uid = uid;
- (void)strncpy(cp->name, pw->pw_name, UT_NAMESIZE);
- cp->name[UT_NAMESIZE] = '\0';
}
- return (cp->name);
+ return ((nouser && !cp->found) ? NULL : cp->name);
}
char *
@@ -85,10 +89,10 @@ group_from_gid(gid, nogroup)
{
static struct ncache {
gid_t gid;
+ int found;
char name[UT_NAMESIZE + 1];
} c_gid[NCACHE];
static int gropen;
- static char nbuf[15]; /* 32 bits == 10 digits */
struct group *gr;
struct ncache *cp;
@@ -98,15 +102,18 @@ group_from_gid(gid, nogroup)
setgroupent(1);
gropen = 1;
}
- if ((gr = getgrgid(gid)) == NULL) {
+ gr = getgrgid(gid);
+ cp->gid = gid;
+ if (gr != NULL) {
+ cp->found = 1;
+ (void)strncpy(cp->name, gr->gr_name, UT_NAMESIZE);
+ cp->name[UT_NAMESIZE] = '\0';
+ } else {
+ cp->found = 0;
+ (void)snprintf(cp->name, UT_NAMESIZE, "%u", gid);
if (nogroup)
return (NULL);
- (void)snprintf(nbuf, sizeof(nbuf), "%u", gid);
- return (nbuf);
}
- cp->gid = gid;
- (void)strncpy(cp->name, gr->gr_name, UT_NAMESIZE);
- cp->name[UT_NAMESIZE] = '\0';
}
- return (cp->name);
+ return ((nogroup && !cp->found) ? NULL : cp->name);
}
diff --git a/lib/libc/gen/raise.c b/lib/libc/gen/raise.c
index 75ecaa1..2562c81 100644
--- a/lib/libc/gen/raise.c
+++ b/lib/libc/gen/raise.c
@@ -38,6 +38,7 @@ static char sccsid[] = "@(#)raise.c 8.1 (Berkeley) 6/4/93";
#include <signal.h>
#include <unistd.h>
+int
raise(s)
int s;
{
diff --git a/lib/libc/gen/rand48.3 b/lib/libc/gen/rand48.3
new file mode 100644
index 0000000..356f2f3
--- /dev/null
+++ b/lib/libc/gen/rand48.3
@@ -0,0 +1,160 @@
+\" 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
+.\"
+.Dd October 8, 1993
+.Dt RAND48 3
+.Os FreeBSD
+.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 SYNOPSIS
+.Fd #include <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 = 0xfdeece66d = 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
+.Fn drand48
+and
+.Fn erand48
+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
+.Fn lrand48
+and
+.Fn nrand48
+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
+.Fn mrand48
+and
+.Fn jrand48
+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
+.Fn drand48 ,
+.Fn lrand48 ,
+and
+.Fn mrand48
+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
+.Fn srand48
+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
+.Fn seed48
+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.
+.Fn seed48
+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 parameter; 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 AUTHOR
+Martin Birgmeier
+.Sh SEE ALSO
+.Xr rand 3 ,
+.Xr random 3 .
diff --git a/lib/libc/gen/rand48.h b/lib/libc/gen/rand48.h
new file mode 100644
index 0000000..5b9f87d
--- /dev/null
+++ b/lib/libc/gen/rand48.h
@@ -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.
+ */
+
+#ifndef _RAND48_H_
+#define _RAND48_H_
+
+#include <math.h>
+#include <stdlib.h>
+
+void _dorand48 __P((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/rewinddir.c b/lib/libc/gen/rewinddir.c
index b46bcf3..2076ddd 100644
--- a/lib/libc/gen/rewinddir.c
+++ b/lib/libc/gen/rewinddir.c
@@ -38,6 +38,8 @@ static char sccsid[] = "@(#)rewinddir.c 8.1 (Berkeley) 6/8/93";
#include <sys/types.h>
#include <dirent.h>
+extern void _seekdir __P(( DIR *, long ));
+
void
rewinddir(dirp)
DIR *dirp;
diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c
index 1c1fee1..e6e8408 100644
--- a/lib/libc/gen/scandir.c
+++ b/lib/libc/gen/scandir.c
@@ -79,7 +79,7 @@ scandir(dirname, namelist, select, dcomp)
/*
* estimate the array size by taking the size of the directory file
- * and dividing it by a multiple of the minimum size entry.
+ * and dividing it by a multiple of the minimum size entry.
*/
arraysz = (stb.st_size / 24);
names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
@@ -96,7 +96,8 @@ scandir(dirname, namelist, select, dcomp)
p = (struct dirent *)malloc(DIRSIZ(d));
if (p == NULL)
return(-1);
- p->d_ino = d->d_ino;
+ 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);
diff --git a/lib/libc/gen/seed48.c b/lib/libc/gen/seed48.c
new file mode 100644
index 0000000..258c4ba
--- /dev/null
+++ b/lib/libc/gen/seed48.c
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+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
index 48b4646..1934bcc 100644
--- a/lib/libc/gen/seekdir.c
+++ b/lib/libc/gen/seekdir.c
@@ -38,6 +38,8 @@ static char sccsid[] = "@(#)seekdir.c 8.1 (Berkeley) 6/4/93";
#include <sys/param.h>
#include <dirent.h>
+extern void _seekdir __P(( DIR *, long ));
+
/*
* Seek to an entry in a directory.
* _seekdir is in telldir.c so that it can share opaque data structures.
diff --git a/lib/libc/gen/semconfig.c b/lib/libc/gen/semconfig.c
new file mode 100644
index 0000000..cf5399b
--- /dev/null
+++ b/lib/libc/gen/semconfig.c
@@ -0,0 +1,13 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+#if __STDC__
+int semconfig(int cmd, int p1, int p2, int p3)
+#else
+int semconfig(cmd, p1, p2, p3)
+ int cmd, p1, p2, p3;
+#endif
+{
+ return (semsys(3, cmd, p1, p2, p3));
+}
diff --git a/lib/libc/gen/semctl.c b/lib/libc/gen/semctl.c
new file mode 100644
index 0000000..313a1db
--- /dev/null
+++ b/lib/libc/gen/semctl.c
@@ -0,0 +1,15 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+#if __STDC__
+int semctl(int semid, int semnum, int cmd, union semun semun)
+#else
+int semctl(semid, int semnum, cmd, semun)
+ int semid, semnum;
+ int cmd;
+ union semun semun;
+#endif
+{
+ return (semsys(0, semid, semnum, cmd, &semun));
+}
diff --git a/lib/libc/gen/semget.c b/lib/libc/gen/semget.c
new file mode 100644
index 0000000..81c6a86
--- /dev/null
+++ b/lib/libc/gen/semget.c
@@ -0,0 +1,15 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+#if __STDC__
+int semget(key_t key, int nsems, int semflg)
+#else
+int semget(key, nsems, semflg)
+ key_t key;
+ int nsems;
+ int semflg;
+#endif
+{
+ return (semsys(1, key, nsems, semflg));
+}
diff --git a/lib/libc/gen/semop.c b/lib/libc/gen/semop.c
new file mode 100644
index 0000000..0b97c6a
--- /dev/null
+++ b/lib/libc/gen/semop.c
@@ -0,0 +1,15 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+#if __STDC__
+int semop(int semid, struct sembuf *sops, unsigned nsops)
+#else
+int semop(semid, sops, nsops)
+ int semid;
+ struct sembuf *sops;
+ unsigned nsops;
+#endif
+{
+ return (semsys(2, semid, sops, nsops, 0));
+}
diff --git a/lib/libc/net/getnetbyaddr.c b/lib/libc/gen/setdomainname.c
index fd3f260..b7021a5 100644
--- a/lib/libc/net/getnetbyaddr.c
+++ b/lib/libc/gen/setdomainname.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1993
+ * 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
@@ -32,25 +32,26 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
+/*
+static char sccsid[] = "From: @(#)sethostname.c 8.1 (Berkeley) 6/4/93";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
-#include <netdb.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
-extern int _net_stayopen;
+#include <unistd.h>
-struct netent *
-getnetbyaddr(net, type)
- register long net;
- register int type;
+int
+setdomainname(const char *name, int namelen)
{
- register struct netent *p;
+ int mib[2];
- setnetent(_net_stayopen);
- while (p = getnetent())
- if (p->n_addrtype == type && p->n_net == net)
- break;
- if (!_net_stayopen)
- endnetent();
- return (p);
+ 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/setflags.c b/lib/libc/gen/setflags.c
new file mode 100644
index 0000000..b1e7062
--- /dev/null
+++ b/lib/libc/gen/setflags.c
@@ -0,0 +1,163 @@
+/*-
+ * 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.
+ * 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.
+ *
+ * $Id: stat_flags.c,v 1.5 1997/02/22 14:04:02 peter Exp $
+ */
+
+#ifndef lint
+static char const sccsid[] = "@(#)stat_flags.c 8.1 (Berkeley) 5/31/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stddef.h>
+#include <string.h>
+
+#define SAPPEND(s) { \
+ if (prefix != NULL) \
+ (void)strcat(string, prefix); \
+ (void)strcat(string, s); \
+ prefix = ","; \
+}
+
+/*
+ * flags_to_string --
+ * Convert stat flags to a comma-separated string. If no flags
+ * are set, return the default string.
+ */
+char *
+flags_to_string(flags, def)
+ u_long flags;
+ char *def;
+{
+ static char string[128];
+ char *prefix;
+
+ string[0] = '\0';
+ prefix = NULL;
+ if (flags & UF_APPEND)
+ SAPPEND("uappnd");
+ if (flags & UF_IMMUTABLE)
+ SAPPEND("uchg");
+ if (flags & UF_NOUNLINK)
+ SAPPEND("uunlnk");
+ if (flags & UF_NODUMP)
+ SAPPEND("nodump");
+ if (flags & UF_OPAQUE)
+ SAPPEND("opaque");
+ if (flags & SF_APPEND)
+ SAPPEND("sappnd");
+ if (flags & SF_ARCHIVED)
+ SAPPEND("arch");
+ if (flags & SF_IMMUTABLE)
+ SAPPEND("schg");
+ if (flags & SF_NOUNLINK)
+ SAPPEND("sunlnk");
+ return (prefix == NULL && def != NULL ? def : string);
+}
+
+#define TEST(a, b, f) { \
+ if (!memcmp(a, b, sizeof(b))) { \
+ if (clear) { \
+ if (clrp) \
+ *clrp |= (f); \
+ } else if (setp) \
+ *setp |= (f); \
+ break; \
+ } \
+}
+
+/*
+ * string_to_flags --
+ * Take string of arguments and return stat flags. Return 0 on
+ * success, 1 on failure. On failure, stringp is set to point
+ * to the offending token.
+ */
+int
+string_to_flags(stringp, setp, clrp)
+ char **stringp;
+ u_long *setp, *clrp;
+{
+ int clear;
+ char *string, *p;
+
+ clear = 0;
+ if (setp)
+ *setp = 0;
+ if (clrp)
+ *clrp = 0;
+ string = *stringp;
+ while ((p = strsep(&string, "\t ,")) != NULL) {
+ *stringp = p;
+ if (*p == '\0')
+ continue;
+ if (p[0] == 'n' && p[1] == 'o') {
+ clear = 1;
+ p += 2;
+ }
+ switch (p[0]) {
+ case 'a':
+ TEST(p, "arch", SF_ARCHIVED);
+ TEST(p, "archived", SF_ARCHIVED);
+ return (1);
+ case 'd':
+ clear = !clear;
+ TEST(p, "dump", UF_NODUMP);
+ return (1);
+ case 'o':
+ TEST(p, "opaque", UF_OPAQUE);
+ return (1);
+ case 's':
+ TEST(p, "sappnd", SF_APPEND);
+ TEST(p, "sappend", SF_APPEND);
+ TEST(p, "schg", SF_IMMUTABLE);
+ TEST(p, "schange", SF_IMMUTABLE);
+ TEST(p, "simmutable", SF_IMMUTABLE);
+ TEST(p, "sunlnk", SF_NOUNLINK);
+ TEST(p, "sunlink", SF_NOUNLINK);
+ return (1);
+ case 'u':
+ TEST(p, "uappnd", UF_APPEND);
+ TEST(p, "uappend", UF_APPEND);
+ TEST(p, "uchg", UF_IMMUTABLE);
+ TEST(p, "uchange", UF_IMMUTABLE);
+ TEST(p, "uimmutable", UF_IMMUTABLE);
+ TEST(p, "uunlnk", UF_NOUNLINK);
+ TEST(p, "uunlink", UF_NOUNLINK);
+ /* FALLTHROUGH */
+ default:
+ return (1);
+ }
+ }
+ return (0);
+}
diff --git a/lib/libc/gen/setflagsbyname.c b/lib/libc/gen/setflagsbyname.c
new file mode 100644
index 0000000..b1e7062
--- /dev/null
+++ b/lib/libc/gen/setflagsbyname.c
@@ -0,0 +1,163 @@
+/*-
+ * 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.
+ * 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.
+ *
+ * $Id: stat_flags.c,v 1.5 1997/02/22 14:04:02 peter Exp $
+ */
+
+#ifndef lint
+static char const sccsid[] = "@(#)stat_flags.c 8.1 (Berkeley) 5/31/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stddef.h>
+#include <string.h>
+
+#define SAPPEND(s) { \
+ if (prefix != NULL) \
+ (void)strcat(string, prefix); \
+ (void)strcat(string, s); \
+ prefix = ","; \
+}
+
+/*
+ * flags_to_string --
+ * Convert stat flags to a comma-separated string. If no flags
+ * are set, return the default string.
+ */
+char *
+flags_to_string(flags, def)
+ u_long flags;
+ char *def;
+{
+ static char string[128];
+ char *prefix;
+
+ string[0] = '\0';
+ prefix = NULL;
+ if (flags & UF_APPEND)
+ SAPPEND("uappnd");
+ if (flags & UF_IMMUTABLE)
+ SAPPEND("uchg");
+ if (flags & UF_NOUNLINK)
+ SAPPEND("uunlnk");
+ if (flags & UF_NODUMP)
+ SAPPEND("nodump");
+ if (flags & UF_OPAQUE)
+ SAPPEND("opaque");
+ if (flags & SF_APPEND)
+ SAPPEND("sappnd");
+ if (flags & SF_ARCHIVED)
+ SAPPEND("arch");
+ if (flags & SF_IMMUTABLE)
+ SAPPEND("schg");
+ if (flags & SF_NOUNLINK)
+ SAPPEND("sunlnk");
+ return (prefix == NULL && def != NULL ? def : string);
+}
+
+#define TEST(a, b, f) { \
+ if (!memcmp(a, b, sizeof(b))) { \
+ if (clear) { \
+ if (clrp) \
+ *clrp |= (f); \
+ } else if (setp) \
+ *setp |= (f); \
+ break; \
+ } \
+}
+
+/*
+ * string_to_flags --
+ * Take string of arguments and return stat flags. Return 0 on
+ * success, 1 on failure. On failure, stringp is set to point
+ * to the offending token.
+ */
+int
+string_to_flags(stringp, setp, clrp)
+ char **stringp;
+ u_long *setp, *clrp;
+{
+ int clear;
+ char *string, *p;
+
+ clear = 0;
+ if (setp)
+ *setp = 0;
+ if (clrp)
+ *clrp = 0;
+ string = *stringp;
+ while ((p = strsep(&string, "\t ,")) != NULL) {
+ *stringp = p;
+ if (*p == '\0')
+ continue;
+ if (p[0] == 'n' && p[1] == 'o') {
+ clear = 1;
+ p += 2;
+ }
+ switch (p[0]) {
+ case 'a':
+ TEST(p, "arch", SF_ARCHIVED);
+ TEST(p, "archived", SF_ARCHIVED);
+ return (1);
+ case 'd':
+ clear = !clear;
+ TEST(p, "dump", UF_NODUMP);
+ return (1);
+ case 'o':
+ TEST(p, "opaque", UF_OPAQUE);
+ return (1);
+ case 's':
+ TEST(p, "sappnd", SF_APPEND);
+ TEST(p, "sappend", SF_APPEND);
+ TEST(p, "schg", SF_IMMUTABLE);
+ TEST(p, "schange", SF_IMMUTABLE);
+ TEST(p, "simmutable", SF_IMMUTABLE);
+ TEST(p, "sunlnk", SF_NOUNLINK);
+ TEST(p, "sunlink", SF_NOUNLINK);
+ return (1);
+ case 'u':
+ TEST(p, "uappnd", UF_APPEND);
+ TEST(p, "uappend", UF_APPEND);
+ TEST(p, "uchg", UF_IMMUTABLE);
+ TEST(p, "uchange", UF_IMMUTABLE);
+ TEST(p, "uimmutable", UF_IMMUTABLE);
+ TEST(p, "uunlnk", UF_NOUNLINK);
+ TEST(p, "uunlink", UF_NOUNLINK);
+ /* FALLTHROUGH */
+ default:
+ return (1);
+ }
+ }
+ return (0);
+}
diff --git a/lib/libc/gen/sethostname.c b/lib/libc/gen/sethostname.c
index 639837e..6c3adc3 100644
--- a/lib/libc/gen/sethostname.c
+++ b/lib/libc/gen/sethostname.c
@@ -39,10 +39,10 @@ static char sccsid[] = "@(#)sethostname.c 8.1 (Berkeley) 6/4/93";
#include <sys/sysctl.h>
#if __STDC__
-long
+int
sethostname(const char *name, int namelen)
#else
-long
+int
sethostname(name, namelen)
char *name;
int namelen;
diff --git a/lib/libc/gen/setjmp.3 b/lib/libc/gen/setjmp.3
index 47cdfa5..3b5d89e 100644
--- a/lib/libc/gen/setjmp.3
+++ b/lib/libc/gen/setjmp.3
@@ -44,7 +44,8 @@
.Nm setjmp ,
.Nm longjmp ,
.Nm _setjmp ,
-.Nm _longjmp longjmperror
+.Nm _longjmp ,
+.Nm longjmperror
.Nd non-local jumps
.Sh SYNOPSIS
.Fd #include <setjmp.h>
@@ -125,7 +126,7 @@ 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 sigmask 2 . )
+.Fn sigprocmask 2 . )
.Pp
The
.Fn sigsetjmp Ns / Ns Fn siglongjmp
@@ -144,7 +145,7 @@ routine calls the routine
If
.Fn longjmperror
returns the program is aborted (see
-.Xr abort 2 ) .
+.Xr abort 3 ) .
The default version of
.Fn longjmperror
prints the message
diff --git a/lib/libc/gen/setmode.3 b/lib/libc/gen/setmode.3
index 04c2a6b..4c85b30 100644
--- a/lib/libc/gen/setmode.3
+++ b/lib/libc/gen/setmode.3
@@ -39,6 +39,7 @@
.Nm setmode
.Nd modify mode bits
.Sh SYNOPSIS
+.Fd #include <unistd.h>
.Ft mode_t
.Fn getmode "const void *set" "mode_t mode"
.Ft void *
@@ -101,4 +102,5 @@ The
.Fn getmode
and
.Fn setmode
-functions first appeared in 4.4BSD.
+functions first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/setmode.c b/lib/libc/gen/setmode.c
index 84cadcb..c69d775 100644
--- a/lib/libc/gen/setmode.c
+++ b/lib/libc/gen/setmode.c
@@ -67,7 +67,7 @@ typedef struct bitcmd {
#define CMD2_UBITS 0x10
static BITCMD *addcmd __P((BITCMD *, int, int, int, u_int));
-static int compress_mode __P((BITCMD *));
+static void compress_mode __P((BITCMD *));
#ifdef SETMODE_DEBUG
static void dumpmode __P((BITCMD *));
#endif
@@ -172,7 +172,7 @@ setmode(p)
BITCMD *set, *saveset, *endset;
sigset_t sigset, sigoset;
mode_t mask;
- int equalopdone, permXbits, setlen;
+ int equalopdone=0, permXbits, setlen;
if (!*p)
return (NULL);
@@ -190,7 +190,7 @@ setmode(p)
(void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
setlen = SET_LEN + 2;
-
+
if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
return (NULL);
saveset = set;
@@ -368,7 +368,7 @@ addcmd(set, op, who, oparg, mask)
set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
set->bits = mask;
}
-
+
if (oparg == '+')
set->cmd2 |= CMD2_SET;
else if (oparg == '-')
@@ -399,10 +399,10 @@ dumpmode(set)
/*
* 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
+ * 'g' and 'o' commands continue to be separate. They could probably be
* compacted, but it's not worth the effort.
*/
-static int
+static void
compress_mode(set)
register BITCMD *set;
{
diff --git a/lib/libc/gen/setproctitle.3 b/lib/libc/gen/setproctitle.3
new file mode 100644
index 0000000..c3f2031
--- /dev/null
+++ b/lib/libc/gen/setproctitle.3
@@ -0,0 +1,113 @@
+.\" 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.
+.\"
+.\" $Id: setproctitle.3,v 1.8 1997/04/17 23:31:47 danny Exp $
+.\"
+.\" The following requests are required for all man pages.
+.Dd December 16, 1995
+.Os FreeBSD
+.Dt SETPROCTITLE 3
+.Sh NAME
+.Nm setproctitle
+.Nd set the process title for
+.Xr ps 1
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <libutil.h>
+.Ft void
+.Fn setproctitle "const char *fmt" "..."
+.Pp
+Link with
+.Va -lutil
+on the
+.Xr cc 1
+command line.
+.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.
+.Pp
+If
+.Va fmt
+is NULL, the process title is reset to simply the name of the executable.
+.\" The following requests should be uncommented and used where appropriate.
+.\" This next request is for sections 2 and 3 function return values only.
+.\" .Sh RETURN VALUES
+.\" This next request is for sections 1, 6, 7 & 8 only
+.\" .Sh ENVIRONMENT
+.\" .Sh FILES
+.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
+.\" This next request is for sections 1, 6, 7 & 8 only
+.\" (command return values (to shell) and fprintf/stderr type diagnostics)
+.\" .Sh DIAGNOSTICS
+.\" The next request is for sections 2 and 3 error and signal handling only.
+.\" .Sh ERRORS
+.Sh SEE ALSO
+.Xr ps 1 ,
+.Xr w 1 ,
+.Xr kvm 3 ,
+.Xr kvm_getargv 3 ,
+.Xr printf 3
+.Sh STANDARDS
+.Fn setproctitle
+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
+.Tn NetBSD
+and
+.Tn BSD/OS .
+.Sh HISTORY
+.Fn setproctitle
+first appeared in
+.Fx 2.2 .
+Other operating systems have
+similar functions.
+.Sh AUTHORS
+.Sy "Peter Wemm <peter@FreeBSD.org>"
+stole the idea from the
+.Sy "Sendmail 8.7.3"
+source code by
+.Sy "Eric Allman <eric@sendmail.org>" .
+.\" .Sh BUGS
diff --git a/lib/libc/gen/setproctitle.c b/lib/libc/gen/setproctitle.c
new file mode 100644
index 0000000..ba21d1c
--- /dev/null
+++ b/lib/libc/gen/setproctitle.c
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#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>
+
+/*
+ * 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)))
+
+#if defined(__STDC__) /* from other parts of sendmail */
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+
+#define SPT_BUFSIZE 2048 /* from other parts of sendmail */
+extern char * __progname; /* is this defined in a .h anywhere? */
+
+void
+#if defined(__STDC__)
+setproctitle(const char *fmt, ...)
+#else
+setproctitle(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ static char buf[SPT_BUFSIZE];
+ static char *ps_argv[2];
+ va_list ap;
+ int mib[2];
+ struct ps_strings *ps_strings;
+ size_t len;
+
+#if defined(__STDC__)
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+
+ buf[sizeof(buf) - 1] = '\0';
+ if (fmt) {
+
+ /* print program name heading for grep */
+ (void) snprintf(buf, sizeof(buf) - 1, "%s: ", __progname);
+
+ /*
+ * can't use return from sprintf, as that is the count of how
+ * much it wanted to write, not how much it actually did.
+ */
+
+ len = strlen(buf);
+
+ /* print the argument string */
+ (void) vsnprintf(buf + len, sizeof(buf) - 1 - len, fmt, ap);
+ } else {
+ /* Idea from NetBSD - reset the title on fmt == NULL */
+ strncpy(buf, __progname, sizeof(buf) - 1);
+ }
+
+ va_end(ap);
+
+ ps_strings = NULL;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PS_STRINGS;
+ len = sizeof(ps_strings);
+ if (sysctl(mib, 2, &ps_strings, &len, NULL, 0) < 0 ||
+ ps_strings == NULL)
+ ps_strings = PS_STRINGS;
+
+ /* PS_STRINGS points to zeroed memory on a style #2 kernel */
+ if (ps_strings->ps_argvstr) {
+ /* style #3 */
+ ps_argv[0] = buf;
+ ps_argv[1] = NULL;
+ ps_strings->ps_nargvstr = 1;
+ ps_strings->ps_argvstr = ps_argv;
+ } else {
+ /* style #2 */
+ OLD_PS_STRINGS->old_ps_nargvstr = 1;
+ OLD_PS_STRINGS->old_ps_argvstr = buf;
+ }
+}
diff --git a/lib/libc/gen/shmat.c b/lib/libc/gen/shmat.c
new file mode 100644
index 0000000..1cd0779
--- /dev/null
+++ b/lib/libc/gen/shmat.c
@@ -0,0 +1,19 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#if __STDC__
+void *shmat(int shmid, void *shmaddr, int shmflg)
+#else
+void *shmat(shmid, shmaddr, shmflg)
+ int shmid;
+ void *shmaddr;
+ int shmflg;
+#endif
+{
+ return ((void *)shmsys(0, shmid, shmaddr, shmflg));
+}
diff --git a/lib/libc/gen/shmctl.c b/lib/libc/gen/shmctl.c
new file mode 100644
index 0000000..b0585fd
--- /dev/null
+++ b/lib/libc/gen/shmctl.c
@@ -0,0 +1,19 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#if __STDC__
+int shmctl(int shmid, int cmd, struct shmid_ds *buf)
+#else
+int shmctl(shmid, cmd, buf)
+ int shmid;
+ int cmd;
+ struct shmid_ds *buf;
+#endif
+{
+ return (shmsys(4, shmid, cmd, buf));
+}
diff --git a/lib/libc/gen/shmdt.c b/lib/libc/gen/shmdt.c
new file mode 100644
index 0000000..feae3d1
--- /dev/null
+++ b/lib/libc/gen/shmdt.c
@@ -0,0 +1,17 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#if __STDC__
+int shmdt(void *shmaddr)
+#else
+int shmdt(shmaddr)
+ void *shmaddr;
+#endif
+{
+ return (shmsys(2, shmaddr));
+}
diff --git a/lib/libc/gen/shmget.c b/lib/libc/gen/shmget.c
new file mode 100644
index 0000000..0119511
--- /dev/null
+++ b/lib/libc/gen/shmget.c
@@ -0,0 +1,19 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#if __STDC__
+int shmget(key_t key, int size, int shmflg)
+#else
+int shmget(key, size, shmflg)
+ key_t key;
+ int size;
+ int shmflg;
+#endif
+{
+ return (shmsys(3, key, size, shmflg));
+}
diff --git a/lib/libc/gen/siginterrupt.3 b/lib/libc/gen/siginterrupt.3
index 1dadb28..46eb8de 100644
--- a/lib/libc/gen/siginterrupt.3
+++ b/lib/libc/gen/siginterrupt.3
@@ -50,8 +50,10 @@ 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 is the default behavior on
-.Bx 4.2 .
+System call restart has been the default behavior since
+.Bx 4.2 ,
+and is the default behaviour on
+.Tn FreeBSD .
.Pp
If the flag is true (1),
then restarting of system calls is disabled.
diff --git a/lib/libc/gen/siginterrupt.c b/lib/libc/gen/siginterrupt.c
index 3105d13..06960ab 100644
--- a/lib/libc/gen/siginterrupt.c
+++ b/lib/libc/gen/siginterrupt.c
@@ -41,6 +41,7 @@ static char sccsid[] = "@(#)siginterrupt.c 8.1 (Berkeley) 6/4/93";
* Set signal state to prevent restart of system calls
* after an instance of the indicated signal.
*/
+int
siginterrupt(sig, flag)
int sig, flag;
{
diff --git a/lib/libc/gen/signal.3 b/lib/libc/gen/signal.3
index e17c2df..192e2d8 100644
--- a/lib/libc/gen/signal.3
+++ b/lib/libc/gen/signal.3
@@ -39,12 +39,13 @@
.Nd simplified software signal facilities
.Sh SYNOPSIS
.Fd #include <signal.h>
-.Ft void
-.Fn *signal sig func\*(lp\*(rp
-.Ft void
-.\" can not do this with .Fn yet
-.br
-\*(lp\|\*(fN*func\*(rp\*(lp\|\*(rp\fR
+.Ft void \*(lp*
+.Fn signal "int sig" "void \*(lp*func\*(rp\*(lpint\*(rp\*(rp\*(rp\*(lpint"
+
+or in FreeBSD's equivalent but easier to read typedef'd version:
+.Ft typedef "void \*(lp*sig_t\*(rp \*(lpint\*(rp"
+.Ft sig_t
+.Fn signal "int sig" "sig_t func"
.Sh DESCRIPTION
This
.Fn signal
@@ -97,7 +98,7 @@ call (formerly
.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" " system call given invalid argument"
+.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"
@@ -126,6 +127,9 @@ is possible on a descriptor (see
.El
.Pp
The
+.Fa sig
+parameter 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,
@@ -148,7 +152,7 @@ automatically blocked and
.Fa func
is called.
.Pp
-The handled signal is unblocked with the
+The handled signal is unblocked when the
function returns and
the process continues from where it left off when the signal occurred.
.Bf -symbolic
@@ -192,7 +196,7 @@ Otherwise, \-1 is returned and the global variable
.Va errno
is set to indicate the error.
.Sh ERRORS
-.Xr Signal
+.Fn Signal
will fail and no action will take place if one of the
following occur:
.Bl -tag -width [EINVAL]
@@ -206,8 +210,8 @@ or
.Ev SIGSTOP .
.Sh SEE ALSO
.Xr kill 1 ,
-.Xr ptrace 2 ,
.Xr kill 2 ,
+.Xr ptrace 2 ,
.Xr sigaction 2 ,
.Xr sigaltstack 2 ,
.Xr sigprocmask 2 ,
diff --git a/lib/libc/gen/sigsetops.3 b/lib/libc/gen/sigsetops.3
index b62253e..97b3316 100644
--- a/lib/libc/gen/sigsetops.3
+++ b/lib/libc/gen/sigsetops.3
@@ -43,11 +43,16 @@
.Nd manipulate signal sets
.Sh SYNOPSIS
.Fd #include <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"
-.Fn sigismember "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 .
diff --git a/lib/libc/gen/sigsetops.c b/lib/libc/gen/sigsetops.c
index e6acb77..c3bd870 100644
--- a/lib/libc/gen/sigsetops.c
+++ b/lib/libc/gen/sigsetops.c
@@ -45,6 +45,7 @@ static char sccsid[] = "@(#)sigsetops.c 8.1 (Berkeley) 6/4/93";
#undef sigdelset
#undef sigismember
+int
sigemptyset(set)
sigset_t *set;
{
@@ -52,6 +53,7 @@ sigemptyset(set)
return (0);
}
+int
sigfillset(set)
sigset_t *set;
{
@@ -59,6 +61,7 @@ sigfillset(set)
return (0);
}
+int
sigaddset(set, signo)
sigset_t *set;
int signo;
@@ -67,6 +70,7 @@ sigaddset(set, signo)
return (0);
}
+int
sigdelset(set, signo)
sigset_t *set;
int signo;
@@ -75,6 +79,7 @@ sigdelset(set, signo)
return (0);
}
+int
sigismember(set, signo)
const sigset_t *set;
int signo;
diff --git a/lib/libc/gen/sleep.3 b/lib/libc/gen/sleep.3
index 9e3c797..f488a0b 100644
--- a/lib/libc/gen/sleep.3
+++ b/lib/libc/gen/sleep.3
@@ -70,12 +70,33 @@ A similar but less compatible function can be obtained with a single
.Xr select 2 ;
such a function would not restart after signals, but would not interfere
with other uses of
-.Xr setitimer .
+.Xr setitimer 2 .
.Sh RETURN VALUES
+The
+.Fn sleep
+function returns the number of seconds remaining to complete the operation. If
+sleep is interrupted or cannot allocate a timer it may will return the value
+needed to be passed to a subsequent sleep to complete the necessary delay.
+.Fn sleep
+repeatedly until it returns zero may busy-wait until a timer
+is available.
.Sh SEE ALSO
.Xr setitimer 2 ,
.Xr sigpause 2 ,
.Xr usleep 3
+.Sh CAVEAT
+In practice the
+.Tn FreeBSD
+implementation will not be interrupted: it will
+always return the original argument or zero. Code that depends on
+sleep being interrupted (using it as a timed pause, for example) needs
+to be recoded to use
+.Xr select 2
+or some other delay mechanism. Code that
+calls
+.Fn sleep
+repeatedly until it returns zero may busy-wait until a timer
+is available.
.Sh HISTORY
A
.Fn sleep
diff --git a/lib/libc/gen/sleep.c b/lib/libc/gen/sleep.c
index 3c0b8fa..49f2d89 100644
--- a/lib/libc/gen/sleep.c
+++ b/lib/libc/gen/sleep.c
@@ -36,62 +36,88 @@ static char sccsid[] = "@(#)sleep.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/time.h>
-#include <sys/signal.h>
+#include <signal.h>
#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
-#define setvec(vec, a) \
- vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
-
-static int ringring;
+#ifndef _THREAD_SAFE
+static void
+sleephandler()
+{
+ return;
+}
+#endif /* _THREAD_SAFE */
unsigned int
sleep(seconds)
unsigned int seconds;
{
- register struct itimerval *itp;
- struct itimerval itv, oitv;
- struct sigvec vec, ovec;
- long omask;
- static void sleephandler();
+#ifdef _THREAD_SAFE
+ struct timespec time_to_sleep;
+ struct timespec time_remaining;
+
+ if (seconds != 0) {
+ time_to_sleep.tv_sec = seconds;
+ time_to_sleep.tv_nsec = 0;
+ nanosleep(&time_to_sleep, &time_remaining);
+ seconds = time_remaining.tv_sec;
+ if (time_remaining.tv_nsec > 0)
+ seconds++; /* round up */
+ }
+ return (seconds);
+#else
+ struct timespec time_to_sleep;
+ struct timespec time_remaining;
+ struct sigaction act, oact;
+ sigset_t mask, omask;
+ int alarm_blocked;
+
+ if (seconds != 0) {
+ time_to_sleep.tv_sec = seconds;
+ time_to_sleep.tv_nsec = 0;
+
+ /* Block SIGALRM while fiddling with it */
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGALRM);
+ sigprocmask(SIG_BLOCK, &mask, &omask);
+
+ /* Was SIGALRM blocked already? */
+ alarm_blocked = sigismember(&omask, SIGALRM);
- itp = &itv;
- if (!seconds)
- return 0;
- timerclear(&itp->it_interval);
- timerclear(&itp->it_value);
- if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
- return seconds;
- itp->it_value.tv_sec = seconds;
- if (timerisset(&oitv.it_value)) {
- if (timercmp(&oitv.it_value, &itp->it_value, >))
- oitv.it_value.tv_sec -= itp->it_value.tv_sec;
- else {
- itp->it_value = oitv.it_value;
+ if (!alarm_blocked) {
/*
- * This is a hack, but we must have time to return
- * from the setitimer after the alarm or else it'll
- * be restarted. And, anyway, sleep never did
- * anything more than this before.
+ * Set up handler to interrupt signanosleep only if
+ * SIGALRM was unblocked. (Save some syscalls)
*/
- oitv.it_value.tv_sec = 1;
- oitv.it_value.tv_usec = 0;
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = sleephandler;
+ sigaction(SIGALRM, &act, &oact);
}
- }
- setvec(vec, sleephandler);
- (void) sigvec(SIGALRM, &vec, &ovec);
- omask = sigblock(sigmask(SIGALRM));
- ringring = 0;
- (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
- while (!ringring)
- sigpause(omask &~ sigmask(SIGALRM));
- (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
- (void) sigsetmask(omask);
- (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
- return 0;
-}
-static void
-sleephandler()
-{
- ringring = 1;
+ /*
+ * signanosleep() uses the given mask for the lifetime of
+ * the syscall only - it resets on return. Note that the
+ * Old sleep explicitly unblocks SIGALRM during the sleep,
+ * we don't do that now since we don't depend on SIGALRM
+ * to end the timout. If the process blocks SIGALRM, it
+ * gets what it asks for.
+ */
+ signanosleep(&time_to_sleep, &time_remaining, &omask);
+
+ if (!alarm_blocked) {
+ /* Unwind */
+ sigaction(SIGALRM, &oact, (struct sigaction *)0);
+ sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
+ }
+
+ /* return how long is left */
+ seconds = time_remaining.tv_sec;
+ if (time_remaining.tv_nsec > 0)
+ seconds++; /* round up */
+ }
+ return (seconds);
+#endif /* _THREAD_SAFE */
}
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/stringlist.3 b/lib/libc/gen/stringlist.3
new file mode 100644
index 0000000..5023c5c
--- /dev/null
+++ b/lib/libc/gen/stringlist.3
@@ -0,0 +1,120 @@
+.\" $NetBSD: stringlist.3,v 1.2 1997/04/09 08:59:25 kleink Exp $
+.\"
+.\" Copyright (c) 1997 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.
+.\" 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 REGENTS OR CONTRIBUTORS BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (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 February 24, 1997
+.Os NetBSD 1.3
+.Dt STRINGLIST 3
+.Sh NAME
+.Nm stringlist ,
+.Nm sl_init ,
+.Nm sl_add ,
+.Nm sl_free ,
+.Nm sl_find
+.Nd stringlist manipulation functions
+.Sh SYNOPSIS
+.Fd #include <stringlist.h>
+.Ft StringList *
+.Fn sl_init
+.Ft void
+.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
+.Ar 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
+.Pp
+.Bl -tag -width "sl_str" -offset indent
+.It Ar sl_str
+a pointer to the base of the array containing the list.
+.It Ar sl_max
+the size of
+.Ar sl_str .
+.It Ar sl_cur
+the offset in
+.Ar 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
+.Ar StringList .
+.It Fn sl_free
+Releases memory occupied by
+.Ar sl
+and the
+.Ar sl->sl_str
+array.
+If
+.Ar freeall
+is non-zero, then each of the items within
+.Ar sl->sl_str
+is released as well.
+.It Fn sl_add
+Add
+.Ar item
+to
+.Ar sl->sl_str
+at
+.Ar sl->sl_cur ,
+extending the size of
+.Ar sl->sl_str
+.It Fn sl_find
+Find
+.Ar item
+in
+.Ar sl ,
+returning NULL if it's not found.
+.El
+.Sh SEE ALSO
+.Xr free 3 ,
+.Xr malloc 3
diff --git a/lib/libc/gen/stringlist.c b/lib/libc/gen/stringlist.c
new file mode 100644
index 0000000..57c4d91
--- /dev/null
+++ b/lib/libc/gen/stringlist.c
@@ -0,0 +1,120 @@
+/* $NetBSD: stringlist.c,v 1.2 1997/01/17 07:26:20 lukem Exp $ */
+
+/*
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 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 <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <stdlib.h>
+#include <stringlist.h>
+
+#define _SL_CHUNKSIZE 20
+
+/*
+ * sl_init(): Initialize a string list
+ */
+StringList *
+sl_init()
+{
+ StringList *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
+ */
+void
+sl_add(sl, name)
+ StringList *sl;
+ char *name;
+{
+ if (sl->sl_cur == sl->sl_max - 1) {
+ sl->sl_max += _SL_CHUNKSIZE;
+ sl->sl_str = realloc(sl->sl_str, sl->sl_max * sizeof(char *));
+ if (sl->sl_str == NULL)
+ err(1, "stringlist: %m");
+ }
+ sl->sl_str[sl->sl_cur++] = name;
+}
+
+
+/*
+ * 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.c b/lib/libc/gen/strtofflags.c
new file mode 100644
index 0000000..b1e7062
--- /dev/null
+++ b/lib/libc/gen/strtofflags.c
@@ -0,0 +1,163 @@
+/*-
+ * 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.
+ * 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.
+ *
+ * $Id: stat_flags.c,v 1.5 1997/02/22 14:04:02 peter Exp $
+ */
+
+#ifndef lint
+static char const sccsid[] = "@(#)stat_flags.c 8.1 (Berkeley) 5/31/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stddef.h>
+#include <string.h>
+
+#define SAPPEND(s) { \
+ if (prefix != NULL) \
+ (void)strcat(string, prefix); \
+ (void)strcat(string, s); \
+ prefix = ","; \
+}
+
+/*
+ * flags_to_string --
+ * Convert stat flags to a comma-separated string. If no flags
+ * are set, return the default string.
+ */
+char *
+flags_to_string(flags, def)
+ u_long flags;
+ char *def;
+{
+ static char string[128];
+ char *prefix;
+
+ string[0] = '\0';
+ prefix = NULL;
+ if (flags & UF_APPEND)
+ SAPPEND("uappnd");
+ if (flags & UF_IMMUTABLE)
+ SAPPEND("uchg");
+ if (flags & UF_NOUNLINK)
+ SAPPEND("uunlnk");
+ if (flags & UF_NODUMP)
+ SAPPEND("nodump");
+ if (flags & UF_OPAQUE)
+ SAPPEND("opaque");
+ if (flags & SF_APPEND)
+ SAPPEND("sappnd");
+ if (flags & SF_ARCHIVED)
+ SAPPEND("arch");
+ if (flags & SF_IMMUTABLE)
+ SAPPEND("schg");
+ if (flags & SF_NOUNLINK)
+ SAPPEND("sunlnk");
+ return (prefix == NULL && def != NULL ? def : string);
+}
+
+#define TEST(a, b, f) { \
+ if (!memcmp(a, b, sizeof(b))) { \
+ if (clear) { \
+ if (clrp) \
+ *clrp |= (f); \
+ } else if (setp) \
+ *setp |= (f); \
+ break; \
+ } \
+}
+
+/*
+ * string_to_flags --
+ * Take string of arguments and return stat flags. Return 0 on
+ * success, 1 on failure. On failure, stringp is set to point
+ * to the offending token.
+ */
+int
+string_to_flags(stringp, setp, clrp)
+ char **stringp;
+ u_long *setp, *clrp;
+{
+ int clear;
+ char *string, *p;
+
+ clear = 0;
+ if (setp)
+ *setp = 0;
+ if (clrp)
+ *clrp = 0;
+ string = *stringp;
+ while ((p = strsep(&string, "\t ,")) != NULL) {
+ *stringp = p;
+ if (*p == '\0')
+ continue;
+ if (p[0] == 'n' && p[1] == 'o') {
+ clear = 1;
+ p += 2;
+ }
+ switch (p[0]) {
+ case 'a':
+ TEST(p, "arch", SF_ARCHIVED);
+ TEST(p, "archived", SF_ARCHIVED);
+ return (1);
+ case 'd':
+ clear = !clear;
+ TEST(p, "dump", UF_NODUMP);
+ return (1);
+ case 'o':
+ TEST(p, "opaque", UF_OPAQUE);
+ return (1);
+ case 's':
+ TEST(p, "sappnd", SF_APPEND);
+ TEST(p, "sappend", SF_APPEND);
+ TEST(p, "schg", SF_IMMUTABLE);
+ TEST(p, "schange", SF_IMMUTABLE);
+ TEST(p, "simmutable", SF_IMMUTABLE);
+ TEST(p, "sunlnk", SF_NOUNLINK);
+ TEST(p, "sunlink", SF_NOUNLINK);
+ return (1);
+ case 'u':
+ TEST(p, "uappnd", UF_APPEND);
+ TEST(p, "uappend", UF_APPEND);
+ TEST(p, "uchg", UF_IMMUTABLE);
+ TEST(p, "uchange", UF_IMMUTABLE);
+ TEST(p, "uimmutable", UF_IMMUTABLE);
+ TEST(p, "uunlnk", UF_NOUNLINK);
+ TEST(p, "uunlink", UF_NOUNLINK);
+ /* FALLTHROUGH */
+ default:
+ return (1);
+ }
+ }
+ return (0);
+}
diff --git a/lib/libc/gen/sysconf.3 b/lib/libc/gen/sysconf.3
index 53622f6..aca1a432 100644
--- a/lib/libc/gen/sysconf.3
+++ b/lib/libc/gen/sysconf.3
@@ -64,11 +64,11 @@ The available values are as follows:
.Pp
.It Li _SC_ARG_MAX
The maximum bytes of argument to
-.Xr exec 2 .
+.Xr execve 2 .
.It Li _SC_CHILD_MAX
The maximum number of simultaneous processes per user id.
.It Li _SC_CLK_TCK
-Number of micro-seconds per hz tick.
+The frequency of the statistics clock in ticks per second.
.It Li _SC_NGROUPS_MAX
The maximum number of supplemental groups.
.It Li _SC_OPEN_MAX
@@ -145,7 +145,7 @@ otherwise \-1.
.El
.Sh RETURN VALUES
If the call to
-.Nm sysconf
+.Fn sysconf
is not successful, \-1 is returned and
.Va errno
is set appropriately.
@@ -174,11 +174,13 @@ 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.
.Sh STANDARDS
-The
+Except for the fact that values returned by
.Fn sysconf
-function conforms to
+may change over the lifetime of the calling process,
+this function conforms to
.St -p1003.1-88 .
.Sh HISTORY
The
-.Nm sysconf
-function first appeared in 4.4BSD.
+.Fn sysconf
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/sysconf.c b/lib/libc/gen/sysconf.c
index 12d6f58..16a3efa 100644
--- a/lib/libc/gen/sysconf.c
+++ b/lib/libc/gen/sysconf.c
@@ -39,11 +39,12 @@ static char sccsid[] = "@(#)sysconf.c 8.2 (Berkeley) 3/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
-#include <sys/sysctl.h>
#include <sys/time.h>
+#include <sys/sysctl.h>
#include <sys/resource.h>
#include <errno.h>
+#include <time.h>
#include <unistd.h>
/*
@@ -62,7 +63,6 @@ long
sysconf(name)
int name;
{
- struct clockinfo clk;
struct rlimit rl;
size_t len;
int mib[2], value;
@@ -184,5 +184,5 @@ yesno: if (sysctl(mib, 2, &value, &len, NULL, 0) == -1)
errno = EINVAL;
return (-1);
}
- return (sysctl(mib, 2, &value, &len, NULL, 0) == -1 ? -1 : value);
+ return (sysctl(mib, 2, &value, &len, NULL, 0) == -1 ? -1 : value);
}
diff --git a/lib/libc/gen/sysctl.3 b/lib/libc/gen/sysctl.3
index 5470574..df0b4c2 100644
--- a/lib/libc/gen/sysctl.3
+++ b/lib/libc/gen/sysctl.3
@@ -31,36 +31,37 @@
.\"
.\" @(#)sysctl.3 8.4 (Berkeley) 5/9/95
.\"
-.Dd "May 9, 1995"
+.Dd May 9, 1995
.Dt SYSCTL 3
.Os
.Sh NAME
.Nm sysctl
.Nd get or set system information
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
.Fd #include <sys/sysctl.h>
.Ft int
.Fn sysctl "int *name" "u_int namelen" "void *oldp" "size_t *oldlenp" "void *newp" "size_t newlen"
.Sh DESCRIPTION
The
-.Nm sysctl
+.Fn sysctl
function retrieves system information and allows processes with
appropriate privileges to set system information.
The information available from
-.Nm sysctl
+.Fn sysctl
consists of integers, strings, and tables.
Information may be retrieved and set from the command interface
using the
-.Xr sysctl 1
+.Xr sysctl 8
utility.
.Pp
Unless explicitly noted below,
-.Nm sysctl
+.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
-.Nm sysctl
+.Fn sysctl
are serialized to avoid deadlock.
.Pp
The state is described using a ``Management Information Base'' (MIB)
@@ -75,7 +76,8 @@ The information is copied into the buffer specified by
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 that location gives the amount of data copied after a successful call
+and after a call that returns with the error code 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
@@ -87,7 +89,7 @@ and
should be set to NULL.
.Pp
The size of the available data can be determined by calling
-.Nm sysctl
+.Fn sysctl
with a NULL parameter for
.Fa oldp .
The size of the available data will be returned in the location pointed to by
@@ -128,22 +130,24 @@ listed here, and described in separate sections below.
.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;
-.sp
+
mib[0] = CTL_KERN;
mib[1] = KERN_MAXPROC;
len = sizeof(maxproc);
sysctl(mib, 2, &maxproc, &len, NULL, 0);
.Ed
-.sp
+.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;
-.sp
+
mib[0] = CTL_USER;
mib[1] = USER_CS_PATH;
sysctl(mib, 2, NULL, &len, NULL, 0);
@@ -153,10 +157,10 @@ sysctl(mib, 2, p, &len, NULL, 0);
.Sh CTL_DEBUG
The debugging variables vary from system to system.
A debugging variable may be added or deleted without need to recompile
-.Nm sysctl
+.Fn sysctl
to know about it.
Each time it runs,
-.Nm sysctl
+.Fn sysctl
gets the list of debugging variables from the kernel and
displays their current values.
The system defines twenty
@@ -207,6 +211,7 @@ privilege may change the value.
.It HW\_PHYSMEM integer no
.It HW\_USERMEM integer no
.It HW\_PAGESIZE integer no
+.It HW\_FLOATINGPOINT integer no
.\".It HW\_DISKNAMES integer no
.\".It HW\_DISKSTATS integer no
.El
@@ -227,6 +232,8 @@ The bytes of physical memory.
The bytes of non-kernel memory.
.It Li HW_PAGESIZE
The software page size.
+.It Li HW_FLOATINGPOINT
+Nonzero if the floating point support is in hardware.
.\".It Fa HW_DISKNAMES
.\".It Fa HW_DISKSTATS
.El
@@ -239,36 +246,33 @@ 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 "KERNXCHOWNXRESTRICTEDXXX" "struct clockrateXXX" -offset indent
+.Bl -column "KERNXMAXFILESPERPROCXXX" "struct clockrateXXX" -offset indent
.It Sy Pa Second level name Type Changeable
.It KERN\_ARGMAX integer no
+.It KERN\_BOOTFILE string yes
.It KERN\_BOOTTIME struct timeval no
-.It KERN\_CHOWN\_RESTRICTED integer no
.It KERN\_CLOCKRATE struct clockinfo no
.It KERN\_FILE struct file no
.It KERN\_HOSTID integer yes
.It KERN\_HOSTNAME string yes
.It KERN\_JOB\_CONTROL integer no
-.It KERN\_LINK\_MAX integer no
.It KERN\_MAXFILES integer yes
+.It KERN\_MAXFILESPERPROC integer yes
.It KERN\_MAXPROC integer yes
+.It KERN\_MAXPROCPERUID integer yes
.It KERN\_MAXVNODES integer yes
-.It KERN\_MAX\_CANON integer no
-.It KERN\_MAX\_INPUT integer no
-.It KERN\_NAME\_MAX integer no
.It KERN\_NGROUPS integer no
-.It KERN\_NO\_TRUNC 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\_PATH\_MAX integer no
-.It KERN\_PIPE\_BUF integer no
.It KERN\_POSIX1 integer no
.It KERN\_PROC struct proc no
.It KERN\_PROF node not applicable
.It KERN\_SAVED\_IDS integer no
.It KERN\_SECURELVL integer raise only
-.It KERN\_VDISABLE integer no
+.It KERN\_UPDATEINTERVAL integer no
.It KERN\_VERSION string no
.It KERN\_VNODE struct vnode no
.El
@@ -277,22 +281,20 @@ information.
.Bl -tag -width "123456"
.It Li KERN_ARGMAX
The maximum bytes of argument to
-.Xr exec 2 .
+.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_CHOWN_RESTRICTED
-Return 1 if appropriate privileges are required for the
-.Xr chown 2
-system call, otherwise 0.
.It Li KERN_CLOCKRATE
A
.Va struct clockinfo
structure is returned.
This structure contains the clock, statistics clock and profiling clock
-frequencies, and the number of micro-seconds per hz tick.
+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 a single
@@ -306,35 +308,38 @@ Get or set the host id.
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_LINK_MAX
-The maximum file link count.
.It Li KERN_MAXFILES
-The maximum number of open files that may be open in the system.
+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 simultaneous processes the system will allow.
+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_MAX_CANON
-The maximum number of bytes in terminal canonical input line.
-.It Li KERN_MAX_INPUT
-The minimum maximum number of bytes for which space is available in
-a terminal input queue.
-.It Li KERN_NAME_MAX
-The maximum number of bytes in a file name.
.It Li KERN_NGROUPS
The maximum number of supplemental groups.
-.It Li KERN_NO_TRUNC
-Return 1 if file names longer than KERN_NAME_MAX are truncated.
+.It Li KERN_NISDOMAINNAME
+The name of the current YP/NIS domain.
+.It Li KERN_OSRELDATE
+The system release date in YYYYMM format
+(January 1996 is encoded as 199601).
.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_PATH_MAX
-The maximum number of bytes in a pathname.
-.It Li KERN_PIPE_BUF
-The maximum number of bytes which will be written atomically to a pipe.
.It Li KERN_POSIX1
The version of ISO/IEC 9945 (POSIX 1003.1) with which the system
attempts to comply.
@@ -395,8 +400,6 @@ Returns 1 if saved set-group and saved set-user ID is available.
The system security level.
This level may be raised by processes with appropriate privilege.
It may only be lowered by process 1.
-.It Li KERN_VDISABLE
-Returns the terminal character disabling value.
.It Li KERN_VERSION
The system version string.
.It Li KERN_VNODE
@@ -409,13 +412,23 @@ Each element of the array contains the kernel address of a vnode
.Va struct vnode *
followed by the vnode itself
.Va struct vnode .
+.It Li KERN_UPDATEINTERVAL
+The interval between
+.Xr sync 2
+calls in the
+.Xr update 4
+process.
.El
.Sh CTL_MACHDEP
The set of variables defined is architecture dependent.
-Most architectures define at least the following variables.
-.Bl -column "CONSOLE_DEVICEXXX" "integerXXX" -offset indent
+The following variables are defined for the i386 architecture.
+.Bl -column "CONSOLE_DEVICEXXX" "struct bootinfoXXX" -offset indent
.It Sy Pa Second level name Type Changeable
.It Li CPU_CONSDEV dev_t no
+.It Li CPU_ADJKERNTZ int yes
+.It Li CPU_DISRTCSET int yes
+.It Li CPU_BOOTINFO struct bootinfo no
+.It Li CPU_WALLCLOCK int yes
.El
.Sh CTL_NET
The string and integer information available for the CTL_NET level
@@ -600,7 +613,7 @@ The returned data consists of a
.El
.Sh RETURN VALUES
If the call to
-.Nm sysctl
+.Fn sysctl
is successful, the number of bytes copied out is returned.
Otherwise \-1 is returned and
.Va errno
@@ -666,5 +679,6 @@ definitions for fourth level UDP identifiers
.Xr sysctl 8
.Sh HISTORY
The
-.Nm sysctl
-function first appeared in 4.4BSD.
+.Fn sysctl
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/sysctl.c b/lib/libc/gen/sysctl.c
index f67a533..cb7448a 100644
--- a/lib/libc/gen/sysctl.c
+++ b/lib/libc/gen/sysctl.c
@@ -43,6 +43,7 @@ static char sccsid[] = "@(#)sysctl.c 8.2 (Berkeley) 1/4/94";
#include <paths.h>
#include <stdio.h>
#include <unistd.h>
+#include <string.h>
int
sysctl(name, namelen, oldp, oldlenp, newp, newlen)
diff --git a/lib/libc/gen/sysctlbyname.c b/lib/libc/gen/sysctlbyname.c
new file mode 100644
index 0000000..a3133af
--- /dev/null
+++ b/lib/libc/gen/sysctlbyname.c
@@ -0,0 +1,33 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+int
+sysctlbyname(char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen)
+{
+ int name2oid_oid[2];
+ int real_oid[CTL_MAXNAME+2];
+ int error, oidlen;
+
+ name2oid_oid[0] = 0; /* This is magic & undocumented! */
+ name2oid_oid[1] = 3;
+
+ oidlen = sizeof(real_oid);
+ error = sysctl(name2oid_oid, 2, real_oid, &oidlen, name, strlen(name));
+ if (error < 0)
+ return error;
+ oidlen /= sizeof (int);
+ error = sysctl(real_oid, oidlen, oldp, oldlenp, newp, newlen);
+ return (error);
+}
+
diff --git a/lib/libc/gen/syslog.3 b/lib/libc/gen/syslog.3
index 8a46d05..ab1bd9d 100644
--- a/lib/libc/gen/syslog.3
+++ b/lib/libc/gen/syslog.3
@@ -139,12 +139,12 @@ one or more of the following values:
If
.Fn syslog
cannot pass the message to
-.Xr syslogd
+.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
+.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
@@ -173,11 +173,15 @@ The same as
but logged to a file readable only by
selected individuals.
.It Dv LOG_CRON
-The clock daemon.
+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 daemon:
+.Xr ftpd 8 .
.It Dv LOG_KERN
Messages generated by the kernel.
These cannot be generated by any user processes.
@@ -248,8 +252,10 @@ always returns the previous log mask level.
.Bd -literal -offset indent -compact
syslog(LOG_ALERT, "who: internal error 23");
-openlog("ftpd", LOG_PID, LOG_DAEMON);
+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");
diff --git a/lib/libc/gen/syslog.c b/lib/libc/gen/syslog.c
index c18c776..0eb721e 100644
--- a/lib/libc/gen/syslog.c
+++ b/lib/libc/gen/syslog.c
@@ -32,7 +32,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+/*
static char sccsid[] = "@(#)syslog.c 8.5 (Berkeley) 4/29/95";
+*/
+static const char rcsid[] =
+ "$Id: syslog.c,v 1.12 1997/03/11 11:52:33 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -57,12 +61,50 @@ static char sccsid[] = "@(#)syslog.c 8.5 (Berkeley) 4/29/95";
static int LogFile = -1; /* fd for log */
static int connected; /* have done connect */
+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 */
extern char *__progname; /* Program name, from crt0. */
+static void disconnectlog __P((void)); /* disconnect from syslogd */
+static void connectlog __P((void)); /* (re)connect to syslogd */
+
+/*
+ * 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(cookie, buf, len)
+ void *cookie; /* really [struct bufcookie *] */
+ char *buf; /* characters to copy */
+ int len; /* length to copy */
+{
+ 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 0;
+}
+
/*
* syslog, vsyslog --
* print message on log file; output is intended for syslogd(8).
@@ -95,10 +137,13 @@ vsyslog(pri, fmt, ap)
va_list ap;
{
register int cnt;
- register char ch, *p, *t;
+ register char ch, *p;
time_t now;
int fd, saved_errno;
char *stdp, tbuf[2048], fmt_cpy[1024];
+ 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. */
@@ -118,35 +163,66 @@ vsyslog(pri, fmt, ap)
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)
+ return;
+
/* Build the message. */
(void)time(&now);
- p = tbuf + sprintf(tbuf, "<%d>", pri);
- p += strftime(p, sizeof (tbuf) - (p - tbuf), "%h %e %T ",
- localtime(&now));
- if (LogStat & LOG_PERROR)
- stdp = p;
+ (void)fprintf(fp, "<%d>", pri);
+ (void)fprintf(fp, "%.15s ", ctime(&now) + 4);
+ if (LogStat & LOG_PERROR) {
+ /* Transfer to string buffer */
+ (void)fflush(fp);
+ stdp = tbuf + (sizeof(tbuf) - tbuf_cookie.left);
+ }
if (LogTag == NULL)
LogTag = __progname;
if (LogTag != NULL)
- p += sprintf(p, "%s", LogTag);
+ (void)fprintf(fp, "%s", LogTag);
if (LogStat & LOG_PID)
- p += sprintf(p, "[%d]", getpid());
+ (void)fprintf(fp, "[%d]", getpid());
if (LogTag != NULL) {
- *p++ = ':';
- *p++ = ' ';
+ (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);
+ return;
+ }
+
+ /* Substitute error message for %m. */
+ for ( ; (ch = *fmt); ++fmt)
+ if (ch == '%' && fmt[1] == 'm') {
+ ++fmt;
+ fputs(strerror(saved_errno), 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;
}
- /* Substitute error message for %m. */
- for (t = fmt_cpy; ch = *fmt; ++fmt)
- if (ch == '%' && fmt[1] == 'm') {
- ++fmt;
- t += sprintf(t, "%s", strerror(saved_errno));
- } else
- *t++ = ch;
- *t = '\0';
+ (void)vfprintf(fp, fmt, ap);
+ (void)fclose(fp);
- p += vsprintf(p, fmt_cpy, ap);
- cnt = p - tbuf;
+ cnt = sizeof(tbuf) - tbuf_cookie.left;
/* Output to stderr if requested. */
if (LogStat & LOG_PERROR) {
@@ -162,8 +238,18 @@ vsyslog(pri, fmt, ap)
}
/* Get connected, output the message to the local logger. */
- if (!connected)
+ if (!opened)
openlog(LogTag, LogStat | LOG_NDELAY, 0);
+ connectlog();
+ if (send(LogFile, tbuf, cnt, 0) >= 0)
+ return;
+
+ /*
+ * If the send() failed, the odds are syslogd was restarted.
+ * Make one (only) attempt to reconnect to /dev/log.
+ */
+ disconnectlog();
+ connectlog();
if (send(LogFile, tbuf, cnt, 0) >= 0)
return;
@@ -174,15 +260,69 @@ vsyslog(pri, fmt, ap)
*/
if (LogStat & LOG_CONS &&
(fd = open(_PATH_CONSOLE, O_WRONLY, 0)) >= 0) {
- (void)strcat(tbuf, "\r\n");
- cnt += 2;
- p = index(tbuf, '>') + 1;
- (void)write(fd, p, cnt - (p - tbuf));
+ struct iovec iov[2];
+ register 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);
}
}
+static void
+disconnectlog()
+{
+ /*
+ * 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;
+ }
+ connected = 0; /* retry connect */
+}
+
+static void
+connectlog()
+{
+ struct sockaddr 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, 1);
+ }
+ if (LogFile != -1 && !connected) {
+ SyslogAddr.sa_len = sizeof(SyslogAddr);
+ SyslogAddr.sa_family = AF_UNIX;
+ (void)strncpy(SyslogAddr.sa_data, _PATH_LOG,
+ sizeof(SyslogAddr.sa_data));
+ connected = connect(LogFile, &SyslogAddr,
+ sizeof(SyslogAddr)) != -1;
-static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */
+ if (!connected) {
+ /*
+ * Try the old "/dev/log" path, for backward
+ * compatibility.
+ */
+ (void)strncpy(SyslogAddr.sa_data, _PATH_OLDLOG,
+ sizeof(SyslogAddr.sa_data));
+ connected = connect(LogFile, &SyslogAddr,
+ sizeof(SyslogAddr)) != -1;
+ }
+
+ if (!connected) {
+ (void)close(LogFile);
+ LogFile = -1;
+ }
+ }
+}
void
openlog(ident, logstat, logfac)
@@ -195,22 +335,10 @@ openlog(ident, logstat, logfac)
if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
LogFacility = logfac;
- if (LogFile == -1) {
- SyslogAddr.sa_family = AF_UNIX;
- (void)strncpy(SyslogAddr.sa_data, _PATH_LOG,
- sizeof(SyslogAddr.sa_data));
- if (LogStat & LOG_NDELAY) {
- if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
- return;
- (void)fcntl(LogFile, F_SETFD, 1);
- }
- }
- if (LogFile != -1 && !connected)
- if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) == -1) {
- (void)close(LogFile);
- LogFile = -1;
- } else
- connected = 1;
+ if (LogStat & LOG_NDELAY) /* open immediately */
+ connectlog();
+
+ opened = 1; /* ident and facility has been set */
}
void
diff --git a/lib/libc/gen/tcgetpgrp.3 b/lib/libc/gen/tcgetpgrp.3
index e97c256..045c569 100644
--- a/lib/libc/gen/tcgetpgrp.3
+++ b/lib/libc/gen/tcgetpgrp.3
@@ -31,7 +31,7 @@
.\"
.\" @(#)tcgetpgrp.3 8.1 (Berkeley) 6/4/93
.\"
-.Dd "June 4, 1993"
+.Dd June 4, 1993
.Dt TCGETPGRP 3
.Os
.Sh NAME
@@ -44,15 +44,15 @@
.Fn tcgetpgrp "int fd"
.Sh DESCRIPTION
The
-.Nm tcgetpgrp
+.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,
-.Nm tcgetpgrp
+.Fn tcgetpgrp
returns an invalid process ID.
.Sh ERRORS
If an error occurs,
-.Nm tcgetpgrp
+.Fn tcgetpgrp
returns -1 and the global variable
.Va errno
is set to indicate the error, as follows:
@@ -68,12 +68,12 @@ underlying terminal device represented by
is not the controlling terminal.
.El
.Sh SEE ALSO
-.Xr setpgid 3 ,
+.Xr setpgid 2 ,
.Xr setsid 2 ,
.Xr tcsetpgrp 3
.Sh STANDARDS
The
-.Nm tcgetpgrp
+.Fn tcgetpgrp
function is expected to be compliant with the
.St -p1003.1-88
specification.
diff --git a/lib/libc/gen/tcsendbreak.3 b/lib/libc/gen/tcsendbreak.3
index 2ff9ece..1e80265 100644
--- a/lib/libc/gen/tcsendbreak.3
+++ b/lib/libc/gen/tcsendbreak.3
@@ -31,7 +31,7 @@
.\"
.\" @(#)tcsendbreak.3 8.1 (Berkeley) 6/4/93
.\"
-.Dd "June 4, 1993"
+.Dd June 4, 1993
.Dt TCSENDBREAK 3
.Os
.Sh NAME
@@ -52,13 +52,13 @@
.Fn tcsendbreak "int fd" "int len"
.Sh DESCRIPTION
The
-.Nm tcdrain
+.Fn tcdrain
function waits until all output written to the terminal referenced by
.Fa fd
has been transmitted to the terminal.
.Pp
The
-.Nm tcflow
+.Fn tcflow
function suspends transmission of data to or the reception of data from
the terminal referenced by
.Fa fd
@@ -89,7 +89,7 @@ section of
.El
.Pp
The
-.Nm tcflush
+.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
@@ -108,7 +108,7 @@ Flush both data received but not read and data written but not transmitted.
.El
.Pp
The
-.Nm tcsendbreak
+.Fn tcsendbreak
function transmits a continuous stream of zero-valued bits for four-tenths
of a second to the terminal referenced by
.Fa fd .
@@ -136,7 +136,7 @@ The file associated with
is not a terminal.
.It Bq Er EINTR
A signal interrupted the
-.Nm tcdrain
+.Fn tcdrain
function.
.El
.Sh SEE ALSO
@@ -144,11 +144,11 @@ function.
.Xr termios 4
.Sh STANDARDS
The
-.Nm tcsendbreak ,
-.Nm tcdrain ,
-.Nm tcflush
+.Fn tcsendbreak ,
+.Fn tcdrain ,
+.Fn tcflush
and
-.Nm tcflow
+.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
index d3b2b4f..05dbe08 100644
--- a/lib/libc/gen/tcsetattr.3
+++ b/lib/libc/gen/tcsetattr.3
@@ -31,7 +31,7 @@
.\"
.\" @(#)tcsetattr.3 8.3 (Berkeley) 1/2/94
.\"
-.Dd "January 2, 1994"
+.Dd January 2, 1994
.Dt TCSETATTR 3
.Os
.Sh NAME
@@ -47,11 +47,11 @@
.Sh SYNOPSIS
.Fd #include <termios.h>
.Ft speed_t
-.Fn cfgetispeed "struct termios *t"
+.Fn cfgetispeed "const struct termios *t"
.Ft int
.Fn cfsetispeed "struct termios *t" "speed_t speed"
.Ft speed_t
-.Fn cfgetospeed "struct termios *t"
+.Fn cfgetospeed "const struct termios *t"
.Ft int
.Fn cfsetospeed "struct termios *t" "speed_t speed"
.Ft int
@@ -61,33 +61,33 @@
.Ft int
.Fn tcgetattr "int fd" "struct termios *t"
.Ft int
-.Fn tcsetattr "int fd" "int action" "struct termios *t"
+.Fn tcsetattr "int fd" "int action" "const struct termios *t"
.Sh DESCRIPTION
The
-.Nm cfmakeraw ,
-.Nm tcgetattr
+.Fn cfmakeraw ,
+.Fn tcgetattr
and
-.Nm tcsetattr
+.Fn tcsetattr
functions are provided for getting and setting the termios structure.
.Pp
The
-.Nm cfgetispeed ,
-.Nm cfsetispeed ,
-.Nm cfgetospeed ,
-.Nm cfsetospeed
+.Fn cfgetispeed ,
+.Fn cfsetispeed ,
+.Fn cfgetospeed ,
+.Fn cfsetospeed
and
-.Nm cfsetspeed
+.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
-.Nm tcsetattr
+.Fn tcsetattr
function is called.
Certain values for baud rates set in the termios structure and passed to
-.Nm tcsetattr
+.Fn tcsetattr
have special meanings.
These are discussed in the portion of the manual page that describes the
-.Nm tcsetattr
+.Fn tcsetattr
function.
.Sh GETTING AND SETTING THE BAUD RATE
The input and output baud rates are found in the termios structure.
@@ -121,31 +121,31 @@ represented, however, the following symbolic values are defined.
.Ed
.Pp
The
-.Nm cfgetispeed
+.Fn cfgetispeed
function returns the input baud rate in the termios structure referenced by
.Fa tp .
.Pp
The
-.Nm cfsetispeed
+.Fn cfsetispeed
function sets the input baud rate in the termios structure referenced by
.Fa tp
to
.Fa speed .
.Pp
The
-.Nm cfgetospeed
+.Fn cfgetospeed
function returns the output baud rate in the termios structure referenced by
.Fa tp .
.Pp
The
-.Nm cfsetospeed
+.Fn cfsetospeed
function sets the output baud rate in the termios structure referenced by
.Fa tp
to
.Fa speed .
.Pp
The
-.Nm cfsetspeed
+.Fn cfsetspeed
function sets both the input and output baud rate in the termios structure
referenced by
.Fa tp
@@ -153,10 +153,10 @@ to
.Fa speed .
.Pp
Upon successful completion, the functions
-.Nm cfsetispeed ,
-.Nm cfsetospeed ,
+.Fn cfsetispeed ,
+.Fn cfsetospeed ,
and
-.Nm cfsetspeed
+.Fn cfsetspeed
return a value of 0.
Otherwise, a value of -1 is returned and the global variable
.Va errno
@@ -178,7 +178,7 @@ file, not just the open file description associated with the particular
file descriptor.
.Pp
The
-.Nm cfmakeraw
+.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.
@@ -186,17 +186,17 @@ 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
-.Nm tcgetattr ,
+.Fn tcgetattr ,
setting raw mode with
-.Nm cfmakeraw
+.Fn cfmakeraw
and the subsequent
-.Nm tcsetattr ,
+.Fn tcsetattr ,
and then using another
-.Nm tcsetattr
+.Fn tcsetattr
with the saved state to revert to the previous terminal state.
.Pp
The
-.Nm tcgetattr
+.Fn tcgetattr
function copies the parameters associated with the terminal referenced
by
.Fa fd
@@ -206,7 +206,7 @@ This function is allowed from a background process, however, the terminal
attributes may be subsequently changed by a foreground process.
.Pp
The
-.Nm tcsetattr
+.Fn tcsetattr
function sets the parameters associated with the terminal from the
termios structure referenced by
.Fa tp .
@@ -246,17 +246,17 @@ fields are ignored.
.Pp
The 0 baud rate is used to terminate the connection.
If 0 is specified as the output speed to the function
-.Nm tcsetattr ,
+.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
-.Nm tcsetattr ,
+.Fn tcsetattr ,
the input baud rate will be set to the same value as that specified by
the output baud rate.
.Pp
If
-.Nm tcsetattr
+.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.
@@ -264,9 +264,9 @@ 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
-.Nm tcgetattr
+.Fn tcgetattr
and
-.Nm tcsetattr
+.Fn tcsetattr
return a value of 0.
Otherwise, they
return -1 and the global variable
@@ -277,28 +277,28 @@ is set to indicate the error, as follows:
The
.Fa fd
argument to
-.Nm tcgetattr
+.Fn tcgetattr
or
-.Nm tcsetattr
+.Fn tcsetattr
was not a valid file descriptor.
.It Bq Er EINTR
The
-.Nm tcsetattr
+.Fn tcsetattr
function was interrupted by a signal.
.It Bq Er EINVAL
The
.Fa action
argument to the
-.Nm tcsetattr
+.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
-.Nm tcgetattr
+.Fn tcgetattr
or
-.Nm tcsetattr
+.Fn tcsetattr
is not a terminal.
.El
.Sh SEE ALSO
@@ -306,25 +306,25 @@ is not a terminal.
.Xr termios 4
.Sh STANDARDS
The
-.Nm cfgetispeed ,
-.Nm cfsetispeed ,
-.Nm cfgetospeed ,
-.Nm cfsetospeed ,
-.Nm tcgetattr
+.Fn cfgetispeed ,
+.Fn cfsetispeed ,
+.Fn cfgetospeed ,
+.Fn cfsetospeed ,
+.Fn tcgetattr
and
-.Nm tcsetattr
+.Fn tcsetattr
functions are expected to be compliant with the
.St -p1003.1-88
specification.
The
-.Nm cfmakeraw
+.Fn cfmakeraw
and
-.Nm cfsetspeed
+.Fn cfsetspeed
functions,
as well as the
.Li TCSASOFT
option to the
-.Nm tcsetattr
+.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
index e1f8af0..684ec4c 100644
--- a/lib/libc/gen/tcsetpgrp.3
+++ b/lib/libc/gen/tcsetpgrp.3
@@ -31,7 +31,7 @@
.\"
.\" @(#)tcsetpgrp.3 8.1 (Berkeley) 6/4/93
.\"
-.Dd "June 4, 1993"
+.Dd June 4, 1993
.Dt TCSETPGRP 3
.Os
.Sh NAME
@@ -89,7 +89,7 @@ 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 3 ,
+.Xr setpgid 2 ,
.Xr setsid 2 ,
.Xr tcgetpgrp 3
.Sh STANDARDS
diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c
index 979fee4..ab23d9d 100644
--- a/lib/libc/gen/telldir.c
+++ b/lib/libc/gen/telldir.c
@@ -49,7 +49,7 @@ static char sccsid[] = "@(#)telldir.c 8.1 (Berkeley) 6/4/93";
/*
* One of these structures is malloced to describe the current directory
- * position each time telldir is called. It records the current magic
+ * 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.
*/
@@ -58,6 +58,7 @@ struct ddloc {
long loc_index; /* key associated with structure */
long loc_seek; /* magic cookie returned by getdirentries */
long loc_loc; /* offset of entry in buffer */
+ const DIR* loc_dirp; /* directory which used this entry */
};
#define NDIRHASH 32 /* Num of hash lists, must be a power of 2 */
@@ -82,6 +83,7 @@ telldir(dirp)
lp->loc_index = index;
lp->loc_seek = dirp->dd_seek;
lp->loc_loc = dirp->dd_loc;
+ lp->loc_dirp = dirp;
lp->loc_next = dd_hash[LOCHASH(index)];
dd_hash[LOCHASH(index)] = lp;
return (index);
@@ -126,3 +128,30 @@ found:
free((caddr_t)lp);
#endif
}
+
+/*
+ * Reclaim memory for telldir cookies which weren't used.
+ */
+void
+_reclaim_telldir(dirp)
+ register const DIR *dirp;
+{
+ register struct ddloc *lp;
+ register struct ddloc **prevlp;
+ int i;
+
+ for (i = 0; i < NDIRHASH; i++) {
+ prevlp = &dd_hash[i];
+ lp = *prevlp;
+ while (lp != NULL) {
+ if (lp->loc_dirp == dirp) {
+ *prevlp = lp->loc_next;
+ free((caddr_t)lp);
+ lp = *prevlp;
+ continue;
+ }
+ prevlp = &lp->loc_next;
+ lp = lp->loc_next;
+ }
+ }
+}
diff --git a/lib/libc/gen/termios.c b/lib/libc/gen/termios.c
index a99d86f..5264a2d 100644
--- a/lib/libc/gen/termios.c
+++ b/lib/libc/gen/termios.c
@@ -36,15 +36,11 @@ static char sccsid[] = "@(#)termios.c 8.2 (Berkeley) 2/21/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
+#include <sys/fcntl.h>
#include <sys/ioctl.h>
-#include <sys/tty.h>
#include <sys/time.h>
-#define KERNEL /* XXX - FREAD and FWRITE ifdef'd KERNEL*/
-#include <sys/fcntl.h>
-#undef KERNEL
#include <errno.h>
-#include <stdio.h>
#include <termios.h>
#include <unistd.h>
@@ -99,6 +95,7 @@ tcsetpgrp(fd, pgrp)
pid_t
tcgetpgrp(fd)
+ int fd;
{
int s;
@@ -163,14 +160,17 @@ cfmakeraw(t)
struct termios *t;
{
- t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ 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|ECHONL|ICANON|ISIG|IEXTEN);
+ t->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN|NOFLSH|TOSTOP|PENDIN);
t->c_cflag &= ~(CSIZE|PARENB);
- t->c_cflag |= CS8;
- /* XXX set MIN/TIME */
+ t->c_cflag |= CS8|CREAD;
+ t->c_cc[VMIN] = 1;
+ t->c_cc[VTIME] = 0;
}
+int
tcsendbreak(fd, len)
int fd, len;
{
@@ -186,6 +186,7 @@ tcsendbreak(fd, len)
return (0);
}
+int
tcdrain(fd)
int fd;
{
@@ -193,6 +194,7 @@ tcdrain(fd)
return (ioctl(fd, TIOCDRAIN, 0));
}
+int
tcflush(fd, which)
int fd, which;
{
@@ -215,6 +217,7 @@ tcflush(fd, which)
return (ioctl(fd, TIOCFLUSH, &com));
}
+int
tcflow(fd, action)
int fd, action;
{
diff --git a/lib/libc/gen/time.3 b/lib/libc/gen/time.3
index 1343836..ecf767d 100644
--- a/lib/libc/gen/time.3
+++ b/lib/libc/gen/time.3
@@ -42,7 +42,7 @@
.Nm time
.Nd get time of day
.Sh SYNOPSIS
-.Fd #include <sys/types.h>
+.Fd #include <time.h>
.Ft time_t
.Fn time "time_t *tloc"
.Sh DESCRIPTION
diff --git a/lib/libc/gen/times.3 b/lib/libc/gen/times.3
index 93207b1..4bf6689 100644
--- a/lib/libc/gen/times.3
+++ b/lib/libc/gen/times.3
@@ -127,7 +127,8 @@ and
.Xr time 1 ,
.Xr getrusage 2 ,
.Xr gettimeofday 2 ,
-.Xr wait 2
+.Xr wait 2 ,
+.Xr clocks 7
.Sh STANDARDS
The
.Fn times
diff --git a/lib/libc/gen/timezone.3 b/lib/libc/gen/timezone.3
index 68adeb9..d7ac13c 100644
--- a/lib/libc/gen/timezone.3
+++ b/lib/libc/gen/timezone.3
@@ -31,7 +31,7 @@
.\"
.\" @(#)timezone.3 8.2 (Berkeley) 4/19/94
.\"
-.Dd "April 19, 1994"
+.Dd April 19, 1994
.Dt TIMEZONE 3
.Os
.Sh NAME
diff --git a/lib/libc/gen/timezone.c b/lib/libc/gen/timezone.c
index 9ce6142..fe3ce23 100644
--- a/lib/libc/gen/timezone.c
+++ b/lib/libc/gen/timezone.c
@@ -40,7 +40,7 @@ static char sccsid[] = "@(#)timezone.c 8.1 (Berkeley) 6/4/93";
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <tzfile.h>
+#define TZ_MAX_CHARS 255
char *_tztab();
@@ -62,8 +62,8 @@ timezone(zone, dst)
register char *beg,
*end;
- if (beg = getenv("TZNAME")) { /* set in environment */
- if (end = index(beg, ',')) { /* "PST,PDT" */
+ if ( (beg = getenv("TZNAME")) ) { /* set in environment */
+ if ( (end = index(beg, ',')) ) {/* "PST,PDT" */
if (dst)
return(++end);
*end = '\0';
@@ -82,22 +82,22 @@ static struct zone {
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 */
+ {-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 */
+ {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
+ {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}
};
/*
diff --git a/lib/libc/gen/ttyname.c b/lib/libc/gen/ttyname.c
index 2f47bd6..b2f3f79 100644
--- a/lib/libc/gen/ttyname.c
+++ b/lib/libc/gen/ttyname.c
@@ -39,11 +39,122 @@ static char sccsid[] = "@(#)ttyname.c 8.2 (Berkeley) 1/27/94";
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
-#include <sgtty.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
#include <db.h>
#include <string.h>
#include <paths.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+static struct pthread_mutex _ttyname_lockd = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t ttyname_lock = &_ttyname_lockd;
+static pthread_key_t ttyname_key;
+static int ttyname_init = 0;
+
+char *
+ttyname(int fd)
+{
+ char *ret;
+
+ if (_thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__) == 0) {
+ ret = __ttyname_basic(fd);
+ _thread_fd_unlock(fd, FD_READ);
+ } else {
+ ret = NULL;
+ }
+
+ return (ret);
+}
+
+char *
+__ttyname_r_basic(int fd, char *buf, size_t len)
+{
+ register struct dirent *dirp;
+ register DIR *dp;
+ struct stat dsb;
+ struct stat sb;
+ char *rval;
+ int minlen;
+
+ rval = NULL;
+
+ /* Must be a terminal. */
+ if (!isatty(fd))
+ return (rval);
+ /* Must be a character device. */
+ if (_thread_sys_fstat(fd, &sb) || !S_ISCHR(sb.st_mode))
+ return (rval);
+ /* Must have enough room */
+ if (len <= sizeof(_PATH_DEV))
+ return (rval);
+
+ if ((dp = opendir(_PATH_DEV)) != NULL) {
+ memcpy(buf, _PATH_DEV, sizeof(_PATH_DEV));
+ for (rval = NULL; (dirp = readdir(dp)) != NULL;) {
+ if (dirp->d_fileno != sb.st_ino)
+ continue;
+ minlen = (len - (sizeof(_PATH_DEV) - 1)) < (dirp->d_namlen + 1) ?
+ (len - (sizeof(_PATH_DEV) - 1)) : (dirp->d_namlen + 1);
+ memcpy(buf + sizeof(_PATH_DEV) - 1, dirp->d_name, minlen);
+ if (stat(buf, &dsb) || sb.st_dev != dsb.st_dev ||
+ sb.st_ino != dsb.st_ino)
+ continue;
+ rval = buf;
+ break;
+ }
+ (void) closedir(dp);
+ }
+ return (rval);
+}
+
+char *
+__ttyname_basic(int fd)
+{
+ char *buf;
+
+ pthread_mutex_lock(&ttyname_lock);
+ if (ttyname_init == 0) {
+ if (pthread_key_create(&ttyname_key, free)) {
+ pthread_mutex_unlock(&ttyname_lock);
+ return (NULL);
+ }
+ ttyname_init = 1;
+ }
+ pthread_mutex_unlock(&ttyname_lock);
+
+ /* Must have thread specific data field to put data */
+ if ((buf = pthread_getspecific(ttyname_key)) != 0) {
+ return (NULL);
+ } else if (buf == NULL) {
+ if ((buf = malloc(sizeof(_PATH_DEV) + MAXNAMLEN)) != NULL) {
+ if (pthread_setspecific(ttyname_key, buf) != 0) {
+ free(buf);
+ return (NULL);
+ }
+ } else {
+ return (NULL);
+ }
+ }
+ return (__ttyname_r_basic(fd, buf, sizeof(_PATH_DEV) + MAXNAMLEN));
+}
+
+char *
+ttyname_r(int fd, char *buf, size_t len)
+{
+ char *ret;
+
+ if (_thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__) == 0) {
+ ret = __ttyname_r_basic(fd, buf, len);
+ _thread_fd_unlock(fd, FD_READ);
+ } else {
+ ret = NULL;
+ }
+ return (ret);
+}
+#else
static char buf[sizeof(_PATH_DEV) + MAXNAMLEN] = _PATH_DEV;
static char *oldttyname __P((int, struct stat *));
@@ -52,7 +163,7 @@ ttyname(fd)
int fd;
{
struct stat sb;
- struct sgttyb ttyb;
+ struct termios ttyb;
DB *db;
DBT data, key;
struct {
@@ -61,13 +172,13 @@ ttyname(fd)
} bkey;
/* Must be a terminal. */
- if (ioctl(fd, TIOCGETP, &ttyb) < 0)
+ if (tcgetattr(fd, &ttyb) < 0)
return (NULL);
/* Must be a character device. */
if (fstat(fd, &sb) || !S_ISCHR(sb.st_mode))
return (NULL);
- if (db = dbopen(_PATH_DEVDB, O_RDONLY, 0, DB_HASH, NULL)) {
+ if ( (db = dbopen(_PATH_DEVDB, O_RDONLY, 0, DB_HASH, NULL)) ) {
memset(&bkey, 0, sizeof(bkey));
bkey.type = S_IFCHR;
bkey.dev = sb.st_rdev;
@@ -96,7 +207,7 @@ oldttyname(fd, sb)
if ((dp = opendir(_PATH_DEV)) == NULL)
return (NULL);
- while (dirp = readdir(dp)) {
+ while ( (dirp = readdir(dp)) ) {
if (dirp->d_fileno != sb->st_ino)
continue;
bcopy(dirp->d_name, buf + sizeof(_PATH_DEV) - 1,
@@ -110,3 +221,4 @@ oldttyname(fd, sb)
(void)closedir(dp);
return (NULL);
}
+#endif
diff --git a/lib/libc/gen/ttyslot.c b/lib/libc/gen/ttyslot.c
index 3d9fee6..2f72ebb 100644
--- a/lib/libc/gen/ttyslot.c
+++ b/lib/libc/gen/ttyslot.c
@@ -50,13 +50,13 @@ ttyslot()
char *name;
setttyent();
- for (cnt = 0; cnt < 3; ++cnt)
- if (name = ttyname(cnt)) {
- if (p = rindex(name, '/'))
+ for (cnt = 0; cnt < 3; ++cnt)
+ if ( (name = ttyname(cnt)) ) {
+ if ( (p = rindex(name, '/')) )
++p;
else
p = name;
- for (slot = 1; ttyp = getttyent(); ++slot)
+ for (slot = 1; (ttyp = getttyent()); ++slot)
if (!strcmp(ttyp->ty_name, p)) {
endttyent();
return(slot);
diff --git a/lib/libc/gen/tzset.3 b/lib/libc/gen/tzset.3
index d9606c5..3c5b276 100644
--- a/lib/libc/gen/tzset.3
+++ b/lib/libc/gen/tzset.3
@@ -318,7 +318,8 @@ leap seconds are loaded from
.Xr tzfile 5
.Sh HISTORY
The
-.Nm tzset
+.Fn tzset
and
-.Nm tzsetwall
-functions first appeared in 4.4BSD.
+.Fn tzsetwall
+functions first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/ualarm.3 b/lib/libc/gen/ualarm.3
index 666029a..958dda5 100644
--- a/lib/libc/gen/ualarm.3
+++ b/lib/libc/gen/ualarm.3
@@ -29,7 +29,8 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)ualarm.3 8.2 (Berkeley) 4/19/94
+.\" From: @(#)ualarm.3 8.2 (Berkeley) 4/19/94
+.\" $Id$
.\"
.Dd April 19, 1994
.Dt UALARM 3
@@ -68,7 +69,7 @@ microseconds after the timer expires (e.g. after
microseconds have passed).
.Sh RETURN VALUES
When the signal has successfully been caught,
-.Fn alarm
+.Fn ualarm
returns the amount of time left on the clock.
The maximum number of
.Ar microseconds
@@ -79,9 +80,9 @@ is 2147483647.
.Xr setitimer 2 ,
.Xr sigpause 2 ,
.Xr sigvec 2 ,
+.Xr alarm 3 ,
.Xr signal 3 ,
.Xr sleep 3 ,
-.Xr alarm 3 ,
.Xr usleep 3
.Sh HISTORY
The
diff --git a/lib/libc/gen/ualarm.c b/lib/libc/gen/ualarm.c
index e9e051d..ec49a2d 100644
--- a/lib/libc/gen/ualarm.c
+++ b/lib/libc/gen/ualarm.c
@@ -54,7 +54,7 @@ ualarm(usecs, reload)
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;
diff --git a/lib/libc/gen/uname.3 b/lib/libc/gen/uname.3
index a72e21f..8155289 100644
--- a/lib/libc/gen/uname.3
+++ b/lib/libc/gen/uname.3
@@ -31,7 +31,7 @@
.\"
.\" @(#)uname.3 8.1 (Berkeley) 1/4/94
.\"
-.Dd "January 4, 1994"
+.Dd January 4, 1994
.Dt UNAME 3
.Os
.Sh NAME
@@ -67,7 +67,7 @@ Machine hardware platform.
.El
.Sh RETURN VALUES
If
-.Nm uname
+.Fn uname
is successful, 0 is returned, otherwise, -1 is returned and
.Va errno
is set appropriately.
@@ -88,5 +88,6 @@ function conforms to
.St -p1003.1-88 .
.Sh HISTORY
The
-.Nm uname
-function first appeared in 4.4BSD.
+.Fn uname
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/uname.c b/lib/libc/gen/uname.c
index 9857b29..25431d4 100644
--- a/lib/libc/gen/uname.c
+++ b/lib/libc/gen/uname.c
@@ -32,12 +32,15 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)uname.c 8.1 (Berkeley) 1/4/94";
+/*static char sccsid[] = "From: @(#)uname.c 8.1 (Berkeley) 1/4/94";*/
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/utsname.h>
+#include <errno.h>
int
uname(name)
@@ -46,45 +49,77 @@ uname(name)
int mib[2], rval;
size_t len;
char *p;
+ int oerrno;
rval = 0;
mib[0] = CTL_KERN;
mib[1] = KERN_OSTYPE;
len = sizeof(name->sysname);
- if (sysctl(mib, 2, &name->sysname, &len, NULL, 0) == -1)
- rval = -1;
+ oerrno = errno;
+ if (sysctl(mib, 2, &name->sysname, &len, NULL, 0) == -1) {
+ if(errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ name->sysname[sizeof(name->sysname) - 1] = '\0';
mib[0] = CTL_KERN;
mib[1] = KERN_HOSTNAME;
len = sizeof(name->nodename);
- if (sysctl(mib, 2, &name->nodename, &len, NULL, 0) == -1)
- rval = -1;
+ oerrno = errno;
+ if (sysctl(mib, 2, &name->nodename, &len, NULL, 0) == -1) {
+ if(errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ name->nodename[sizeof(name->nodename) - 1] = '\0';
mib[0] = CTL_KERN;
mib[1] = KERN_OSRELEASE;
len = sizeof(name->release);
- if (sysctl(mib, 2, &name->release, &len, NULL, 0) == -1)
- rval = -1;
+ oerrno = errno;
+ if (sysctl(mib, 2, &name->release, &len, NULL, 0) == -1) {
+ if(errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ name->release[sizeof(name->release) - 1] = '\0';
/* The version may have newlines in it, turn them into spaces. */
mib[0] = CTL_KERN;
mib[1] = KERN_VERSION;
len = sizeof(name->version);
- if (sysctl(mib, 2, &name->version, &len, NULL, 0) == -1)
- rval = -1;
- else
- for (p = name->version; len--; ++p)
- if (*p == '\n' || *p == '\t')
- if (len > 1)
- *p = ' ';
- else
- *p = '\0';
+ oerrno = errno;
+ if (sysctl(mib, 2, &name->version, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ name->version[sizeof(name->version) - 1] = '\0';
+ for (p = name->version; len--; ++p) {
+ if (*p == '\n' || *p == '\t') {
+ if (len > 1)
+ *p = ' ';
+ else
+ *p = '\0';
+ }
+ }
mib[0] = CTL_HW;
mib[1] = HW_MACHINE;
len = sizeof(name->machine);
- if (sysctl(mib, 2, &name->machine, &len, NULL, 0) == -1)
- rval = -1;
+ oerrno = errno;
+ if (sysctl(mib, 2, &name->machine, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ name->machine[sizeof(name->machine) - 1] = '\0';
return (rval);
}
diff --git a/lib/libc/gen/unvis.3 b/lib/libc/gen/unvis.3
index 807a851..833e13c 100644
--- a/lib/libc/gen/unvis.3
+++ b/lib/libc/gen/unvis.3
@@ -41,9 +41,9 @@
.Sh SYNOPSIS
.Fd #include <vis.h>
.Ft int
-.Fn unvis "u_char *cp" "u_char c" "int *astate" "int flag"
+.Fn unvis "char *cp" "int c" "int *astate" "int flag"
.Ft int
-.Fn strunvis "char *dst" "char *src"
+.Fn strunvis "char *dst" "const char *src"
.Sh DESCRIPTION
The
.Fn unvis
@@ -100,7 +100,7 @@ to zero. Call
with each successive byte, along with a pointer
to this integer, and a pointer to a destination character.
The
-.Xr unvis
+.Fn unvis
function
has several return codes that must be handled properly. They are:
.Bl -tag -width UNVIS_VALIDPUSH
@@ -159,4 +159,5 @@ if (unvis(&out, (char)0, &state, UNVIS_END) == UNVIS_VALID)
The
.Nm unvis
function
-first appeared in 4.4BSD.
+first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/unvis.c b/lib/libc/gen/unvis.c
index 6126d6a..32405df 100644
--- a/lib/libc/gen/unvis.c
+++ b/lib/libc/gen/unvis.c
@@ -36,7 +36,6 @@ static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
-#include <ctype.h>
#include <vis.h>
/*
@@ -65,7 +64,7 @@ unvis(cp, c, astate, flag)
if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
*astate = S_GROUND;
return (UNVIS_VALID);
- }
+ }
return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
}
@@ -76,7 +75,7 @@ unvis(cp, c, astate, flag)
if (c == '\\') {
*astate = S_START;
return (0);
- }
+ }
*cp = c;
return (UNVIS_VALID);
@@ -149,7 +148,7 @@ unvis(cp, c, astate, flag)
}
*astate = S_GROUND;
return (UNVIS_SYNBAD);
-
+
case S_META:
if (c == '-')
*astate = S_META1;
@@ -160,12 +159,12 @@ unvis(cp, c, astate, flag)
return (UNVIS_SYNBAD);
}
return (0);
-
+
case S_META1:
*astate = S_GROUND;
*cp |= c;
return (UNVIS_VALID);
-
+
case S_CTRL:
if (c == '?')
*cp |= 0177;
@@ -176,15 +175,15 @@ unvis(cp, c, astate, flag)
case S_OCTAL2: /* second possible octal digit */
if (isoctal(c)) {
- /*
- * yes - and maybe a third
+ /*
+ * yes - and maybe a third
*/
*cp = (*cp << 3) + (c - '0');
- *astate = S_OCTAL3;
+ *astate = S_OCTAL3;
return (0);
- }
- /*
- * no - done with current sequence, push back passed char
+ }
+ /*
+ * no - done with current sequence, push back passed char
*/
*astate = S_GROUND;
return (UNVIS_VALIDPUSH);
@@ -199,10 +198,10 @@ unvis(cp, c, astate, flag)
* we were done, push back passed char
*/
return (UNVIS_VALIDPUSH);
-
- default:
- /*
- * decoder in unknown state - (probably uninitialized)
+
+ default:
+ /*
+ * decoder in unknown state - (probably uninitialized)
*/
*astate = S_GROUND;
return (UNVIS_SYNBAD);
@@ -210,7 +209,7 @@ unvis(cp, c, astate, flag)
}
/*
- * strunvis - decode src into dst
+ * strunvis - decode src into dst
*
* Number of chars decoded into dst is returned, -1 on error.
* Dst is null terminated.
@@ -225,7 +224,7 @@ strunvis(dst, src)
char *start = dst;
int state = 0;
- while (c = *src++) {
+ while ( (c = *src++) ) {
again:
switch (unvis(dst, c, &state, 0)) {
case UNVIS_VALID:
diff --git a/lib/libc/gen/usleep.3 b/lib/libc/gen/usleep.3
index 630e386..66b317a 100644
--- a/lib/libc/gen/usleep.3
+++ b/lib/libc/gen/usleep.3
@@ -72,12 +72,12 @@ such a function would not restart after signals, but would not interfere
with other uses of
.Xr setitimer .
.Sh SEE ALSO
-.Xr setitimer 2 ,
.Xr getitimer 2 ,
+.Xr setitimer 2 ,
.Xr sigpause 2 ,
-.Xr ualarm 3 ,
+.Xr alarm 3 ,
.Xr sleep 3 ,
-.Xr alarm 3
+.Xr ualarm 3
.Sh HISTORY
The
.Fn usleep
diff --git a/lib/libc/gen/usleep.c b/lib/libc/gen/usleep.c
index 9127bfc..4bcb7e9 100644
--- a/lib/libc/gen/usleep.c
+++ b/lib/libc/gen/usleep.c
@@ -36,64 +36,88 @@ static char sccsid[] = "@(#)usleep.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/time.h>
-#include <sys/signal.h>
+#include <signal.h>
#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
-#define TICK 10000 /* system clock resolution in microseconds */
-#define USPS 1000000 /* number of microseconds in a second */
-
-#define setvec(vec, a) \
- vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
+#ifndef _THREAD_SAFE
+static void
+sleephandler()
+{
+ return;
+}
+#endif /* _THREAD_SAFE */
-static int ringring;
void
usleep(useconds)
unsigned int useconds;
{
- register struct itimerval *itp;
- struct itimerval itv, oitv;
- struct sigvec vec, ovec;
- long omask;
- static void sleephandler();
+#ifdef _THREAD_SAFE
+ struct timespec time_to_sleep;
+ struct timespec time_remaining;
- itp = &itv;
- if (!useconds)
- return;
- timerclear(&itp->it_interval);
- timerclear(&itp->it_value);
- if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
- return;
- itp->it_value.tv_sec = useconds / USPS;
- itp->it_value.tv_usec = useconds % USPS;
- if (timerisset(&oitv.it_value)) {
- if (timercmp(&oitv.it_value, &itp->it_value, >)) {
- oitv.it_value.tv_sec -= itp->it_value.tv_sec;
- oitv.it_value.tv_usec -= itp->it_value.tv_usec;
- if (oitv.it_value.tv_usec < 0) {
- oitv.it_value.tv_usec += USPS;
- oitv.it_value.tv_sec--;
- }
- } else {
- itp->it_value = oitv.it_value;
- oitv.it_value.tv_sec = 0;
- oitv.it_value.tv_usec = 2 * TICK;
- }
+ if (useconds) {
+ time_to_sleep.tv_nsec = (useconds % 1000000) * 1000;
+ time_to_sleep.tv_sec = useconds / 1000000;
+ do {
+ nanosleep(&time_to_sleep, &time_remaining);
+ time_to_sleep = time_remaining;
+ } while (time_to_sleep.tv_sec != 0 &&
+ time_to_sleep.tv_nsec != 0);
}
- setvec(vec, sleephandler);
- (void) sigvec(SIGALRM, &vec, &ovec);
- omask = sigblock(sigmask(SIGALRM));
- ringring = 0;
- (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
- while (!ringring)
- sigpause(omask &~ sigmask(SIGALRM));
- (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
- (void) sigsetmask(omask);
- (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
-}
+#else
+ struct timespec time_to_sleep;
+ struct timespec time_remaining;
+ struct sigaction act, oact;
+ sigset_t mask, omask;
+ int alarm_blocked;
-static void
-sleephandler()
-{
- ringring = 1;
+ if (useconds != 0) {
+ time_to_sleep.tv_nsec = (useconds % 1000000) * 1000;
+ time_to_sleep.tv_sec = useconds / 1000000;
+
+ /* Block SIGALRM while fiddling with it */
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGALRM);
+ sigprocmask(SIG_BLOCK, &mask, &omask);
+
+ /* Was SIGALRM blocked already? */
+ alarm_blocked = sigismember(&omask, SIGALRM);
+
+ if (!alarm_blocked) {
+ /*
+ * Set up handler to interrupt signanosleep only if
+ * SIGALRM was unblocked. (Save some syscalls)
+ */
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = sleephandler;
+ sigaction(SIGALRM, &act, &oact);
+ }
+
+ /*
+ * signanosleep() uses the given mask for the lifetime of
+ * the syscall only - it resets on return. Note that the
+ * Old sleep explicitly unblocks SIGALRM during the sleep,
+ * we don't do that now since we don't depend on SIGALRM
+ * to end the timout. If the process blocks SIGALRM, it
+ * gets what it asks for.
+ */
+
+ do {
+ signanosleep(&time_to_sleep, &time_remaining, &mask);
+ time_to_sleep = time_remaining;
+ } while (time_to_sleep.tv_sec != 0 &&
+ time_to_sleep.tv_nsec != 0);
+
+ if (!alarm_blocked) {
+ /* Unwind */
+ sigaction(SIGALRM, &oact, (struct sigaction *)0);
+ sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
+ }
+ }
+#endif /* _THREAD_SAFE */
}
diff --git a/lib/libc/gen/utime.3 b/lib/libc/gen/utime.3
index 3397bb7..785a945 100644
--- a/lib/libc/gen/utime.3
+++ b/lib/libc/gen/utime.3
@@ -73,8 +73,8 @@ function may fail and set
for any of the errors specified for the library function
.Xr utimes 2 .
.Sh SEE ALSO
-.Xr utimes 2 ,
-.Xr stat 2
+.Xr stat 2 ,
+.Xr utimes 2
.Sh HISTORY
A
.Fn utime
@@ -82,6 +82,6 @@ function appeared in
.At v7 .
.Sh STANDARDS
The
-.Nm utime
+.Fn utime
function conforms to
.St -p1003.1-88 .
diff --git a/lib/libc/gen/valloc.3 b/lib/libc/gen/valloc.3
index c428552..ee32438 100644
--- a/lib/libc/gen/valloc.3
+++ b/lib/libc/gen/valloc.3
@@ -39,8 +39,8 @@
.Nd aligned memory allocation function
.Sh SYNOPSIS
.Fd #include <unistd.h>
-.Ft char *
-.Fn valloc "unsigned size"
+.Ft void *
+.Fn valloc "size_t size"
.Sh DESCRIPTION
.Bf -symbolic
Valloc is obsoleted by the current version of malloc(3),
diff --git a/lib/libc/gen/vis.3 b/lib/libc/gen/vis.3
index ee77b72..f749573 100644
--- a/lib/libc/gen/vis.3
+++ b/lib/libc/gen/vis.3
@@ -29,9 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)vis.3 8.1 (Berkeley) 6/9/93
+.\" From: @(#)vis.3 8.1 (Berkeley) 6/9/93
+.\" $Id: vis.3,v 1.6 1997/02/22 14:58:21 peter Exp $
.\"
-.Dd June 9, 1993
+.Dd July 25, 1996
.Dt VIS 3
.Os
.Sh NAME
@@ -40,11 +41,11 @@
.Sh SYNOPSIS
.Fd #include <vis.h>
.Ft char *
-.Fn vis "char *dst" "char c" "int flag" "char nextc"
+.Fn vis "char *dst" "int c" "int flag" "int nextc"
.Ft int
-.Fn strvis "char *dst" "char *src" "int flag"
+.Fn strvis "char *dst" "const char *src" "int flag"
.Ft int
-.Fn strvisx "char *dst" "char *src" "int len" "int flag"
+.Fn strvisx "char *dst" "const char *src" "size_t len" "int flag"
.Sh DESCRIPTION
The
.Fn vis
@@ -59,11 +60,11 @@ 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 NULL ) ;
+.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 NULL .
+.Dv NUL .
The flag parameter is used for altering the default range of
characters considered for encoding and for altering the visual
representation.
@@ -88,7 +89,7 @@ function encodes characters from
.Fa src
up to the
first
-.Dv NULL .
+.Dv NUL .
The
.Fn strvisx
function encodes exactly
@@ -97,9 +98,9 @@ characters from
.Fa src
(this
is useful for encoding a block of data that may contain
-.Dv NULL Ns 's).
+.Dv NUL Ns 's).
Both forms
-.Dv NULL
+.Dv NUL
terminate
.Fa dst .
The size of
@@ -108,13 +109,13 @@ must be four times the number
of characters encoded from
.Fa src
(plus one for the
-.Dv NULL ) .
+.Dv NUL ) .
Both
forms return the number of characters in dst (not including
the trailing
-.Dv NULL ) .
+.Dv NUL ) .
.Pp
-The encoding is a unique, invertible representation comprised entirely of
+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
@@ -226,7 +227,7 @@ The following sequences are used to represent the indicated characters:
.Pp
When using this format, the nextc parameter is looked at to determine
if a
-.Dv NULL
+.Dv NUL
character can be encoded as
.Ql \e0
instead of
@@ -256,8 +257,9 @@ With this flag set, the encoding is
ambiguous and non-invertible.
.Sh SEE ALSO
.Xr unvis 1 ,
+.Xr strunvis 3 ,
.Xr unvis 3
-.Xr strunvis 3
.Sh HISTORY
-These functions first appeared in 4.4BSD.
+These functions first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/vis.c b/lib/libc/gen/vis.c
index 2232149..61aa836 100644
--- a/lib/libc/gen/vis.c
+++ b/lib/libc/gen/vis.c
@@ -51,7 +51,8 @@ vis(dst, c, flag, nextc)
int c, nextc;
register int flag;
{
- if ((u_int)c <= UCHAR_MAX && isgraph(c) ||
+ c = (unsigned char)c;
+ if (isgraph(c) ||
((flag & VIS_SP) == 0 && c == ' ') ||
((flag & VIS_TAB) == 0 && c == '\t') ||
((flag & VIS_NL) == 0 && c == '\n') ||
@@ -111,7 +112,7 @@ vis(dst, c, flag, nextc)
goto done;
}
}
- if (((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
+ if (((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
*dst++ = '\\';
*dst++ = ((u_char)c >> 6 & 07) + '0';
*dst++ = ((u_char)c >> 3 & 07) + '0';
@@ -141,10 +142,10 @@ done:
/*
* 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 NULL,
- * is returned.
+ * is returned.
*
* Strvisx encodes exactly len bytes from src into dst.
* This is useful for encoding a block of data.
@@ -158,7 +159,7 @@ strvis(dst, src, flag)
register char c;
char *start;
- for (start = dst; c = *src;)
+ for (start = dst; (c = *src); )
dst = vis(dst, c, flag, *++src);
*dst = '\0';
return (dst - start);
diff --git a/lib/libc/gmon/Makefile.inc b/lib/libc/gmon/Makefile.inc
index 959c3fb..a264d09 100644
--- a/lib/libc/gmon/Makefile.inc
+++ b/lib/libc/gmon/Makefile.inc
@@ -1,10 +1,16 @@
-# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
# gmon sources
-.PATH: ${.CURDIR}/gmon
+.PATH: ${.CURDIR}/../libc/gmon
SRCS+= gmon.c mcount.c
-MAN3+= moncontrol.0
+
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN3+= gmon/moncontrol.3
+MLINKS+= moncontrol.3 monstartup.3
+.endif
# mcount cannot be compiled with profiling
mcount.po: mcount.o
diff --git a/lib/libc/gmon/gmon.c b/lib/libc/gmon/gmon.c
index 022ffb5..81e36dd 100644
--- a/lib/libc/gmon/gmon.c
+++ b/lib/libc/gmon/gmon.c
@@ -44,7 +44,11 @@ static char sccsid[] = "@(#)gmon.c 8.1 (Berkeley) 6/4/93";
#include <fcntl.h>
#include <unistd.h>
+#if defined(__ELF__)
+extern char *minbrk asm (".minbrk");
+#else
extern char *minbrk asm ("minbrk");
+#endif
struct gmonparam _gmonparam = { GMON_PROF_OFF };
@@ -106,7 +110,7 @@ monstartup(lowpc, highpc)
s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1;
#else /* avoid floating point */
int quot = o / p->kcountsize;
-
+
if (quot >= 0x10000)
s_scale = 1;
else if (quot >= 0x100)
@@ -239,7 +243,7 @@ static int
hertz()
{
struct itimerval tim;
-
+
tim.it_interval.tv_sec = 0;
tim.it_interval.tv_usec = 1;
tim.it_value.tv_sec = 0;
diff --git a/lib/libc/gmon/mcount.c b/lib/libc/gmon/mcount.c
index 523217d..a48e558 100644
--- a/lib/libc/gmon/mcount.c
+++ b/lib/libc/gmon/mcount.c
@@ -32,11 +32,25 @@
*/
#if !defined(lint) && !defined(KERNEL) && defined(LIBC_SCCS)
+#if 0
static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
#endif
+static const char rcsid[] =
+ "$Id$";
+#endif
#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 __P((void));
+void btrap __P((void));
+void eintr __P((void));
+void user __P((void));
+#endif
/*
* mcount is called on entry to each function compiled with the profiling
@@ -48,44 +62,132 @@ static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
* _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_DECL(frompc, selfpc) /* _mcount; may be static, inline, etc */
- register u_long frompc, selfpc;
+ register fptrint_t frompc, selfpc;
{
+#ifdef GUPROF
+ u_int delta;
+#endif
+ register fptrdiff_t frompci;
register u_short *frompcindex;
register struct tostruct *top, *prevtop;
register struct gmonparam *p;
register long toindex;
#ifdef KERNEL
- register int s;
+ 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;
+ MCOUNT_ENTER(s);
#else
p->state = GMON_PROF_BUSY;
#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
+ >= (fptrint_t)(VM_MAXUSER_ADDRESS + UPAGES * PAGE_SIZE))
+ goto done;
+ frompci = (fptrint_t)user - p->lowpc;
+ if (frompci >= p->textsize)
+ goto done;
+ }
+#endif /* KERNEL */
+
+#ifdef GUPROF
+ if (p->state != GMON_PROF_HIRES)
+ goto skip_guprof_stuff;
/*
- * check that frompcindex is a reasonable pc value.
+ * 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 ((fptrint_t)selfpc >= (fptrint_t)btrap
+ && (fptrint_t)selfpc < (fptrint_t)eintr) {
+ if ((fptrint_t)selfpc >= (fptrint_t)bintr)
+ frompci = (fptrint_t)bintr - p->lowpc;
+ else
+ frompci = (fptrint_t)btrap - p->lowpc;
+ }
+#endif /* KERNEL */
+
+ /*
+ * check that frompc is a reasonable pc value.
* for example: signal catchers get called from the stack,
* not from text space. too bad.
*/
- frompc -= p->lowpc;
- if (frompc > p->textsize)
+ if (frompci >= p->textsize)
goto done;
- frompcindex = &p->froms[frompc / (p->hashfraction * sizeof(*p->froms))];
+ frompcindex = &p->froms[frompci / (p->hashfraction * sizeof(*p->froms))];
toindex = *frompcindex;
if (toindex == 0) {
/*
@@ -154,11 +256,11 @@ _MCOUNT_DECL(frompc, selfpc) /* _mcount; may be static, inline, etc */
*frompcindex = toindex;
goto done;
}
-
+
}
done:
#ifdef KERNEL
- MCOUNT_EXIT;
+ MCOUNT_EXIT(s);
#else
p->state = GMON_PROF_ON;
#endif
@@ -166,7 +268,7 @@ done:
overflow:
p->state = GMON_PROF_ERROR;
#ifdef KERNEL
- MCOUNT_EXIT;
+ MCOUNT_EXIT(s);
#endif
return;
}
@@ -176,3 +278,48 @@ overflow:
* which is included by <sys/gmon.h>.
*/
MCOUNT
+
+#ifdef GUPROF
+void
+mexitcount(selfpc)
+ fptrint_t selfpc;
+{
+ struct gmonparam *p;
+ fptrint_t selfpcdiff;
+
+ p = &_gmonparam;
+ selfpcdiff = selfpc - (fptrint_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
index 9b01f2b..92993cd 100644
--- a/lib/libc/gmon/moncontrol.3
+++ b/lib/libc/gmon/moncontrol.3
@@ -39,7 +39,10 @@
.Nm monstartup
.Nd control execution profile
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Ft int
.Fn moncontrol "int mode"
+.Ft int
.Fn monstartup "u_long *lowpc" "u_long *highpc"
.Sh DESCRIPTION
An executable program compiled using the
@@ -98,4 +101,5 @@ Profiling begins on return from
.Sh SEE ALSO
.Xr cc 1 ,
.Xr gprof 1 ,
-.Xr profil 2
+.Xr profil 2 ,
+.Xr clocks 7
diff --git a/lib/libc/i386/DEFS.h b/lib/libc/i386/DEFS.h
index 10d9f9b..fbc11bc 100644
--- a/lib/libc/i386/DEFS.h
+++ b/lib/libc/i386/DEFS.h
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -33,15 +33,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)DEFS.h 8.1 (Berkeley) 6/4/93
+ * from: @(#)DEFS.h 5.1 (Berkeley) 4/23/90
+ *
+ * $Id: DEFS.h,v 1.6 1997/02/22 14:58:29 peter Exp $
*/
-#ifdef PROF
-#define ENTRY(x) .globl _/**/x; _/**/x: \
- .data; 1:; .long 0; .text; lea 1b,%eax ; call mcount
-#define ASENTRY(x) .globl x; x: \
- .data; 1:; .long 0; .text; lea 1b,%eax ; call mcount
-#else
-#define ENTRY(x) .globl _/**/x; _/**/x:
-#define ASENTRY(x) .globl x; x:
-#endif
+#include <machine/asm.h>
diff --git a/lib/libc/i386/SYS.h b/lib/libc/i386/SYS.h
index dfb679f..593b2ed 100644
--- a/lib/libc/i386/SYS.h
+++ b/lib/libc/i386/SYS.h
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -33,25 +33,54 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)SYS.h 8.1 (Berkeley) 6/4/93
+ * from: @(#)SYS.h 5.5 (Berkeley) 5/7/91
+ *
+ * $Id: SYS.h,v 1.10 1997/02/22 14:58:30 peter Exp $
*/
#include <sys/syscall.h>
+#include "DEFS.h"
-#ifdef PROF
-#define ENTRY(x) .globl _/**/x; \
- .data; 1:; .long 0; .text; .align 2; _/**/x: \
- movl $1b,%eax; call mcount
-#else
-#define ENTRY(x) .globl _/**/x; .text; .align 2; _/**/x:
-#endif PROF
-#define SYSCALL(x) 2: jmp cerror; ENTRY(x); lea SYS_/**/x,%eax; LCALL(7,0); jb 2b
+#define SYSCALL(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \
+ ENTRY(x); lea __CONCAT(SYS_,x),%eax; KERNCALL; jb 2b
#define RSYSCALL(x) SYSCALL(x); ret
-#define PSEUDO(x,y) ENTRY(x); lea SYS_/**/y, %eax; ; LCALL(7,0); ret
-#define CALL(x,y) call _/**/y; addl $4*x,%esp
-/* gas fucks up offset -- although we don't currently need it, do for BCS */
+
+#define PSEUDO(x,y) ENTRY(x); lea __CONCAT(SYS_,y), %eax; KERNCALL; ret
+/* 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 ASMSTR .asciz
+/*
+ * Design note:
+ *
+ * The macros PSYSCALL() and PRSYSCALL() are intended for use where a
+ * syscall needs to be renamed in the threaded library. When building
+ * a normal library, they default to the traditional SYSCALL() and
+ * RSYSCALL(). This avoids the need to #ifdef _THREAD_SAFE everywhere
+ * that the renamed function needs to be called.
+ */
+#ifdef _THREAD_SAFE
+/*
+ * For the thread_safe versions, we prepend _thread_sys_ to the function
+ * name so that the 'C' wrapper can go around the real name.
+ */
+#define PSYSCALL(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \
+ ENTRY(__CONCAT(_thread_sys_,x)); \
+ lea __CONCAT(SYS_,x),%eax; KERNCALL; jb 2b
+#define PRSYSCALL(x) PSYSCALL(x); ret
+#define PPSEUDO(x,y) ENTRY(__CONCAT(_thread_sys_,x)); \
+ lea __CONCAT(SYS_,y), %eax; KERNCALL; ret
+#else
+/*
+ * The non-threaded library defaults to traditional syscalls where
+ * the function name matches the syscall name.
+ */
+#define PSYSCALL(x) SYSCALL(x)
+#define PRSYSCALL(x) RSYSCALL(x)
+#define PPSEUDO(x,y) PSEUDO(x,y)
+#endif
- .globl cerror
+#ifdef __ELF__
+#define KERNCALL int $0x80 /* Faster */
+#else
+#define KERNCALL LCALL(7,0) /* The old way */
+#endif
diff --git a/lib/libc/i386/gen/Makefile.inc b/lib/libc/i386/gen/Makefile.inc
index 814013d..457d5c3 100644
--- a/lib/libc/i386/gen/Makefile.inc
+++ b/lib/libc/i386/gen/Makefile.inc
@@ -1,5 +1,5 @@
# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
-SRCS+= isinf.c
-SRCS+= _setjmp.s alloca.s fabs.s ldexp.c modf.s setjmp.s
-SRCS+= divsi3.s fixdfsi.s fixunsdfsi.s udivsi3.s
+SRCS+= isinf.c infinity.c
+SRCS+= _setjmp.S alloca.S fabs.S ldexp.c modf.S setjmp.S sigsetjmp.S
diff --git a/lib/libc/i386/gen/_setjmp.S b/lib/libc/i386/gen/_setjmp.S
index 47e319a..62259ce 100644
--- a/lib/libc/i386/gen/_setjmp.S
+++ b/lib/libc/i386/gen/_setjmp.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,11 +32,14 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
- .asciz "@(#)_setjmp.s 8.1 (Berkeley) 6/4/93"
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
/*
* C library -- _setjmp, _longjmp
@@ -44,13 +47,17 @@
* _longjmp(a,v)
* will generate a "return(v)" from the last call to
* _setjmp(a)
- * by restoring registers from the stack.
+ * by restoring registers from the environment 'a'.
* The previous signal state is NOT restored.
*/
#include "DEFS.h"
+#ifdef _THREAD_SAFE
+ENTRY(__thread_sys_setjmp)
+#else
ENTRY(_setjmp)
+#endif
movl 4(%esp),%eax
movl 0(%esp),%edx
movl %edx, 0(%eax) /* rta */
@@ -59,10 +66,15 @@ ENTRY(_setjmp)
movl %ebp,12(%eax)
movl %esi,16(%eax)
movl %edi,20(%eax)
- movl $0,%eax
+ fnstcw 28(%eax)
+ xorl %eax,%eax
ret
+#ifdef _THREAD_SAFE
+ENTRY(__thread_sys_longjmp)
+#else
ENTRY(_longjmp)
+#endif
movl 4(%esp),%edx
movl 8(%esp),%eax
movl 0(%edx),%ecx
@@ -71,8 +83,10 @@ ENTRY(_longjmp)
movl 12(%edx),%ebp
movl 16(%edx),%esi
movl 20(%edx),%edi
- cmpl $0,%eax
- jne 1f
- movl $1,%eax
+ fninit
+ fldcw 28(%edx)
+ testl %eax,%eax
+ jnz 1f
+ incl %eax
1: movl %ecx,0(%esp)
ret
diff --git a/lib/libc/i386/gen/alloca.S b/lib/libc/i386/gen/alloca.S
index a2d6a41..f76b37b 100644
--- a/lib/libc/i386/gen/alloca.S
+++ b/lib/libc/i386/gen/alloca.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,11 +32,14 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
- .asciz "@(#)alloca.s 8.1 (Berkeley) 6/4/93"
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
/* like alloc, but automatic automatic free in return */
diff --git a/lib/libc/i386/gen/fabs.S b/lib/libc/i386/gen/fabs.S
index 40e72c8..5ae5370 100644
--- a/lib/libc/i386/gen/fabs.S
+++ b/lib/libc/i386/gen/fabs.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,11 +32,14 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
- .asciz "@(#)fabs.s 8.1 (Berkeley) 6/4/93"
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
#include "DEFS.h"
diff --git a/lib/libc/i386/gen/frexp.c b/lib/libc/i386/gen/frexp.c
index 6cdcd2c..aba4802 100644
--- a/lib/libc/i386/gen/frexp.c
+++ b/lib/libc/i386/gen/frexp.c
@@ -29,11 +29,13 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)frexp.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
#include <sys/types.h>
#include <math.h>
diff --git a/lib/libc/i386/gen/infinity.c b/lib/libc/i386/gen/infinity.c
new file mode 100644
index 0000000..e46f676
--- /dev/null
+++ b/lib/libc/i386/gen/infinity.c
@@ -0,0 +1,9 @@
+/*
+ * infinity.c
+ * $Id$
+ */
+
+#include <math.h>
+
+/* bytes for +Infinity on a 387 */
+char __infinity[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f };
diff --git a/lib/libc/i386/gen/isinf.c b/lib/libc/i386/gen/isinf.c
index bcbeded..a796dcf 100644
--- a/lib/libc/i386/gen/isinf.c
+++ b/lib/libc/i386/gen/isinf.c
@@ -29,14 +29,17 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)isinf.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
#include <sys/types.h>
+int
isnan(d)
double d;
{
@@ -50,6 +53,7 @@ isnan(d)
return(p->exp == 2047 && (p->manh || p->manl));
}
+int
isinf(d)
double d;
{
diff --git a/lib/libc/i386/gen/ldexp.c b/lib/libc/i386/gen/ldexp.c
index 7046c4e..8b63f52 100644
--- a/lib/libc/i386/gen/ldexp.c
+++ b/lib/libc/i386/gen/ldexp.c
@@ -32,11 +32,13 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)ldexp.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
/*
* ldexp(value, exp): return value * (2 ** exp).
@@ -55,8 +57,18 @@ ldexp (double value, int exp)
{
double temp, texp, temp2;
texp = exp;
+#ifdef __GNUC__
+#if __GNUC__ >= 2
+ asm ("fscale "
+ : "=u" (temp2), "=t" (temp)
+ : "0" (texp), "1" (value));
+#else
asm ("fscale ; fxch %%st(1) ; fstp%L1 %1 "
: "=f" (temp), "=0" (temp2)
: "0" (texp), "f" (value));
+#endif
+#else
+error unknown asm
+#endif
return (temp);
}
diff --git a/lib/libc/i386/gen/modf.S b/lib/libc/i386/gen/modf.S
index 2551237..b457097 100644
--- a/lib/libc/i386/gen/modf.S
+++ b/lib/libc/i386/gen/modf.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Sean Eric Fagan.
@@ -32,11 +32,14 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
- .asciz "@(#)modf.s 8.1 (Berkeley) 6/4/93"
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
/*
* modf(value, iptr): return fractional part of value, and stores the
@@ -47,9 +50,10 @@
*/
/* With CHOP mode on, frndint behaves as TRUNC does. Useful. */
-.text
-.globl _modf
-_modf:
+
+#include "DEFS.h"
+
+ENTRY(modf)
pushl %ebp
movl %esp,%ebp
subl $16,%esp
diff --git a/lib/libc/i386/gen/setjmp.S b/lib/libc/i386/gen/setjmp.S
index b24da11..6525a16 100644
--- a/lib/libc/i386/gen/setjmp.S
+++ b/lib/libc/i386/gen/setjmp.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,11 +32,14 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
- .asciz "@(#)setjmp.s 8.1 (Berkeley) 6/4/93"
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
/*
* C library -- _setjmp, _longjmp
@@ -44,16 +47,27 @@
* longjmp(a,v)
* will generate a "return(v)" from the last call to
* setjmp(a)
- * by restoring registers from the stack.
+ * by restoring registers from the environment 'a'.
* The previous signal state is restored.
*/
#include "DEFS.h"
+#include "SYS.h"
+#ifdef _THREAD_SAFE
+ENTRY(_thread_sys_setjmp)
+#else
ENTRY(setjmp)
+#endif
+ PIC_PROLOGUE
pushl $0
- call _sigblock
+#ifdef _THREAD_SAFE
+ call PIC_PLT(CNAME(_thread_sys_sigblock))
+#else
+ call PIC_PLT(CNAME(sigblock))
+#endif
popl %edx
+ PIC_EPILOGUE
movl 4(%esp),%ecx
movl 0(%esp),%edx
movl %edx, 0(%ecx)
@@ -63,14 +77,25 @@ ENTRY(setjmp)
movl %esi,16(%ecx)
movl %edi,20(%ecx)
movl %eax,24(%ecx)
- movl $0,%eax
+ fnstcw 28(%ecx)
+ xorl %eax,%eax
ret
+#ifdef _THREAD_SAFE
+ENTRY(_thread_sys_longjmp)
+#else
ENTRY(longjmp)
+#endif
movl 4(%esp),%edx
+ PIC_PROLOGUE
pushl 24(%edx)
- call _sigsetmask
+#ifdef _THREAD_SAFE
+ call PIC_PLT(CNAME(_thread_sys_sigsetmask))
+#else
+ call PIC_PLT(CNAME(sigsetmask)) /* XXX this is not reentrant */
+#endif
popl %eax
+ PIC_EPILOGUE
movl 4(%esp),%edx
movl 8(%esp),%eax
movl 0(%edx),%ecx
@@ -79,8 +104,10 @@ ENTRY(longjmp)
movl 12(%edx),%ebp
movl 16(%edx),%esi
movl 20(%edx),%edi
- cmpl $0,%eax
- jne 1f
- movl $1,%eax
+ fninit
+ fldcw 28(%edx)
+ testl %eax,%eax
+ jnz 1f
+ incl %eax
1: movl %ecx,0(%esp)
ret
diff --git a/lib/libc/i386/gen/sigsetjmp.S b/lib/libc/i386/gen/sigsetjmp.S
new file mode 100644
index 0000000..1220598
--- /dev/null
+++ b/lib/libc/i386/gen/sigsetjmp.S
@@ -0,0 +1,125 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+#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).
+ *
+ * Use sigprocmask() instead of sigblock() and sigsetmask(), and
+ * check for and handle errors.
+ *
+ * Restore _all_ the registers and the signal mask atomically. Can
+ * use sigreturn() if sigreturn() works.
+ */
+
+#ifdef _THREAD_SAFE
+ENTRY(_thread_sys_sigsetjmp)
+#else
+ENTRY(sigsetjmp)
+#endif
+ movl 8(%esp),%eax
+ movl 4(%esp),%ecx
+ movl %eax,32(%ecx)
+ testl %eax,%eax
+ jz 2f
+ PIC_PROLOGUE
+ pushl $0
+#ifdef _THREAD_SAFE
+ call PIC_PLT(CNAME(_thread_sys_sigblock))
+#else
+ call PIC_PLT(CNAME(sigblock))
+#endif
+ addl $4,%esp
+ PIC_EPILOGUE
+ movl 4(%esp),%ecx
+ movl %eax,24(%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 28(%ecx)
+ xorl %eax,%eax
+ ret
+
+#ifdef _THREAD_SAFE
+ENTRY(_thread_sys_siglongjmp)
+#else
+ENTRY(siglongjmp)
+#endif
+ movl 4(%esp),%edx
+ cmpl $0,32(%edx)
+ jz 2f
+ PIC_PROLOGUE
+ pushl 24(%edx)
+#ifdef _THREAD_SAFE
+ call PIC_PLT(CNAME(_thread_sys_sigsetmask))
+#else
+ call PIC_PLT(CNAME(sigsetmask))
+#endif
+ addl $4,%esp
+ PIC_EPILOGUE
+2: 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
+ fninit
+ fldcw 28(%edx)
+ testl %eax,%eax
+ jnz 1f
+ incl %eax
+1: movl %ecx,0(%esp)
+ ret
diff --git a/lib/libc/i386/net/Makefile.inc b/lib/libc/i386/net/Makefile.inc
index 81a6c91..dff7fd1 100644
--- a/lib/libc/i386/net/Makefile.inc
+++ b/lib/libc/i386/net/Makefile.inc
@@ -1,3 +1,4 @@
# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
-SRCS+= htonl.s htons.s ntohl.s ntohs.s
+SRCS+= htonl.S htons.S ntohl.S ntohs.S
diff --git a/lib/libc/i386/net/htonl.S b/lib/libc/i386/net/htonl.S
new file mode 100644
index 0000000..095c40a
--- /dev/null
+++ b/lib/libc/i386/net/htonl.S
@@ -0,0 +1,53 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+/* netorder = htonl(hostorder) */
+
+#include "DEFS.h"
+
+ENTRY(htonl)
+ movl 4(%esp),%eax
+ xchgb %al,%ah
+ roll $16,%eax
+ xchgb %al,%ah
+ ret
diff --git a/lib/libc/i386/net/htons.S b/lib/libc/i386/net/htons.S
new file mode 100644
index 0000000..238dfc2
--- /dev/null
+++ b/lib/libc/i386/net/htons.S
@@ -0,0 +1,51 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+/* netorder = htons(hostorder) */
+
+#include "DEFS.h"
+
+ENTRY(htons)
+ movzwl 4(%esp),%eax
+ xchgb %al,%ah
+ ret
diff --git a/lib/libc/i386/net/ntohl.S b/lib/libc/i386/net/ntohl.S
new file mode 100644
index 0000000..5af5008
--- /dev/null
+++ b/lib/libc/i386/net/ntohl.S
@@ -0,0 +1,53 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+/* hostorder = ntohl(netorder) */
+
+#include "DEFS.h"
+
+ENTRY(ntohl)
+ movl 4(%esp),%eax
+ xchgb %al,%ah
+ roll $16,%eax
+ xchgb %al,%ah
+ ret
diff --git a/lib/libc/i386/net/ntohs.S b/lib/libc/i386/net/ntohs.S
new file mode 100644
index 0000000..4bed4a2
--- /dev/null
+++ b/lib/libc/i386/net/ntohs.S
@@ -0,0 +1,51 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+/* hostorder = ntohs(netorder) */
+
+#include "DEFS.h"
+
+ENTRY(ntohs)
+ movzwl 4(%esp),%eax
+ xchgb %al,%ah
+ ret
diff --git a/lib/libc/i386/stdlib/Makefile.inc b/lib/libc/i386/stdlib/Makefile.inc
index 37d5037..65ce348 100644
--- a/lib/libc/i386/stdlib/Makefile.inc
+++ b/lib/libc/i386/stdlib/Makefile.inc
@@ -1,3 +1,4 @@
# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
-SRCS+= abs.s
+SRCS+= abs.S
diff --git a/lib/libc/i386/stdlib/abs.S b/lib/libc/i386/stdlib/abs.S
index 755ea56..4915d16 100644
--- a/lib/libc/i386/stdlib/abs.S
+++ b/lib/libc/i386/stdlib/abs.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,17 +32,20 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
- .asciz "@(#)abs.s 8.1 (Berkeley) 6/4/93"
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
#include "DEFS.h"
ENTRY(abs)
movl 4(%esp),%eax
- cmpl $0,%eax
- jge 1f
+ testl %eax,%eax
+ jns 1f
negl %eax
1: ret
diff --git a/lib/libc/i386/stdlib/div.S b/lib/libc/i386/stdlib/div.S
new file mode 100644
index 0000000..b2a9901
--- /dev/null
+++ b/lib/libc/i386/stdlib/div.S
@@ -0,0 +1,47 @@
+/*
+ * 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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+ENTRY(div)
+ movl 4(%esp),%eax
+ movl 8(%esp),%ecx
+ cdq
+ idiv %ecx
+ movl %eax,4(%esp)
+ movl %edx,8(%esp)
+ ret
diff --git a/lib/libc/i386/stdlib/labs.S b/lib/libc/i386/stdlib/labs.S
new file mode 100644
index 0000000..5c5afe1
--- /dev/null
+++ b/lib/libc/i386/stdlib/labs.S
@@ -0,0 +1,51 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+ENTRY(labs)
+ movl 4(%esp),%eax
+ testl %eax,%eax
+ jns 1f
+ negl %eax
+1: ret
diff --git a/lib/libc/i386/stdlib/ldiv.S b/lib/libc/i386/stdlib/ldiv.S
new file mode 100644
index 0000000..38cdf3f
--- /dev/null
+++ b/lib/libc/i386/stdlib/ldiv.S
@@ -0,0 +1,47 @@
+/*
+ * 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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+ENTRY(ldiv)
+ movl 4(%esp),%eax
+ movl 8(%esp),%ecx
+ cdq
+ idiv %ecx
+ movl %eax,4(%esp)
+ movl %edx,8(%esp)
+ ret
diff --git a/lib/libc/i386/string/Makefile.inc b/lib/libc/i386/string/Makefile.inc
index c36af74..870cc3b 100644
--- a/lib/libc/i386/string/Makefile.inc
+++ b/lib/libc/i386/string/Makefile.inc
@@ -1,5 +1,8 @@
# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id: Makefile.inc,v 1.6 1997/02/22 14:59:02 peter Exp $
-SRCS+= bcmp.c bcopy.c bzero.s ffs.c index.c memchr.c memcmp.c memset.c \
- rindex.c strcat.c strcmp.c strcpy.c strcspn.c strlen.c strncat.c \
- strncmp.c strncpy.c strpbrk.c strsep.c strspn.c strstr.c
+SRCS+= bcmp.S bcopy.S bzero.S ffs.S index.S memchr.S memcmp.S \
+ memmove.S memcpy.S memset.S \
+ rindex.S strcat.S strchr.S strcmp.S strcpy.S strcspn.c \
+ strlen.S strncat.c strncmp.S strncpy.c strpbrk.c strsep.c \
+ strspn.c strrchr.S strstr.c swab.S
diff --git a/lib/libc/i386/string/bcmp.S b/lib/libc/i386/string/bcmp.S
new file mode 100644
index 0000000..1c0c934
--- /dev/null
+++ b/lib/libc/i386/string/bcmp.S
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * 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
+ xorl %eax,%eax /* clear return value */
+ 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
+ je L2
+
+L1: incl %eax
+L2: popl %esi
+ popl %edi
+ ret
diff --git a/lib/libc/i386/string/bcopy.S b/lib/libc/i386/string/bcopy.S
new file mode 100644
index 0000000..d2a571e
--- /dev/null
+++ b/lib/libc/i386/string/bcopy.S
@@ -0,0 +1,103 @@
+/*-
+ * 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. 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.
+ */
+
+#include <machine/asm.h>
+
+ RCSID("$NetBSD: bcopy.S,v 1.6 1996/11/12 00:50:06 jtc Exp $")
+
+ /*
+ * (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
+#else
+ movl 12(%esp),%esi
+ movl 16(%esp),%edi
+#endif
+ movl 20(%esp),%ecx
+ movl %edi,%eax
+ subl %esi,%eax
+ cmpl %ecx,%eax /* overlapping? */
+ jb 1f
+ cld /* nope, copy forwards. */
+ shrl $2,%ecx /* copy by words */
+ rep
+ movsl
+ movl 20(%esp),%ecx
+ andl $3,%ecx /* any bytes left? */
+ rep
+ movsb
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ movl 12(%esp),%eax
+#endif
+ popl %edi
+ popl %esi
+ ret
+1:
+ addl %ecx,%edi /* copy backwards. */
+ addl %ecx,%esi
+ std
+ andl $3,%ecx /* any fractional bytes? */
+ decl %edi
+ decl %esi
+ rep
+ movsb
+ movl 20(%esp),%ecx /* copy remainder by words */
+ shrl $2,%ecx
+ subl $3,%esi
+ subl $3,%edi
+ rep
+ movsl
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ movl 12(%esp),%eax
+#endif
+ popl %edi
+ popl %esi
+ cld
+ ret
diff --git a/lib/libc/i386/string/bzero.S b/lib/libc/i386/string/bzero.S
index 79a5a69..8cc8f9f 100644
--- a/lib/libc/i386/string/bzero.S
+++ b/lib/libc/i386/string/bzero.S
@@ -1,9 +1,6 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
+/*
+ * 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
@@ -15,39 +12,76 @@
* 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 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 withough 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.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
- .asciz "@(#)bzero.s 8.1 (Berkeley) 6/4/93"
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
-/* bzero (base,cnt) */
+#include "DEFS.h"
- .globl _bzero
-_bzero:
+/*
+ * 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
- movl 8(%esp),%edi
- movl 12(%esp),%ecx
- movb $0x00,%al
- cld
+ 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
diff --git a/lib/libc/i386/string/ffs.S b/lib/libc/i386/string/ffs.S
new file mode 100644
index 0000000..084115b
--- /dev/null
+++ b/lib/libc/i386/string/ffs.S
@@ -0,0 +1,59 @@
+/*
+ * 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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * 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
diff --git a/lib/libc/i386/string/index.S b/lib/libc/i386/string/index.S
new file mode 100644
index 0000000..0a6c6a3
--- /dev/null
+++ b/lib/libc/i386/string/index.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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * index(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(index)
+ 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
diff --git a/lib/libc/i386/string/memchr.S b/lib/libc/i386/string/memchr.S
new file mode 100644
index 0000000..cc2dc76
--- /dev/null
+++ b/lib/libc/i386/string/memchr.S
@@ -0,0 +1,64 @@
+/*
+ * 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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * 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
diff --git a/lib/libc/i386/string/memcmp.S b/lib/libc/i386/string/memcmp.S
new file mode 100644
index 0000000..a362533
--- /dev/null
+++ b/lib/libc/i386/string/memcmp.S
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * 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
diff --git a/lib/libc/i386/string/memcpy.S b/lib/libc/i386/string/memcpy.S
new file mode 100644
index 0000000..1617c71
--- /dev/null
+++ b/lib/libc/i386/string/memcpy.S
@@ -0,0 +1,2 @@
+#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..f5a94ed
--- /dev/null
+++ b/lib/libc/i386/string/memmove.S
@@ -0,0 +1,2 @@
+#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..5db1661
--- /dev/null
+++ b/lib/libc/i386/string/memset.S
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * 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
diff --git a/lib/libc/i386/string/rindex.S b/lib/libc/i386/string/rindex.S
new file mode 100644
index 0000000..6e023d1
--- /dev/null
+++ b/lib/libc/i386/string/rindex.S
@@ -0,0 +1,70 @@
+/*
+ * 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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * rindex(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(rindex)
+ 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
diff --git a/lib/libc/i386/string/strcat.S b/lib/libc/i386/string/strcat.S
new file mode 100644
index 0000000..9ec6053
--- /dev/null
+++ b/lib/libc/i386/string/strcat.S
@@ -0,0 +1,106 @@
+/*
+ * 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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * 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
+ * cashe.
+ */
+
+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
diff --git a/lib/libc/i386/string/strchr.S b/lib/libc/i386/string/strchr.S
new file mode 100644
index 0000000..a483edd
--- /dev/null
+++ b/lib/libc/i386/string/strchr.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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * 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
diff --git a/lib/libc/i386/string/strcmp.S b/lib/libc/i386/string/strcmp.S
new file mode 100644
index 0000000..ecdb0b0
--- /dev/null
+++ b/lib/libc/i386/string/strcmp.S
@@ -0,0 +1,125 @@
+/*
+ * 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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * 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
+ * cashe.
+ */
+
+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
diff --git a/lib/libc/i386/string/strcpy.S b/lib/libc/i386/string/strcpy.S
new file mode 100644
index 0000000..d8e673a
--- /dev/null
+++ b/lib/libc/i386/string/strcpy.S
@@ -0,0 +1,95 @@
+/*
+ * 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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * 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
+ * cashe.
+ */
+
+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
diff --git a/lib/libc/i386/string/strlen.S b/lib/libc/i386/string/strlen.S
new file mode 100644
index 0000000..93190cf
--- /dev/null
+++ b/lib/libc/i386/string/strlen.S
@@ -0,0 +1,59 @@
+/*
+ * 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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * strlen (s)
+ * compute the length of the string s.
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+ENTRY(strlen)
+ pushl %edi
+ movl 8(%esp),%edi /* string 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
+ notl %ecx /* get length by taking complement */
+ leal -1(%ecx),%eax /* and subtracting one */
+ popl %edi
+ ret
diff --git a/lib/libc/i386/string/strncmp.S b/lib/libc/i386/string/strncmp.S
new file mode 100644
index 0000000..62686dc
--- /dev/null
+++ b/lib/libc/i386/string/strncmp.S
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * 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
diff --git a/lib/libc/i386/string/strrchr.S b/lib/libc/i386/string/strrchr.S
new file mode 100644
index 0000000..0cc08d7
--- /dev/null
+++ b/lib/libc/i386/string/strrchr.S
@@ -0,0 +1,70 @@
+/*
+ * 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 withough 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$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
+
+#include "DEFS.h"
+
+/*
+ * 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
diff --git a/lib/libc/i386/string/swab.S b/lib/libc/i386/string/swab.S
new file mode 100644
index 0000000..717b7a2
--- /dev/null
+++ b/lib/libc/i386/string/swab.S
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif
+
+#include "DEFS.h"
+
+/*
+ * 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 a 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
diff --git a/lib/libc/i386/sys/Makefile.inc b/lib/libc/i386/sys/Makefile.inc
new file mode 100644
index 0000000..0cf1aad
--- /dev/null
+++ b/lib/libc/i386/sys/Makefile.inc
@@ -0,0 +1,13 @@
+# from: Makefile.inc,v 1.1 1993/09/03 19:04:23 jtc Exp
+# $Id: Makefile.inc,v 1.4 1997/02/22 14:59:27 peter Exp $
+
+.PATH: ${.CURDIR}/../libc/${MACHINE}/sys
+
+SRCS+= i386_get_ldt.c i386_set_ldt.c
+
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN2+= i386/sys/i386_get_ldt.2
+
+MLINKS+=i386_get_ldt.2 i386_set_ldt.2
+.endif
diff --git a/lib/libc/i386/sys/Ovfork.S b/lib/libc/i386/sys/Ovfork.S
index c7e6b8a..e4ed257 100644
--- a/lib/libc/i386/sys/Ovfork.S
+++ b/lib/libc/i386/sys/Ovfork.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,12 +32,16 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)Ovfork.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
+#include "DEFS.h"
#include "SYS.h"
/*
@@ -47,22 +51,49 @@
* %eax == pid of child in parent, %eax == pid of parent in child.
*
*/
- .set vfork,66
-.globl _vfork
-_vfork:
+ENTRY(vfork)
popl %ecx /* my rta into ecx */
- movl $vfork, %eax
- LCALL(7,0)
+ lea SYS_vfork,%eax
+ KERNCALL
jb verror
vforkok:
cmpl $0,%edx /* child process? */
jne child /* yes */
jmp parent
-.globl _errno
+#ifdef _THREAD_SAFE
+ /*
+ * Threaded version using __error().
+ */
+ .globl CNAME(__error)
+ .type CNAME(__error),@function
+verror:
+ pushl %eax
+#ifdef PIC
+ call PIC_PLT(CNAME(__error))
+#else
+ call CNAME(__error)
+#endif
+ popl %ecx
+ movl %ecx,(%eax)
+ movl $-1,%eax
+ movl $-1,%edx
+#else /* !_THREAD_SAFE */
+ /*
+ * Non-threaded version using global errno.
+ */
+ .globl CNAME(errno)
verror:
- movl %eax,_errno
+#ifdef PIC
+ PIC_PROLOGUE
+ movl PIC_GOT(CNAME(errno)), %edx
+ movl %eax,(%edx)
+ PIC_EPILOGUE
+#else
+ movl %eax,CNAME(errno)
+#endif
movl $-1,%eax
+#endif /* !_THREAD_SAFE */
jmp %ecx
child:
movl $0,%eax
diff --git a/lib/libc/i386/sys/brk.S b/lib/libc/i386/sys/brk.S
index f85186c..4fdf0c6 100644
--- a/lib/libc/i386/sys/brk.S
+++ b/lib/libc/i386/sys/brk.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,34 +32,60 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)brk.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
-#define SYS_brk 17
-
- .globl curbrk
- .globl minbrk
+ .globl HIDENAME(curbrk)
+ .globl HIDENAME(minbrk)
ENTRY(_brk)
jmp ok
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:
+ lea 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,minbrk
- jl ok
- movl minbrk,%eax
+ cmpl %eax,HIDENAME(minbrk)
+ jbe ok
+ movl HIDENAME(minbrk),%eax
movl %eax,4(%esp)
ok:
- lea SYS_brk,%eax
- LCALL(7,0)
+ lea SYS_break,%eax
+ KERNCALL
jb err
movl 4(%esp),%eax
- movl %eax,curbrk
+ movl %eax,HIDENAME(curbrk)
movl $0,%eax
ret
err:
- jmp cerror
+ jmp HIDENAME(cerror)
+#endif
diff --git a/lib/libc/i386/sys/cerror.S b/lib/libc/i386/sys/cerror.S
index cc2d82f..2d8f935 100644
--- a/lib/libc/i386/sys/cerror.S
+++ b/lib/libc/i386/sys/cerror.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,16 +32,56 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)cerror.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
- .globl _errno
-cerror:
- movl %eax,_errno
+ .globl HIDENAME(cerror)
+
+#ifdef _THREAD_SAFE
+ /*
+ * Threaded version using __error().
+ */
+ .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
+
+#else /* _THREAD_SAFE */
+ /*
+ * Non-threaded version using global errno.
+ */
+ .globl CNAME(errno)
+HIDENAME(cerror):
+#ifdef PIC
+ /* The caller must execute the PIC prologue before jumping to cerror. */
+ movl PIC_GOT(CNAME(errno)),%ecx
+ movl %eax,(%ecx)
+ PIC_EPILOGUE
+#else
+ movl %eax,CNAME(errno)
+#endif
movl $-1,%eax
+ movl $-1,%edx
ret
+#endif /* _THREAD_SAFE */
diff --git a/lib/libc/i386/sys/exect.S b/lib/libc/i386/sys/exect.S
index 6b42cf8..af0d2ee 100644
--- a/lib/libc/i386/sys/exect.S
+++ b/lib/libc/i386/sys/exect.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,11 +32,14 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)exect.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
#include <machine/psl.h>
@@ -48,5 +51,6 @@ ENTRY(exect)
orl $ PSL_T,%edx
pushl %edx
popf
- LCALL(7,0)
- jmp cerror /* exect(file, argv, env); */
+ KERNCALL
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror)) /* exect(file, argv, env); */
diff --git a/lib/libc/i386/sys/fork.S b/lib/libc/i386/sys/fork.S
index ff4d948..ab908a9 100644
--- a/lib/libc/i386/sys/fork.S
+++ b/lib/libc/i386/sys/fork.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,15 +32,18 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)fork.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
-SYSCALL(fork)
+PSYSCALL(fork)
cmpl $0,%edx /* parent, since %edx == 0 in parent, 1 in child */
je 1f
movl $0,%eax
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..ddf6e0c
--- /dev/null
+++ b/lib/libc/i386/sys/i386_get_ldt.2
@@ -0,0 +1,98 @@
+.\" 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.
+.\" 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: @(#)fork.2 6.5 (Berkeley) 3/10/91
+.\" $Id$
+.\"
+.Dd September 20, 1993
+.Dt I386_GET_LDT 2
+.Os FreeBSD
+.Sh NAME
+.Nm i386_get_ldt ,
+.Nm i386_set_ldt
+.Nd manage i386 per-process Local Descriptor Table entries
+.Sh SYNOPSIS
+.Fd #include <machine/segments.h>
+.Fd #include <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
+.Fn i386_get_ldt
+will return the list of i386 descriptors that the process has in its
+LDT.
+.Fn i386_set_ldt
+will set a list of i386 descriptors for the current process in its
+LDT.
+Both routines accept a starting selector number
+.Fa start_sel
+, an array of memory that
+will contain the descriptors to be set or returned
+.Fa descs
+, and the number of entries to set or return
+.Fa num_sels .
+.Pp
+The argument
+.Fa descs
+can be either segment_descriptor or gate_descriptor and are defined in
+.Fd <i386/segments.h> .
+These structures are defined by the architecure
+as disjoint bit-fields, so care must be taken in constructing them.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn i386_get_ldt
+returns the number of descriptors currently in the LDT.
+.Fn i386_set_ldt
+returns the first selector set.
+Otherwise, a value of -1 is returned and the global
+variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Fn i386_get_ldt
+and
+.Fn i386_set_ldt
+will fail if:
+.Bl -tag -width [EINVAL]
+.It Bq Er EINVAL
+An inappropriate parameter was used for
+.Fa start_sel
+or
+.Fa num_sels .
+.It Bq Er EACESS
+The caller attempted to use a descriptor that would
+circumvent protection or cause a failure.
+.El
+.Sh REFERENCES
+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..628052b
--- /dev/null
+++ b/lib/libc/i386/sys/i386_get_ldt.c
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
+
+#include <sys/cdefs.h>
+#include <machine/segments.h>
+#include <machine/sysarch.h>
+
+struct parms {
+ int start;
+ union descriptor *descs;
+ int num;
+};
+
+int
+i386_get_ldt(int start, union descriptor *descs, int num)
+{
+ struct parms p;
+
+ p.start = start;
+ p.descs = descs;
+ p.num = num;
+
+ return sysarch(I386_GET_LDT, (char *)&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..6a54b30
--- /dev/null
+++ b/lib/libc/i386/sys/i386_set_ldt.c
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
+
+#include <sys/cdefs.h>
+#include <machine/segments.h>
+#include <machine/sysarch.h>
+
+struct parms {
+ int start;
+ union descriptor *descs;
+ int num;
+};
+
+int
+i386_set_ldt(int start, union descriptor *descs, int num)
+{
+ struct parms p;
+
+ p.start = start;
+ p.descs = descs;
+ p.num = num;
+
+ return sysarch(I386_SET_LDT, (char *)&p);
+}
diff --git a/lib/libc/i386/sys/mount.S b/lib/libc/i386/sys/mount.S
index ac418f7..85b8837 100644
--- a/lib/libc/i386/sys/mount.S
+++ b/lib/libc/i386/sys/mount.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,11 +32,14 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)mount.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
diff --git a/lib/libc/i386/sys/pipe.S b/lib/libc/i386/sys/pipe.S
index 6469397..637b86f 100644
--- a/lib/libc/i386/sys/pipe.S
+++ b/lib/libc/i386/sys/pipe.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,15 +32,18 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)pipe.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
-SYSCALL(pipe)
+PSYSCALL(pipe)
movl 4(%esp),%ecx
movl %eax,(%ecx)
movl %edx,4(%ecx)
diff --git a/lib/libc/i386/sys/ptrace.S b/lib/libc/i386/sys/ptrace.S
index 98994ea..018a02c 100644
--- a/lib/libc/i386/sys/ptrace.S
+++ b/lib/libc/i386/sys/ptrace.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,20 +32,31 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)ptrace.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
ENTRY(ptrace)
xorl %eax,%eax
- movl %eax,_errno
+#ifdef PIC
+ PIC_PROLOGUE
+ movl PIC_GOT(CNAME(errno)),%edx
+ movl %eax,(%edx)
+ PIC_EPILOGUE
+#else
+ movl %eax,CNAME(errno)
+#endif
lea SYS_ptrace,%eax
- LCALL(7,0)
+ KERNCALL
jb err
ret
err:
- jmp cerror
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
diff --git a/lib/libc/i386/sys/reboot.S b/lib/libc/i386/sys/reboot.S
index 020bea0..70049b2 100644
--- a/lib/libc/i386/sys/reboot.S
+++ b/lib/libc/i386/sys/reboot.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,11 +32,14 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)reboot.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
diff --git a/lib/libc/i386/sys/rfork.S b/lib/libc/i386/sys/rfork.S
new file mode 100644
index 0000000..189d399
--- /dev/null
+++ b/lib/libc/i386/sys/rfork.S
@@ -0,0 +1,51 @@
+/*-
+ * 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. 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.
+ *
+ * $Id$
+ */
+
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
+
+#include "SYS.h"
+
+PSYSCALL(rfork)
+ cmpl $0,%edx /* parent, since %edx == 0 in parent, 1 in child */
+ je 1f
+ movl $0,%eax
+1:
+ ret /* pid = rfork(); */
diff --git a/lib/libc/i386/sys/sbrk.S b/lib/libc/i386/sys/sbrk.S
index 7fecd93..a3afd89 100644
--- a/lib/libc/i386/sys/sbrk.S
+++ b/lib/libc/i386/sys/sbrk.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,34 +32,64 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)sbrk.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
-#define SYS_brk 17
-
- .globl _end
- .globl minbrk
- .globl curbrk
+ .globl CNAME(end)
+ .globl HIDENAME(minbrk)
+ .globl HIDENAME(curbrk)
.data
-minbrk: .long _end
-curbrk: .long _end
+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)
+ lea 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 curbrk,%eax
+ movl HIDENAME(curbrk),%eax
+ testl %ecx,%ecx
+ jz back
addl %eax,4(%esp)
- lea SYS_brk,%eax
- LCALL(7,0)
+ lea SYS_break,%eax
+ KERNCALL
jb err
- movl curbrk,%eax
- addl %ecx,curbrk
+ movl HIDENAME(curbrk),%eax
+ addl %ecx,HIDENAME(curbrk)
+back:
ret
err:
- jmp cerror
+ jmp HIDENAME(cerror)
+#endif /* PIC */
diff --git a/lib/libc/i386/sys/setlogin.S b/lib/libc/i386/sys/setlogin.S
index 43d31d7..7bcf3bd 100644
--- a/lib/libc/i386/sys/setlogin.S
+++ b/lib/libc/i386/sys/setlogin.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,16 +32,28 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
- .asciz "@(#)setlogin.s 8.1 (Berkeley) 6/4/93"
-#endif /* LIBC_SCCS and not lint */
+#if defined(LIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* LIBC_RCS and not lint */
#include "SYS.h"
-.globl __logname_valid /* in getlogin() */
+.globl CNAME(_logname_valid) /* in getlogin() */
SYSCALL(setlogin)
- movl $0,__logname_valid
+#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) */
diff --git a/lib/libc/i386/sys/sigpending.S b/lib/libc/i386/sys/sigpending.S
index 63b06a2..2ce0df8 100644
--- a/lib/libc/i386/sys/sigpending.S
+++ b/lib/libc/i386/sys/sigpending.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,15 +32,18 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)sigpending.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
-SYSCALL(sigpending)
+PSYSCALL(sigpending)
movl 4(%esp),%ecx # fetch pointer to...
movl %eax,(%ecx) # store old mask
xorl %eax,%eax
diff --git a/lib/libc/i386/sys/sigprocmask.S b/lib/libc/i386/sys/sigprocmask.S
index ef91e80..6dbc8c9 100644
--- a/lib/libc/i386/sys/sigprocmask.S
+++ b/lib/libc/i386/sys/sigprocmask.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,18 +32,26 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)sigprocmask.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
err:
- jmp cerror
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
+#ifdef _THREAD_SAFE
+ENTRY(_thread_sys_sigprocmask)
+#else
ENTRY(sigprocmask)
+#endif
movl 8(%esp),%ecx # fetch new sigset pointer
cmpl $0,%ecx # check new sigset pointer
jne 1f # if not null, indirect
@@ -52,8 +60,8 @@ ENTRY(sigprocmask)
jmp 2f
1: movl (%ecx),%ecx # fetch indirect ...
movl %ecx,8(%esp) # to new mask arg
-2: movl $ SYS_sigprocmask , %eax
- LCALL(0x7,0)
+2: lea SYS_sigprocmask,%eax
+ KERNCALL
jb err
movl 12(%esp),%ecx # fetch old mask requested
cmpl $0,%ecx # test if old mask requested
diff --git a/lib/libc/i386/sys/sigreturn.S b/lib/libc/i386/sys/sigreturn.S
index 1bd6a3b..65deb40 100644
--- a/lib/libc/i386/sys/sigreturn.S
+++ b/lib/libc/i386/sys/sigreturn.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,23 +32,21 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)sigreturn.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
/*
- * We must preserve the state of the registers as the user has set them up.
+ * NOTE: If the profiling ENTRY() code ever changes any registers, they
+ * must be saved. On FreeBSD, this is not the case.
*/
-#ifdef PROF
-#undef ENTRY
-#define ENTRY(x) \
- .globl _/**/x; .align 2; _/**/x: pusha ; \
- .data; 1:; .long 0; .text; movl $1b,%eax; call mcount; popa ; nop
-#endif /* PROF */
-SYSCALL(sigreturn)
+PSYSCALL(sigreturn)
ret
diff --git a/lib/libc/i386/sys/sigsuspend.S b/lib/libc/i386/sys/sigsuspend.S
index afbc1ba..660eabf 100644
--- a/lib/libc/i386/sys/sigsuspend.S
+++ b/lib/libc/i386/sys/sigsuspend.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,23 +32,31 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)sigsuspend.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
err:
- jmp cerror
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
+#ifdef _THREAD_SAFE
+ENTRY(_thread_sys_sigsuspend)
+#else
ENTRY(sigsuspend)
+#endif
movl 4(%esp),%eax # fetch mask arg
movl (%eax),%eax # indirect to mask arg
movl %eax,4(%esp)
- movl $ SYS_sigsuspend ,%eax
- LCALL(0x7,0)
+ lea SYS_sigsuspend,%eax
+ KERNCALL
jb err
xorl %eax,%eax # shouldn t happen
ret
diff --git a/lib/libc/i386/sys/syscall.S b/lib/libc/i386/sys/syscall.S
index 189f4dd..711a770 100644
--- a/lib/libc/i386/sys/syscall.S
+++ b/lib/libc/i386/sys/syscall.S
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * 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.
@@ -32,11 +32,14 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(SYSLIBC_SCCS) && !defined(lint)
- .asciz "@(#)syscall.s 8.1 (Berkeley) 6/4/93"
-#endif /* SYSLIBC_SCCS and not lint */
+#if defined(SYSLIBC_RCS) && !defined(lint)
+ .text
+ .asciz "$Id$"
+#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
@@ -44,8 +47,11 @@ ENTRY(syscall)
pop %ecx /* rta */
pop %eax /* syscall number */
push %ecx
- LCALL(7,0)
+ 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:
- jmp cerror
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
diff --git a/lib/libc/locale/Makefile.inc b/lib/libc/locale/Makefile.inc
index 8d03f24..57ffdcc 100644
--- a/lib/libc/locale/Makefile.inc
+++ b/lib/libc/locale/Makefile.inc
@@ -1,13 +1,26 @@
-# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
# locale sources
-.PATH: ${.CURDIR}/${MACHINE}/locale ${.CURDIR}/locale
+.PATH: ${.CURDIR}/../libc/${MACHINE}/locale ${.CURDIR}/../libc/locale
SRCS+= ansi.c ctype.c euc.c frune.c isctype.c lconv.c localeconv.c \
- mbrune.c none.c rune.c setlocale.c table.c utf2.c
+ mbrune.c none.c rune.c setlocale.c table.c utf2.c setrunelocale.c \
+ runetype.c tolower.c toupper.c nomacros.c collate.c setinvalidrune.c \
+ collcmp.c
-MAN3+= ctype.0 isalnum.0 isalpha.0 isascii.0 isblank.0 iscntrl.0 \
- isdigit.0 isgraph.0 islower.0 isprint.0 ispunct.0 isspace.0 \
- isupper.0 isxdigit.0 mbrune.0 multibyte.0 rune.0 setlocale.0 \
- toascii.0 tolower.0 toupper.0
-MAN4+= euc.0 utf2.0
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN3+= locale/ctype.3 locale/isalnum.3 locale/isalpha.3 locale/isascii.3 \
+ locale/isblank.3 locale/iscntrl.3 locale/isdigit.3 locale/isgraph.3 \
+ locale/islower.3 locale/isprint.3 locale/ispunct.3 locale/isspace.3 \
+ locale/isupper.3 locale/isxdigit.3 locale/mbrune.3 locale/multibyte.3 \
+ locale/rune.3 locale/setlocale.3 locale/toascii.3 locale/tolower.3 \
+ locale/toupper.3
+MAN4+= locale/euc.4 locale/utf2.4
+MLINKS+= rune.3 setrunelocale.3 rune.3 setinvalidrune.3 rune.3 sgetrune.3 \
+ rune.3 sputrune.3 rune.3 fgetrune.3 rune.3 fungetrune.3 \
+ rune.3 fputrune.3 mbrune.3 mbrrune.3 mbrune.3 mbmb.3 \
+ multibyte.3 mblen.3 multibyte.3 mbstowcs.3 multibyte.3 mbtowc.3 \
+ multibyte.3 wcstombs.3 multibyte.3 wctomb.3 setlocale.3 localeconv.3
+.endif
diff --git a/lib/libc/locale/ansi.c b/lib/libc/locale/ansi.c
index e5c8e8f..a5a3362 100644
--- a/lib/libc/locale/ansi.c
+++ b/lib/libc/locale/ansi.c
@@ -53,7 +53,7 @@ mblen(s, n)
if (s == 0 || *s == 0)
return (0); /* No support for state dependent encodings. */
- if (sgetrune(s, (int)n, &e) == _INVALID_RUNE)
+ if (sgetrune(s, n, &e) == _INVALID_RUNE)
return (s - e);
return (e - s);
}
@@ -70,7 +70,7 @@ mbtowc(pwc, s, n)
if (s == 0 || *s == 0)
return (0); /* No support for state dependent encodings. */
- if ((r = sgetrune(s, (int)n, &e)) == _INVALID_RUNE)
+ if ((r = sgetrune(s, n, &e)) == _INVALID_RUNE)
return (s - e);
if (pwc)
*pwc = r;
@@ -137,11 +137,12 @@ wcstombs(s, pwcs, n)
*s = 0;
break;
}
- if (!sputrune(*pwcs++, s, (int)n, &e))
+ if (!sputrune(*pwcs++, s, n, &e))
return (-1); /* encoding error */
if (!e) /* too long */
return (cnt);
cnt += e - s;
+ n -= e - s;
s = e;
}
return (cnt);
diff --git a/lib/libc/locale/collate.c b/lib/libc/locale/collate.c
new file mode 100644
index 0000000..d1f03e7
--- /dev/null
+++ b/lib/libc/locale/collate.c
@@ -0,0 +1,197 @@
+/*-
+ * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
+ * at Electronni Visti IA, Kiev, Ukraine.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list 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.
+ *
+ * $Id$
+ */
+
+#include <rune.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sysexits.h>
+#include "collate.h"
+#include "setlocale.h"
+
+int __collate_load_error = 1;
+char __collate_version[STR_LEN];
+u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN];
+struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
+struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE];
+
+#define FREAD(a, b, c, d) \
+ do { \
+ if(fread(a, b, c, d) != c) { \
+ fclose(d); \
+ return -1; \
+ } \
+ } while(0)
+
+void __collate_err(int ex, const char *f) __dead2;
+
+int
+__collate_load_tables(encoding)
+ char *encoding;
+{
+ char buf[PATH_MAX];
+ FILE *fp;
+ int save_load_error;
+
+ save_load_error = __collate_load_error;
+ __collate_load_error = 1;
+ if (!encoding) {
+ __collate_load_error = save_load_error;
+ return -1;
+ }
+ if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX"))
+ return 0;
+ if (!_PathLocale) {
+ __collate_load_error = save_load_error;
+ return -1;
+ }
+ /* 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) {
+ __collate_load_error = save_load_error;
+ return -1;
+ }
+ FREAD(__collate_version, sizeof(__collate_version), 1, fp);
+ if (strcmp(__collate_version, COLLATE_VERSION) != 0) {
+ fclose(fp);
+ return -1;
+ }
+ FREAD(__collate_substitute_table, sizeof(__collate_substitute_table),
+ 1, fp);
+ FREAD(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1,
+ fp);
+ FREAD(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1,
+ fp);
+ fclose(fp);
+ __collate_load_error = 0;
+ return 0;
+}
+
+u_char *
+__collate_substitute(s)
+ const u_char *s;
+{
+ int dest_len = 0, len = 0;
+ int delta = strlen(s);
+ u_char *dest_str = NULL;
+
+ if(s == NULL || *s == '\0')
+ return __collate_strdup("");
+ while(*s) {
+ len += strlen(__collate_substitute_table[*s]);
+ while(dest_len <= len) {
+ if(!dest_str)
+ dest_str = calloc(dest_len = delta, 1);
+ else
+ dest_str = realloc(dest_str, dest_len += delta);
+ if(dest_str == NULL)
+ __collate_err(EX_OSERR, __FUNCTION__);
+ }
+ strcat(dest_str, __collate_substitute_table[*s++]);
+ }
+ return dest_str;
+}
+
+void
+__collate_lookup(t, len, prim, sec)
+ u_char *t;
+ int *len, *prim, *sec;
+{
+ struct __collate_st_chain_pri *p2;
+
+ *len = 1;
+ *prim = *sec = 0;
+ for(p2 = __collate_chain_pri_table; p2->str[0]; p2++) {
+ if(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(s)
+ u_char *s;
+{
+ u_char *t = strdup(s);
+
+ if (t == NULL)
+ __collate_err(EX_OSERR, __FUNCTION__);
+ return t;
+}
+
+void
+__collate_err(int ex, const char *f)
+{
+ extern char *__progname; /* Program name, from crt0. */
+ const char *s;
+ int serrno = errno;
+
+ s = __progname;
+ 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]; p2++)
+ printf("\t\"%s\" : %d %d\n\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..638b4be
--- /dev/null
+++ b/lib/libc/locale/collate.h
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
+ * at Electronni Visti IA, Kiev, Ukraine.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list 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.
+ *
+ * $Id$
+ */
+
+#ifndef COLLATE_H_INCLUDED
+#define COLLATE_H_INCLUDED
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#define STR_LEN 10
+#define TABLE_SIZE 100
+#define COLLATE_VERSION "1.0\n"
+
+struct __collate_st_char_pri {
+ int prim, sec;
+};
+struct __collate_st_chain_pri {
+ u_char str[STR_LEN];
+ int prim, sec;
+};
+
+extern int __collate_load_error;
+extern char __collate_version[STR_LEN];
+extern u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN];
+extern struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
+extern struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE];
+
+__BEGIN_DECLS
+u_char *__collate_strdup __P((u_char *));
+u_char *__collate_substitute __P((const u_char *));
+int __collate_load_tables __P((char *));
+void __collate_lookup __P((u_char *, int *, int *, int *));
+int __collate_range_cmp __P((int, int));
+#ifdef COLLATE_DEBUG
+void __collate_print_tables __P((void));
+#endif
+__END_DECLS
+
+#endif /* not COLLATE_H_INCLUDED */
diff --git a/lib/libc/locale/collcmp.c b/lib/libc/locale/collcmp.c
new file mode 100644
index 0000000..35d0640
--- /dev/null
+++ b/lib/libc/locale/collcmp.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 1996 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.
+ *
+ * $Id$
+ */
+
+#define ASCII_COMPATIBLE_COLLATE /* see usr.bin/colldef/data */
+
+#include <string.h>
+#include "collate.h"
+#ifndef ASCII_COMPATIBLE_COLLATE
+#include <ctype.h>
+#endif
+
+/* Temporary backward compatibility */
+
+int collate_range_cmp (c1, c2)
+ int c1, c2;
+{
+ return __collate_range_cmp(c1, c2);
+}
+
+
+/*
+ * Compare two characters converting collate information
+ * into ASCII-compatible range, it allows to handle
+ * "[a-z]"-type ranges with national characters.
+ */
+
+int __collate_range_cmp (c1, c2)
+ int c1, c2;
+{
+ static char s1[2], s2[2];
+ int ret;
+#ifndef ASCII_COMPATIBLE_COLLATE
+ int as1, as2, al1, al2;
+#endif
+
+ c1 &= UCHAR_MAX;
+ c2 &= UCHAR_MAX;
+ if (c1 == c2)
+ return (0);
+
+#ifndef ASCII_COMPATIBLE_COLLATE
+ as1 = isascii(c1);
+ as2 = isascii(c2);
+ al1 = isalpha(c1);
+ al2 = isalpha(c2);
+
+ if (as1 || as2 || al1 || al2) {
+ if ((as1 && as2) || (!al1 && !al2))
+ return (c1 - c2);
+ if (al1 && !al2) {
+ if (isupper(c1))
+ return ('A' - c2);
+ else
+ return ('a' - c2);
+ } else if (al2 && !al1) {
+ if (isupper(c2))
+ return (c1 - 'A');
+ else
+ return (c1 - 'a');
+ }
+ }
+#endif
+ s1[0] = c1;
+ s2[0] = c2;
+ if ((ret = strcoll(s1, s2)) != 0)
+ return (ret);
+ return (c1 - c2);
+}
diff --git a/lib/libc/locale/ctype.3 b/lib/libc/locale/ctype.3
index 528df27..1493cc3 100644
--- a/lib/libc/locale/ctype.3
+++ b/lib/libc/locale/ctype.3
@@ -54,22 +54,35 @@
.Nd character classification macros
.Sh SYNOPSIS
.Fd #include <ctype.h>
-.Fa int c
-.br
+.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 islower "int c"
+.Ft int
.Fn isprint "int c"
+.Ft int
.Fn ispunct "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
diff --git a/lib/libc/locale/euc.4 b/lib/libc/locale/euc.4
index 966b896..ffcf6d8 100644
--- a/lib/libc/locale/euc.4
+++ b/lib/libc/locale/euc.4
@@ -34,16 +34,26 @@
.\"
.\" @(#)euc.4 8.1 (Berkeley) 6/4/93
.\"
-.Dd "June 4, 1993"
+.Dd June 4, 1993
.Dt EUC 4
.Os
.Sh NAME
-.Nm EUC
+.Nm euc
.Nd EUC encoding of runes
.Sh SYNOPSIS
-\fBENCODING "EUC"\fP
-.br
-\fBVARIABLE \fP\fIlen1 mask1 len2 mask2 len3 mask3 len4 mask4 mask\fP
+.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
@@ -89,32 +99,32 @@ as follows:
.Bd -literal
byte0 << ((\fIlen\fPN-1) * 8) | byte1 << ((\fIlen\fPN-2) * 8) | ... | byte\fIlen\fPN-1
.Ed
-.sp
+.Pp
The result is then ANDed with
.Ar ~mask
and ORed with
-.Ar mask\fPN.
+.Ar maskN .
Codesets 2 and 3 are special in that the leading byte (0x8e or 0x8f) is
first removed and the
-.Ar len\fPN
+.Ar lenN
argument is reduced by 1.
-.sp
+.Pp
For example, the Japanese locale has the following
.Ev VARIABLE
line:
.Bd -literal
VARIABLE 1 0x0000 2 0x8080 2 0x0080 3 0x8000 0x8080
.Ed
-.sp
+.Pp
Codeset 1 consists of the values 0x0000 - 0x007f.
-.sp
+.Pp
Codeset 2 consists of the values who have the bits 0x8080 set.
-.sp
+.Pp
Codeset 3 consists of the values 0x0080 - 0x00ff.
-.sp
+.Pp
Codeset 4 consists of the values 0x8000 - 0xff7f excluding the values
which have the 0x0080 bit set.
-.sp
+.Pp
Notice that the global
.Ar mask
is set to 0x8080, this implies that from those 2 bits the codeset can
diff --git a/lib/libc/locale/euc.5 b/lib/libc/locale/euc.5
new file mode 100644
index 0000000..ffcf6d8
--- /dev/null
+++ b/lib/libc/locale/euc.5
@@ -0,0 +1,241 @@
+.\" 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. 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.
+.\"
+.\" @(#)euc.4 8.1 (Berkeley) 6/4/93
+.\"
+.Dd June 4, 1993
+.Dt EUC 4
+.Os
+.Sh NAME
+.Nm euc
+.Nd EUC encoding of runes
+.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 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
+.Ev rune_t
+encoding of
+.Nm EUC
+multibyte characters is dependent on the
+.Ar len
+and
+.Ar mask
+arguments.
+First, the bytes are moved into a
+.Ev rune_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 Japanese locale has the following
+.Ev 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 "EXAMPLE - Japanese Locale"
+This is a complete example of an
+.Ev LC_CTYPE
+source file for the Japanese locale
+.Bd -literal
+/*
+ * Japanese LOCALE_CTYPE definitions using EUC of JIS character sets
+ */
+
+ENCODING "EUC"
+
+/* JIS JIS JIS */
+/* X201 X208 X201 */
+/* 00-7f 84-fe */
+
+VARIABLE 1 0x0000 2 0x8080 2 0x0080 3 0x8000 0x8080
+
+/*
+ * Code Set 1
+ */
+ALPHA 'A' - 'Z' 'a' - 'z'
+CONTROL 0x00 - 0x1f 0x7f
+DIGIT '0' - '9'
+GRAPH 0x21 - 0x7e
+LOWER 'a' - 'z'
+PUNCT 0x21 - 0x2f 0x3a - 0x40 0x5b - 0x60 0x7b - 0x7e
+SPACE 0x09 - 0x0d 0x20
+UPPER 'A' - 'Z'
+XDIGIT 'a' - 'f' 'A' - 'F'
+BLANK ' ' '\t'
+PRINT 0x20 - 0x7e
+
+MAPLOWER < 'A' - 'Z' : 'a' > < 'a' - 'z' : 'a' >
+MAPUPPER < 'A' - 'Z' : 'A' > < 'a' - 'z' : 'A' >
+TODIGIT < '0' - '9' : 0 >
+TODIGIT < 'A' - 'F' : 10 > < 'a' - 'f' : 10 >
+
+/*
+ * Code Set 2
+ */
+
+SPACE 0xa1a1
+PHONOGRAM 0xa1bc
+SPECIAL 0xa1a2 - 0xa1fe
+PUNCT 0xa1a2 - 0xa1f8 /* A few too many in here... */
+
+SPECIAL 0xa2a1 - 0xa2ae 0xa2ba - 0xa2c1 0xa2ca - 0xa2d0 0xa2dc - 0xa2ea
+SPECIAL 0xa2f2 - 0xa2f9 0xa2fe
+
+DIGIT 0xa3b0 - 0xa3b9
+UPPER 0xa3c1 - 0xa3da /* Romaji */
+LOWER 0xa3e1 - 0xa3fa /* Romaji */
+MAPLOWER < 0xa3c1 - 0xa3da : 0xa3e1 > /* English */
+MAPLOWER < 0xa3e1 - 0xa3fa : 0xa3e1 > /* English */
+MAPUPPER < 0xa3c1 - 0xa3da : 0xa3c1 >
+MAPUPPER < 0xa3e1 - 0xa3fa : 0xa3c1 >
+
+XDIGIT 0xa3c1 - 0xa3c6 0xa3e1 - 0xa3e6
+
+TODIGIT < 0xa3b0 - 0xa3b9 : 0 >
+TODIGIT < 0xa3c1 - 0xa3c6 : 10 > < 0xa3e1 - 0xa3e6 : 10 >
+
+PHONOGRAM 0xa4a1 - 0xa4f3
+PHONOGRAM 0xa5a1 - 0xa5f6
+
+UPPER 0xa6a1 - 0xa6b8 /* Greek */
+LOWER 0xa6c1 - 0xa6d8 /* Greek */
+MAPLOWER < 0xa6a1 - 0xa6b8 : 0xa6c1 > < 0xa6c1 - 0xa6d8 : 0xa6c1 >
+MAPUPPER < 0xa6a1 - 0xa6b8 : 0xa6a1 > < 0xa6c1 - 0xa6d8 : 0xa6a1 >
+
+UPPER 0xa7a1 - 0xa7c1 /* Cyrillic */
+LOWER 0xa7d1 - 0xa7f1 /* Cyrillic */
+MAPLOWER < 0xa7a1 - 0xa7c1 : 0xa7d1 > < 0xa7d1 - 0xa7f1 : 0xa7d1 >
+MAPUPPER < 0xa7a1 - 0xa7c1 : 0xa7a1 > < 0xa7d1 - 0xa7f1 : 0xa7a1 >
+
+SPECIAL 0xa8a1 - 0xa8c0
+
+IDEOGRAM 0xb0a1 - 0xb0fe 0xb1a1 - 0xb1fe 0xb2a1 - 0xb2fe
+IDEOGRAM 0xb3a1 - 0xb3fe 0xb4a1 - 0xb4fe 0xb5a1 - 0xb5fe
+IDEOGRAM 0xb6a1 - 0xb6fe 0xb7a1 - 0xb7fe 0xb8a1 - 0xb8fe
+IDEOGRAM 0xb9a1 - 0xb9fe 0xbaa1 - 0xbafe 0xbba1 - 0xbbfe
+IDEOGRAM 0xbca1 - 0xbcfe 0xbda1 - 0xbdfe 0xbea1 - 0xbefe
+IDEOGRAM 0xbfa1 - 0xbffe 0xc0a1 - 0xc0fe 0xc1a1 - 0xc1fe
+IDEOGRAM 0xc2a1 - 0xc2fe 0xc3a1 - 0xc3fe 0xc4a1 - 0xc4fe
+IDEOGRAM 0xc5a1 - 0xc5fe 0xc6a1 - 0xc6fe 0xc7a1 - 0xc7fe
+IDEOGRAM 0xc8a1 - 0xc8fe 0xc9a1 - 0xc9fe 0xcaa1 - 0xcafe
+IDEOGRAM 0xcba1 - 0xcbfe 0xcca1 - 0xccfe 0xcda1 - 0xcdfe
+IDEOGRAM 0xcea1 - 0xcefe 0xcfa1 - 0xcfd3 0xd0a1 - 0xd0fe
+IDEOGRAM 0xd1a1 - 0xd1fe 0xd2a1 - 0xd2fe 0xd3a1 - 0xd3fe
+IDEOGRAM 0xd4a1 - 0xd4fe 0xd5a1 - 0xd5fe 0xd6a1 - 0xd6fe
+IDEOGRAM 0xd7a1 - 0xd7fe 0xd8a1 - 0xd8fe 0xd9a1 - 0xd9fe
+IDEOGRAM 0xdaa1 - 0xdafe 0xdba1 - 0xdbfe 0xdca1 - 0xdcfe
+IDEOGRAM 0xdda1 - 0xddfe 0xdea1 - 0xdefe 0xdfa1 - 0xdffe
+IDEOGRAM 0xe0a1 - 0xe0fe 0xe1a1 - 0xe1fe 0xe2a1 - 0xe2fe
+IDEOGRAM 0xe3a1 - 0xe3fe 0xe4a1 - 0xe4fe 0xe5a1 - 0xe5fe
+IDEOGRAM 0xe6a1 - 0xe6fe 0xe7a1 - 0xe7fe 0xe8a1 - 0xe8fe
+IDEOGRAM 0xe9a1 - 0xe9fe 0xeaa1 - 0xeafe 0xeba1 - 0xebfe
+IDEOGRAM 0xeca1 - 0xecfe 0xeda1 - 0xedfe 0xeea1 - 0xeefe
+IDEOGRAM 0xefa1 - 0xeffe 0xf0a1 - 0xf0fe 0xf1a1 - 0xf1fe
+IDEOGRAM 0xf2a1 - 0xf2fe 0xf3a1 - 0xf3fe 0xf4a1 - 0xf4a4
+/*
+ * This is for Code Set 3, half-width kana
+ */
+SPECIAL 0xa1 - 0xdf
+PHONOGRAM 0xa1 - 0xdf
+CONTROL 0x84 - 0x97 0x9b - 0x9f 0xe0 - 0xfe
+.Ed
+.Sh "SEE ALSO"
+.Xr mklocale 1 ,
+.Xr setlocale 3
diff --git a/lib/libc/locale/euc.c b/lib/libc/locale/euc.c
index e58c855..bc33ff6 100644
--- a/lib/libc/locale/euc.c
+++ b/lib/libc/locale/euc.c
@@ -34,6 +34,7 @@
* SUCH DAMAGE.
*/
+#ifdef XPG4
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)euc.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
@@ -218,3 +219,4 @@ CodeSet1:
}
return (len);
}
+#endif /* XPG4 */
diff --git a/lib/libc/locale/isalnum.3 b/lib/libc/locale/isalnum.3
index ad92c41..5c37978 100644
--- a/lib/libc/locale/isalnum.3
+++ b/lib/libc/locale/isalnum.3
@@ -44,7 +44,7 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn isalnum "int c";
+.Fn isalnum "int c"
.Sh DESCRIPTION
The
.Fn isalnum
@@ -54,7 +54,7 @@ or
.Xr isdigit 3
is true.
In the ASCII character set, this includes the following characters:
-.sp
+.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It \&060\ ``0'' \t061\ ``1'' \t062\ ``2'' \t063\ ``3'' \t064\ ``4''
.It \&065\ ``5'' \t066\ ``6'' \t067\ ``7'' \t070\ ``8'' \t071\ ``9''
diff --git a/lib/libc/locale/isalpha.3 b/lib/libc/locale/isalpha.3
index a36dd4b..23dd46b 100644
--- a/lib/libc/locale/isalpha.3
+++ b/lib/libc/locale/isalpha.3
@@ -44,7 +44,7 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn isalpha "int c";
+.Fn isalpha "int c"
.Sh DESCRIPTION
The
.Fn isalpha
@@ -54,7 +54,7 @@ or
.Xr islower 3
is true.
In the ASCII character set, this includes the following characters:
-.sp
+.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It \&101\ ``A'' \t102\ ``B'' \t103\ ``C'' \t104\ ``D'' \t105\ ``E''
.It \&106\ ``F'' \t107\ ``G'' \t110\ ``H'' \t111\ ``I'' \t112\ ``J''
diff --git a/lib/libc/locale/isascii.3 b/lib/libc/locale/isascii.3
index 9509dc5..0688c9c 100644
--- a/lib/libc/locale/isascii.3
+++ b/lib/libc/locale/isascii.3
@@ -40,7 +40,7 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn isascii "int c";
+.Fn isascii "int c"
.Sh DESCRIPTION
The
.Fn isascii
diff --git a/lib/libc/locale/isblank.3 b/lib/libc/locale/isblank.3
index 7c83d18..7be87bb 100644
--- a/lib/libc/locale/isblank.3
+++ b/lib/libc/locale/isblank.3
@@ -40,7 +40,7 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn isblank "int c";
+.Fn isblank "int c"
.Sh DESCRIPTION
The
.Fn isblank
diff --git a/lib/libc/locale/iscntrl.3 b/lib/libc/locale/iscntrl.3
index 33859a2..5bc3a5a 100644
--- a/lib/libc/locale/iscntrl.3
+++ b/lib/libc/locale/iscntrl.3
@@ -44,13 +44,13 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn iscntrl "int c";
+.Fn iscntrl "int c"
.Sh DESCRIPTION
The
.Fn iscntrl
function tests for any control character.
In the ASCII character set, this includes the following characters:
-.sp
+.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It \&000\ nul \t001\ soh \t002\ stx \t003\ etx \t004\ eot
.It \&005\ enq \t006\ ack \t007\ bel \t010\ bs \t011\ ht
diff --git a/lib/libc/locale/isctype.c b/lib/libc/locale/isctype.c
index 6610e0e..55cfdf0 100644
--- a/lib/libc/locale/isctype.c
+++ b/lib/libc/locale/isctype.c
@@ -43,7 +43,6 @@
static char sccsid[] = "@(#)isctype.c 8.3 (Berkeley) 2/24/94";
#endif /* LIBC_SCCS and not lint */
-#define _ANSI_LIBRARY
#include <ctype.h>
#undef isalnum
@@ -51,7 +50,7 @@ int
isalnum(c)
int c;
{
- return(__istype((c), (_A|_D)));
+ return (__istype((c), (_A|_D)));
}
#undef isalpha
@@ -67,7 +66,7 @@ int
isascii(c)
int c;
{
- return((c & ~0x7F) == 0);
+ return (((c) & ~0x7F) == 0);
}
#undef isblank
@@ -155,7 +154,7 @@ int
toascii(c)
int c;
{
- return (c & 0177);
+ return ((c) & 0x7F);
}
#undef tolower
@@ -163,7 +162,7 @@ int
tolower(c)
int c;
{
- return((c & _CRMASK) ? ___tolower(c) : _CurrentRuneLocale->maplower[c]);
+ return (__tolower(c));
}
#undef toupper
@@ -171,5 +170,5 @@ int
toupper(c)
int c;
{
- return((c & _CRMASK) ? ___toupper(c) : _CurrentRuneLocale->mapupper[c]);
+ return (__toupper(c));
}
diff --git a/lib/libc/locale/isdigit.3 b/lib/libc/locale/isdigit.3
index aa70c30..781a418 100644
--- a/lib/libc/locale/isdigit.3
+++ b/lib/libc/locale/isdigit.3
@@ -44,13 +44,13 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn isdigit "int c";
+.Fn isdigit "int c"
.Sh DESCRIPTION
The
.Fn isdigit
function tests for any decimal-digit character.
In the ASCII character set, this includes the following characters:
-.sp
+.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It \&060\ ``0'' \t061\ ``1'' \t062\ ``2'' \t063\ ``3'' \t064\ ``4''
.It \&065\ ``5'' \t066\ ``6'' \t067\ ``7'' \t070\ ``8'' \t071\ ``9''
diff --git a/lib/libc/locale/isgraph.3 b/lib/libc/locale/isgraph.3
index e8b1ee5..4ef232a 100644
--- a/lib/libc/locale/isgraph.3
+++ b/lib/libc/locale/isgraph.3
@@ -44,13 +44,13 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn isgraph "int c";
+.Fn isgraph "int c"
.Sh DESCRIPTION
The
.Fn isgraph
function tests for any printing character except space.
In the ASCII character set, this includes the following characters:
-.sp
+.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It \&041\ ``!'' \t042\ ``"'' \t043\ ``#'' \t044\ ``$'' \t045\ ``%''
.It \&046\ ``&'' \t047\ ``''' \t050\ ``('' \t051\ ``)'' \t052\ ``*''
diff --git a/lib/libc/locale/islower.3 b/lib/libc/locale/islower.3
index e985498..0c354d2 100644
--- a/lib/libc/locale/islower.3
+++ b/lib/libc/locale/islower.3
@@ -44,13 +44,13 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn islower "int c";
+.Fn islower "int c"
.Sh DESCRIPTION
The
.Fn islower
function tests for any lower-case letters.
In the ASCII character set, this includes the following characters:
-.sp
+.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It \&141\ ``a'' \t142\ ``b'' \t143\ ``c'' \t144\ ``d'' \t145\ ``e''
.It \&146\ ``f'' \t147\ ``g'' \t150\ ``h'' \t151\ ``i'' \t152\ ``j''
diff --git a/lib/libc/locale/isprint.3 b/lib/libc/locale/isprint.3
index dc04d50..8b84dbf 100644
--- a/lib/libc/locale/isprint.3
+++ b/lib/libc/locale/isprint.3
@@ -44,13 +44,13 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn isprint "int c";
+.Fn isprint "int c"
.Sh DESCRIPTION
The
.Fn isprint
function tests for any printing character including space (' ').
In the ASCII character set, this includes the following characters:
-.sp
+.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It \&040\ sp \t041\ ``!'' \t042\ ``"'' \t043\ ``#'' \t044\ ``$''
.It \&045\ ``%'' \t046\ ``&'' \t047\ ``''' \t050\ ``('' \t051\ ``)''
diff --git a/lib/libc/locale/ispunct.3 b/lib/libc/locale/ispunct.3
index d5b3722..f0ed395 100644
--- a/lib/libc/locale/ispunct.3
+++ b/lib/libc/locale/ispunct.3
@@ -44,7 +44,7 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn ispunct "int c";
+.Fn ispunct "int c"
.Sh DESCRIPTION
The
.Fn ispunct
@@ -53,7 +53,7 @@ character for which
.Xr isalnum 3
is true.
In the ASCII character set, this includes the following characters:
-.sp
+.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It \&041\ ``!'' \t042\ ``"'' \t043\ ``#'' \t044\ ``$'' \t045\ ``%''
.It \&046\ ``&'' \t047\ ``''' \t050\ ``('' \t051\ ``)'' \t052\ ``*''
diff --git a/lib/libc/locale/isspace.3 b/lib/libc/locale/isspace.3
index fb077e4..bd38107 100644
--- a/lib/libc/locale/isspace.3
+++ b/lib/libc/locale/isspace.3
@@ -44,13 +44,13 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn isspace "int c";
+.Fn isspace "int c"
.Sh DESCRIPTION
The
.Fn isspace
function tests for the standard white-space characters.
In the ASCII character set, this includes the following characters:
-.sp
+.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It \&011\ ht \t012\ nl \t013\ vt \t014\ np \t015\ cr
.It \&040\ sp
diff --git a/lib/libc/locale/isupper.3 b/lib/libc/locale/isupper.3
index 6035f09..633c1e0 100644
--- a/lib/libc/locale/isupper.3
+++ b/lib/libc/locale/isupper.3
@@ -44,13 +44,13 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn isupper "int c";
+.Fn isupper "int c"
.Sh DESCRIPTION
The
.Fn isupper
function tests for any upper-case letter.
In the ASCII character set, this includes the following characters:
-.sp
+.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It \&101\ ``A'' \t102\ ``B'' \t103\ ``C'' \t104\ ``D'' \t105\ ``E''
.It \&106\ ``F'' \t107\ ``G'' \t110\ ``H'' \t111\ ``I'' \t112\ ``J''
@@ -69,6 +69,6 @@ returns non-zero if the character tests true.
.Xr ascii 7
.Sh STANDARDS
The
-.Xr isupper
+.Fn isupper
function conforms to
.St -ansiC .
diff --git a/lib/libc/locale/isxdigit.3 b/lib/libc/locale/isxdigit.3
index ec1a502..cee6cc7 100644
--- a/lib/libc/locale/isxdigit.3
+++ b/lib/libc/locale/isxdigit.3
@@ -44,13 +44,13 @@
.Sh SYNOPSIS
.Fd #include <ctype.h>
.Ft int
-.Fn isxdigit "int c";
+.Fn isxdigit "int c"
.Sh DESCRIPTION
The
.Fn isxdigit
function tests for any hexadecimal-digit character.
In the ASCII character set, this includes the following characters:
-.sp
+.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It \&060\ ``0'' \t061\ ``1'' \t062\ ``2'' \t063\ ``3'' \t064\ ``4''
.It \&065\ ``5'' \t066\ ``6'' \t067\ ``7'' \t070\ ``8'' \t071\ ``9''
diff --git a/lib/libc/locale/mbrune.3 b/lib/libc/locale/mbrune.3
index d843a02..7d0f41e 100644
--- a/lib/libc/locale/mbrune.3
+++ b/lib/libc/locale/mbrune.3
@@ -34,7 +34,7 @@
.\"
.\" @(#)mbrune.3 8.2 (Berkeley) 4/19/94
.\"
-.Dd "April 19, 1994"
+.Dd April 19, 1994
.Dt MBRUNE 3
.Os
.Sh NAME
@@ -138,10 +138,10 @@ if the
.Fa pattern
does not appear in the string.
.Sh "SEE ALSO
-.Xr euc 4 ,
.Xr mbrune 3 ,
.Xr rune 3 ,
.Xr setlocale 3 ,
+.Xr euc 4 ,
.Xr utf2 4
.Sh HISTORY
The
diff --git a/lib/libc/locale/multibyte.3 b/lib/libc/locale/multibyte.3
index 3ea10e5..6eb9c70 100644
--- a/lib/libc/locale/multibyte.3
+++ b/lib/libc/locale/multibyte.3
@@ -34,7 +34,7 @@
.\"
.\" @(#)multibyte.3 8.1 (Berkeley) 6/4/93
.\"
-.Dd "June 4, 1993"
+.Dd June 4, 1993
.Dt MULTIBYTE 3
.Os
.Sh NAME
@@ -47,7 +47,7 @@
.Sh SYNOPSIS
.Fd #include <stdlib.h>
.Ft int
-.Fn mblen "const char *mbchar" "int nbytes"
+.Fn mblen "const char *mbchar" "size_t nbytes"
.Ft size_t
.Fn mbstowcs "wchar_t *wcstring" "const char *mbstring" "size_t nwchars"
.Ft int
@@ -222,10 +222,10 @@ not counting any terminating null byte.
If any invalid multibyte characters are encountered,
both functions return \-1.
.Sh "SEE ALSO
-.Xr euc 4 ,
.Xr mbrune 3 ,
.Xr rune 3 ,
.Xr setlocale 3 ,
+.Xr euc 4 ,
.Xr utf2 4
.Sh STANDARDS
The
diff --git a/lib/libc/locale/nomacros.c b/lib/libc/locale/nomacros.c
new file mode 100644
index 0000000..45c0db7
--- /dev/null
+++ b/lib/libc/locale/nomacros.c
@@ -0,0 +1,9 @@
+/*
+ * 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_
+
+#include <ctype.h>
diff --git a/lib/libc/locale/none.c b/lib/libc/locale/none.c
index b5d8e44..41f70ae 100644
--- a/lib/libc/locale/none.c
+++ b/lib/libc/locale/none.c
@@ -64,8 +64,6 @@ _none_sgetrune(string, n, result)
size_t n;
char const **result;
{
- int c;
-
if (n < 1) {
if (result)
*result = string;
diff --git a/lib/libc/locale/rune.3 b/lib/libc/locale/rune.3
index 659133f..5ba1604 100644
--- a/lib/libc/locale/rune.3
+++ b/lib/libc/locale/rune.3
@@ -34,7 +34,7 @@
.\"
.\" @(#)rune.3 8.2 (Berkeley) 12/11/93
.\"
-.Dd "December 11, 1993"
+.Dd December 11, 1993
.Dt RUNE 3
.Os
.Sh NAME
@@ -54,7 +54,7 @@
.Fn sgetrune "const char *string" "size_t n" "char const **result"
.Ft int
.Fn sputrune "rune_t rune" "char *string" "size_t n" "char **result"
-.sp
+.Pp
.Fd #include <stdio.h>
.Ft long
.Fn fgetrune "FILE *stream"
@@ -67,7 +67,7 @@ The
.Fn setrunelocale
controls the type of encoding used to represent runes as multibyte strings
as well as the properties of the runes as defined in
-\fB<ctype.h>\fP.
+.Aq Pa ctype.h .
The
.Fa locale
argument indicates which locale to load.
@@ -233,14 +233,15 @@ function returns the number of bytes needed to store
as a multibyte string.
.Sh FILES
.Bl -tag -width /usr/share/locale/locale/LC_CTYPE -compact
-.It Pa $PATH_LOCALE/\fIlocale\fP/LC_CTYPE
-.It Pa /usr/share/locale/\fIlocale\fP/LC_CTYPE
-binary LC_CTYPE file for the locale \fIlocale\fP.
+.It Pa $PATH_LOCALE/ Ns Em locale Ns /LC_CTYPE
+.It Pa /usr/share/locale/ Ns Em locale Ns /LC_CTYPE
+binary LC_CTYPE file for the locale
+.Em locale .
.El
.Sh "SEE ALSO
-.Xr euc 4 ,
.Xr mbrune 3 ,
.Xr setlocale 3 ,
+.Xr euc 4 ,
.Xr utf2 4
.Sh NOTE
The ANSI C type
diff --git a/lib/libc/locale/rune.c b/lib/libc/locale/rune.c
index b239484..bc4d07c 100644
--- a/lib/libc/locale/rune.c
+++ b/lib/libc/locale/rune.c
@@ -38,78 +38,18 @@
static char sccsid[] = "@(#)rune.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
#include <rune.h>
#include <stdio.h>
+#include <string.h>
#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
-extern int _none_init __P((_RuneLocale *));
-extern int _UTF2_init __P((_RuneLocale *));
-extern int _EUC_init __P((_RuneLocale *));
-static _RuneLocale *_Read_RuneMagi __P((FILE *));
-
-static char *PathLocale = 0;
-
-int
-setrunelocale(encoding)
- char *encoding;
-{
- FILE *fp;
- char name[PATH_MAX];
- _RuneLocale *rl;
-
- if (!encoding)
- return(EFAULT);
-
- /*
- * The "C" and "POSIX" locale are always here.
- */
- if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) {
- _CurrentRuneLocale = &_DefaultRuneLocale;
- return(0);
- }
-
- if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
- PathLocale = _PATH_LOCALE;
-
- sprintf(name, "%s/%s/LC_CTYPE", PathLocale, encoding);
-
- if ((fp = fopen(name, "r")) == NULL)
- return(ENOENT);
-
- if ((rl = _Read_RuneMagi(fp)) == 0) {
- fclose(fp);
- return(EFTYPE);
- }
-
- if (!rl->encoding[0] || !strcmp(rl->encoding, "UTF2")) {
- return(_UTF2_init(rl));
- } else if (!strcmp(rl->encoding, "NONE")) {
- return(_none_init(rl));
- } else if (!strcmp(rl->encoding, "EUC")) {
- return(_EUC_init(rl));
- } else
- return(EINVAL);
-}
-
-void
-setinvalidrune(ir)
- rune_t ir;
-{
- _INVALID_RUNE = ir;
-}
-
-static _RuneLocale *
+_RuneLocale *
_Read_RuneMagi(fp)
FILE *fp;
{
char *data;
- void *np;
void *lastp;
_RuneLocale *rl;
_RuneEntry *rr;
@@ -228,107 +168,6 @@ _Read_RuneMagi(fp)
if (!rl->mapupper_ext.nranges)
rl->mapupper_ext.ranges = 0;
-
- return(rl);
-}
-unsigned long
-___runetype(c)
- _BSD_RUNE_T_ c;
-{
- int x;
- _RuneRange *rr = &_CurrentRuneLocale->runetype_ext;
- _RuneEntry *re = rr->ranges;
-
- if (c == EOF)
- return(0);
- for (x = 0; x < rr->nranges; ++x, ++re) {
- if (c < re->min)
- return(0L);
- if (c <= re->max) {
- if (re->types)
- return(re->types[c - re->min]);
- else
- return(re->map);
- }
- }
- return(0L);
-}
-
-_BSD_RUNE_T_
-___toupper(c)
- _BSD_RUNE_T_ c;
-{
- int x;
- _RuneRange *rr = &_CurrentRuneLocale->mapupper_ext;
- _RuneEntry *re = rr->ranges;
-
- if (c == EOF)
- return(EOF);
- for (x = 0; x < rr->nranges; ++x, ++re) {
- if (c < re->min)
- return(c);
- if (c <= re->max)
- return(re->map + c - re->min);
- }
- return(c);
-}
-
-_BSD_RUNE_T_
-___tolower(c)
- _BSD_RUNE_T_ c;
-{
- int x;
- _RuneRange *rr = &_CurrentRuneLocale->maplower_ext;
- _RuneEntry *re = rr->ranges;
-
- if (c == EOF)
- return(EOF);
- for (x = 0; x < rr->nranges; ++x, ++re) {
- if (c < re->min)
- return(c);
- if (c <= re->max)
- return(re->map + c - re->min);
- }
- return(c);
-}
-
-
-#if !defined(_USE_CTYPE_INLINE_) && !defined(_USE_CTYPE_MACROS_)
-/*
- * See comments in <machine/ansi.h>
- */
-int
-__istype(c, f)
- _BSD_RUNE_T_ c;
- unsigned long f;
-{
- return ((((c & _CRMASK) ? ___runetype(c)
- : _CurrentRuneLocale->runetype[c]) & f) ? 1 : 0);
-}
-
-int
-__isctype(_BSD_RUNE_T_ c, unsigned long f)
- _BSD_RUNE_T_ c;
- unsigned long f;
-{
- return ((((c & _CRMASK) ? 0
- : _DefaultRuneLocale.runetype[c]) & f) ? 1 : 0);
-}
-
-_BSD_RUNE_T_
-toupper(c)
- _BSD_RUNE_T_ c;
-{
- return ((c & _CRMASK) ?
- ___toupper(c) : _CurrentRuneLocale->mapupper[c]);
-}
-
-_BSD_RUNE_T_
-tolower(c)
- _BSD_RUNE_T_ c;
-{
- return ((c & _CRMASK) ?
- ___tolower(c) : _CurrentRuneLocale->maplower[c]);
+ return(rl);
}
-#endif
diff --git a/lib/libc/locale/runetype.c b/lib/libc/locale/runetype.c
new file mode 100644
index 0000000..282f806
--- /dev/null
+++ b/lib/libc/locale/runetype.c
@@ -0,0 +1,64 @@
+/*-
+ * 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. 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.
+ */
+
+#include <stdio.h>
+#include <rune.h>
+
+unsigned long
+___runetype(c)
+ _BSD_CT_RUNE_T_ c;
+{
+#ifdef XPG4
+ int x;
+ _RuneRange *rr = &_CurrentRuneLocale->runetype_ext;
+ _RuneEntry *re = rr->ranges;
+
+ if (c < 0 || c == EOF)
+ return(0L);
+
+ for (x = 0; x < rr->nranges; ++x, ++re) {
+ if (c < re->min)
+ return(0L);
+ if (c <= re->max) {
+ if (re->types)
+ return(re->types[c - re->min]);
+ else
+ return(re->map);
+ }
+ }
+#endif
+ return(0L);
+}
diff --git a/lib/libc/locale/setinvalidrune.c b/lib/libc/locale/setinvalidrune.c
new file mode 100644
index 0000000..45a2a47
--- /dev/null
+++ b/lib/libc/locale/setinvalidrune.c
@@ -0,0 +1,44 @@
+/*-
+ * 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. 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.
+ */
+
+#include <rune.h>
+
+void
+setinvalidrune(ir)
+ rune_t ir;
+{
+ _INVALID_RUNE = ir;
+}
diff --git a/lib/libc/locale/setlocale.3 b/lib/libc/locale/setlocale.3
index 74cce03..18ee80b 100644
--- a/lib/libc/locale/setlocale.3
+++ b/lib/libc/locale/setlocale.3
@@ -271,18 +271,22 @@ or
.Fn localeconv .
.Sh FILES
.Bl -tag -width /usr/share/locale/locale/category -compact
-.It Pa $PATH_LOCALE/\fIlocale\fP/\fIcategory\fP
-.It Pa /usr/share/locale/\fIlocale\fP/\fIcategory\fP
-locale file for the locale \fIlocale\fP
-and the category \fIcategory\fP.
+.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 "SEE ALSO
-.Xr euc 4 ,
+.Xr colldef 1 ,
+.Xr mklocale 1 ,
.Xr mbrune 3 ,
.Xr multibyte 3 ,
.Xr rune 3 ,
.Xr strcoll 3 ,
.Xr strxfrm 3 ,
+.Xr euc 4 ,
.Xr utf2 4
.Sh STANDARDS
The
@@ -296,21 +300,25 @@ The
.Fn setlocale
and
.Fn localeconv
-functions first appeared in 4.4BSD.
+functions first appeared in
+.Bx 4.4 .
.Sh BUGS
The current implementation supports only the
.Li "\&""C""
and
.Li "\&""POSIX""
-locales for all but the LC_CTYPE locale.
+locales for all but the
+.Dv LC_COLLATE ,
+.Dv LC_CTYPE ,
+and
+.Dv LC_TIME
+categories.
.Pp
In spite of the gnarly currency support in
.Fn localeconv ,
the standards don't include any functions
for generalized currency formatting.
.Pp
-.Dv LC_COLLATE
-does not make sense for many languages.
Use of
.Dv LC_MONETARY
could lead to misleading results until we have a real time currency
diff --git a/lib/libc/locale/setlocale.c b/lib/libc/locale/setlocale.c
index 414f58e..4b7a1b1 100644
--- a/lib/libc/locale/setlocale.c
+++ b/lib/libc/locale/setlocale.c
@@ -32,17 +32,29 @@
* LIABILITY, OR TORT (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: setlocale.c,v 1.20 1997/02/22 14:59:56 peter Exp $
*/
+#ifdef LIBC_RCS
+static const char rcsid[] =
+ "$Id: setlocale.c,v 1.20 1997/02/22 14:59:56 peter Exp $";
+#endif
+
#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/types.h>
+#include <sys/stat.h>
#include <limits.h>
#include <locale.h>
#include <rune.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+#include "collate.h"
+#include "setlocale.h"
/*
* Category names for getenv()
@@ -59,7 +71,7 @@ static char *categories[_LC_LAST] = {
/*
* Current locales for each category
*/
-static char current_categories[_LC_LAST][32] = {
+static char current_categories[_LC_LAST][ENCODING_LEN + 1] = {
"C",
"C",
"C",
@@ -71,30 +83,34 @@ static char current_categories[_LC_LAST][32] = {
/*
* The locales we are going to try and load
*/
-static char new_categories[_LC_LAST][32];
+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 * 33];
-static char *PathLocale;
+static char current_locale_string[_LC_LAST * (ENCODING_LEN + 1/*"/"*/ + 1)];
static char *currentlocale __P((void));
static char *loadlocale __P((int));
+static int stub_load_locale __P((const char *));
+
+extern int __time_load_locale __P((const char *)); /* strftime.c */
+
+#ifdef XPG4
+extern int _xpg4_setrunelocale __P((char *));
+#endif
char *
setlocale(category, locale)
int category;
const char *locale;
{
- int found, i, len;
+ int i, j, len;
char *env, *r;
- if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
- PathLocale = _PATH_LOCALE;
-
- if (category < 0 || category >= _LC_LAST)
+ if (category < LC_ALL || category >= _LC_LAST)
return (NULL);
if (!locale)
- return (category ?
+ return (category != LC_ALL ?
current_categories[category] : currentlocale());
/*
@@ -109,42 +125,43 @@ setlocale(category, locale)
if (!*locale) {
env = getenv(categories[category]);
- if (!env)
- env = getenv(categories[0]);
+ if (category != LC_ALL && (!env || !*env))
+ env = getenv(categories[LC_ALL]);
- if (!env)
+ if (!env || !*env)
env = getenv("LANG");
- if (!env)
+ if (!env || !*env)
env = "C";
- (void) strncpy(new_categories[category], env, 31);
- new_categories[category][31] = 0;
- if (!category) {
+ (void) strncpy(new_categories[category], env, ENCODING_LEN);
+ new_categories[category][ENCODING_LEN] = '\0';
+ if (category == LC_ALL) {
for (i = 1; i < _LC_LAST; ++i) {
- if (!(env = getenv(categories[i])))
- env = new_categories[0];
- (void)strncpy(new_categories[i], env, 31);
- new_categories[i][31] = 0;
+ if (!(env = getenv(categories[i])) || !*env)
+ env = new_categories[LC_ALL];
+ (void)strncpy(new_categories[i], env, ENCODING_LEN);
+ new_categories[i][ENCODING_LEN] = '\0';
}
}
- } else if (category) {
- (void)strncpy(new_categories[category], locale, 31);
- new_categories[category][31] = 0;
+ } else if (category != LC_ALL) {
+ (void)strncpy(new_categories[category], locale, ENCODING_LEN);
+ new_categories[category][ENCODING_LEN] = '\0';
} else {
- if ((r = strchr(locale, '/')) == 0) {
+ if ((r = strchr(locale, '/')) == NULL) {
for (i = 1; i < _LC_LAST; ++i) {
- (void)strncpy(new_categories[i], locale, 31);
- new_categories[i][31] = 0;
+ (void)strncpy(new_categories[i], locale, ENCODING_LEN);
+ new_categories[i][ENCODING_LEN] = '\0';
}
} else {
for (i = 1; r[1] == '/'; ++r);
if (!r[1])
return (NULL); /* Hmm, just slashes... */
do {
- len = r - locale > 31 ? 31 : r - locale;
- (void)strncpy(new_categories[i++], locale, len);
- new_categories[i++][len] = 0;
+ len = r - locale > ENCODING_LEN ? ENCODING_LEN : r - locale;
+ (void)strncpy(new_categories[i], locale, len);
+ new_categories[i][len] = '\0';
+ i++;
locale = r;
while (*locale == '/')
++locale;
@@ -159,13 +176,19 @@ setlocale(category, locale)
if (category)
return (loadlocale(category));
- found = 0;
- for (i = 1; i < _LC_LAST; ++i)
- if (loadlocale(i) != NULL)
- found = 1;
- if (found)
- return (currentlocale());
- return (NULL);
+ for (i = 1; i < _LC_LAST; ++i) {
+ (void)strcpy(saved_categories[i], current_categories[i]);
+ if (loadlocale(i) == NULL) {
+ for (j = 1; j < i; j++) {
+ (void)strcpy(new_categories[j],
+ saved_categories[j]);
+ /* XXX can fail too */
+ (void)loadlocale(j);
+ }
+ return (NULL);
+ }
+ }
+ return (currentlocale());
}
static char *
@@ -177,11 +200,15 @@ currentlocale()
for (i = 2; i < _LC_LAST; ++i)
if (strcmp(current_categories[1], current_categories[i])) {
- (void)snprintf(current_locale_string,
- sizeof(current_locale_string), "%s/%s/%s/%s/%s",
- current_categories[1], current_categories[2],
- current_categories[3], current_categories[4],
- current_categories[5]);
+ (void) strcpy(current_locale_string, current_categories[1]);
+ (void) strcat(current_locale_string, "/");
+ (void) strcat(current_locale_string, current_categories[2]);
+ (void) strcat(current_locale_string, "/");
+ (void) strcat(current_locale_string, current_categories[3]);
+ (void) strcat(current_locale_string, "/");
+ (void) strcat(current_locale_string, current_categories[4]);
+ (void) strcat(current_locale_string, "/");
+ (void) strcat(current_locale_string, current_categories[5]);
break;
}
return (current_locale_string);
@@ -191,44 +218,99 @@ static char *
loadlocale(category)
int category;
{
- char name[PATH_MAX];
+ char *ret;
+ char *new = new_categories[category];
+ char *old = current_categories[category];
+
+ if (_PathLocale == NULL) {
+ char *p = getenv("PATH_LOCALE");
+
+ if (p != NULL && !issetugid()) {
+ if (strlen(p) + 1/*"/"*/ + ENCODING_LEN +
+ 1/*"/"*/ + CATEGORY_LEN >= PATH_MAX)
+ return (NULL);
+ _PathLocale = strdup(p);
+ if (_PathLocale == NULL)
+ return (NULL);
+ } else
+ _PathLocale = _PATH_LOCALE;
+ }
- if (strcmp(new_categories[category],
- current_categories[category]) == 0)
- return (current_categories[category]);
+ if (strcmp(new, old) == 0)
+ return (old);
if (category == LC_CTYPE) {
- if (setrunelocale(new_categories[LC_CTYPE]))
- return (NULL);
- (void)strcpy(current_categories[LC_CTYPE],
- new_categories[LC_CTYPE]);
- return (current_categories[LC_CTYPE]);
+#ifdef XPG4
+ ret = _xpg4_setrunelocale(new) ? NULL : new;
+#else
+ ret = setrunelocale(new) ? NULL : new;
+#endif
+ if (!ret) {
+#ifdef XPG4
+ (void)_xpg4_setrunelocale(old);
+#else
+ (void)setrunelocale(old);
+#endif
+ } else
+ (void)strcpy(old, new);
+ return (ret);
+ }
+
+ if (category == LC_COLLATE) {
+ ret = (__collate_load_tables(new) < 0) ? NULL : new;
+ if (!ret)
+ (void)__collate_load_tables(old);
+ else
+ (void)strcpy(old, new);
+ return (ret);
+ }
+
+ if (category == LC_TIME) {
+ ret = (__time_load_locale(new) < 0) ? NULL : new;
+ if (!ret)
+ (void)__time_load_locale(old);
+ else
+ (void)strcpy(old, new);
+ return (ret);
}
- if (!strcmp(new_categories[category], "C") ||
- !strcmp(new_categories[category], "POSIX")) {
-
- /*
- * Some day this will need to reset the locale to the default
- * C locale. Since we have no way to change them as of yet,
- * there is no need to reset them.
- */
- (void)strcpy(current_categories[category],
- new_categories[category]);
- return (current_categories[category]);
+ if (category == LC_MONETARY || category == LC_NUMERIC) {
+ ret = stub_load_locale(new) ? NULL : new;
+ if (!ret)
+ (void)stub_load_locale(old);
+ else
+ (void)strcpy(old, new);
+ return (ret);
}
+ /* Just in case...*/
+ return (NULL);
+}
+
+static int
+stub_load_locale(encoding)
+const char *encoding;
+{
+ char name[PATH_MAX];
+ struct stat st;
+
+ if (!encoding)
+ return(1);
+ /*
+ * The "C" and "POSIX" locale are always here.
+ */
+ if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX"))
+ return(0);
+ if (!_PathLocale)
+ return(1);
+ /* Range checking not needed, encoding has fixed size */
+ strcpy(name, _PathLocale);
+ strcat(name, "/");
+ strcat(name, encoding);
+#if 0
/*
* Some day we will actually look at this file.
*/
- (void)snprintf(name, sizeof(name), "%s/%s/%s",
- PathLocale, new_categories[category], categories[category]);
-
- switch (category) {
- case LC_COLLATE:
- case LC_MONETARY:
- case LC_NUMERIC:
- case LC_TIME:
- return (NULL);
- }
+#endif
+ return (stat(name, &st) != 0 || !S_ISDIR(st.st_mode));
}
diff --git a/lib/libc/locale/setlocale.h b/lib/libc/locale/setlocale.h
new file mode 100644
index 0000000..f3b2a22
--- /dev/null
+++ b/lib/libc/locale/setlocale.h
@@ -0,0 +1,34 @@
+#ifndef _SETLOCALE_H
+#define _SETLOCALE_H
+/*
+ * 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.
+ */
+
+#define ENCODING_LEN 31
+#define CATEGORY_LEN 11
+
+extern char *_PathLocale;
+
+#endif /* SETLOCALE_H */
diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c
new file mode 100644
index 0000000..d44f8e2
--- /dev/null
+++ b/lib/libc/locale/setrunelocale.c
@@ -0,0 +1,130 @@
+/*-
+ * 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. 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.
+ */
+
+#include <rune.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "setlocale.h"
+
+extern int _none_init __P((_RuneLocale *));
+#ifdef XPG4
+extern int _UTF2_init __P((_RuneLocale *));
+extern int _EUC_init __P((_RuneLocale *));
+extern int _xpg4_setrunelocale __P((char *));
+#endif
+extern _RuneLocale *_Read_RuneMagi __P((FILE *));
+
+#ifdef XPG4
+int
+setrunelocale(encoding)
+ char *encoding;
+{
+ return _xpg4_setrunelocale(encoding);
+}
+#endif
+
+int
+#ifndef XPG4
+setrunelocale(encoding)
+#else
+_xpg4_setrunelocale(encoding)
+#endif
+ char *encoding;
+{
+ FILE *fp;
+ char name[PATH_MAX];
+ _RuneLocale *rl;
+
+ if (!encoding || strlen(encoding) > ENCODING_LEN)
+ return(EFAULT);
+
+ /*
+ * The "C" and "POSIX" locale are always here.
+ */
+ if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) {
+ _CurrentRuneLocale = &_DefaultRuneLocale;
+ return(0);
+ }
+
+ if (_PathLocale == NULL) {
+ char *p = getenv("PATH_LOCALE");
+
+ if (p != NULL && !issetugid()) {
+ if (strlen(p) + 1/*"/"*/ + ENCODING_LEN +
+ 1/*"/"*/ + CATEGORY_LEN >= PATH_MAX)
+ return(EFAULT);
+ _PathLocale = strdup(p);
+ if (_PathLocale == NULL)
+ return (errno);
+ } else
+ _PathLocale = _PATH_LOCALE;
+ }
+ /* Range checking not needed, encoding length already checked above */
+ (void) strcpy(name, _PathLocale);
+ (void) strcat(name, "/");
+ (void) strcat(name, encoding);
+ (void) strcat(name, "/LC_CTYPE");
+
+ if ((fp = fopen(name, "r")) == NULL)
+ return(ENOENT);
+
+ if ((rl = _Read_RuneMagi(fp)) == 0) {
+ fclose(fp);
+ return(EFTYPE);
+ }
+ fclose(fp);
+
+#ifdef XPG4
+ if (!rl->encoding[0] || !strcmp(rl->encoding, "UTF2")) {
+ return(_UTF2_init(rl));
+#else
+ if (!rl->encoding[0]) {
+ return(EINVAL);
+#endif
+ } else if (!strcmp(rl->encoding, "NONE")) {
+ return(_none_init(rl));
+#ifdef XPG4
+ } else if (!strcmp(rl->encoding, "EUC")) {
+ return(_EUC_init(rl));
+#endif
+ } else
+ return(EINVAL);
+}
+
diff --git a/lib/libc/locale/table.c b/lib/libc/locale/table.c
index fb7344e..00f80d7 100644
--- a/lib/libc/locale/table.c
+++ b/lib/libc/locale/table.c
@@ -32,14 +32,14 @@
* LIABILITY, OR TORT (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: table.c,v 1.10 1997/05/13 11:19:26 ache Exp $
*/
#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/types.h>
-
#include <ctype.h>
#include <rune.h>
@@ -158,3 +158,5 @@ _RuneLocale _DefaultRuneLocale = {
_RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale;
int __mb_cur_max = 1;
+
+char *_PathLocale;
diff --git a/lib/libc/locale/toascii.3 b/lib/libc/locale/toascii.3
index 54fa292..788d2f2 100644
--- a/lib/libc/locale/toascii.3
+++ b/lib/libc/locale/toascii.3
@@ -51,9 +51,9 @@ The
.Fn toascii
function always returns a valid ASCII character.
.Sh SEE ALSO
-.Xr isascii 3 ,
.Xr isalnum 3 ,
.Xr isalpha 3 ,
+.Xr isascii 3 ,
.Xr iscntrl 3 ,
.Xr isdigit 3 ,
.Xr isgraph 3 ,
@@ -63,7 +63,7 @@ function always returns a valid ASCII character.
.Xr isspace 3 ,
.Xr isupper 3 ,
.Xr isxdigit 3 ,
+.Xr stdio 3 ,
.Xr tolower 3 ,
.Xr toupper 3 ,
-.Xr stdio 3 ,
.Xr ascii 7
diff --git a/lib/libc/locale/tolower.3 b/lib/libc/locale/tolower.3
index fe503d4..3f98965 100644
--- a/lib/libc/locale/tolower.3
+++ b/lib/libc/locale/tolower.3
@@ -65,9 +65,9 @@ one; otherwise the argument is returned unchanged.
.\" .Xr islower
.\" is true.
.Sh SEE ALSO
-.Xr isascii 3 ,
.Xr isalnum 3 ,
.Xr isalpha 3 ,
+.Xr isascii 3 ,
.Xr iscntrl 3 ,
.Xr isdigit 3 ,
.Xr isgraph 3 ,
@@ -77,9 +77,9 @@ one; otherwise the argument is returned unchanged.
.Xr isspace 3 ,
.Xr isupper 3 ,
.Xr isxdigit 3 ,
+.Xr stdio 3 ,
.Xr toascii 3 ,
.Xr toupper 3 ,
-.Xr stdio 3
.Xr ascii 7
.Sh STANDARDS
The
diff --git a/lib/libc/locale/tolower.c b/lib/libc/locale/tolower.c
new file mode 100644
index 0000000..65d5175
--- /dev/null
+++ b/lib/libc/locale/tolower.c
@@ -0,0 +1,60 @@
+/*-
+ * 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. 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.
+ */
+
+#include <stdio.h>
+#include <rune.h>
+
+_BSD_CT_RUNE_T_
+___tolower(c)
+ _BSD_CT_RUNE_T_ c;
+{
+#ifdef XPG4
+ int x;
+ _RuneRange *rr = &_CurrentRuneLocale->maplower_ext;
+ _RuneEntry *re = rr->ranges;
+
+ if (c < 0 || c == EOF)
+ return(c);
+
+ for (x = 0; x < rr->nranges; ++x, ++re) {
+ if (c < re->min)
+ return(c);
+ if (c <= re->max)
+ return(re->map + c - re->min);
+ }
+#endif
+ return(c);
+}
diff --git a/lib/libc/locale/toupper.3 b/lib/libc/locale/toupper.3
index c3ff593..2802637 100644
--- a/lib/libc/locale/toupper.3
+++ b/lib/libc/locale/toupper.3
@@ -65,9 +65,9 @@ one; otherwise the argument is returned unchanged.
.\" .Xr isupper
.\" is true.
.Sh SEE ALSO
-.Xr isascii 3 ,
.Xr isalnum 3 ,
.Xr isalpha 3 ,
+.Xr isascii 3 ,
.Xr iscntrl 3 ,
.Xr isdigit 3 ,
.Xr isgraph 3 ,
@@ -77,12 +77,12 @@ one; otherwise the argument is returned unchanged.
.Xr isspace 3 ,
.Xr isupper 3 ,
.Xr isxdigit 3 ,
+.Xr stdio 3 ,
.Xr toascii 3 ,
-.Xr toupper 3 ,
-.Xr stdio 3
+.Xr tolower 3 ,
.Xr ascii 7
.Sh STANDARDS
The
-.Fn tolower
+.Fn toupper
function conforms to
.St -ansiC .
diff --git a/lib/libc/locale/toupper.c b/lib/libc/locale/toupper.c
new file mode 100644
index 0000000..d2e4480
--- /dev/null
+++ b/lib/libc/locale/toupper.c
@@ -0,0 +1,60 @@
+/*-
+ * 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. 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.
+ */
+
+#include <stdio.h>
+#include <rune.h>
+
+_BSD_CT_RUNE_T_
+___toupper(c)
+ _BSD_CT_RUNE_T_ c;
+{
+#ifdef XPG4
+ int x;
+ _RuneRange *rr = &_CurrentRuneLocale->mapupper_ext;
+ _RuneEntry *re = rr->ranges;
+
+ if (c < 0 || c == EOF)
+ return(c);
+
+ for (x = 0; x < rr->nranges; ++x, ++re) {
+ if (c < re->min)
+ return(c);
+ if (c <= re->max)
+ return(re->map + c - re->min);
+ }
+#endif
+ return(c);
+}
diff --git a/lib/libc/locale/utf2.4 b/lib/libc/locale/utf2.4
index 20a9587..d7ef493 100644
--- a/lib/libc/locale/utf2.4
+++ b/lib/libc/locale/utf2.4
@@ -34,14 +34,15 @@
.\"
.\" @(#)utf2.4 8.1 (Berkeley) 6/4/93
.\"
-.Dd "June 4, 1993"
+.Dd June 4, 1993
.Dt UTF2 4
.Os
.Sh NAME
-.Nm UTF2
+.Nm utf2
.Nd "Universal character set Transformation Format encoding of runes
.Sh SYNOPSIS
-\fBENCODING "UTF2"\fP
+.Nm ENCODING
+.Qq UTF2
.Sh DESCRIPTION
The
.Nm UTF2
@@ -62,7 +63,7 @@ encoding is represented by the following table:
[0x0080 - 0x03ff] [00000bbb.bbbbbbbb] -> 110bbbbb, 10bbbbbb
[0x0400 - 0xffff] [bbbbbbbb.bbbbbbbb] -> 1110bbbb, 10bbbbbb, 10bbbbbb
.Ed
-.sp
+.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 (but the longer ones will be correctly decoded).
@@ -78,7 +79,7 @@ The final three encodings provided by X-Open:
[0bbbbbbb.bbbbbbbb.bbbbbbbb.bbbbbbbb] ->
1111110b, 10bbbbbb, 10bbbbbb, 10bbbbbb, 10bbbbbb, 10bbbbbb
.Ed
-.sp
+.Pp
which provides for the entire proposed ISO-10646 31 bit standard are currently
not implemented.
.Sh "SEE ALSO"
diff --git a/lib/libc/gen/realpath.3 b/lib/libc/locale/utf2.5
index 83f4a43..d7ef493 100644
--- a/lib/libc/gen/realpath.3
+++ b/lib/libc/locale/utf2.5
@@ -1,8 +1,8 @@
-.\" Copyright (c) 1994
+.\" Copyright (c) 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
-.\" Jan-Simon Pendry.
+.\" Paul Borman at Krystal Technologies.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -32,94 +32,56 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)realpath.3 8.2 (Berkeley) 2/16/94
+.\" @(#)utf2.4 8.1 (Berkeley) 6/4/93
.\"
-.Dd "February 16, 1994"
-.Dt REALPATH 3
+.Dd June 4, 1993
+.Dt UTF2 4
.Os
.Sh NAME
-.Nm realpath
-.Nd returns the canonicalized absolute pathname
+.Nm utf2
+.Nd "Universal character set Transformation Format encoding of runes
.Sh SYNOPSIS
-.Fd #include <sys/param.h>
-.Fd #include <stdlib.h>
-.Ft "char *"
-.Fn realpath "const char *pathname" "char resolvedname[MAXPATHLEN]"
+.Nm ENCODING
+.Qq UTF2
.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 referenced by
-.Fa resolvedname .
-The
-.Fa resolvedname
-argument
-.Em must
-refer to a buffer capable of storing at least
-.Dv MAXPATHLEN
-characters.
+.Nm UTF2
+encoding is based on a proposed X-Open multibyte
+\s-1FSS-UCS-TF\s+1 (File System Safe Universal Character Set Transformation Format) encoding as used in
+.Nm Plan 9 from Bell Labs.
+Although it is capable of representing more than 16 bits,
+the current implementation is limited to 16 bits as defined by the
+Unicode Standard.
.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_name
-on success.
-If an error occurs,
-.Fn realpath
-returns
-.Dv NULL ,
-and
-.Fa resolved_name
-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 chdir 2 ,
-.Xr close 2 ,
-.Xr fchdir 2 ,
-.Xr lstat 2 ,
-.Xr open 2 ,
-.Xr readlink 2
-and
-.Xr getcwd 3 .
-.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 .
+.Nm UTF2
+representation is backwards compatible with ASCII, so 0x00-0x7f refer to the
+ASCII character set. The multibyte encoding of runes between 0x0080 and 0xffff
+consist entirely of bytes whose high order bit is set. The actual
+encoding is represented by the following table:
+.Bd -literal
+[0x0000 - 0x007f] [00000000.0bbbbbbb] -> 0bbbbbbb
+[0x0080 - 0x03ff] [00000bbb.bbbbbbbb] -> 110bbbbb, 10bbbbbb
+[0x0400 - 0xffff] [bbbbbbbb.bbbbbbbb] -> 1110bbbb, 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 (but the longer ones will be correctly decoded).
+.Pp
+The final three encodings provided by X-Open:
+.Bd -literal
+[00000000.000bbbbb.bbbbbbbb.bbbbbbbb] ->
+ 11110bbb, 10bbbbbb, 10bbbbbb, 10bbbbbb
+
+[000000bb.bbbbbbbb.bbbbbbbb.bbbbbbbb] ->
+ 111110bb, 10bbbbbb, 10bbbbbb, 10bbbbbb, 10bbbbbb
+
+[0bbbbbbb.bbbbbbbb.bbbbbbbb.bbbbbbbb] ->
+ 1111110b, 10bbbbbb, 10bbbbbb, 10bbbbbb, 10bbbbbb, 10bbbbbb
+.Ed
+.Pp
+which provides for the entire proposed ISO-10646 31 bit standard are currently
+not implemented.
.Sh "SEE ALSO"
-.Xr getcwd 3
-.Sh HISTORY
-The
-.Fn realpath
-function call first appeared in
-.Bx 4.4 .
+.Xr mklocale 1 ,
+.Xr setlocale 3
diff --git a/lib/libc/locale/utf2.c b/lib/libc/locale/utf2.c
index 846fad9..c46dd93 100644
--- a/lib/libc/locale/utf2.c
+++ b/lib/libc/locale/utf2.c
@@ -34,6 +34,7 @@
* SUCH DAMAGE.
*/
+#ifdef XPG4
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)utf2.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
@@ -146,3 +147,4 @@ _UTF2_sputrune(c, string, n, result)
return (1);
}
}
+#endif /* XPG4 */
diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc
index 320b742..d654c02 100644
--- a/lib/libc/net/Makefile.inc
+++ b/lib/libc/net/Makefile.inc
@@ -1,27 +1,44 @@
-# @(#)Makefile.inc 8.2 (Berkeley) 9/5/93
+# from @(#)Makefile.inc 8.2 (Berkeley) 9/5/93
+# $Id$
# machine-independent net sources
-.PATH: ${.CURDIR}/${MACHINE}/net ${.CURDIR}/net
+.PATH: ${.CURDIR}/../libc/${MACHINE}/net ${.CURDIR}/../libc/net
-SRCS+= gethostnamadr.c getnetbyaddr.c getnetbyname.c getnetent.c \
+SRCS+= addr2ascii.c ascii2addr.c base64.c \
+ gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \
+ getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \
getproto.c getprotoent.c getprotoname.c getservbyname.c \
getservbyport.c getservent.c herror.c inet_addr.c inet_lnaof.c \
- inet_makeaddr.c inet_netof.c inet_network.c inet_ntoa.c \
- iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c rcmd.c recv.c res_comp.c \
- res_debug.c res_init.c res_mkquery.c res_query.c res_send.c \
- send.c sethostent.c
+ inet_makeaddr.c inet_netof.c inet_network.c inet_ntoa.c inet_ntop.c \
+ inet_net_ntop.c inet_net_pton.c inet_neta.c \
+ inet_pton.c linkaddr.c map_v4v6.c nsap_addr.c \
+ rcmd.c recv.c res_comp.c res_data.c res_debug.c \
+ res_init.c res_mkquery.c res_query.c res_send.c res_stubs.c \
+ send.c ether_addr.c \
+ ns_addr.c ns_ntoa.c
+# iso_addr.c
# machine-dependent net sources
-.include "${.CURDIR}/${MACHINE}/net/Makefile.inc"
+.include "${.CURDIR}/../libc/${MACHINE}/net/Makefile.inc"
-MAN3+= byteorder.0 gethostbyname.0 getnetent.0 getprotoent.0 getservent.0 \
- inet.0 linkaddr.0 ns.0 rcmd.0 resolver.0 \
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN3+= net/addr2ascii.3 \
+ net/byteorder.3 net/ethers.3 net/gethostbyname.3 net/getnetent.3 \
+ net/getprotoent.3 net/getservent.3 net/inet.3 net/linkaddr.3 \
+ net/rcmd.3 resolver.3
+# not installed: net/ns.3 net/iso_addr.3
+
+MLINKS+=addr2ascii.3 ascii2addr.3
MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \
byteorder.3 ntohs.3
+MLINKS+=ethers.3 ether_line.3 ethers.3 ether_aton.3 ethers.3 ether_ntoa.3 \
+ ethers.3 ether_ntohost.3 ethers.3 ether_hostton.3
MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
gethostbyname.3 sethostent.3 gethostbyname.3 gethostent.3 \
- gethostbyname.3 herror.3
+ gethostbyname.3 herror.3 gethostbyname.3 hstrerror.3 \
+ gethostbyname.3 gethostbyname2.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 \
@@ -31,9 +48,10 @@ MLINKS+=getservent.3 endservent.3 getservent.3 getservbyname.3 \
MLINKS+=inet.3 addr.3 inet.3 inet_addr.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 network.3 inet.3 ntoa.3 inet.3 inet_aton.3
-MLINKS+=linkaddr.3 linkntoa.3
-MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3
-MLINKS+=rcmd.3 rresvport.3 rcmd.3 ruserok.3
+MLINKS+=linkaddr.3 link_addr.3 linkaddr.3 link_ntoa.3
+#MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3
+MLINKS+=rcmd.3 rresvport.3 rcmd.3 iruserok.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_send.3 resolver.3 res_query.3 \
resolver.3 res_search.3
+.endif
diff --git a/lib/libc/net/addr2ascii.3 b/lib/libc/net/addr2ascii.3
new file mode 100644
index 0000000..282acac
--- /dev/null
+++ b/lib/libc/net/addr2ascii.3
@@ -0,0 +1,215 @@
+.\"
+.\" Copyright 1996 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.
+.\"
+.\" $ANA: addr2ascii.3,v 1.1 1996/06/13 18:41:46 wollman Exp $
+.\"
+.Dd June 13, 1996
+.Dt ADDR2ASCII 3
+.Os
+.Sh NAME
+.Nm addr2ascii ,
+.Nm ascii2addr
+.Nd Generic address formatting routines
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <netinet/in.h>
+.Fd #include <arpa/inet.h>
+.Ft "char *"
+.Fn addr2ascii "int af" "const void *addrp" "int len" "char *buf"
+.Ft int
+.Fn ascii2addr "int af" "const char *ascii" "void *result"
+.Sh DESCRIPTION
+The routines
+.Fn addr2ascii
+and
+.Fn ascii2addr
+are used to convert network addresses between binary form and a
+printable form appropriate to the address family. Both functions take
+an
+.Fa af
+argument, specifying the address family to be used in the conversion
+process.
+(Currently, only the
+.Dv AF_INET
+and
+.Dv AF_LINK
+address families are supported.)
+.Pp
+The
+.Fn addr2ascii
+function
+is used to convert binary, network-format addresses into printable
+form. In addition to
+.Fa af ,
+there are three other arguments. The
+.Fa addrp
+argument is a pointer to the network address to be converted.
+The
+.Fa len
+argument is the length of the address. The
+.Fa buf
+argument is an optional pointer to a caller-allocated buffer to hold
+the result; if a null pointer is passed,
+.Fn addr2ascii
+uses a statically-allocated buffer.
+.Pp
+The
+.Fn ascii2addr
+function performs the inverse operation to
+.Fn addr2ascii .
+In addition to
+.Fa af ,
+it takes two parameters,
+.Fa ascii
+and
+.Fa result .
+The
+.Fa ascii
+parameter is a pointer to the string which is to be converted into
+binary. The
+.Fa result
+parameter is a pointer to an appropriate network address structure for
+the specified family.
+.Pp
+The following gives the appropriate structure to use for binary
+addresses in the specified family:
+.Pp
+.Bl -tag -width AF_INETxxxx -compact
+.It Dv AF_INET
+.Li struct in_addr
+.Pq in Aq Pa netinet/in.h
+.It Dv AF_LINK
+.Li struct sockaddr_dl
+.Pq in Aq Pa net/if_dl.h
+.\" .It Dv AF_INET6
+.\" .Li struct in6_addr
+.\" .Pq in Aq Pa netinet6/in6.h
+.El
+.Sh RETURN VALUES
+The
+.Fn addr2ascii
+function returns the address of the buffer it was passed, or a static
+buffer if the a null pointer was passed; on failure, it returns a null
+pointer.
+The
+.Fn ascii2addr
+function returns the length of the binary address in bytes, or -1 on
+failure.
+.Sh EXAMPLES
+The
+.Xr inet 3
+functions
+.Fn inet_ntoa
+and
+.Fn inet_aton
+could be implemented thusly:
+.Bd -literal -offset indent
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+char *
+inet_ntoa(struct in_addr addr)
+{
+ return addr2ascii(AF_INET, &addr, sizeof addr, 0);
+}
+
+int
+inet_aton(const char *ascii, struct in_addr *addr)
+{
+ return (ascii2addr(AF_INET, ascii, addr)
+ == sizeof(*addr));
+}
+.Ed
+.Pp
+In actuality, this cannot be done because
+.Fn addr2ascii
+and
+.Fn ascii2addr
+are implemented in terms of the
+.Xr inet 3
+functions, rather than the other way around.
+.Sh ERRORS
+When a failure is returned,
+.Li errno
+is set to one of the following values:
+.Bl -tag -width [EPROTONOSUPPORT]
+.It Bq Er ENAMETOOLONG
+The
+.Fn addr2ascii
+routine was passed a
+.Fa len
+parameter which was inappropriate for the address family given by
+.Fa af .
+.It Bq Er EPROTONOSUPPORT
+Either routine was passed an
+.Fa af
+parameter other than
+.Dv AF_INET
+or
+.Dv AF_LINK .
+.It Bq Er EINVAL
+The string passed to
+.Fn ascii2addr
+was improperly formatted for address family
+.Fa af .
+.El
+.Sh SEE ALSO
+.Xr inet 3 ,
+.Xr linkaddr 3 ,
+.Xr inet 4
+.Sh HISTORY
+An interface close to this one was originally suggested by Craig
+Partridge. This particular interface originally apppeared in the
+.Tn INRIA
+.Tn IPv6
+implementation.
+.Sh AUTHOR
+Code and documentation by Garrett A. Wollman, MIT Laboratory for
+Computer Science.
+.Sh BUGS
+The original implementations supported IPv6. This support should
+eventually be resurrected. The
+.Tn NRL
+implementation also included support for the
+.Dv AF_ISO
+and
+.Dv AF_NS
+address families.
+.Pp
+The genericity of this interface is somewhat questionable. A truly
+generic interface would provide a means for determining the length of
+the buffer to be used so that it could be dynamically allocated, and
+would always require a
+.Dq Li "struct sockaddr"
+to hold the binary address. Unfortunately, this is incompatible with existing
+practice. This limitation means that a routine for printing network
+addresses from arbitrary address families must still have internal
+knowledge of the maximum buffer length needed and the appropriate part
+of the address to use as the binary address.
diff --git a/lib/libc/net/addr2ascii.c b/lib/libc/net/addr2ascii.c
new file mode 100644
index 0000000..5bee3ea
--- /dev/null
+++ b/lib/libc/net/addr2ascii.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright 1996 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.
+ *
+ * $ANA: addr2ascii.c,v 1.1 1996/06/13 18:41:46 wollman Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/*-
+ * Convert a network address from binary to printable numeric format.
+ * This API is copied from INRIA's IPv6 implementation, but it is a
+ * bit bogus in two ways:
+ *
+ * 1) There is no value in passing both an address family and
+ * an address length; either one should imply the other,
+ * or we should be passing sockaddrs instead.
+ * 2) There should by contrast be /added/ a length for the buffer
+ * that we pass in, so that programmers are spared the need to
+ * manually calculate (read: ``guess'') the maximum length.
+ *
+ * Flash: the API is also the same in the NRL implementation, and seems to
+ * be some sort of standard, so we appear to be stuck with both the bad
+ * naming and the poor choice of arguments.
+ */
+char *
+addr2ascii(af, addrp, len, buf)
+ int af;
+ const void *addrp;
+ int len; /* should be size_t XXX */
+ char *buf; /* XXX should pass length of buffer */
+{
+ static char staticbuf[64]; /* 64 for AF_LINK > 16 for AF_INET */
+
+ if (!buf)
+ buf = staticbuf;
+
+ switch(af) {
+ case AF_INET:
+ if (len != sizeof(struct in_addr)) {
+ errno = ENAMETOOLONG;
+ return 0;
+ }
+ strcpy(buf, inet_ntoa(*(const struct in_addr *)addrp));
+ break;
+
+ case AF_LINK:
+ if (len != sizeof(struct sockaddr_dl)) {
+ errno = ENAMETOOLONG;
+ return 0;
+ }
+ strcpy(buf, link_ntoa((const struct sockaddr_dl *)addrp));
+ break;
+
+ default:
+ errno = EPROTONOSUPPORT;
+ return 0;
+ }
+ return buf;
+}
diff --git a/lib/libc/net/ascii2addr.c b/lib/libc/net/ascii2addr.c
new file mode 100644
index 0000000..0b5bab4
--- /dev/null
+++ b/lib/libc/net/ascii2addr.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 1996 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.
+ *
+ * $ANA: ascii2addr.c,v 1.2 1996/06/13 18:46:02 wollman Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+int
+ascii2addr(af, ascii, result)
+ int af;
+ const char *ascii;
+ void *result;
+{
+ struct in_addr *ina;
+ char strbuf[4*sizeof("123")]; /* long enough for V4 only */
+
+ switch(af) {
+ case AF_INET:
+ ina = result;
+ strbuf[0] = '\0';
+ strncat(strbuf, ascii, (sizeof strbuf)-1);
+ if (inet_aton(strbuf, ina))
+ return sizeof(struct in_addr);
+ errno = EINVAL;
+ break;
+
+ case AF_LINK:
+ link_addr(ascii, result);
+ /* oops... no way to detect failure */
+ return sizeof(struct sockaddr_dl);
+
+ default:
+ errno = EPROTONOSUPPORT;
+ break;
+ }
+
+ return -1;
+}
diff --git a/lib/libc/net/base64.c b/lib/libc/net/base64.c
new file mode 100644
index 0000000..868826a
--- /dev/null
+++ b/lib/libc/net/base64.c
@@ -0,0 +1,321 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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/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>
+
+#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
+# include <stdlib.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+#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(src, srclength, target, targsize)
+ u_char const *src;
+ size_t srclength;
+ char *target;
+ size_t targsize;
+{
+ size_t datalength = 0;
+ u_char input[3];
+ u_char output[4];
+ int 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(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 (tarindex >= targsize)
+ return (-1);
+ target[tarindex] = (pos - Base64) << 2;
+ }
+ state = 1;
+ break;
+ case 1:
+ if (target) {
+ if (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 (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 (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 (NULL; ch != '\0'; ch = *src++)
+ if (!isspace(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 (NULL; ch != '\0'; ch = *src++)
+ if (!isspace(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/ether_addr.c b/lib/libc/net/ether_addr.c
new file mode 100644
index 0000000..9b7a9ab
--- /dev/null
+++ b/lib/libc/net/ether_addr.c
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ *
+ * ethernet address conversion and lookup routines
+ *
+ * Written by Bill Paul <wpaul@ctr.columbia.edu>
+ * Center for Telecommunications Research
+ * Columbia University, New York City
+ *
+ * $Id$
+ */
+
+
+#include <stdio.h>
+#include <paths.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.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
+
+#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(l, e, hostname)
+ 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(a)
+ char *a;
+{
+ int i;
+ static struct ether_addr o;
+ 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);
+
+ o.octet[0]=o0;
+ o.octet[1]=o1;
+ o.octet[2]=o2;
+ o.octet[3]=o3;
+ o.octet[4]=o4;
+ o.octet[5]=o5;
+
+ return ((struct ether_addr *)&o);
+}
+
+/*
+ * Convert a binary representation of an ethernet address to
+ * an ASCII string.
+ */
+char *ether_ntoa(n)
+ struct ether_addr *n;
+{
+ int i;
+ static char a[18];
+
+ i = sprintf(a,"%x:%x:%x:%x:%x:%x",n->octet[0],n->octet[1],n->octet[2],
+ n->octet[3],n->octet[4],n->octet[5]);
+ if (i < 11)
+ return (NULL);
+ return ((char *)&a);
+}
+
+/*
+ * Map an ethernet address to a hostname. Use either /etc/ethers or
+ * NIS/YP.
+ */
+
+int ether_ntohost(hostname, e)
+ 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 *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(hostname, e)
+ 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..afea483
--- /dev/null
+++ b/lib/libc/net/ethers.3
@@ -0,0 +1,193 @@
+.\" 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.
+.\"
+.\" $Id$
+.\"
+.Dd April 12, 1995
+.Dt ETHERS 3
+.Os FreeBSD 2.1
+.Sh NAME
+.Nm ethers ,
+.Nm ether_line ,
+.Nm ether_aton ,
+.Nm ether_ntoa ,
+.Nm ether_ntohost ,
+.Nm ether_hostton
+.Nd Ethernet address conversion and lookup routines
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <net/ethernet.h>
+.Ft int
+.Fn ether_line "char *l" "struct ether_addr *e" "char *hostname"
+.Ft struct ether_addr *
+.Fn ether_aton "char *a"
+.Ft char *
+.Fn ether_ntoa "struct ether_addr *n"
+.Ft int
+.Fn ether_ntohost "char *hostname" "struct ether_addr *e"
+.Ft int
+.Fn ether_hostton "char *hostname" "struct ether_addr *e"
+.Sh DESCRIPTION
+These functions operate on ethernet addresses using an
+.Ar ether_addr
+structure, which is defined in the header file
+.Aq Pa netinet/if_ether.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
+.Ar l ,
+an
+.Tn ASCII
+string in
+.Xr ethers 5
+format and sets
+.Ar e
+to the ethernet address specified in the string and
+.Ar h
+to the hostname. This function is used to parse lines from
+.Pa /etc/ethers
+into their component parts.
+.Pp
+The
+.Fn ether_aton
+function converts an
+.Tn ASCII
+representation of an ethernet address into an
+.Ar ether_addr
+structure. Likewise,
+.Fn ether_ntoa
+converts an ethernet address specified as an
+.Ar ether_addr
+structure into an
+.Tn ASCII
+string.
+.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.
+.Fn ether_ntohost
+converts from ethernet address to hostname, and
+.Fn ether_hostton
+converts from hostname to ethernet address.
+.Sh RETURN VALUES
+.Fn ether_line
+returns zero on success and non-zero if it was unable to parse
+any part of the supplied line
+.Ar l .
+It returns the extracted ethernet address in the supplied
+.Ar ether_addr
+structure
+.Ar e
+and the hostname in the supplied string
+.Ar h .
+.Pp
+On success,
+.Fn ether_ntoa
+returns a pointer to a string containing an
+.Tn ASCII
+representation of an ethernet address. If it is unable to convert
+the supplied
+.Ar ether_addr
+structure, it returns a
+.Dv NULL
+pointer. Likewise,
+.Fn ether_aton
+returns a pointer to an
+.Ar ether_addr
+structure on success and a
+.Dv NULL
+pointer on failure.
+.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 insure that the hostname strings passed to the
+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 yp 4 ,
+.Xr ethers 5
+.Sh BUGS
+.Pp
+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.
+.Sh HISTORY
+This particular implementation of the
+.Nm ethers
+library functions were written for and first appeared in
+.Fx 2.1 .
diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c
new file mode 100644
index 0000000..4d13e2e
--- /dev/null
+++ b/lib/libc/net/gethostbydns.c
@@ -0,0 +1,736 @@
+/*
+ * ++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--
+ */
+
+#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.21 1997/06/01 20:34:37 vixie Exp";
+static char rcsid[] = "$Id: gethostbydns.c,v 1.21 1997/03/12 11:02:00 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#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 <unistd.h>
+#include <string.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <syslog.h>
+
+#include "res_config.h"
+
+#define SPRINTF(x) ((size_t)sprintf x)
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+static const char AskedForGot[] =
+ "gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
+
+static char *h_addr_ptrs[MAXADDRS + 1];
+
+static struct hostent host;
+static char *host_aliases[MAXALIASES];
+static char hostbuf[8*1024];
+static u_char host_addr[16]; /* IPv4 or IPv6 */
+
+#ifdef RESOLVSORT
+static void addrsort __P((char **, int));
+#endif
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+ int32_t al;
+ char ac;
+} align;
+
+extern int h_errno;
+int _dns_ttl_;
+
+#ifdef DEBUG
+static void
+dprintf(msg, num)
+ char *msg;
+ int num;
+{
+ if (_res.options & RES_DEBUG) {
+ int save = errno;
+
+ printf(msg, num);
+ errno = save;
+ }
+}
+#else
+# define dprintf(msg, num) /*nada*/
+#endif
+
+static struct hostent *
+gethostanswer(answer, anslen, qname, qtype)
+ const querybuf *answer;
+ int anslen;
+ const char *qname;
+ int qtype;
+{
+ register const HEADER *hp;
+ register const u_char *cp;
+ register int n;
+ const u_char *eom;
+ char *bp, **ap, **hap;
+ int type, class, buflen, ancount, qdcount;
+ int haveanswer, had_error;
+ int toobig = 0;
+ char tbuf[MAXDNAME];
+ const char *tname;
+ int (*name_ok) __P((const char *));
+
+ tname = qname;
+ host.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:
+ h_errno = NO_RECOVERY;
+ return (NULL); /* XXX should be abort(); */
+ }
+ /*
+ * find first satisfactory answer
+ */
+ hp = &answer->hdr;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ bp = hostbuf;
+ buflen = sizeof hostbuf;
+ cp = answer->buf + HFIXEDSZ;
+ if (qdcount != 1) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ cp += 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) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ host.h_name = bp;
+ bp += n;
+ buflen -= n;
+ /* The qname can be abbreviated, but h_name is now absolute. */
+ qname = host.h_name;
+ }
+ ap = host_aliases;
+ *ap = NULL;
+ host.h_aliases = host_aliases;
+ hap = h_addr_ptrs;
+ *hap = NULL;
+ host.h_addr_list = 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, buflen);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ had_error++;
+ continue;
+ }
+ cp += n; /* name */
+ 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 */
+ 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 >= &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;
+ /* Store alias. */
+ *ap++ = bp;
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ bp += n;
+ buflen -= n;
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > buflen || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strcpy(bp, tbuf);
+ host.h_name = bp;
+ bp += n;
+ buflen -= 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;
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > buflen || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strcpy(bp, tbuf);
+ tname = bp;
+ bp += n;
+ buflen -= n;
+ continue;
+ }
+ if (type != qtype) {
+ 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, buflen);
+ if ((n < 0) || !res_hnok(bp)) {
+ had_error++;
+ break;
+ }
+#if MULTI_PTRS_ARE_ALIASES
+ cp += n;
+ if (!haveanswer)
+ host.h_name = bp;
+ else if (ap < &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;
+ buflen -= n;
+ }
+ break;
+#else
+ host.h_name = bp;
+ if (_res.options & RES_USE_INET6) {
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ break;
+ }
+ bp += n;
+ buflen -= n;
+ _map_v4v6_hostent(&host, &bp, &buflen);
+ }
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+#endif
+ case T_A:
+ case T_AAAA:
+ if (strcasecmp(host.h_name, bp) != 0) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, host.h_name, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if (n != host.h_length) {
+ cp += n;
+ continue;
+ }
+ if (!haveanswer) {
+ register int nn;
+
+ host.h_name = bp;
+ nn = strlen(bp) + 1; /* for the \0 */
+ bp += nn;
+ buflen -= nn;
+ }
+
+ bp += sizeof(align) - ((u_long)bp % sizeof(align));
+
+ if (bp + n >= &hostbuf[sizeof hostbuf]) {
+ dprintf("size (%d) too big\n", n);
+ had_error++;
+ continue;
+ }
+ if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
+ if (!toobig++)
+ dprintf("Too many addresses (%d)\n",
+ MAXADDRS);
+ cp += n;
+ continue;
+ }
+ bcopy(cp, *hap++ = bp, n);
+ bp += n;
+ buflen -= n;
+ cp += n;
+ break;
+ default:
+ dprintf("Impossible condition (type=%d)\n", type);
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ /* 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 (_res.nsort && haveanswer > 1 && qtype == T_A)
+ addrsort(h_addr_ptrs, haveanswer);
+# endif /*RESOLVSORT*/
+ if (!host.h_name) {
+ n = strlen(qname) + 1; /* for the \0 */
+ if (n > buflen || n >= MAXHOSTNAMELEN)
+ goto no_recovery;
+ strcpy(bp, qname);
+ host.h_name = bp;
+ bp += n;
+ buflen -= n;
+ }
+ if (_res.options & RES_USE_INET6)
+ _map_v4v6_hostent(&host, &bp, &buflen);
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+ }
+ no_recovery:
+ h_errno = NO_RECOVERY;
+ return (NULL);
+}
+
+struct hostent *
+__dns_getanswer(answer, anslen, qname, qtype)
+ const char *answer;
+ int anslen;
+ const char *qname;
+ int qtype;
+{
+ switch(qtype) {
+ case T_AAAA:
+ host.h_addrtype = AF_INET6;
+ host.h_length = IN6ADDRSZ;
+ break;
+ case T_A:
+ default:
+ host.h_addrtype = AF_INET;
+ host.h_length = INADDRSZ;
+ break;
+ }
+
+ return(gethostanswer((const querybuf *)answer, anslen, qname, qtype));
+}
+
+struct hostent *
+_gethostbydnsname(name, af)
+ const char *name;
+ int af;
+{
+ querybuf buf;
+ register const char *cp;
+ char *bp;
+ int n, size, type, len;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+
+ switch (af) {
+ case AF_INET:
+ size = INADDRSZ;
+ type = T_A;
+ break;
+ case AF_INET6:
+ size = IN6ADDRSZ;
+ type = T_AAAA;
+ break;
+ default:
+ h_errno = NETDB_INTERNAL;
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+
+ host.h_addrtype = af;
+ host.h_length = size;
+
+ /*
+ * 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 = __hostalias(name)))
+ name = cp;
+
+ /*
+ * disallow names consisting only of digits/dots, unless
+ * they end in a dot.
+ */
+ if (isdigit(name[0]))
+ for (cp = name;; ++cp) {
+ if (!*cp) {
+ if (*--cp == '.')
+ break;
+ /*
+ * All-numeric, no dot at the end.
+ * Fake up a hostent as if we'd actually
+ * done a lookup.
+ */
+ if (inet_pton(af, name, host_addr) <= 0) {
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ strncpy(hostbuf, name, MAXDNAME);
+ hostbuf[MAXDNAME] = '\0';
+ bp = hostbuf + MAXDNAME;
+ len = sizeof hostbuf - MAXDNAME;
+ host.h_name = hostbuf;
+ host.h_aliases = host_aliases;
+ host_aliases[0] = NULL;
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ host.h_addr_list = h_addr_ptrs;
+ if (_res.options & RES_USE_INET6)
+ _map_v4v6_hostent(&host, &bp, &len);
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+ }
+ if (!isdigit(*cp) && *cp != '.')
+ break;
+ }
+ if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
+ name[0] == ':')
+ for (cp = name;; ++cp) {
+ if (!*cp) {
+ if (*--cp == '.')
+ break;
+ /*
+ * All-IPv6-legal, no dot at the end.
+ * Fake up a hostent as if we'd actually
+ * done a lookup.
+ */
+ if (inet_pton(af, name, host_addr) <= 0) {
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ strncpy(hostbuf, name, MAXDNAME);
+ hostbuf[MAXDNAME] = '\0';
+ bp = hostbuf + MAXDNAME;
+ len = sizeof hostbuf - MAXDNAME;
+ host.h_name = hostbuf;
+ host.h_aliases = host_aliases;
+ host_aliases[0] = NULL;
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ host.h_addr_list = h_addr_ptrs;
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+ }
+ if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
+ break;
+ }
+
+ if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
+ dprintf("res_search failed (%d)\n", n);
+ return (NULL);
+ }
+ return (gethostanswer(&buf, n, name, type));
+}
+
+struct hostent *
+_gethostbydnsaddr(addr, len, af)
+ const char *addr; /* XXX should have been def'd as u_char! */
+ int len, af;
+{
+ const u_char *uaddr = (const u_char *)addr;
+ static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
+ static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
+ int n, size;
+ querybuf buf;
+ register struct hostent *hp;
+ char qbuf[MAXDNAME+1], *qp;
+#ifdef SUNSECURITY
+ register struct hostent *rhp;
+ char **haddr;
+ u_long old_options;
+ char hname2[MAXDNAME+1];
+#endif /*SUNSECURITY*/
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ if (af == AF_INET6 && len == IN6ADDRSZ &&
+ (!bcmp(uaddr, mapped, sizeof mapped) ||
+ !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
+ /* Unmap. */
+ addr += sizeof mapped;
+ uaddr += sizeof mapped;
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+ switch (af) {
+ case AF_INET:
+ size = INADDRSZ;
+ break;
+ case AF_INET6:
+ size = IN6ADDRSZ;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ if (size != len) {
+ errno = EINVAL;
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ 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 = IN6ADDRSZ - 1; n >= 0; n--) {
+ qp += SPRINTF((qp, "%x.%x.",
+ uaddr[n] & 0xf,
+ (uaddr[n] >> 4) & 0xf));
+ }
+ strcpy(qp, "ip6.int");
+ break;
+ default:
+ abort();
+ }
+ n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
+ if (n < 0) {
+ dprintf("res_query failed (%d)\n", n);
+ return (NULL);
+ }
+ if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR)))
+ return (NULL); /* h_errno was set by gethostanswer() */
+#ifdef SUNSECURITY
+ if (af == AF_INET) {
+ /*
+ * turn off search as the name should be absolute,
+ * 'localhost' should be matched by defnames
+ */
+ strncpy(hname2, hp->h_name, MAXDNAME);
+ hname2[MAXDNAME] = '\0';
+ old_options = _res.options;
+ _res.options &= ~RES_DNSRCH;
+ _res.options |= RES_DEFNAMES;
+ if (!(rhp = gethostbyname(hname2))) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: No A record for %s (verifying [%s])",
+ hname2, inet_ntoa(*((struct in_addr *)addr)));
+ _res.options = old_options;
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ _res.options = old_options;
+ for (haddr = rhp->h_addr_list; *haddr; haddr++)
+ if (!memcmp(*haddr, addr, INADDRSZ))
+ break;
+ if (!*haddr) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: A record of %s != PTR record [%s]",
+ hname2, inet_ntoa(*((struct in_addr *)addr)));
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ }
+#endif /*SUNSECURITY*/
+ hp->h_addrtype = af;
+ hp->h_length = len;
+ bcopy(addr, host_addr, len);
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ if (af == AF_INET && (_res.options & RES_USE_INET6)) {
+ _map_v4v6_address((char*)host_addr, (char*)host_addr);
+ hp->h_addrtype = AF_INET6;
+ hp->h_length = IN6ADDRSZ;
+ }
+ h_errno = NETDB_SUCCESS;
+ return (hp);
+}
+
+#ifdef RESOLVSORT
+static void
+addrsort(ap, num)
+ char **ap;
+ int num;
+{
+ 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(stayopen)
+ int stayopen;
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return;
+ if (stayopen)
+ _res.options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+_endhostdnsent()
+{
+ _res.options &= ~(RES_STAYOPEN | RES_USEVC);
+ res_close();
+}
diff --git a/lib/libc/net/gethostbyht.c b/lib/libc/net/gethostbyht.c
new file mode 100644
index 0000000..cf12f57
--- /dev/null
+++ b/lib/libc/net/gethostbyht.c
@@ -0,0 +1,202 @@
+/*-
+ * 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--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id: gethostbyht.c,v 1.9 1997/02/22 15:00:07 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#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 <arpa/nameser.h> /* XXX */
+#include <resolv.h> /* XXX */
+
+#define MAXALIASES 35
+
+static struct hostent host;
+static char *host_aliases[MAXALIASES];
+static char hostbuf[BUFSIZ+1];
+static FILE *hostf = NULL;
+static u_char host_addr[16]; /* IPv4 or IPv6 */
+static char *h_addr_ptrs[2];
+static int stayopen = 0;
+
+void
+_sethosthtent(f)
+ int f;
+{
+ if (!hostf)
+ hostf = fopen(_PATH_HOSTS, "r" );
+ else
+ rewind(hostf);
+ stayopen = f;
+}
+
+void
+_endhosthtent()
+{
+ if (hostf && !stayopen) {
+ (void) fclose(hostf);
+ hostf = NULL;
+ }
+}
+
+struct hostent *
+gethostent()
+{
+ char *p;
+ register char *cp, **q;
+ int af, len;
+
+ if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ again:
+ if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ if (*p == '#')
+ goto again;
+ if (!(cp = strpbrk(p, "#\n")))
+ goto again;
+ *cp = '\0';
+ if (!(cp = strpbrk(p, " \t")))
+ goto again;
+ *cp++ = '\0';
+ if (inet_pton(AF_INET6, p, host_addr) > 0) {
+ af = AF_INET6;
+ len = IN6ADDRSZ;
+ } else if (inet_pton(AF_INET, p, host_addr) > 0) {
+ if (_res.options & RES_USE_INET6) {
+ _map_v4v6_address((char*)host_addr, (char*)host_addr);
+ af = AF_INET6;
+ len = IN6ADDRSZ;
+ } else {
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+ } else {
+ goto again;
+ }
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ host.h_addr_list = h_addr_ptrs;
+ host.h_length = len;
+ host.h_addrtype = af;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ host.h_name = cp;
+ q = host.h_aliases = host_aliases;
+ if ((cp = strpbrk(cp, " \t")) != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &host_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ if ((cp = strpbrk(cp, " \t")) != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+}
+
+struct hostent *
+_gethostbyhtname(name, af)
+ const char *name;
+ int af;
+{
+ register struct hostent *p;
+ register char **cp;
+
+ sethostent(0);
+ while ((p = gethostent()) != NULL) {
+ if (p->h_addrtype != af)
+ continue;
+ if (strcasecmp(p->h_name, name) == 0)
+ break;
+ for (cp = p->h_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ endhostent();
+ return (p);
+}
+
+struct hostent *
+_gethostbyhtaddr(addr, len, af)
+ const char *addr;
+ int len, af;
+{
+ register struct hostent *p;
+
+ sethostent(0);
+ while ((p = gethostent()) != NULL)
+ if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
+ break;
+ endhostent();
+ return (p);
+}
diff --git a/lib/libc/net/gethostbyname.3 b/lib/libc/net/gethostbyname.3
index b3b2d1f..e520e33 100644
--- a/lib/libc/net/gethostbyname.3
+++ b/lib/libc/net/gethostbyname.3
@@ -29,34 +29,45 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
+.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
+.\" $Id$
.\"
.Dd May 25, 1995
.Dt GETHOSTBYNAME 3
.Os BSD 4.2
.Sh NAME
.Nm gethostbyname ,
+.Nm gethostbyname2 ,
.Nm gethostbyaddr ,
.Nm gethostent ,
.Nm sethostent ,
.Nm endhostent ,
-.Nm herror
+.Nm herror ,
+.Nm hstrerror
.Nd get network host entry
.Sh SYNOPSIS
.Fd #include <netdb.h>
.Fd extern int h_errno;
.Ft struct hostent *
-.Fn gethostbyname "char *name"
+.Fn gethostbyname "const char *name"
.Ft struct hostent *
-.Fn gethostbyaddr "char *addr" "int len" "int type"
+.Fn gethostbyname2 "const char *name" "int af"
+.Ft struct hostent *
+.Fn gethostbyaddr "const char *addr" "int len" "int type"
.Ft struct hostent *
.Fn gethostent void
+.Ft void
.Fn sethostent "int stayopen"
+.Ft void
.Fn endhostent void
-.Fn herror "char *string"
+.Ft void
+.Fn herror "const char *string"
+.Ft const char *
+.Fn hstrerror "int err"
.Sh DESCRIPTION
The
-.Fn gethostbyname
+.Fn gethostbyname ,
+.Fn gethostbyname2
and
.Fn gethostbyaddr
functions
@@ -87,7 +98,7 @@ Official name of the host.
.It Fa h_aliases
A NULL-terminated array of alternate names for the host.
.It Fa h_addrtype
-The type of address being returned; currently always
+The type of address being returned; usually
.Dv AF_INET .
.It Fa h_length
The length, in bytes, of the address.
@@ -102,6 +113,8 @@ this is for backward compatibility.
.Pp
When using the nameserver,
.Fn gethostbyname
+and
+.Fn gethostbyname
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
@@ -113,6 +126,25 @@ See
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 .
+Currently the
+.Fa af
+argument must be specified as
+.Dv AF_INET
+else the fuction will return
+.Dv NULL
+after having set
+.Va h_errno
+to
+.Dv NETDB_INTERNAL
+.Pp
+The
.Fn sethostent
function
may be used to request the use of a connected
@@ -124,7 +156,8 @@ 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 gethostbyname ,
+.Fn gethostbyname2
or
.Fn gethostbyaddr .
Otherwise, queries are performed using
@@ -137,13 +170,31 @@ function
closes the
.Tn TCP
connection.
+.Pp
+The
+.Fn herror
+function writes a message to the diagnostic output consisting of the
+string parameter
+.Fa s ,
+the constant string ": ", 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
+parameter.
.Sh FILES
-.Bl -tag -width /etc/hosts -compact
+.Bl -tag -width /etc/resolv.conf -compact
.It Pa /etc/hosts
+.It Pa /etc/host.conf
+.It Pa /etc/resolv.conf
.El
.Sh DIAGNOSTICS
Error return status from
-.Fn gethostbyname
+.Fn gethostbyname ,
+.Fn gethostbyname2
and
.Fn gethostbyaddr
is indicated by return of a null pointer.
@@ -220,7 +271,8 @@ If the
.Fa stayopen
argument is non-zero,
the file will not be closed after each call to
-.Fn gethostbyname
+.Fn gethostbyname ,
+.Fn gethostbyname2
or
.Fn gethostbyaddr .
.Pp
@@ -242,6 +294,9 @@ and
.Fn sethostent
functions appeared in
.Bx 4.2 .
+The
+.Fn gethostbyname2
+function first appeared in bind-4.9.4.
.Sh BUGS
These functions use static data storage;
if the data is needed for future use, it should be
diff --git a/lib/libc/net/gethostbynis.c b/lib/libc/net/gethostbynis.c
new file mode 100644
index 0000000..45dbe5a
--- /dev/null
+++ b/lib/libc/net/gethostbynis.c
@@ -0,0 +1,142 @@
+/*-
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)$Id$";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+#ifdef YP
+static char *host_aliases[MAXALIASES];
+static char hostaddr[MAXADDRS];
+static char *host_addrs[2];
+#endif /* YP */
+
+static struct hostent *
+_gethostbynis(name, map, af)
+ const char *name;
+ char *map;
+ int af;
+{
+#ifdef YP
+ register char *cp, **q;
+ char *result;
+ int resultlen;
+ static struct hostent h;
+ static char *domain = (char *)NULL;
+ static char ypbuf[YPMAXRECORD + 2];
+
+ switch(af) {
+ case AF_INET:
+ break;
+ default:
+ case AF_INET6:
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+
+ if (domain == (char *)NULL)
+ if (yp_get_default_domain (&domain))
+ return ((struct hostent *)NULL);
+
+ if (yp_match(domain, map, name, strlen(name), &result, &resultlen))
+ return ((struct hostent *)NULL);
+
+ /* avoid potential memory leak */
+ bcopy((char *)result, (char *)&ypbuf, resultlen);
+ ypbuf[resultlen] = '\0';
+ free(result);
+ result = (char *)&ypbuf;
+
+ if ((cp = index(result, '\n')))
+ *cp = '\0';
+
+ cp = strpbrk(result, " \t");
+ *cp++ = '\0';
+ h.h_addr_list = host_addrs;
+ h.h_addr = hostaddr;
+ *((u_long *)h.h_addr) = inet_addr(result);
+ h.h_length = sizeof(u_long);
+ h.h_addrtype = AF_INET;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ h.h_name = cp;
+ q = h.h_aliases = host_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &host_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&h);
+#else
+ return (NULL);
+#endif /* YP */
+}
+
+struct hostent *
+_gethostbynisname(name, af)
+ const char *name;
+ int af;
+{
+ return _gethostbynis(name, "hosts.byname", af);
+}
+
+struct hostent *
+_gethostbynisaddr(addr, len, af)
+ const char *addr;
+ int len;
+ int af;
+{
+ return _gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr", af);
+}
diff --git a/lib/libc/net/gethostnamadr.c b/lib/libc/net/gethostnamadr.c
index e0cc9aa..1912bba 100644
--- a/lib/libc/net/gethostnamadr.c
+++ b/lib/libc/net/gethostnamadr.c
@@ -1,6 +1,5 @@
/*-
- * Copyright (c) 1985, 1988, 1993
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1994, Garrett Wollman
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,15 +9,8 @@
* 2. Redistributions in binary form must 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
+ * 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
@@ -29,424 +21,204 @@
* LIABILITY, OR TORT (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 rcsid[] = "$Id: gethnamaddr.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $";
+static char sccsid[] = "@(#)$Id$";
+static char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <arpa/nameser.h>
#include <netdb.h>
-#include <resolv.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
-
-#define MAXALIASES 35
-#define MAXADDRS 35
-
-static char *h_addr_ptrs[MAXADDRS + 1];
-
-static struct hostent host;
-static char *host_aliases[MAXALIASES];
-static char hostbuf[BUFSIZ+1];
-static struct in_addr host_addr;
-static FILE *hostf = NULL;
-static char hostaddr[MAXADDRS];
-static char *host_addrs[2];
-static int stayopen = 0;
-char *strpbrk();
-
-#if PACKETSZ > 1024
-#define MAXPACKET PACKETSZ
-#else
-#define MAXPACKET 1024
-#endif
-
-typedef union {
- HEADER hdr;
- u_char buf[MAXPACKET];
-} querybuf;
-
-typedef union {
- int32_t al;
- char ac;
-} align;
-
-extern int h_errno;
-
-static struct hostent *
-getanswer(answer, anslen, iquery)
- querybuf *answer;
- int anslen;
- int iquery;
-{
- register HEADER *hp;
- register u_char *cp;
- register int n;
- u_char *eom;
- char *bp, **ap;
- int type, class, buflen, ancount, qdcount;
- int haveanswer, getclass = C_ANY;
- char **hap;
-
- eom = answer->buf + anslen;
- /*
- * find first satisfactory answer
- */
- hp = &answer->hdr;
- ancount = ntohs(hp->ancount);
- qdcount = ntohs(hp->qdcount);
- bp = hostbuf;
- buflen = sizeof(hostbuf);
- cp = answer->buf + sizeof(HEADER);
- if (qdcount) {
- if (iquery) {
- if ((n = dn_expand((u_char *)answer->buf,
- (u_char *)eom, (u_char *)cp, (u_char *)bp,
- buflen)) < 0) {
- h_errno = NO_RECOVERY;
- return ((struct hostent *) NULL);
- }
- cp += n + QFIXEDSZ;
- host.h_name = bp;
- n = strlen(bp) + 1;
- bp += n;
- buflen -= n;
- } else
- cp += __dn_skipname(cp, eom) + QFIXEDSZ;
- while (--qdcount > 0)
- cp += __dn_skipname(cp, eom) + QFIXEDSZ;
- } else if (iquery) {
- if (hp->aa)
- h_errno = HOST_NOT_FOUND;
- else
- h_errno = TRY_AGAIN;
- return ((struct hostent *) NULL);
- }
- ap = host_aliases;
- *ap = NULL;
- host.h_aliases = host_aliases;
- hap = h_addr_ptrs;
- *hap = NULL;
-#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
- host.h_addr_list = h_addr_ptrs;
-#endif
- haveanswer = 0;
- while (--ancount >= 0 && cp < eom) {
- if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom,
- (u_char *)cp, (u_char *)bp, buflen)) < 0)
- break;
- cp += n;
- type = _getshort(cp);
- cp += sizeof(u_int16_t);
- class = _getshort(cp);
- cp += sizeof(u_int16_t) + sizeof(u_int32_t);
- n = _getshort(cp);
- cp += sizeof(u_int16_t);
- if (type == T_CNAME) {
- cp += n;
- if (ap >= &host_aliases[MAXALIASES-1])
- continue;
- *ap++ = bp;
- n = strlen(bp) + 1;
- bp += n;
- buflen -= n;
- continue;
+#include <arpa/nameser.h> /* XXX hack for _res */
+#include <resolv.h> /* XXX hack for _res */
+
+#define _PATH_HOSTCONF "/etc/host.conf"
+
+enum service_type {
+ SERVICE_NONE = 0,
+ SERVICE_BIND,
+ SERVICE_HOSTS,
+ SERVICE_NIS };
+#define SERVICE_MAX SERVICE_NIS
+
+static struct {
+ const char *name;
+ enum service_type type;
+} service_names[] = {
+ { "hosts", SERVICE_HOSTS },
+ { "/etc/hosts", SERVICE_HOSTS },
+ { "hosttable", SERVICE_HOSTS },
+ { "htable", SERVICE_HOSTS },
+ { "bind", SERVICE_BIND },
+ { "dns", SERVICE_BIND },
+ { "domain", SERVICE_BIND },
+ { "yp", SERVICE_NIS },
+ { "yellowpages", SERVICE_NIS },
+ { "nis", SERVICE_NIS },
+ { 0, SERVICE_NONE }
+};
+
+static enum service_type service_order[SERVICE_MAX + 1];
+static int service_done = 0;
+
+static enum service_type
+get_service_name(const char *name) {
+ int i;
+ for(i = 0; service_names[i].type != SERVICE_NONE; i++) {
+ if(!strcasecmp(name, service_names[i].name)) {
+ return service_names[i].type;
}
- if (iquery && type == T_PTR) {
- if ((n = dn_expand((u_char *)answer->buf,
- (u_char *)eom, (u_char *)cp, (u_char *)bp,
- buflen)) < 0)
- break;
- cp += n;
- host.h_name = bp;
- return(&host);
- }
- if (iquery || type != T_A) {
-#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf("unexpected answer type %d, size %d\n",
- type, n);
-#endif
- cp += n;
- continue;
- }
- if (haveanswer) {
- if (n != host.h_length) {
- cp += n;
- continue;
- }
- if (class != getclass) {
- cp += n;
- continue;
- }
- } else {
- host.h_length = n;
- getclass = class;
- host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
- if (!iquery) {
- host.h_name = bp;
- bp += strlen(bp) + 1;
- }
- }
-
- bp += sizeof(align) - ((u_int32_t)bp % sizeof(align));
-
- if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
-#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf("size (%d) too big\n", n);
-#endif
- break;
- }
- bcopy(cp, *hap++ = bp, n);
- bp +=n;
- cp += n;
- haveanswer++;
- }
- if (haveanswer) {
- *ap = NULL;
-#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
- *hap = NULL;
-#else
- host.h_addr = h_addr_ptrs[0];
-#endif
- return (&host);
- } else {
- h_errno = TRY_AGAIN;
- return ((struct hostent *) NULL);
}
+ return SERVICE_NONE;
}
-struct hostent *
-gethostbyname(name)
- const char *name;
+static void
+init_services()
{
- querybuf buf;
- register const char *cp;
- int n;
- extern struct hostent *_gethtbyname();
+ char *cp, *p, buf[BUFSIZ];
+ register int cc = 0;
+ FILE *fd;
+
+ if ((fd = (FILE *)fopen(_PATH_HOSTCONF, "r")) == NULL) {
+ /* make some assumptions */
+ service_order[0] = SERVICE_BIND;
+ service_order[1] = SERVICE_HOSTS;
+ service_order[2] = SERVICE_NONE;
+ } else {
+ while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) {
+ if(buf[0] == '#')
+ continue;
- /*
- * disallow names consisting only of digits/dots, unless
- * they end in a dot.
- */
- if (isdigit(name[0]))
- for (cp = name;; ++cp) {
- if (!*cp) {
- if (*--cp == '.')
- break;
- /*
- * All-numeric, no dot at the end.
- * Fake up a hostent as if we'd actually
- * done a lookup.
- */
- if (!inet_aton(name, &host_addr)) {
- h_errno = HOST_NOT_FOUND;
- return((struct hostent *) NULL);
+ p = buf;
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ if (cp == NULL)
+ continue;
+ do {
+ if (isalpha(cp[0])) {
+ service_order[cc] = get_service_name(cp);
+ if(service_order[cc] != SERVICE_NONE)
+ cc++;
}
- host.h_name = (char *)name;
- host.h_aliases = host_aliases;
- host_aliases[0] = NULL;
- host.h_addrtype = AF_INET;
- host.h_length = sizeof(u_int32_t);
- h_addr_ptrs[0] = (char *)&host_addr;
- h_addr_ptrs[1] = (char *)0;
-#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
- host.h_addr_list = h_addr_ptrs;
-#else
- host.h_addr = h_addr_ptrs[0];
-#endif
- return (&host);
- }
- if (!isdigit(*cp) && *cp != '.')
- break;
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ } while(cp != NULL && cc < SERVICE_MAX);
}
-
- if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
-#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf("res_search failed\n");
-#endif
- if (errno == ECONNREFUSED)
- return (_gethtbyname(name));
- else
- return ((struct hostent *) NULL);
+ service_order[cc] = SERVICE_NONE;
+ fclose(fd);
}
- return (getanswer(&buf, n, 0));
+ service_done = 1;
}
struct hostent *
-gethostbyaddr(addr, len, type)
- const char *addr;
- int len, type;
+gethostbyname(const char *name)
{
- int n;
- querybuf buf;
- register struct hostent *hp;
- char qbuf[MAXDNAME];
- extern struct hostent *_gethtbyaddr();
-
- if (type != AF_INET)
- return ((struct hostent *) NULL);
- (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
- ((unsigned)addr[3] & 0xff),
- ((unsigned)addr[2] & 0xff),
- ((unsigned)addr[1] & 0xff),
- ((unsigned)addr[0] & 0xff));
- n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf));
- if (n < 0) {
-#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf("res_query failed\n");
-#endif
- if (errno == ECONNREFUSED)
- return (_gethtbyaddr(addr, len, type));
- return ((struct hostent *) NULL);
- }
- hp = getanswer(&buf, n, 1);
- if (hp == NULL)
- return ((struct hostent *) NULL);
- hp->h_addrtype = type;
- hp->h_length = len;
- h_addr_ptrs[0] = (char *)&host_addr;
- h_addr_ptrs[1] = (char *)0;
- host_addr = *(struct in_addr *)addr;
-#if BSD < 43 && !defined(h_addr) /* new-style hostent structure */
- hp->h_addr = h_addr_ptrs[0];
-#endif
- return(hp);
+ struct hostent *hp;
+
+ if (_res.options & RES_USE_INET6) { /* XXX */
+ hp = gethostbyname2(name, AF_INET6); /* XXX */
+ if (hp) /* XXX */
+ return (hp); /* XXX */
+ } /* XXX */
+ return (gethostbyname2(name, AF_INET));
}
-void
-_sethtent(f)
- int f;
-{
- if (hostf == NULL)
- hostf = fopen(_PATH_HOSTS, "r" );
- else
- rewind(hostf);
- stayopen |= f;
-}
-
-void
-_endhtent()
+struct hostent *
+gethostbyname2(const char *name, int type)
{
- if (hostf && !stayopen) {
- (void) fclose(hostf);
- hostf = NULL;
+ struct hostent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return NULL;
+ case SERVICE_HOSTS:
+ hp = _gethostbyhtname(name, type);
+ break;
+ case SERVICE_BIND:
+ hp = _gethostbydnsname(name, type);
+ break;
+ case SERVICE_NIS:
+ hp = _gethostbynisname(name, type);
+ break;
+ }
+ nserv++;
}
+ return hp;
}
struct hostent *
-_gethtent()
+gethostbyaddr(const char *addr, int len, int type)
{
- char *p;
- register char *cp, **q;
-
- if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL)
- return (NULL);
-again:
- if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
- return (NULL);
- if (*p == '#')
- goto again;
- cp = strpbrk(p, "#\n");
- if (cp == NULL)
- goto again;
- *cp = '\0';
- cp = strpbrk(p, " \t");
- if (cp == NULL)
- goto again;
- *cp++ = '\0';
- /* THIS STUFF IS INTERNET SPECIFIC */
-#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
- host.h_addr_list = host_addrs;
-#endif
- host.h_addr = hostaddr;
- *((u_int32_t *)host.h_addr) = inet_addr(p);
- host.h_length = sizeof (u_int32_t);
- host.h_addrtype = AF_INET;
- while (*cp == ' ' || *cp == '\t')
- cp++;
- host.h_name = cp;
- q = host.h_aliases = host_aliases;
- cp = strpbrk(cp, " \t");
- if (cp != NULL)
- *cp++ = '\0';
- while (cp && *cp) {
- if (*cp == ' ' || *cp == '\t') {
- cp++;
- continue;
+ struct hostent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return 0;
+ case SERVICE_HOSTS:
+ hp = _gethostbyhtaddr(addr, len, type);
+ break;
+ case SERVICE_BIND:
+ hp = _gethostbydnsaddr(addr, len, type);
+ break;
+ case SERVICE_NIS:
+ hp = _gethostbynisaddr(addr, len, type);
+ break;
}
- if (q < &host_aliases[MAXALIASES - 1])
- *q++ = cp;
- cp = strpbrk(cp, " \t");
- if (cp != NULL)
- *cp++ = '\0';
+ nserv++;
}
- *q = NULL;
- return (&host);
+ return hp;
}
-struct hostent *
-_gethtbyname(name)
- char *name;
+#ifdef _THREAD_SAFE
+struct hostent_data;
+
+/*
+ * Temporary function (not thread safe)
+ */
+int gethostbyaddr_r(const char *addr, int len, int type,
+ struct hostent *result, struct hostent_data *buffer)
{
- register struct hostent *p;
- register char **cp;
-
- _sethtent(0);
- while (p = _gethtent()) {
- if (strcasecmp(p->h_name, name) == 0)
- break;
- for (cp = p->h_aliases; *cp != 0; cp++)
- if (strcasecmp(*cp, name) == 0)
- goto found;
+ struct hostent *hp = 0;
+ int ret;
+ if ((hp = gethostbyaddr(addr, len, type)) == NULL) {
+ ret = -1;
+ } else {
+ memcpy(result, hp, sizeof(struct hostent));
+ ret = 0;
}
-found:
- _endhtent();
- return (p);
+ return(ret);
}
+#endif
-struct hostent *
-_gethtbyaddr(addr, len, type)
- const char *addr;
- int len, type;
+void
+sethostent(stayopen)
+ int stayopen;
{
- register struct hostent *p;
+ _sethosthtent(stayopen);
+ _sethostdnsent(stayopen);
+}
- _sethtent(0);
- while (p = _gethtent())
- if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
- break;
- _endhtent();
- return (p);
+void
+endhostent()
+{
+ _endhosthtent();
+ _endhostdnsent();
}
diff --git a/lib/libc/net/getnetbydns.c b/lib/libc/net/getnetbydns.c
new file mode 100644
index 0000000..2228a5c
--- /dev/null
+++ b/lib/libc/net/getnetbydns.c
@@ -0,0 +1,310 @@
+/*-
+ * 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--
+ */
+/* 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";
+static char rcsid[] = "$Id: getnetbydns.c,v 1.10 1997/02/22 15:00:10 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#include "res_config.h"
+
+extern int h_errno;
+
+#define BYADDR 0
+#define BYNAME 1
+#define MAXALIASES 35
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+ long al;
+ char ac;
+} align;
+
+static struct netent *
+getnetanswer(answer, anslen, net_i)
+ querybuf *answer;
+ int anslen;
+ int net_i;
+{
+
+ register HEADER *hp;
+ register u_char *cp;
+ register int n;
+ u_char *eom;
+ int type, class, buflen, ancount, qdcount, haveanswer, i, nchar;
+ char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap,
+ *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
+static struct netent net_entry;
+static char *net_aliases[MAXALIASES], netbuf[PACKETSZ];
+
+ /*
+ * 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 = netbuf;
+ buflen = sizeof(netbuf);
+ cp = answer->buf + HFIXEDSZ;
+ if (!qdcount) {
+ if (hp->aa)
+ h_errno = HOST_NOT_FOUND;
+ else
+ h_errno = TRY_AGAIN;
+ return (NULL);
+ }
+ while (qdcount-- > 0)
+ cp += __dn_skipname(cp, eom) + QFIXEDSZ;
+ ap = net_aliases;
+ *ap = NULL;
+ net_entry.n_aliases = net_aliases;
+ haveanswer = 0;
+ while (--ancount >= 0 && cp < eom) {
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !res_dnok(bp))
+ break;
+ cp += n;
+ ans[0] = '\0';
+ (void)strcpy(&ans[0], bp);
+ 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, buflen);
+ if ((n < 0) || !res_hnok(bp)) {
+ cp += n;
+ return (NULL);
+ }
+ cp += n;
+ *ap++ = bp;
+ bp += strlen(bp) + 1;
+ net_entry.n_addrtype =
+ (class == C_IN) ? AF_INET : AF_UNSPEC;
+ haveanswer++;
+ }
+ }
+ if (haveanswer) {
+ *ap = NULL;
+ switch (net_i) {
+ case BYADDR:
+ net_entry.n_name = *net_entry.n_aliases;
+ net_entry.n_net = 0L;
+ break;
+ case BYNAME:
+ in = *net_entry.n_aliases;
+ net_entry.n_name = &ans[0];
+ aux2[0] = '\0';
+ for (i = 0; i < 4; i++) {
+ for (st = in, nchar = 0;
+ *st != '.';
+ st++, nchar++)
+ ;
+ if (nchar != 1 || *in != '0' || flag) {
+ flag = 1;
+ (void)strncpy(paux1,
+ (i==0) ? in : in-1,
+ (i==0) ?nchar : nchar+1);
+ paux1[(i==0) ? nchar : nchar+1] = '\0';
+ pauxt = paux2;
+ paux2 = strcat(paux1, paux2);
+ paux1 = pauxt;
+ }
+ in = ++st;
+ }
+ net_entry.n_net = inet_network(paux2);
+ break;
+ }
+ net_entry.n_aliases++;
+ return (&net_entry);
+ }
+ h_errno = TRY_AGAIN;
+ return (NULL);
+}
+
+struct netent *
+_getnetbydnsaddr(net, net_type)
+ register unsigned long net;
+ register int net_type;
+{
+ unsigned int netbr[4];
+ int nn, anslen;
+ querybuf buf;
+ char qbuf[MAXDNAME];
+ unsigned long net2;
+ struct netent *net_entry;
+
+ if (net_type != AF_INET)
+ return (NULL);
+
+ 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;
+ }
+ anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+ if (anslen < 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf("res_query failed\n");
+#endif
+ return (NULL);
+ }
+ net_entry = getnetanswer(&buf, anslen, BYADDR);
+ if (net_entry) {
+ unsigned u_net = net; /* maybe net should be unsigned ? */
+
+ /* Strip trailing zeros */
+ while ((u_net & 0xff) == 0 && u_net != 0)
+ u_net >>= 8;
+ net_entry->n_net = u_net;
+ return (net_entry);
+ }
+ return (NULL);
+}
+
+struct netent *
+_getnetbydnsname(net)
+ register const char *net;
+{
+ int anslen;
+ querybuf buf;
+ char qbuf[MAXDNAME];
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ strcpy(&qbuf[0], net);
+ anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+ if (anslen < 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf("res_query failed\n");
+#endif
+ return (NULL);
+ }
+ return getnetanswer(&buf, anslen, BYNAME);
+}
+
+void
+_setnetdnsent(stayopen)
+ int stayopen;
+{
+ if (stayopen)
+ _res.options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+_endnetdnsent()
+{
+ _res.options &= ~(RES_STAYOPEN | RES_USEVC);
+ res_close();
+}
diff --git a/lib/libc/net/getnetbyht.c b/lib/libc/net/getnetbyht.c
new file mode 100644
index 0000000..f7b7b10
--- /dev/null
+++ b/lib/libc/net/getnetbyht.c
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ * 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 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";
+static chat rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+#define MAXALIASES 35
+
+static FILE *netf;
+static char line[BUFSIZ+1];
+static struct netent net;
+static char *net_aliases[MAXALIASES];
+static int _net_stayopen;
+
+void
+_setnethtent(f)
+ int f;
+{
+
+ if (netf == NULL)
+ netf = fopen(_PATH_NETWORKS, "r" );
+ else
+ rewind(netf);
+ _net_stayopen |= f;
+}
+
+void
+_endnethtent()
+{
+
+ if (netf) {
+ fclose(netf);
+ netf = NULL;
+ }
+ _net_stayopen = 0;
+}
+
+struct netent *
+getnetent()
+{
+ char *p;
+ register char *cp, **q;
+
+ if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
+ return (NULL);
+again:
+ p = fgets(line, sizeof line, netf);
+ if (p == NULL)
+ return (NULL);
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+ goto again;
+ *cp = '\0';
+ net.n_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';
+ net.n_net = inet_network(cp);
+ net.n_addrtype = AF_INET;
+ q = net.n_aliases = net_aliases;
+ if (p != NULL)
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &net_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&net);
+}
+
+struct netent *
+_getnetbyhtname(name)
+ register const char *name;
+{
+ register struct netent *p;
+ register char **cp;
+
+ setnetent(_net_stayopen);
+ while ( (p = getnetent()) ) {
+ if (strcasecmp(p->n_name, name) == 0)
+ break;
+ for (cp = p->n_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ if (!_net_stayopen)
+ endnetent();
+ return (p);
+}
+
+struct netent *
+_getnetbyhtaddr(net, type)
+ register unsigned long net;
+ register int type;
+{
+ register struct netent *p;
+
+ setnetent(_net_stayopen);
+ while ( (p = getnetent()) )
+ if (p->n_addrtype == type && p->n_net == net)
+ break;
+ if (!_net_stayopen)
+ endnetent();
+ return (p);
+}
diff --git a/lib/libc/net/getnetbynis.c b/lib/libc/net/getnetbynis.c
new file mode 100644
index 0000000..0549016
--- /dev/null
+++ b/lib/libc/net/getnetbynis.c
@@ -0,0 +1,177 @@
+/*-
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)$Id$";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <arpa/nameser.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+#ifdef YP
+static char *host_aliases[MAXALIASES];
+#endif /* YP */
+
+static struct netent *
+_getnetbynis(name, map, af)
+ const char *name;
+ char *map;
+ int af;
+{
+#ifdef YP
+ register char *cp, **q;
+ static char *result;
+ int resultlen;
+ static struct netent h;
+ static char *domain = (char *)NULL;
+ static char ypbuf[YPMAXRECORD + 2];
+
+ switch(af) {
+ case AF_INET:
+ break;
+ default:
+ case AF_INET6:
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+
+ if (domain == (char *)NULL)
+ if (yp_get_default_domain (&domain))
+ return (NULL);
+
+ if (yp_match(domain, map, name, strlen(name), &result, &resultlen))
+ return (NULL);
+
+ bcopy((char *)result, (char *)&ypbuf, resultlen);
+ ypbuf[resultlen] = '\0';
+ free(result);
+ result = (char *)&ypbuf;
+
+ if ((cp = index(result, '\n')))
+ *cp = '\0';
+
+ cp = strpbrk(result, " \t");
+ *cp++ = '\0';
+ h.n_name = result;
+
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+
+ h.n_net = inet_network(cp);
+ h.n_addrtype = AF_INET;
+
+ q = h.n_aliases = host_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &host_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&h);
+#else
+ return (NULL);
+#endif
+}
+
+struct netent *
+_getnetbynisname(name)
+ const char *name;
+{
+ return _getnetbynis(name, "networks.byname", AF_INET);
+}
+
+struct netent *
+_getnetbynisaddr(addr, af)
+ unsigned long addr;
+ int af;
+{
+ char *str, *cp;
+ unsigned long net2;
+ int nn;
+ unsigned int netbr[4];
+ char buf[MAXDNAME];
+
+ if (af != AF_INET) {
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+
+ 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);
+ }
+
+ return _getnetbynis(str, "networks.byaddr", af);
+}
diff --git a/lib/libc/net/getnetent.3 b/lib/libc/net/getnetent.3
index 7514371c..8fb13c0 100644
--- a/lib/libc/net/getnetent.3
+++ b/lib/libc/net/getnetent.3
@@ -44,13 +44,15 @@
.Sh SYNOPSIS
.Fd #include <netdb.h>
.Ft struct netent *
-.Fn getnetent
+.Fn getnetent void
.Ft struct netent *
-.Fn getnetbyname "char *name"
+.Fn getnetbyname "const char *name"
.Ft struct netent *
-.Fn getnetbyaddr "long net" "int type"
+.Fn getnetbyaddr "unsigned long net" "int type"
+.Ft void
.Fn setnetent "int stayopen"
-.Fn endnetent
+.Ft void
+.Fn endnetent void
.Sh DESCRIPTION
The
.Fn getnetent ,
@@ -117,7 +119,10 @@ net name or
net address and type is found,
or until
.Dv EOF
-is encountered.
+is encountered. The
+.Fa type
+must be
+.Dv AF_INET .
Network numbers are supplied in host order.
.Sh FILES
.Bl -tag -width /etc/networks -compact
@@ -130,6 +135,8 @@ Null pointer
or error.
.Sh SEE ALSO
.Xr networks 5
+.Pp
+.%T RFC 1101
.Sh HISTORY
The
.Fn getnetent ,
diff --git a/lib/libc/net/getnetnamadr.c b/lib/libc/net/getnetnamadr.c
new file mode 100644
index 0000000..c964cff
--- /dev/null
+++ b/lib/libc/net/getnetnamadr.c
@@ -0,0 +1,190 @@
+/*-
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id: getnetnamadr.c,v 1.9 1997/02/22 15:00:12 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#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>
+
+#ifndef _PATH_NETCONF
+#define _PATH_NETCONF "/etc/host.conf"
+#endif
+
+enum service_type {
+ SERVICE_NONE = 0,
+ SERVICE_BIND,
+ SERVICE_TABLE,
+ SERVICE_NIS };
+#define SERVICE_MAX SERVICE_NIS
+
+static struct {
+ const char *name;
+ enum service_type type;
+} service_names[] = {
+ { "hosts", SERVICE_TABLE },
+ { "/etc/hosts", SERVICE_TABLE },
+ { "hosttable", SERVICE_TABLE },
+ { "htable", SERVICE_TABLE },
+ { "bind", SERVICE_BIND },
+ { "dns", SERVICE_BIND },
+ { "domain", SERVICE_BIND },
+ { "yp", SERVICE_NIS },
+ { "yellowpages", SERVICE_NIS },
+ { "nis", SERVICE_NIS },
+ { 0, SERVICE_NONE }
+};
+
+static enum service_type service_order[SERVICE_MAX + 1];
+static int service_done = 0;
+
+static enum service_type
+get_service_name(const char *name) {
+ int i;
+ for(i = 0; service_names[i].type != SERVICE_NONE; i++) {
+ if(!strcasecmp(name, service_names[i].name)) {
+ return service_names[i].type;
+ }
+ }
+ return SERVICE_NONE;
+}
+
+static void
+init_services()
+{
+ char *cp, *p, buf[BUFSIZ];
+ register int cc = 0;
+ FILE *fd;
+
+ if ((fd = (FILE *)fopen(_PATH_NETCONF, "r")) == NULL) {
+ /* make some assumptions */
+ service_order[0] = SERVICE_TABLE;
+ service_order[1] = SERVICE_NONE;
+ } else {
+ while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) {
+ if(buf[0] == '#')
+ continue;
+
+ p = buf;
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ if (cp == NULL)
+ continue;
+ do {
+ if (isalpha(cp[0])) {
+ service_order[cc] = get_service_name(cp);
+ if(service_order[cc] != SERVICE_NONE)
+ cc++;
+ }
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ } while(cp != NULL && cc < SERVICE_MAX);
+ }
+ service_order[cc] = SERVICE_NONE;
+ fclose(fd);
+ }
+ service_done = 1;
+}
+
+struct netent *
+getnetbyname(const char *name)
+{
+ struct netent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return NULL;
+ case SERVICE_TABLE:
+ hp = _getnetbyhtname(name);
+ break;
+ case SERVICE_BIND:
+ hp = _getnetbydnsname(name);
+ break;
+ case SERVICE_NIS:
+ hp = _getnetbynisname(name);
+ break;
+ }
+ nserv++;
+ }
+ return hp;
+}
+
+struct netent *
+getnetbyaddr(addr, af)
+ u_long addr;
+ int af;
+{
+ struct netent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return 0;
+ case SERVICE_TABLE:
+ hp = _getnetbyhtaddr(addr, af);
+ break;
+ case SERVICE_BIND:
+ hp = _getnetbydnsaddr(addr, af);
+ break;
+ case SERVICE_NIS:
+ hp = _getnetbynisaddr(addr, af);
+ break;
+ }
+ nserv++;
+ }
+ return hp;
+}
+
+void
+setnetent(stayopen)
+ int stayopen;
+{
+ _setnethtent(stayopen);
+ _setnetdnsent(stayopen);
+}
+
+void
+endnetent()
+{
+ _endnethtent();
+ _endnetdnsent();
+}
diff --git a/lib/libc/net/getproto.c b/lib/libc/net/getproto.c
index 92f562b..46f46d3 100644
--- a/lib/libc/net/getproto.c
+++ b/lib/libc/net/getproto.c
@@ -46,7 +46,7 @@ getprotobynumber(proto)
register struct protoent *p;
setprotoent(_proto_stayopen);
- while (p = getprotoent())
+ while ( (p = getprotoent()) )
if (p->p_proto == proto)
break;
if (!_proto_stayopen)
diff --git a/lib/libc/net/getprotoent.3 b/lib/libc/net/getprotoent.3
index d5d610e..dbf3d1a 100644
--- a/lib/libc/net/getprotoent.3
+++ b/lib/libc/net/getprotoent.3
@@ -44,13 +44,15 @@
.Sh SYNOPSIS
.Fd #include <netdb.h>
.Ft struct protoent *
-.Fn getprotoent
+.Fn getprotoent void
.Ft struct protoent *
-.Fn getprotobyname "char *name"
+.Fn getprotobyname "const char *name"
.Ft struct protoent *
.Fn getprotobynumber "int proto"
+.Ft void
.Fn setprotoent "int stayopen"
-.Fn endprotoent
+.Ft void
+.Fn endprotoent void
.Sh DESCRIPTION
The
.Fn getprotoent ,
diff --git a/lib/libc/net/getprotoname.c b/lib/libc/net/getprotoname.c
index 3ee6754..0832acf 100644
--- a/lib/libc/net/getprotoname.c
+++ b/lib/libc/net/getprotoname.c
@@ -48,7 +48,7 @@ getprotobyname(name)
register char **cp;
setprotoent(_proto_stayopen);
- while (p = getprotoent()) {
+ while ( (p = getprotoent()) ) {
if (strcmp(p->p_name, name) == 0)
break;
for (cp = p->p_aliases; *cp != 0; cp++)
diff --git a/lib/libc/net/getservbyname.c b/lib/libc/net/getservbyname.c
index 77bf813..124f5ac 100644
--- a/lib/libc/net/getservbyname.c
+++ b/lib/libc/net/getservbyname.c
@@ -47,8 +47,16 @@ getservbyname(name, proto)
register struct servent *p;
register char **cp;
+#ifdef YP
+ extern char *___getservbyname_yp;
+ extern char *___getservbyproto_yp;
+
+ ___getservbyname_yp = (char *)name;
+ ___getservbyproto_yp = (char *)proto;
+#endif
+
setservent(_serv_stayopen);
- while (p = getservent()) {
+ while ( (p = getservent()) ) {
if (strcmp(name, p->s_name) == 0)
goto gotname;
for (cp = p->s_aliases; *cp; cp++)
@@ -61,5 +69,11 @@ gotname:
}
if (!_serv_stayopen)
endservent();
+
+#ifdef YP
+ ___getservbyname_yp = NULL;
+ ___getservbyproto_yp = NULL;
+#endif
+
return (p);
}
diff --git a/lib/libc/net/getservbyport.c b/lib/libc/net/getservbyport.c
index 0acb31b..ef9a2e8 100644
--- a/lib/libc/net/getservbyport.c
+++ b/lib/libc/net/getservbyport.c
@@ -47,8 +47,16 @@ getservbyport(port, proto)
{
register struct servent *p;
+#ifdef YP
+ extern int ___getservbyport_yp;
+ extern char *___getservbyproto_yp;
+
+ ___getservbyport_yp = port;
+ ___getservbyproto_yp = (char *)proto;
+#endif
+
setservent(_serv_stayopen);
- while (p = getservent()) {
+ while ( (p = getservent()) ) {
if (p->s_port != port)
continue;
if (proto == 0 || strcmp(p->s_proto, proto) == 0)
@@ -56,5 +64,11 @@ getservbyport(port, proto)
}
if (!_serv_stayopen)
endservent();
+
+#ifdef YP
+ ___getservbyport_yp = 0;
+ ___getservbyproto_yp = NULL;
+#endif
+
return (p);
}
diff --git a/lib/libc/net/getservent.3 b/lib/libc/net/getservent.3
index f90571e..79c18a3 100644
--- a/lib/libc/net/getservent.3
+++ b/lib/libc/net/getservent.3
@@ -29,9 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)getservent.3 8.4 (Berkeley) 5/25/95
+.\" From: @(#)getservent.3 8.3 (Berkeley) 1/12/94
+.\" $Id$
.\"
-.Dd May 25, 1995
+.Dd July 9, 1995
.Dt GETSERVENT 3
.Os BSD 4.2
.Sh NAME
@@ -46,9 +47,9 @@
.Ft struct servent *
.Fn getservent
.Ft struct servent *
-.Fn getservbyname "char *name" "char *proto"
+.Fn getservbyname "const char *name" "const char *proto"
.Ft struct servent *
-.Fn getservbyport "int port" proto
+.Fn getservbyport "int port" "const char *proto"
.Ft void
.Fn setservent "int stayopen"
.Ft void
@@ -79,7 +80,7 @@ The members of this structure are:
.It Fa s_name
The official name of the service.
.It Fa s_aliases
-A NULL-terminated list of alternate names for the service.
+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.
@@ -121,7 +122,7 @@ port number is found,
or until
.Dv EOF
is encountered.
-If a protocol name is also supplied (non-\c
+If a protocol name is also supplied (non-
.Dv NULL ) ,
searches must also match the protocol.
.ne 1i
diff --git a/lib/libc/net/getservent.c b/lib/libc/net/getservent.c
index 6bee5d3..cd4449f 100644
--- a/lib/libc/net/getservent.c
+++ b/lib/libc/net/getservent.c
@@ -41,6 +41,14 @@ static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+static int serv_stepping_yp = 0;
+extern int _yp_check __P(( char ** ));
+#endif
+
#define MAXALIASES 35
@@ -50,6 +58,133 @@ static struct servent serv;
static char *serv_aliases[MAXALIASES];
int _serv_stayopen;
+#ifdef YP
+char *___getservbyname_yp = NULL;
+char *___getservbyproto_yp = NULL;
+int ___getservbyport_yp = 0;
+static char *yp_domain = NULL;
+
+static int
+_getservbyport_yp(line)
+ char *line;
+{
+ char *result;
+ int resultlen;
+ char buf[YPMAXRECORD + 2];
+ int rv;
+
+ snprintf(buf, sizeof(buf), "%d/%s", ntohs(___getservbyport_yp),
+ ___getservbyproto_yp);
+
+ ___getservbyport_yp = 0;
+ ___getservbyproto_yp = NULL;
+
+ if(!yp_domain) {
+ if(yp_get_default_domain(&yp_domain))
+ return (0);
+ }
+
+ /*
+ * 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.
+ */
+ if ((rv = yp_match(yp_domain, "services.byport", buf, strlen(buf),
+ &result, &resultlen))) {
+ if (rv == YPERR_MAP) {
+ if (yp_match(yp_domain, "services.byname", buf,
+ strlen(buf), &result, &resultlen))
+ return(0);
+ } else
+ return(0);
+ }
+
+ /* getservent() expects lines terminated with \n -- make it happy */
+ snprintf(line, BUFSIZ, "%.*s\n", resultlen, result);
+
+ free(result);
+ return(1);
+}
+
+static int
+_getservbyname_yp(line)
+ char *line;
+{
+ char *result;
+ int resultlen;
+ char buf[YPMAXRECORD + 2];
+
+ if(!yp_domain) {
+ if(yp_get_default_domain(&yp_domain))
+ return (0);
+ }
+
+ snprintf(buf, sizeof(buf), "%s/%s", ___getservbyname_yp,
+ ___getservbyproto_yp);
+
+ ___getservbyname_yp = 0;
+ ___getservbyproto_yp = NULL;
+
+ if (yp_match(yp_domain, "services.byname", buf, strlen(buf),
+ &result, &resultlen)) {
+ return(0);
+ }
+
+ /* getservent() expects lines terminated with \n -- make it happy */
+ snprintf(line, BUFSIZ, "%.*s\n", resultlen, result);
+
+ free(result);
+ return(1);
+}
+
+static int
+_getservent_yp(line)
+ char *line;
+{
+ static char *key = NULL;
+ static int keylen;
+ char *lastkey, *result;
+ int resultlen;
+ int rv;
+
+ if(!yp_domain) {
+ if(yp_get_default_domain(&yp_domain))
+ return (0);
+ }
+
+ if (!serv_stepping_yp) {
+ if (key)
+ free(key);
+ if ((rv = yp_first(yp_domain, "services.byname", &key, &keylen,
+ &result, &resultlen))) {
+ serv_stepping_yp = 0;
+ return(0);
+ }
+ serv_stepping_yp = 1;
+ } else {
+ lastkey = key;
+ rv = yp_next(yp_domain, "services.byname", key, keylen, &key,
+ &keylen, &result, &resultlen);
+ free(lastkey);
+ if (rv) {
+ serv_stepping_yp = 0;
+ return (0);
+ }
+ }
+
+ /* getservent() expects lines terminated with \n -- make it happy */
+ snprintf(line, BUFSIZ, "%.*s\n", resultlen, result);
+
+ free(result);
+
+ return(1);
+}
+#endif
+
void
setservent(f)
int f;
@@ -77,11 +212,33 @@ getservent()
char *p;
register char *cp, **q;
+#ifdef YP
+ if (serv_stepping_yp && _getservent_yp(line)) {
+ p = (char *)&line;
+ goto unpack;
+ }
+tryagain:
+#endif
if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL)
return (NULL);
again:
if ((p = fgets(line, BUFSIZ, servf)) == NULL)
return (NULL);
+#ifdef YP
+ if (*p == '+' && _yp_check(NULL)) {
+ if (___getservbyname_yp != NULL) {
+ if (!_getservbyname_yp(line))
+ goto tryagain;
+ }
+ else if (___getservbyport_yp != 0) {
+ if (!_getservbyport_yp(line))
+ goto tryagain;
+ }
+ else if (!_getservent_yp(line))
+ goto tryagain;
+ }
+unpack:
+#endif
if (*p == '#')
goto again;
cp = strpbrk(p, "#\n");
diff --git a/lib/libc/net/herror.c b/lib/libc/net/herror.c
index 0366b04..f22f519 100644
--- a/lib/libc/net/herror.c
+++ b/lib/libc/net/herror.c
@@ -31,14 +31,14 @@
* 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
@@ -53,7 +53,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: herror.c,v 4.9.1.1 1993/05/02 23:14:35 vixie Rel $";
+static char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -62,14 +62,14 @@ static char rcsid[] = "$Id: herror.c,v 4.9.1.1 1993/05/02 23:14:35 vixie Rel $";
#include <unistd.h>
#include <string.h>
-char *h_errlist[] = {
- "Error 0",
+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 */
};
-int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
+int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
extern int h_errno;
@@ -92,8 +92,7 @@ herror(s)
v->iov_len = 2;
v++;
}
- v->iov_base = (u_int)h_errno < h_nerr ?
- h_errlist[h_errno] : "Unknown error";
+ v->iov_base = (char *)hstrerror(h_errno);
v->iov_len = strlen(v->iov_base);
v++;
v->iov_base = "\n";
@@ -101,9 +100,13 @@ herror(s)
writev(STDERR_FILENO, iov, (v - iov) + 1);
}
-char *
+const char *
hstrerror(err)
int err;
{
- return (u_int)err < h_nerr ? h_errlist[err] : "Unknown resolver error";
+ if (err < 0)
+ return ("Resolver internal error");
+ else if (err < h_nerr)
+ return (h_errlist[err]);
+ return ("Unknown resolver error");
}
diff --git a/lib/libc/net/inet.3 b/lib/libc/net/inet.3
index 9318f45..6ad1bc6 100644
--- a/lib/libc/net/inet.3
+++ b/lib/libc/net/inet.3
@@ -29,9 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)inet.3 8.1 (Berkeley) 6/4/93
+.\" From: @(#)inet.3 8.1 (Berkeley) 6/4/93
+.\" $Id: inet.3,v 1.5 1997/02/22 15:00:15 peter Exp $
.\"
-.Dd June 4, 1993
+.Dd June 17, 1996
.Dt INET 3
.Os BSD 4.2
.Sh NAME
@@ -44,19 +45,20 @@
.Nm inet_netof
.Nd Internet address manipulation routines
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
.Fd #include <sys/socket.h>
.Fd #include <netinet/in.h>
.Fd #include <arpa/inet.h>
.Ft int
-.Fn inet_aton "char *cp" "struct in_addr *pin"
+.Fn inet_aton "const char *cp" "struct in_addr *pin"
.Ft unsigned long
-.Fn inet_addr "char *cp"
+.Fn inet_addr "const char *cp"
.Ft unsigned long
-.Fn inet_network "char *cp"
+.Fn inet_network "const char *cp"
.Ft char *
.Fn inet_ntoa "struct in_addr in"
.Ft struct in_addr
-.Fn inet_makeaddr "int net" "int lna"
+.Fn inet_makeaddr "unsigned long net" "unsigned long lna"
.Ft unsigned long
.Fn inet_lnaof "struct in_addr in"
.Ft unsigned long
@@ -159,6 +161,18 @@ 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).
+.Pp
+The
+.Fn inet_aton
+and
+.Fn inet_ntoa
+functions are semi-deprecated in favor of the
+.Xr addr2ascii 3
+family. However, since those functions are not yet widely implemented,
+portable programs cannot rely on their presence and will continue
+to use the
+.Xr inet 3
+functions for some time.
.Sh DIAGNOSTICS
The constant
.Dv INADDR_NONE
@@ -168,10 +182,11 @@ and
.Fn inet_network
for malformed requests.
.Sh SEE ALSO
+.Xr addr2ascii 3 ,
.Xr gethostbyname 3 ,
.Xr getnetent 3 ,
.Xr hosts 5 ,
-.Xr networks 5 ,
+.Xr networks 5
.Sh HISTORY
These
functions appeared in
diff --git a/lib/libc/net/inet_addr.c b/lib/libc/net/inet_addr.c
index 246a418..a1ac899 100644
--- a/lib/libc/net/inet_addr.c
+++ b/lib/libc/net/inet_addr.c
@@ -1,7 +1,9 @@
/*
+ * ++Copyright++ 1983, 1990, 1993
+ * -
* Copyright (c) 1983, 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
+ * The Regents of the University of California. All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -12,12 +14,12 @@
* 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.
+ * 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
@@ -29,10 +31,31 @@
* LIABILITY, OR TORT (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[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
+static char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
@@ -73,50 +96,52 @@ inet_aton(cp, addr)
u_int parts[4];
register u_int *pp = parts;
+ c = *cp;
for (;;) {
/*
* Collect number up to ``.''.
* Values are specified as for C:
- * 0x=hex, 0=octal, other=decimal.
+ * 0x=hex, 0=octal, isdigit=decimal.
*/
+ if (!isdigit(c))
+ return (0);
val = 0; base = 10;
- if (*cp == '0') {
- if (*++cp == 'x' || *cp == 'X')
- base = 16, cp++;
+ if (c == '0') {
+ c = *++cp;
+ if (c == 'x' || c == 'X')
+ base = 16, c = *++cp;
else
base = 8;
}
- while ((c = *cp) != '\0') {
+ for (;;) {
if (isascii(c) && isdigit(c)) {
val = (val * base) + (c - '0');
- cp++;
- continue;
- }
- if (base == 16 && isascii(c) && isxdigit(c)) {
- val = (val << 4) +
+ c = *++cp;
+ } else if (base == 16 && isascii(c) && isxdigit(c)) {
+ val = (val << 4) |
(c + 10 - (islower(c) ? 'a' : 'A'));
- cp++;
- continue;
- }
- break;
+ c = *++cp;
+ } else
+ break;
}
- if (*cp == '.') {
+ if (c == '.') {
/*
* Internet format:
* a.b.c.d
- * a.b.c (with c treated as 16-bits)
+ * a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
*/
- if (pp >= parts + 3 || val > 0xff)
+ if (pp >= parts + 3)
return (0);
- *pp++ = val, cp++;
+ *pp++ = val;
+ c = *++cp;
} else
break;
}
/*
* Check for trailing characters.
*/
- if (*cp && (!isascii(*cp) || !isspace(*cp)))
+ if (c != '\0' && (!isascii(c) || !isspace(c)))
return (0);
/*
* Concoct the address according to
@@ -125,6 +150,9 @@ inet_aton(cp, addr)
n = pp - parts + 1;
switch (n) {
+ case 0:
+ return (0); /* initial nondigit */
+
case 1: /* a -- 32 bits */
break;
diff --git a/lib/libc/net/inet_net_ntop.c b/lib/libc/net/inet_net_ntop.c
new file mode 100644
index 0000000..4c7893d
--- /dev/null
+++ b/lib/libc/net/inet_net_ntop.c
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char orig_rcsid[] = "From Id: inet_net_ntop.c,v 8.2 1996/08/08 06:54:44 vixie Exp";
+static const char rcsid[] = "$Id$";
+#endif
+
+#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>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char * inet_net_ntop_ipv4 __P((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));
+ 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
+ * 0x11110000 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';
+ *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);
+}
diff --git a/lib/libc/net/inet_net_pton.c b/lib/libc/net/inet_net_pton.c
new file mode 100644
index 0000000..6fd6a06
--- /dev/null
+++ b/lib/libc/net/inet_net_pton.c
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char orig_rcsid[] = "From Id: inet_net_pton.c,v 8.3 1996/11/11 06:36:52 vixie Exp";
+static const char rcsid[] = "$Id$";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.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 __P((const char *src, u_char *dst,
+ size_t size));
+
+/*
+ * static 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(af, src, dst, size)
+ int af;
+ const char *src;
+ void *dst;
+ size_t size;
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_net_pton_ipv4(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+}
+
+/*
+ * 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
+ * 0x11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+static int
+inet_net_pton_ipv4(src, dst, size)
+ const char *src;
+ u_char *dst;
+ size_t size;
+{
+ static const char
+ xdigits[] = "0123456789abcdef",
+ digits[] = "0123456789";
+ int n, ch, tmp, dirty, bits;
+ const u_char *odst = dst;
+
+ ch = *src++;
+ if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
+ && isascii(src[1]) && isxdigit(src[1])) {
+ /* Hexadecimal: Eat nybble string. */
+ if (size <= 0)
+ goto emsgsize;
+ *dst = 0, 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);
+ *dst |= n;
+ if (!dirty++)
+ *dst <<= 4;
+ else if (size-- > 0)
+ *++dst = 0, dirty = 0;
+ else
+ goto emsgsize;
+ }
+ if (dirty)
+ size--;
+ } 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-- <= 0)
+ 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(src[0]) && isdigit(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;
+ } while ((ch = *src++) != '\0' &&
+ isascii(ch) && isdigit(ch));
+ if (ch != '\0')
+ goto enoent;
+ if (bits > 32)
+ goto emsgsize;
+ }
+
+ /* 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 = 4;
+ 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 >= 8 && bits < ((dst - odst) * 8))
+ bits = (dst - odst) * 8;
+ }
+ /* Extend network to cover the actual mask. */
+ while (bits > ((dst - odst) * 8)) {
+ if (size-- <= 0)
+ goto emsgsize;
+ *dst++ = '\0';
+ }
+ return (bits);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
diff --git a/lib/libc/net/inet_neta.c b/lib/libc/net/inet_neta.c
new file mode 100644
index 0000000..15a1c70
--- /dev/null
+++ b/lib/libc/net/inet_neta.c
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char orig_rcsid[] = "From Id: inet_neta.c,v 8.2 1996/08/08 06:54:44 vixie Exp";
+static const char rcsid[] = "$Id$";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.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 a u_long 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)
+ u_long 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);
+}
diff --git a/lib/libc/net/inet_network.c b/lib/libc/net/inet_network.c
index fda53b6..6da2e8b 100644
--- a/lib/libc/net/inet_network.c
+++ b/lib/libc/net/inet_network.c
@@ -60,7 +60,7 @@ again:
base = 8, cp++;
if (*cp == 'x' || *cp == 'X')
base = 16, cp++;
- while (c = *cp) {
+ while ( (c = *cp) ) {
if (isdigit(c)) {
val = (val * base) + (c - '0');
cp++;
@@ -74,7 +74,7 @@ again:
break;
}
if (*cp == '.') {
- if (pp >= parts + 4)
+ if (pp >= parts + 3)
return (INADDR_NONE);
*pp++ = val, cp++;
goto again;
@@ -83,8 +83,6 @@ again:
return (INADDR_NONE);
*pp++ = val;
n = pp - parts;
- if (n > 4)
- return (INADDR_NONE);
for (val = 0, i = 0; i < n; i++) {
val <<= 8;
val |= parts[i] & 0xff;
diff --git a/lib/libc/net/inet_ntop.c b/lib/libc/net/inet_ntop.c
new file mode 100644
index 0000000..36dcb32
--- /dev/null
+++ b/lib/libc/net/inet_ntop.c
@@ -0,0 +1,190 @@
+/* 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#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 <stdio.h>
+
+#define SPRINTF(x) ((size_t)sprintf x)
+
+/*
+ * 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 __P((const u_char *src, char *dst, size_t size));
+static const char *inet_ntop6 __P((const u_char *src, char *dst, size_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(af, src, dst, size)
+ int af;
+ const void *src;
+ char *dst;
+ size_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, more or less like inet_ntoa()
+ * 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(src, dst, size)
+ const u_char *src;
+ char *dst;
+ size_t size;
+{
+ static const char fmt[] = "%u.%u.%u.%u";
+ char tmp[sizeof "255.255.255.255"];
+
+ if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ 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(src, dst, size)
+ const u_char *src;
+ 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"], *tp;
+ struct { int base, len; } best, cur;
+ u_int words[IN6ADDRSZ / 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 < IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ cur.base = -1;
+ for (i = 0; i < (IN6ADDRSZ / 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 < (IN6ADDRSZ / 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 == 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) == (IN6ADDRSZ / INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t)(tp - tmp) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
diff --git a/lib/libc/net/inet_pton.c b/lib/libc/net/inet_pton.c
new file mode 100644
index 0000000..054ff7d
--- /dev/null
+++ b/lib/libc/net/inet_pton.c
@@ -0,0 +1,214 @@
+/* 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#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>
+
+/*
+ * 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 __P((const char *src, u_char *dst));
+static int inet_pton6 __P((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(af, src, dst)
+ int af;
+ const char *src;
+ void *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(src, dst)
+ const char *src;
+ u_char *dst;
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ u_char tmp[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 (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, 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(src, dst)
+ const char *src;
+ u_char *dst;
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+
+ memset((tp = tmp), '\0', IN6ADDRSZ);
+ endp = tp + IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 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 (val > 0xffff)
+ return (0);
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ }
+ if (tp + INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (saw_xdigit) {
+ if (tp + 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;
+
+ 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, IN6ADDRSZ);
+ return (1);
+}
diff --git a/lib/libc/net/iso_addr.c b/lib/libc/net/iso_addr.c
index 9ca92f3..8829497 100644
--- a/lib/libc/net/iso_addr.c
+++ b/lib/libc/net/iso_addr.c
@@ -65,7 +65,7 @@ iso_addr(addr)
new = *addr - 'a' + 10;
} else if ((*addr >= 'A') && (*addr <= 'F')) {
new = *addr - 'A' + 10;
- } else if (*addr == 0)
+ } else if (*addr == 0)
state |= END;
else
state |= DELIM;
@@ -86,34 +86,32 @@ iso_addr(addr)
break;
}
break;
- } while (cp < cplim);
+ } while (cp < cplim);
out_addr.isoa_len = cp - out_addr.isoa_genaddr;
return (&out_addr);
}
+
static char hexlist[] = "0123456789abcdef";
char *
iso_ntoa(isoa)
const struct iso_addr *isoa;
{
- static char obuf[64];
- register char *out = obuf;
- register int i;
- register u_char *in = (u_char *)isoa->isoa_genaddr;
- u_char *inlim = in + isoa->isoa_len;
+ static char tmpbuf[sizeof(isoa->isoa_genaddr)*3];
+ const u_char *binary;
+ char *cp;
+ int i;
+
+ binary = isoa->isoa_genaddr;
+ cp = tmpbuf;
+
+ for (i = 0; i < isoa->isoa_len; i++) {
+ *cp++ = hexlist[*binary >> 4];
+ *cp++ = hexlist[*binary++ & 0xf];
- out[1] = 0;
- while (in < inlim) {
- i = *in++;
- *out++ = '.';
- if (i > 0xf) {
- out[1] = hexlist[i & 0xf];
- i >>= 4;
- out[0] = hexlist[i];
- out += 2;
- } else
- *out++ = hexlist[i];
+ if ((((i % 2) == 0) && ((i + 1) < isoa->isoa_len)))
+ *cp++ = '.';
}
- *out = 0;
- return(obuf + 1);
+ *cp = '\0';
+ return tmpbuf;
}
diff --git a/lib/libc/net/linkaddr.3 b/lib/libc/net/linkaddr.3
index 54e3206..6999add 100644
--- a/lib/libc/net/linkaddr.3
+++ b/lib/libc/net/linkaddr.3
@@ -32,9 +32,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)linkaddr.3 8.1 (Berkeley) 7/28/93
+.\" From: @(#)linkaddr.3 8.1 (Berkeley) 7/28/93
+.\" $Id$
.\"
-.Dd July 28, 1993
+.Dd June 17, 1996
.Dt LINK_ADDR 3
.Os BSD 4.4
.Sh NAME
@@ -75,7 +76,7 @@ may contain
an optional network interface identifier of the form
.Dq "name unit-number" ,
suitable for the first argument to
-.Xr ifconfig 4 ,
+.Xr ifconfig 8 ,
followed in all cases by a colon and
an interface address in the form of
groups of hexadecimal digits
@@ -93,6 +94,11 @@ Thus
.Li le0:8.0.9.13.d.30
represents an ethernet address
to be transmitted on the first Lance ethernet interface.
+.Pp
+The direct use of these functions is deprecated in favor of the
+.Xr addr2ascii 3
+interface; however, portable programs cannot rely on the latter as it is
+not yet widely implemented.
.Sh RETURN VALUES
.Fn link_ntoa
always returns a null terminated string.
@@ -101,7 +107,8 @@ has no return value.
(See
.Sx BUGS . )
.Sh SEE ALSO
-.Xr iso 4 ,
+.Xr addr2ascii 3
+.\" .Xr iso 4
.Sh HISTORY
The
.Fn link_addr
diff --git a/lib/libc/net/linkaddr.c b/lib/libc/net/linkaddr.c
index 50ab392..68eed3d 100644
--- a/lib/libc/net/linkaddr.c
+++ b/lib/libc/net/linkaddr.c
@@ -112,7 +112,7 @@ link_addr(addr, sdl)
break;
}
break;
- } while (cp < cplim);
+ } while (cp < cplim);
sdl->sdl_alen = cp - LLADDR(sdl);
new = cp - (char *)sdl;
if (new > sizeof(*sdl))
@@ -127,7 +127,7 @@ link_ntoa(sdl)
register const struct sockaddr_dl *sdl;
{
static char obuf[64];
- register char *out = obuf;
+ register char *out = obuf;
register int i;
register u_char *in = (u_char *)LLADDR(sdl);
u_char *inlim = in + sdl->sdl_alen;
diff --git a/lib/libc/net/map_v4v6.c b/lib/libc/net/map_v4v6.c
new file mode 100644
index 0000000..0f8658e
--- /dev/null
+++ b/lib/libc/net/map_v4v6.c
@@ -0,0 +1,128 @@
+/*
+ * ++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--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#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 <errno.h>
+#include <syslog.h>
+
+typedef union {
+ int32_t al;
+ char ac;
+} align;
+
+void
+_map_v4v6_address(src, dst)
+ const char *src;
+ char *dst;
+{
+ u_char *p = (u_char *)dst;
+ char tmp[INADDRSZ];
+ int i;
+
+ /* Stash a temporary copy so our caller can update in place. */
+ bcopy(src, tmp, 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. */
+ bcopy(tmp, (void*)p, INADDRSZ);
+}
+
+void
+_map_v4v6_hostent(hp, bpp, lenp)
+ struct hostent *hp;
+ char **bpp;
+ int *lenp;
+{
+ 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 = sizeof(align) - ((u_long)*bpp % sizeof(align));
+
+ if (*lenp < (i + IN6ADDRSZ)) {
+ /* Out of memory. Truncate address list here. XXX */
+ *ap = NULL;
+ return;
+ }
+ *bpp += i;
+ *lenp -= i;
+ _map_v4v6_address(*ap, *bpp);
+ *ap = *bpp;
+ *bpp += IN6ADDRSZ;
+ *lenp -= IN6ADDRSZ;
+ }
+}
diff --git a/lib/libc/net/ns.3 b/lib/libc/net/ns.3
index 8646826..e621ad2 100644
--- a/lib/libc/net/ns.3
+++ b/lib/libc/net/ns.3
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)ns.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt NS 3
@@ -112,7 +113,7 @@ None. (See
.Sx BUGS . )
.Sh SEE ALSO
.Xr hosts 5 ,
-.Xr networks 5 ,
+.Xr networks 5
.Sh HISTORY
The
.Fn ns_addr
diff --git a/lib/libc/net/ns_addr.c b/lib/libc/net/ns_addr.c
index 9b0b9d1..3446e08 100644
--- a/lib/libc/net/ns_addr.c
+++ b/lib/libc/net/ns_addr.c
@@ -47,7 +47,7 @@ static struct ns_addr addr, zero_addr;
static void Field(), cvtbase();
-struct ns_addr
+struct ns_addr
ns_addr(name)
const char *name;
{
@@ -64,7 +64,7 @@ ns_addr(name)
* form 2-272.AA001234H.01777, i.e. XDE standard.
* Great efforts are made to insure backward compatability.
*/
- if (hostname = strchr(buf, '#'))
+ if ((hostname = strchr(buf, '#')) != NULL)
separator = '#';
else {
hostname = strchr(buf, '.');
@@ -157,7 +157,7 @@ Field(buf, out, len)
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
base16 = 1;
break;
-
+
case 'x': case 'X':
*--bp = '0';
base16 = 1;
diff --git a/lib/libc/net/nsap_addr.c b/lib/libc/net/nsap_addr.c
new file mode 100644
index 0000000..b0c6433
--- /dev/null
+++ b/lib/libc/net/nsap_addr.c
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+
+static char
+xtob(c)
+ register int c;
+{
+ return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
+}
+
+u_int
+inet_nsap_addr(ascii, binary, maxlen)
+ const char *ascii;
+ u_char *binary;
+ int maxlen;
+{
+ register u_char c, nib;
+ u_int len = 0;
+
+ while ((c = *ascii++) != '\0' && len < maxlen) {
+ if (c == '.' || c == '+' || c == '/')
+ continue;
+ if (!isascii(c))
+ return (0);
+ if (islower(c))
+ c = toupper(c);
+ if (isxdigit(c)) {
+ nib = xtob(c);
+ if ((c = *ascii++) != '\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(binlen, binary, ascii)
+ int binlen;
+ register const u_char *binary;
+ register char *ascii;
+{
+ register int nib;
+ int i;
+ static char tmpbuf[255*3];
+ char *start;
+
+ if (ascii)
+ start = ascii;
+ else {
+ ascii = tmpbuf;
+ start = tmpbuf;
+ }
+
+ 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);
+}
diff --git a/lib/libc/net/rcmd.3 b/lib/libc/net/rcmd.3
index 014ef98..e25057f 100644
--- a/lib/libc/net/rcmd.3
+++ b/lib/libc/net/rcmd.3
@@ -29,14 +29,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)rcmd.3 8.1 (Berkeley) 6/4/93
+.\" From: @(#)rcmd.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
-.Dd June 4, 1993
+.Dd February 15, 1996
.Dt RCMD 3
.Os BSD 4.2
.Sh NAME
.Nm rcmd ,
.Nm rresvport ,
+.Nm iruserok ,
.Nm ruserok
.Nd routines for returning a stream to a remote command
.Sh SYNOPSIS
@@ -150,7 +152,7 @@ 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 writeable by anyone other
+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
@@ -162,7 +164,7 @@ and
.Fn ruserok
return \-1.
If the local domain (as obtained from
-.Xr gethostname 2 )
+.Xr gethostname 3 )
is the same as the remote domain, only the machine name need be specified.
.Pp
The
diff --git a/lib/libc/net/rcmd.c b/lib/libc/net/rcmd.c
index 279b9bd..ff108d9 100644
--- a/lib/libc/net/rcmd.c
+++ b/lib/libc/net/rcmd.c
@@ -51,6 +51,15 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
#include <stdio.h>
#include <ctype.h>
#include <string.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+extern int innetgr __P(( const char *, const char *, const char *, const char * ));
+
+#define max(a, b) ((a > b) ? a : b)
int __ivaliduser __P((FILE *, u_long, const char *, const char *));
static int __icheckhost __P((u_long, char *));
@@ -91,9 +100,11 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
return (-1);
}
fcntl(s, F_SETOWN, pid);
+ bzero(&sin, sizeof sin);
+ sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_family = hp->h_addrtype;
- bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
sin.sin_port = rport;
+ bcopy(hp->h_addr_list[0], &sin.sin_addr, MIN(hp->h_length, sizeof sin.sin_addr));
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
break;
(void)close(s);
@@ -114,7 +125,7 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
errno = oerrno;
perror(0);
hp->h_addr_list++;
- bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
+ bcopy(hp->h_addr_list[0], &sin.sin_addr, MIN(hp->h_length, sizeof sin.sin_addr));
(void)fprintf(stderr, "Trying %s...\n",
inet_ntoa(sin.sin_addr));
continue;
@@ -131,6 +142,7 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
char num[8];
int s2 = rresvport(&lport), s3;
int len = sizeof(from);
+ int nfds;
if (s2 < 0)
goto bad;
@@ -143,11 +155,18 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
(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(32, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)) {
+ 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",
@@ -159,6 +178,14 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
goto bad;
}
s3 = accept(s2, (struct sockaddr *)&from, &len);
+ /*
+ * XXX careful for ftp bounce attacks. If discovered, shut them
+ * down and check for the real auxiliary channel to connect.
+ */
+ if (from.sin_family == AF_INET && from.sin_port == htons(20)) {
+ close(s3);
+ goto again;
+ }
(void)close(s2);
if (s3 < 0) {
(void)fprintf(stderr,
@@ -210,26 +237,29 @@ rresvport(alport)
struct sockaddr_in sin;
int s;
+ bzero(&sin, sizeof sin);
+ sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
return (-1);
- for (;;) {
- 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);
- }
- (*alport)--;
- if (*alport == IPPORT_RESERVED/2) {
- (void)close(s);
- errno = EAGAIN; /* close */
- 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
+ sin.sin_port = 0;
+ if (bindresvport(s, &sin) == -1) {
+ (void)close(s);
+ return (-1);
}
+ *alport = (int)ntohs(sin.sin_port);
+ return (s);
}
int __check_rhosts_file = 1;
@@ -347,6 +377,24 @@ __ivaliduser(hostf, raddr, luser, ruser)
register char *user, *p;
int ch;
char buf[MAXHOSTNAMELEN + 128]; /* host + login */
+ char hname[MAXHOSTNAMELEN];
+ struct hostent *hp;
+ /* 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 ((hp = gethostbyaddr((char *)&raddr, sizeof(u_long),
+ AF_INET)) == NULL)
+ return (-1);
+ strncpy(hname, hp->h_name, sizeof(hname));
+ hname[sizeof(hname) - 1] = '\0';
while (fgets(buf, sizeof(buf), hostf)) {
p = buf;
@@ -355,6 +403,10 @@ __ivaliduser(hostf, raddr, luser, ruser)
while ((ch = getc(hostf)) != '\n' && ch != EOF);
continue;
}
+ if (*p == '\n' || *p == '#') {
+ /* comment... */
+ continue;
+ }
while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
*p = isupper(*p) ? tolower(*p) : *p;
p++;
@@ -370,10 +422,68 @@ __ivaliduser(hostf, raddr, luser, ruser)
} else
user = p;
*p = '\0';
- if (__icheckhost(raddr, buf) &&
- strcmp(ruser, *user ? user : luser) == 0) {
- return (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 = innetgr((char *)&buf[2],
+ (char *)&hname, NULL, ypdomain);
+ else /* match a host by addr */
+ hostok = __icheckhost(raddr,(char *)&buf[1]);
+ break;
+ case '-': /* reject '-' hosts and all their users */
+ if (buf[1] == '@') {
+ if (innetgr((char *)&buf[2],
+ (char *)&hname, NULL, ypdomain))
+ return(-1);
+ } else {
+ if (__icheckhost(raddr,(char *)&buf[1]))
+ return(-1);
+ }
+ break;
+ default: /* if no '+' or '-', do a simple match */
+ hostok = __icheckhost(raddr, 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);
}
diff --git a/lib/libc/net/res_comp.c b/lib/libc/net/res_comp.c
new file mode 100644
index 0000000..86fd4ae
--- /dev/null
+++ b/lib/libc/net/res_comp.c
@@ -0,0 +1,496 @@
+/*
+ * ++Copyright++ 1985, 1993
+ * -
+ * 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.
+ * 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--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: res_comp.c,v 8.12 1997/06/01 20:34:37 vixie Exp";
+static char rcsid[] = "$Id: res_comp.c,v 1.11 1997/06/13 19:21:54 ache Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <resolv.h>
+#include <ctype.h>
+
+#include <unistd.h>
+#include <string.h>
+
+static int dn_find __P((u_char *exp_dn, u_char *msg,
+ u_char **dnptrs, u_char **lastdnptr));
+
+/*
+ * Expand compressed domain name 'comp_dn' to full domain name.
+ * 'msg' is a pointer to the begining of the message,
+ * 'eomorig' points to the first location after the message,
+ * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
+ * Return size of compressed name or -1 if there was an error.
+ */
+int
+dn_expand(msg, eomorig, comp_dn, exp_dn, length)
+ const u_char *msg, *eomorig, *comp_dn;
+ char *exp_dn;
+ int length;
+{
+ register const u_char *cp;
+ register char *dn;
+ register int n, c;
+ char *eom;
+ int len = -1, checked = 0, octets = 0;
+
+ dn = exp_dn;
+ cp = comp_dn;
+ eom = exp_dn + length;
+ /*
+ * fetch next label in domain name
+ */
+ while ( (n = *cp++) ) {
+ /*
+ * Check for indirection
+ */
+ switch (n & INDIR_MASK) {
+ case 0:
+ octets += (n + 1);
+ if (octets > MAXCDNAME)
+ return (-1);
+ if (dn != exp_dn) {
+ if (dn >= eom)
+ return (-1);
+ *dn++ = '.';
+ }
+ if (dn+n >= eom)
+ return (-1);
+ checked += n + 1;
+ while (--n >= 0) {
+ if (((c = *cp++) == '.') || (c == '\\')) {
+ if (dn + n + 2 >= eom)
+ return (-1);
+ *dn++ = '\\';
+ }
+ *dn++ = c;
+ if (cp >= eomorig) /* out of range */
+ return (-1);
+ }
+ break;
+
+ case INDIR_MASK:
+ if (len < 0)
+ len = cp - comp_dn + 1;
+ cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
+ if (cp < msg || cp >= eomorig) /* out of range */
+ 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 >= eomorig - msg)
+ return (-1);
+ break;
+
+ default:
+ return (-1); /* flag error */
+ }
+ }
+ *dn = '\0';
+ if (len < 0)
+ len = cp - comp_dn;
+ return (len);
+}
+
+/*
+ * Compress domain name 'exp_dn' into 'comp_dn'.
+ * Return the size of the compressed name or -1.
+ * 'length' is the size of the array pointed to by 'comp_dn'.
+ * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
+ * is a pointer to the beginning of the message. The list ends with NULL.
+ * 'lastdnptr' is a pointer to the end of the arrary pointed to
+ * by 'dnptrs'. Side effect is to update the list of pointers 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
+dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
+ const char *exp_dn;
+ u_char *comp_dn, **dnptrs, **lastdnptr;
+ int length;
+{
+ register u_char *cp, *dn;
+ register int c, l;
+ u_char **cpp, **lpp, *sp, *eob;
+ u_char *msg;
+
+ dn = (u_char *)exp_dn;
+ cp = comp_dn;
+ if (length > MAXCDNAME)
+ length = MAXCDNAME;
+ eob = cp + length;
+ lpp = cpp = NULL;
+ if (dnptrs != NULL) {
+ if ((msg = *dnptrs++) != NULL) {
+ for (cpp = dnptrs; *cpp != NULL; cpp++)
+ ;
+ lpp = cpp; /* end of list to search */
+ }
+ } else
+ msg = NULL;
+ for (c = *dn++; c != '\0'; ) {
+ /* look to see if we can use pointers */
+ if (msg != NULL) {
+ if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
+ if (cp+1 >= eob)
+ return (-1);
+ *cp++ = (l >> 8) | INDIR_MASK;
+ *cp++ = l % 256;
+ return (cp - comp_dn);
+ }
+ /* not found, save it */
+ if (lastdnptr != NULL && cpp < lastdnptr-1) {
+ *cpp++ = cp;
+ *cpp = NULL;
+ }
+ }
+ sp = cp++; /* save ptr to length byte */
+ do {
+ if (c == '.') {
+ c = *dn++;
+ break;
+ }
+ if (c == '\\') {
+ if ((c = *dn++) == '\0')
+ break;
+ }
+ if (cp >= eob) {
+ if (msg != NULL)
+ *lpp = NULL;
+ return (-1);
+ }
+ *cp++ = c;
+ } while ((c = *dn++) != '\0');
+ /* catch trailing '.'s but not '..' */
+ if ((l = cp - sp - 1) == 0 && c == '\0') {
+ cp--;
+ break;
+ }
+ if (l <= 0 || l > MAXLABEL) {
+ if (msg != NULL)
+ *lpp = NULL;
+ return (-1);
+ }
+ *sp = l;
+ }
+ if (cp >= eob) {
+ if (msg != NULL)
+ *lpp = NULL;
+ return (-1);
+ }
+ *cp++ = '\0';
+ return (cp - comp_dn);
+}
+
+/*
+ * Skip over a compressed domain name. Return the size or -1.
+ */
+int
+__dn_skipname(comp_dn, eom)
+ const u_char *comp_dn, *eom;
+{
+ register const u_char *cp;
+ register int n;
+
+ cp = comp_dn;
+ while (cp < eom && (n = *cp++)) {
+ /*
+ * check for indirection
+ */
+ switch (n & INDIR_MASK) {
+ case 0: /* normal case, n == len */
+ cp += n;
+ continue;
+ case INDIR_MASK: /* indirection */
+ cp++;
+ break;
+ default: /* illegal type */
+ return (-1);
+ }
+ break;
+ }
+ if (cp > eom)
+ return (-1);
+ return (cp - comp_dn);
+}
+
+static int
+mklower(ch)
+ register int ch;
+{
+ if (isascii(ch) && isupper(ch))
+ return (tolower(ch));
+ return (ch);
+}
+
+/*
+ * Search for expanded name from a list of previously compressed names.
+ * Return the offset from msg if found or -1.
+ * dnptrs is the pointer to the first name on the list,
+ * not the pointer to the start of the message.
+ */
+static int
+dn_find(exp_dn, msg, dnptrs, lastdnptr)
+ u_char *exp_dn, *msg;
+ u_char **dnptrs, **lastdnptr;
+{
+ register u_char *dn, *cp, **cpp;
+ register int n;
+ u_char *sp;
+
+ for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+ dn = exp_dn;
+ sp = cp = *cpp;
+ while ( (n = *cp++) ) {
+ /*
+ * check for indirection
+ */
+ switch (n & INDIR_MASK) {
+ case 0: /* normal case, n == len */
+ while (--n >= 0) {
+ if (*dn == '.')
+ goto next;
+ if (*dn == '\\')
+ dn++;
+ if (mklower(*dn++) != mklower(*cp++))
+ goto next;
+ }
+ if ((n = *dn++) == '\0' && *cp == '\0')
+ return (sp - msg);
+ if (n == '.')
+ continue;
+ goto next;
+
+ case INDIR_MASK: /* indirection */
+ cp = msg + (((n & 0x3f) << 8) | *cp);
+ break;
+
+ default: /* illegal type */
+ return (-1);
+ }
+ }
+ if (*dn == '\0')
+ return (sp - msg);
+ next: ;
+ }
+ return (-1);
+}
+
+/*
+ * 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 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))
+#define middlechar(c) (borderchar(c) || hyphenchar(c))
+#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
+
+int
+res_hnok(dn)
+ const char *dn;
+{
+ int ppch = '\0', pch = PERIOD, ch = *dn++;
+
+ while (ch != '\0') {
+ int nch = *dn++;
+
+ if (periodchar(ch)) {
+ 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);
+ }
+ ppch = pch, 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(dn)
+ 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(dn)
+ 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 RFC 1034's character sets are only
+ * recommendations.
+ */
+int
+res_dnok(dn)
+ const char *dn;
+{
+ int ch;
+
+ while ((ch = *dn++) != '\0')
+ if (!domainchar(ch))
+ return (0);
+ return (1);
+}
+
+/*
+ * Routines to insert/extract short/long's.
+ */
+
+u_int16_t
+_getshort(msgp)
+ register const u_char *msgp;
+{
+ register u_int16_t u;
+
+ GETSHORT(u, msgp);
+ return (u);
+}
+
+u_int32_t
+_getlong(msgp)
+ register const u_char *msgp;
+{
+ register u_int32_t u;
+
+ GETLONG(u, msgp);
+ return (u);
+}
+
+void
+#if defined(__STDC__) || defined(__cplusplus)
+__putshort(register u_int16_t s, register u_char *msgp) /* must match proto */
+#else
+__putshort(s, msgp)
+ register u_int16_t s;
+ register u_char *msgp;
+#endif
+{
+ PUTSHORT(s, msgp);
+}
+
+void
+__putlong(l, msgp)
+ register u_int32_t l;
+ register u_char *msgp;
+{
+ PUTLONG(l, msgp);
+}
diff --git a/lib/libc/net/res_config.h b/lib/libc/net/res_config.h
new file mode 100644
index 0000000..f29246a
--- /dev/null
+++ b/lib/libc/net/res_config.h
@@ -0,0 +1,8 @@
+#define DEBUG 1 /* enable debugging code (needed for dig) */
+#undef ALLOW_T_UNSPEC /* enable the "unspec" RR type for old athena */
+#define RESOLVSORT /* allow sorting of addresses in gethostbyname */
+#define RFC1535 /* comply with RFC1535 (STRONGLY reccomended by vixie)*/
+#undef USELOOPBACK /* res_init() bind to localhost */
+#undef SUNSECURITY /* verify gethostbyaddr() calls - WE DONT NEED IT */
+#define MULTI_PTRS_ARE_ALIASES 1 /* fold multiple PTR records into aliases */
+#define CHECK_SRVR_ADDR 1 /* confirm that the server requested sent the reply */
diff --git a/lib/libc/net/res_data.c b/lib/libc/net/res_data.c
new file mode 100644
index 0000000..df0e0dd
--- /dev/null
+++ b/lib/libc/net/res_data.c
@@ -0,0 +1,111 @@
+/*
+ * ++Copyright++ 1995
+ * -
+ * 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.
+ * 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--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#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 <stdio.h>
+#include <ctype.h>
+#include <resolv.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+const char *_res_opcodes[] = {
+ "QUERY",
+ "IQUERY",
+ "CQUERYM",
+ "CQUERYU", /* experimental */
+ "NOTIFY", /* experimental */
+ "5",
+ "6",
+ "7",
+ "8",
+ "UPDATEA",
+ "UPDATED",
+ "UPDATEDA",
+ "UPDATEM",
+ "UPDATEMA",
+ "ZONEINIT",
+ "ZONEREF",
+};
+
+const char *_res_resultcodes[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "NOCHANGE",
+};
diff --git a/lib/libc/net/res_debug.c b/lib/libc/net/res_debug.c
new file mode 100644
index 0000000..06b8b42
--- /dev/null
+++ b/lib/libc/net/res_debug.c
@@ -0,0 +1,1520 @@
+/*
+ * ++Copyright++ 1985, 1990, 1993
+ * -
+ * Copyright (c) 1985, 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. 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.
+ * -
+ * 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--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: res_debug.c,v 8.20 1997/06/01 20:34:37 vixie Exp";
+static char rcsid[] = "$Id: res_debug.c,v 1.13 1997/02/22 15:00:31 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include "res_config.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 <ctype.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+extern const char *_res_opcodes[];
+extern const char *_res_resultcodes[];
+
+/* XXX: we should use getservbyport() instead. */
+static const char *
+dewks(wks)
+ int wks;
+{
+ static char nbuf[20];
+
+ switch (wks) {
+ case 5: return "rje";
+ case 7: return "echo";
+ case 9: return "discard";
+ case 11: return "systat";
+ case 13: return "daytime";
+ case 15: return "netstat";
+ case 17: return "qotd";
+ case 19: return "chargen";
+ case 20: return "ftp-data";
+ case 21: return "ftp";
+ case 23: return "telnet";
+ case 25: return "smtp";
+ case 37: return "time";
+ case 39: return "rlp";
+ case 42: return "name";
+ case 43: return "whois";
+ case 53: return "domain";
+ case 57: return "apts";
+ case 59: return "apfs";
+ case 67: return "bootps";
+ case 68: return "bootpc";
+ case 69: return "tftp";
+ case 77: return "rje";
+ case 79: return "finger";
+ case 87: return "link";
+ case 95: return "supdup";
+ case 100: return "newacct";
+ case 101: return "hostnames";
+ case 102: return "iso-tsap";
+ case 103: return "x400";
+ case 104: return "x400-snd";
+ case 105: return "csnet-ns";
+ case 109: return "pop-2";
+ case 111: return "sunrpc";
+ case 113: return "auth";
+ case 115: return "sftp";
+ case 117: return "uucp-path";
+ case 119: return "nntp";
+ case 121: return "erpc";
+ case 123: return "ntp";
+ case 133: return "statsrv";
+ case 136: return "profile";
+ case 144: return "NeWS";
+ case 161: return "snmp";
+ case 162: return "snmp-trap";
+ case 170: return "print-srv";
+ default: (void) sprintf(nbuf, "%d", wks); return (nbuf);
+ }
+}
+
+/* XXX: we should use getprotobynumber() instead. */
+static const char *
+deproto(protonum)
+ int protonum;
+{
+ static char nbuf[20];
+
+ switch (protonum) {
+ case 1: return "icmp";
+ case 2: return "igmp";
+ case 3: return "ggp";
+ case 5: return "st";
+ case 6: return "tcp";
+ case 7: return "ucl";
+ case 8: return "egp";
+ case 9: return "igp";
+ case 11: return "nvp-II";
+ case 12: return "pup";
+ case 16: return "chaos";
+ case 17: return "udp";
+ default: (void) sprintf(nbuf, "%d", protonum); return (nbuf);
+ }
+}
+
+static const u_char *
+do_rrset(msg, len, cp, cnt, pflag, file, hs)
+ int cnt, pflag, len;
+ const u_char *cp, *msg;
+ const char *hs;
+ FILE *file;
+{
+ int n;
+ int sflag;
+
+ /*
+ * Print answer records.
+ */
+ sflag = (_res.pfcode & pflag);
+ if ((n = ntohs(cnt)) != 0) {
+ if ((!_res.pfcode) ||
+ ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
+ fprintf(file, hs);
+ while (--n >= 0) {
+ if ((!_res.pfcode) || sflag) {
+ cp = p_rr(cp, msg, file);
+ } else {
+ unsigned int dlen;
+ cp += __dn_skipname(cp, cp + MAXCDNAME);
+ cp += INT16SZ;
+ cp += INT16SZ;
+ cp += INT32SZ;
+ dlen = _getshort((u_char*)cp);
+ cp += INT16SZ;
+ cp += dlen;
+ }
+ if ((cp - msg) > len)
+ return (NULL);
+ }
+ if ((!_res.pfcode) ||
+ ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
+ putc('\n', file);
+ }
+ return (cp);
+}
+
+void
+__p_query(msg)
+ const u_char *msg;
+{
+ __fp_query(msg, stdout);
+}
+
+/*
+ * Print the current options.
+ * This is intended to be primarily a debugging routine.
+ */
+void
+__fp_resstat(statp, file)
+ struct __res_state *statp;
+ FILE *file;
+{
+ register u_long mask;
+
+ fprintf(file, ";; res options:");
+ if (!statp)
+ statp = &_res;
+ for (mask = 1; mask != 0; mask <<= 1)
+ if (statp->options & mask)
+ fprintf(file, " %s", p_option(mask));
+ putc('\n', file);
+}
+
+/*
+ * Print the contents of a query.
+ * This is intended to be primarily a debugging routine.
+ */
+void
+__fp_nquery(msg, len, file)
+ const u_char *msg;
+ int len;
+ FILE *file;
+{
+ register const u_char *cp, *endMark;
+ register const HEADER *hp;
+ register int n;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return;
+
+#define TruncTest(x) if (x > endMark) goto trunc
+#define ErrorTest(x) if (x == NULL) goto error
+
+ /*
+ * Print header fields.
+ */
+ hp = (HEADER *)msg;
+ cp = msg + HFIXEDSZ;
+ endMark = msg + len;
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
+ fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
+ _res_opcodes[hp->opcode],
+ _res_resultcodes[hp->rcode],
+ ntohs(hp->id));
+ putc('\n', file);
+ }
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
+ putc(';', file);
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
+ fprintf(file, "; flags:");
+ if (hp->qr)
+ fprintf(file, " qr");
+ if (hp->aa)
+ fprintf(file, " aa");
+ if (hp->tc)
+ fprintf(file, " tc");
+ if (hp->rd)
+ fprintf(file, " rd");
+ if (hp->ra)
+ fprintf(file, " ra");
+ if (hp->unused)
+ fprintf(file, " UNUSED-BIT-ON");
+ if (hp->ad)
+ fprintf(file, " ad");
+ if (hp->cd)
+ fprintf(file, " cd");
+ }
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
+ fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
+ fprintf(file, ", Ans: %d", ntohs(hp->ancount));
+ fprintf(file, ", Auth: %d", ntohs(hp->nscount));
+ fprintf(file, ", Addit: %d", ntohs(hp->arcount));
+ }
+ if ((!_res.pfcode) || (_res.pfcode &
+ (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
+ putc('\n',file);
+ }
+ /*
+ * Print question records.
+ */
+ if ((n = ntohs(hp->qdcount)) != 0) {
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+ fprintf(file, ";; QUESTIONS:\n");
+ while (--n >= 0) {
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+ fprintf(file, ";;\t");
+ TruncTest(cp);
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+ cp = p_cdnname(cp, msg, len, file);
+ else {
+ int n;
+ char name[MAXDNAME];
+
+ if ((n = dn_expand(msg, msg+len, cp, name,
+ sizeof name)) < 0)
+ cp = NULL;
+ else
+ cp += n;
+ }
+ ErrorTest(cp);
+ TruncTest(cp);
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+ fprintf(file, ", type = %s",
+ __p_type(_getshort((u_char*)cp)));
+ cp += INT16SZ;
+ TruncTest(cp);
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+ fprintf(file, ", class = %s\n",
+ __p_class(_getshort((u_char*)cp)));
+ cp += INT16SZ;
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+ putc('\n', file);
+ }
+ }
+ /*
+ * Print authoritative answer records
+ */
+ TruncTest(cp);
+ cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
+ ";; ANSWERS:\n");
+ ErrorTest(cp);
+
+ /*
+ * print name server records
+ */
+ TruncTest(cp);
+ cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
+ ";; AUTHORITY RECORDS:\n");
+ ErrorTest(cp);
+
+ TruncTest(cp);
+ /*
+ * print additional records
+ */
+ cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
+ ";; ADDITIONAL RECORDS:\n");
+ ErrorTest(cp);
+ return;
+ trunc:
+ fprintf(file, "\n;; ...truncated\n");
+ return;
+ error:
+ fprintf(file, "\n;; ...malformed\n");
+}
+
+void
+__fp_query(msg, file)
+ const u_char *msg;
+ FILE *file;
+{
+ fp_nquery(msg, PACKETSZ, file);
+}
+
+const u_char *
+__p_cdnname(cp, msg, len, file)
+ const u_char *cp, *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(cp, msg, file)
+ const u_char *cp, *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. (vix)
+ */
+
+const u_char *
+__p_fqname(cp, msg, file)
+ const u_char *cp, *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);
+}
+
+/*
+ * Print resource record fields in human readable form.
+ */
+const u_char *
+__p_rr(cp, msg, file)
+ const u_char *cp, *msg;
+ FILE *file;
+{
+ int type, class, dlen, n, c;
+ struct in_addr inaddr;
+ const u_char *cp1, *cp2;
+ u_int32_t tmpttl, t;
+ int lcnt;
+ u_int16_t keyflags;
+ char rrname[MAXDNAME]; /* The fqdn of this RR */
+ char base64_key[MAX_KEY_BASE64];
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
+ if (!cp)
+ return (NULL); /* compression error */
+ fputs(rrname, file);
+
+ type = _getshort((u_char*)cp);
+ cp += INT16SZ;
+ class = _getshort((u_char*)cp);
+ cp += INT16SZ;
+ tmpttl = _getlong((u_char*)cp);
+ cp += INT32SZ;
+ dlen = _getshort((u_char*)cp);
+ cp += INT16SZ;
+ cp1 = cp;
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
+ fprintf(file, "\t%lu", (u_long)tmpttl);
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
+ fprintf(file, "\t%s", __p_class(class));
+ fprintf(file, "\t%s", __p_type(type));
+ /*
+ * Print type specific data, if appropriate
+ */
+ switch (type) {
+ case T_A:
+ switch (class) {
+ case C_IN:
+ case C_HS:
+ bcopy(cp, (char *)&inaddr, INADDRSZ);
+ if (dlen == 4) {
+ fprintf(file, "\t%s", inet_ntoa(inaddr));
+ cp += dlen;
+ } else if (dlen == 7) {
+ char *address;
+ u_char protocol;
+ u_short port;
+
+ address = inet_ntoa(inaddr);
+ cp += INADDRSZ;
+ protocol = *(u_char*)cp;
+ cp += sizeof (u_char);
+ port = _getshort((u_char*)cp);
+ cp += INT16SZ;
+ fprintf(file, "\t%s\t; proto %d, port %d",
+ address, protocol, port);
+ }
+ break;
+ default:
+ cp += dlen;
+ }
+ break;
+ case T_CNAME:
+ case T_MB:
+ case T_MG:
+ case T_MR:
+ case T_NS:
+ case T_PTR:
+ putc('\t', file);
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL);
+ break;
+
+ case T_HINFO:
+ case T_ISDN:
+ cp2 = cp + dlen;
+ (void) fputs("\t\"", file);
+ if ((n = (unsigned char) *cp++) != 0) {
+ for (c = n; c > 0 && cp < cp2; c--) {
+ if (strchr("\n\"\\", *cp))
+ (void) putc('\\', file);
+ (void) putc(*cp++, file);
+ }
+ }
+ putc('"', file);
+ if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
+ (void) fputs ("\t\"", file);
+ for (c = n; c > 0 && cp < cp2; c--) {
+ if (strchr("\n\"\\", *cp))
+ (void) putc('\\', file);
+ (void) putc(*cp++, file);
+ }
+ putc('"', file);
+ } else if (type == T_HINFO) {
+ (void) fputs("\"?\"", file);
+ fprintf(file, "\n;; *** Warning *** OS-type missing");
+ }
+ break;
+
+ case T_SOA:
+ putc('\t', file);
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL);
+ putc(' ', file);
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL);
+ fputs(" (\n", file);
+ t = _getlong((u_char*)cp); cp += INT32SZ;
+ fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
+ t = _getlong((u_char*)cp); cp += INT32SZ;
+ fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
+ (u_long)t, __p_time(t));
+ t = _getlong((u_char*)cp); cp += INT32SZ;
+ fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
+ (u_long)t, __p_time(t));
+ t = _getlong((u_char*)cp); cp += INT32SZ;
+ fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
+ (u_long)t, __p_time(t));
+ t = _getlong((u_char*)cp); cp += INT32SZ;
+ fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
+ (u_long)t, __p_time(t));
+ break;
+
+ case T_MX:
+ case T_AFSDB:
+ case T_RT:
+ fprintf(file, "\t%d ", _getshort((u_char*)cp));
+ cp += INT16SZ;
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL);
+ break;
+
+ case T_PX:
+ fprintf(file, "\t%d ", _getshort((u_char*)cp));
+ cp += INT16SZ;
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL);
+ putc(' ', file);
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL);
+ break;
+
+ case T_X25:
+ cp2 = cp + dlen;
+ (void) fputs("\t\"", file);
+ if ((n = (unsigned char) *cp++) != 0) {
+ for (c = n; c > 0 && cp < cp2; c--) {
+ if (strchr("\n\"\\", *cp))
+ (void) putc('\\', file);
+ (void) putc(*cp++, file);
+ }
+ }
+ putc('"', file);
+ break;
+
+ case T_TXT:
+ (void) putc('\t', file);
+ cp2 = cp1 + dlen;
+ while (cp < cp2) {
+ putc('"', file);
+ if ((n = (unsigned char) *cp++) != '\0') {
+ for (c = n; c > 0 && cp < cp2; c--) {
+ if (strchr("\n\"\\", *cp))
+ (void) putc('\\', file);
+ (void) putc(*cp++, file);
+ }
+ }
+ putc('"', file);
+ if (cp < cp2)
+ putc(' ', file);
+ }
+ break;
+
+ case T_NSAP:
+ (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
+ cp += dlen;
+ break;
+
+ case T_AAAA: {
+ char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+
+ fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
+ cp += dlen;
+ break;
+ }
+
+ case T_LOC: {
+ char t[255];
+
+ fprintf(file, "\t%s", loc_ntoa(cp, t));
+ cp += dlen;
+ break;
+ }
+
+ case T_NAPTR: {
+ u_int order, preference;
+
+ order = _getshort(cp); cp += INT16SZ;
+ preference = _getshort(cp); cp += INT16SZ;
+ fprintf(file, "\t%u %u ",order, preference);
+ /* Flags */
+ n = *cp++;
+ fprintf(file,"\"%.*s\" ", (int)n, cp);
+ cp += n;
+ /* Service */
+ n = *cp++;
+ fprintf(file,"\"%.*s\" ", (int)n, cp);
+ cp += n;
+ /* Regexp */
+ n = *cp++;
+ fprintf(file,"\"%.*s\" ", (int)n, cp);
+ cp += n;
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL);
+ break;
+ }
+
+ case T_SRV: {
+ u_int priority, weight, port;
+
+ priority = _getshort(cp); cp += INT16SZ;
+ weight = _getshort(cp); cp += INT16SZ;
+ port = _getshort(cp); cp += INT16SZ;
+ fprintf(file, "\t%u %u %u ", priority, weight, port);
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL);
+ break;
+ }
+
+ case T_MINFO:
+ case T_RP:
+ putc('\t', file);
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL);
+ putc(' ', file);
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL);
+ break;
+
+ case T_UINFO:
+ putc('\t', file);
+ fputs((char *)cp, file);
+ cp += dlen;
+ break;
+
+ case T_UID:
+ case T_GID:
+ if (dlen == 4) {
+ fprintf(file, "\t%u", _getlong((u_char*)cp));
+ cp += INT32SZ;
+ }
+ break;
+
+ case T_WKS:
+ if (dlen < INT32SZ + 1)
+ break;
+ bcopy(cp, (char *)&inaddr, INADDRSZ);
+ cp += INT32SZ;
+ fprintf(file, "\t%s %s ( ",
+ inet_ntoa(inaddr),
+ deproto((int) *cp));
+ cp += sizeof (u_char);
+ n = 0;
+ lcnt = 0;
+ while (cp < cp1 + dlen) {
+ c = *cp++;
+ do {
+ if (c & 0200) {
+ if (lcnt == 0) {
+ fputs("\n\t\t\t", file);
+ lcnt = 5;
+ }
+ fputs(dewks(n), file);
+ putc(' ', file);
+ lcnt--;
+ }
+ c <<= 1;
+ } while (++n & 07);
+ }
+ putc(')', file);
+ break;
+
+ case T_KEY:
+ putc('\t', file);
+ keyflags = _getshort(cp);
+ cp += 2;
+ fprintf(file,"0x%04x", keyflags ); /* flags */
+ fprintf(file," %u", *cp++); /* protocol */
+ fprintf(file," %u (", *cp++); /* algorithm */
+
+ n = b64_ntop(cp, (cp1 + dlen) - cp,
+ base64_key, sizeof base64_key);
+ for (c = 0; c < n; ++c) {
+ if (0 == (c & 0x3F))
+ fprintf(file, "\n\t");
+ putc(base64_key[c], file); /* public key data */
+ }
+
+ fprintf(file, " )");
+ if (n < 0)
+ fprintf(file, "\t; BAD BASE64");
+ fflush(file);
+ cp = cp1 + dlen;
+ break;
+
+ case T_SIG:
+ type = _getshort((u_char*)cp);
+ cp += INT16SZ;
+ fprintf(file, " %s", p_type(type));
+ fprintf(file, "\t%d", *cp++); /* algorithm */
+ /* Check label value and print error if wrong. */
+ n = *cp++;
+ c = dn_count_labels (rrname);
+ if (n != c)
+ fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
+ n, c);
+ /* orig ttl */
+ n = _getlong((u_char*)cp);
+ if (n != tmpttl)
+ fprintf(file, " %u", n);
+ cp += INT32SZ;
+ /* sig expire */
+ fprintf(file, " (\n\t%s",
+ __p_secstodate(_getlong((u_char*)cp)));
+ cp += INT32SZ;
+ /* time signed */
+ fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
+ cp += INT32SZ;
+ /* sig footprint */
+ fprintf(file," %u ", _getshort((u_char*)cp));
+ cp += INT16SZ;
+ /* signer's name */
+ cp = p_fqname(cp, msg, file);
+ n = b64_ntop(cp, (cp1 + dlen) - cp,
+ base64_key, sizeof base64_key);
+ for (c = 0; c < n; c++) {
+ if (0 == (c & 0x3F))
+ fprintf (file, "\n\t");
+ putc(base64_key[c], file); /* signature */
+ }
+ /* Clean up... */
+ fprintf(file, " )");
+ if (n < 0)
+ fprintf(file, "\t; BAD BASE64");
+ fflush(file);
+ cp = cp1+dlen;
+ break;
+
+#ifdef ALLOW_T_UNSPEC
+ case T_UNSPEC:
+ {
+ int NumBytes = 8;
+ u_char *DataPtr;
+ int i;
+
+ if (dlen < NumBytes) NumBytes = dlen;
+ fprintf(file, "\tFirst %d bytes of hex data:",
+ NumBytes);
+ for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
+ fprintf(file, " %x", *DataPtr);
+ cp += dlen;
+ }
+ break;
+#endif /* ALLOW_T_UNSPEC */
+
+ default:
+ fprintf(file, "\t?%d?", type);
+ cp += dlen;
+ }
+#if 0
+ fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
+#else
+ putc('\n', file);
+#endif
+ if (cp - cp1 != dlen) {
+ fprintf(file, ";; packet size error (found %d, dlen was %d)\n",
+ cp - cp1, dlen);
+ cp = NULL;
+ }
+ return (cp);
+}
+
+/*
+ * 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"},
+ {C_CHAOS, "CHAOS"},
+ {C_HS, "HS"},
+ {C_HS, "HESIOD"},
+ {C_ANY, "ANY"},
+ {C_IN, (char *)0}
+};
+
+/*
+ * 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[] = {
+ {T_A, "A", "address"},
+ {T_NS, "NS", "name server"},
+ {T_MD, "MD", "mail destination (deprecated)"},
+ {T_MF, "MF", "mail forwarder (deprecated)"},
+ {T_CNAME, "CNAME", "canonical name"},
+ {T_SOA, "SOA", "start of authority"},
+ {T_MB, "MB", "mailbox"},
+ {T_MG, "MG", "mail group member"},
+ {T_MR, "MR", "mail rename"},
+ {T_NULL, "NULL", "null"},
+ {T_WKS, "WKS", "well-known service (deprecated)"},
+ {T_PTR, "PTR", "domain name pointer"},
+ {T_HINFO, "HINFO", "host information"},
+ {T_MINFO, "MINFO", "mailbox information"},
+ {T_MX, "MX", "mail exchanger"},
+ {T_TXT, "TXT", "text"},
+ {T_RP, "RP", "responsible person"},
+ {T_AFSDB, "AFSDB", "DCE or AFS server"},
+ {T_X25, "X25", "X25 address"},
+ {T_ISDN, "ISDN", "ISDN address"},
+ {T_RT, "RT", "router"},
+ {T_NSAP, "NSAP", "nsap address"},
+ {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
+ {T_SIG, "SIG", "signature"},
+ {T_KEY, "KEY", "key"},
+ {T_PX, "PX", "mapping information"},
+ {T_GPOS, "GPOS", "geographical position (withdrawn)"},
+ {T_AAAA, "AAAA", "IPv6 address"},
+ {T_LOC, "LOC", "location"},
+ {T_NXT, "NXT", "next valid name (unimplemented)"},
+ {T_EID, "EID", "endpoint identifier (unimplemented)"},
+ {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
+ {T_SRV, "SRV", "server selection"},
+ {T_ATMA, "ATMA", "ATM address (unimplemented)"},
+ {T_IXFR, "IXFR", "incremental zone transfer"},
+ {T_AXFR, "AXFR", "zone transfer"},
+ {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
+ {T_MAILA, "MAILA", "mail agent (deprecated)"},
+ {T_UINFO, "UINFO", "user information (nonstandard)"},
+ {T_UID, "UID", "user ID (nonstandard)"},
+ {T_GID, "GID", "group ID (nonstandard)"},
+ {T_NAPTR, "NAPTR", "URN Naming Authority"},
+#ifdef ALLOW_T_UNSPEC
+ {T_UNSPEC, "UNSPEC", "unspecified data (nonstandard)"},
+#endif /* ALLOW_T_UNSPEC */
+ {T_ANY, "ANY", "\"any\""},
+ {0, NULL, NULL}
+};
+
+int
+__sym_ston(syms, name, success)
+ const struct res_sym *syms;
+ char *name;
+ int *success;
+{
+ for (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(syms, number, success)
+ const struct res_sym *syms;
+ int number;
+ int *success;
+{
+ static char unname[20];
+
+ for (NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->name);
+ }
+ }
+
+ sprintf (unname, "%d", number);
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+
+const char *
+__sym_ntop(syms, number, success)
+ const struct res_sym *syms;
+ int number;
+ int *success;
+{
+ static char unname[20];
+
+ for (NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->humanname);
+ }
+ }
+ sprintf(unname, "%d", number);
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+/*
+ * Return a string for the type
+ */
+const char *
+__p_type(type)
+ int type;
+{
+ return (__sym_ntos (__p_type_syms, type, (int *)0));
+}
+
+/*
+ * Return a mnemonic for class
+ */
+const char *
+__p_class(class)
+ int class;
+{
+ return (__sym_ntos (__p_class_syms, class, (int *)0));
+}
+
+/*
+ * Return a mnemonic for an option
+ */
+const char *
+__p_option(option)
+ u_long option;
+{
+ static char nbuf[40];
+
+ 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";
+ default: sprintf(nbuf, "?0x%lx?", (u_long)option);
+ return (nbuf);
+ }
+}
+
+/*
+ * Return a mnemonic for a time to live
+ */
+const char *
+p_time(value)
+ u_int32_t value;
+{
+ static char nbuf[40];
+ int secs, mins, hours, days;
+ register char *p;
+
+ if (value == 0) {
+ strcpy(nbuf, "0 secs");
+ return (nbuf);
+ }
+
+ secs = value % 60;
+ value /= 60;
+ mins = value % 60;
+ value /= 60;
+ hours = value % 24;
+ value /= 24;
+ days = value;
+ value = 0;
+
+#define PLURALIZE(x) x, (x == 1) ? "" : "s"
+ p = nbuf;
+ if (days) {
+ (void)sprintf(p, "%d day%s", PLURALIZE(days));
+ while (*++p);
+ }
+ if (hours) {
+ if (days)
+ *p++ = ' ';
+ (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
+ while (*++p);
+ }
+ if (mins) {
+ if (days || hours)
+ *p++ = ' ';
+ (void)sprintf(p, "%d min%s", PLURALIZE(mins));
+ while (*++p);
+ }
+ if (secs || ! (days || hours || mins)) {
+ if (days || hours || mins)
+ *p++ = ' ';
+ (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
+ }
+ return (nbuf);
+}
+
+/*
+ * 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;
+{
+ static char retbuf[sizeof "90000000.00"];
+ 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, "%ld.%.2ld", val/100, val%100);
+ return (retbuf);
+}
+
+/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
+static u_int8_t
+precsize_aton(strptr)
+ char **strptr;
+{
+ u_int8_t retval = 0;
+ char *cp;
+ int exponent = 0;
+ int mantissa = 0;
+
+ cp = *strptr;
+ while (isdigit(*cp)) {
+ if (mantissa == 0)
+ mantissa = *cp - '0';
+ else
+ exponent++;
+ cp++;
+ }
+
+ if (*cp == '.') {
+ cp++;
+ if (isdigit(*cp)) {
+ if (mantissa == 0)
+ mantissa = *cp - '0';
+ else
+ exponent++;
+ cp++;
+
+ if (isdigit(*cp)) {
+ if (mantissa == 0)
+ mantissa = *cp - '0';
+ else
+ exponent++;
+ cp++;
+ }
+ else
+ exponent++;
+ }
+ }
+ else
+ exponent += 2;
+
+ if (mantissa == 0)
+ exponent = 0;
+ 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(latlonstrptr,which)
+ char **latlonstrptr;
+ int *which;
+{
+ register char *cp;
+ u_int32_t retval;
+ int deg = 0, min = 0, secs = 0, secsfrac = 0;
+
+ cp = *latlonstrptr;
+
+ while (isdigit(*cp))
+ deg = deg * 10 + (*cp++ - '0');
+
+ while (isspace(*cp))
+ cp++;
+
+ if (!(isdigit(*cp)))
+ goto fndhemi;
+
+ while (isdigit(*cp))
+ min = min * 10 + (*cp++ - '0');
+
+ while (isspace(*cp))
+ cp++;
+
+ if (!(isdigit(*cp)))
+ goto fndhemi;
+
+ while (isdigit(*cp))
+ secs = secs * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal seconds */
+ cp++;
+ if (isdigit(*cp)) {
+ secsfrac = (*cp++ - '0') * 100;
+ if (isdigit(*cp)) {
+ secsfrac += (*cp++ - '0') * 10;
+ if (isdigit(*cp)) {
+ secsfrac += (*cp++ - '0');
+ }
+ }
+ }
+ }
+
+ while (!isspace(*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace(*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(*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace(*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(*cp))
+ altmeters = altmeters * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal meters */
+ cp++;
+ if (isdigit(*cp)) {
+ altfrac = (*cp++ - '0') * 10;
+ if (isdigit(*cp)) {
+ altfrac += (*cp++ - '0');
+ }
+ }
+ }
+
+ alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
+
+ while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace(*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ siz = precsize_aton(&cp);
+
+ while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace(*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ hp = precsize_aton(&cp);
+
+ while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace(*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 char *error = "?";
+ register const u_char *cp = binary;
+
+ int latdeg, latmin, latsec, latsecfrac;
+ int longdeg, longmin, longsec, longsecfrac;
+ char northsouth, eastwest;
+ int altmeters, altfrac, altsign;
+
+ const int 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 (versionval) {
+ 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 = -1;
+ } else {
+ altval = templ - referencealt;
+ altsign = 1;
+ }
+
+ 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) * altsign;
+
+ if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
+ sizestr = error;
+ if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
+ hpstr = error;
+ if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
+ vpstr = error;
+
+ sprintf(ascii,
+ "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
+ latdeg, latmin, latsec, latsecfrac, northsouth,
+ longdeg, longmin, longsec, longsecfrac, eastwest,
+ altmeters, altfrac, sizestr, hpstr, vpstr);
+
+ if (sizestr != error)
+ free(sizestr);
+ if (hpstr != error)
+ free(hpstr);
+ if (vpstr != error)
+ free(vpstr);
+
+ return (ascii);
+}
+
+
+/* Return the number of DNS hierarchy levels in the name. */
+int
+__dn_count_labels(name)
+ char *name;
+{
+ int i, len, count;
+
+ len = strlen(name);
+
+ for(i = 0, count = 0; i < len; i++) {
+ 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 (secs)
+ unsigned long secs;
+{
+ static char output[15]; /* YYYYMMDDHHMMSS and null */
+ time_t clock = secs;
+ struct tm *time;
+
+ time = gmtime(&clock);
+ 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);
+}
diff --git a/lib/libc/net/res_init.c b/lib/libc/net/res_init.c
new file mode 100644
index 0000000..2fa3cbc
--- /dev/null
+++ b/lib/libc/net/res_init.c
@@ -0,0 +1,459 @@
+/*
+ * ++Copyright++ 1985, 1989, 1993
+ * -
+ * 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.
+ * 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--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
+static char orig_rcsid[] = "From: Id: res_init.c,v 8.8 1997/06/01 20:34:37 vixie Exp";
+static char rcsid[] = "$Id: res_init.c,v 1.12 1997/02/22 15:00:32 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#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 "res_config.h"
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <resolv.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void res_setoptions __P((char *, char *));
+
+#ifdef RESOLVSORT
+static const char sort_mask[] = "/&";
+#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
+static u_int32_t net_mask __P((struct in_addr));
+#endif
+
+/*
+ * Resolver state default settings.
+ */
+
+struct __res_state _res
+# if defined(__BIND_RES_TEXT)
+ = { RES_TIMEOUT, } /* Motorola, et al. */
+# endif
+ ;
+
+/*
+ * 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_init()
+{
+ register FILE *fp;
+ register char *cp, **pp;
+ register int n;
+ char buf[MAXDNAME];
+ int nserv = 0; /* number of nameserver records read from file */
+ int haveenv = 0;
+ int havesearch = 0;
+#ifdef RESOLVSORT
+ int nsort = 0;
+ char *net;
+#endif
+#ifndef RFC1535
+ int dots;
+#endif
+
+ /*
+ * 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 = 4;
+ 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();
+
+#ifdef USELOOPBACK
+ _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+#else
+ _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
+#endif
+ _res.nsaddr.sin_family = AF_INET;
+ _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
+ _res.nscount = 1;
+ _res.ndots = 1;
+ _res.pfcode = 0;
+
+ /* Allow user to override the local domain definition */
+ if ((cp = getenv("LOCALDOMAIN")) != NULL) {
+ (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ 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 = _res.defdname;
+ pp = _res.dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < _res.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'))
+
+ 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(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ if ((cp = strpbrk(_res.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(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ if ((cp = strchr(_res.defdname, '\n')) != NULL)
+ *cp = '\0';
+ /*
+ * Set search list to be blank-separated strings
+ * on rest of line.
+ */
+ cp = _res.defdname;
+ pp = _res.dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < _res.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 in_addr a;
+
+ cp = buf + sizeof("nameserver") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
+ _res.nsaddr_list[nserv].sin_addr = a;
+ _res.nsaddr_list[nserv].sin_family = AF_INET;
+ _res.nsaddr_list[nserv].sin_port =
+ htons(NAMESERVER_PORT);
+ nserv++;
+ }
+ continue;
+ }
+#ifdef RESOLVSORT
+ if (MATCH(buf, "sortlist")) {
+ struct in_addr a;
+
+ 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(*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ _res.sort_list[nsort].addr = a;
+ if (ISSORTMASK(n)) {
+ *cp++ = n;
+ net = cp;
+ while (*cp && *cp != ';' &&
+ isascii(*cp) && !isspace(*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ _res.sort_list[nsort].mask = a.s_addr;
+ } else {
+ _res.sort_list[nsort].mask =
+ net_mask(_res.sort_list[nsort].addr);
+ }
+ } else {
+ _res.sort_list[nsort].mask =
+ net_mask(_res.sort_list[nsort].addr);
+ }
+ nsort++;
+ }
+ *cp = n;
+ }
+ continue;
+ }
+#endif
+ if (MATCH(buf, "options")) {
+ res_setoptions(buf + sizeof("options") - 1, "conf");
+ continue;
+ }
+ }
+ if (nserv > 1)
+ _res.nscount = nserv;
+#ifdef RESOLVSORT
+ _res.nsort = nsort;
+#endif
+ (void) fclose(fp);
+ }
+ if (_res.defdname[0] == 0 &&
+ gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
+ (cp = strchr(buf, '.')) != NULL)
+ strcpy(_res.defdname, cp + 1);
+
+ /* find components of local domain that might be searched */
+ if (havesearch == 0) {
+ pp = _res.dnsrch;
+ *pp++ = _res.defdname;
+ *pp = NULL;
+
+#ifndef RFC1535
+ dots = 0;
+ for (cp = _res.defdname; *cp; cp++)
+ dots += (*cp == '.');
+
+ cp = _res.defdname;
+ while (pp < _res.dnsrch + MAXDFLSRCH) {
+ if (dots < LOCALDOMAINPARTS)
+ break;
+ cp = strchr(cp, '.') + 1; /* we know there is one */
+ *pp++ = cp;
+ dots--;
+ }
+ *pp = NULL;
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG) {
+ printf(";; res_init()... default dnsrch list:\n");
+ for (pp = _res.dnsrch; *pp; pp++)
+ printf(";;\t%s\n", *pp);
+ printf(";;\t..END..\n");
+ }
+#endif /* DEBUG */
+#endif /* !RFC1535 */
+ }
+
+ if ((cp = getenv("RES_OPTIONS")) != NULL)
+ res_setoptions(cp, "env");
+ _res.options |= RES_INIT;
+ return (0);
+}
+
+static void
+res_setoptions(options, source)
+ char *options, *source;
+{
+ char *cp = options;
+ int i;
+
+#ifdef DEBUG
+ if (_res.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)
+ _res.ndots = i;
+ else
+ _res.ndots = RES_MAXNDOTS;
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";;\tndots=%d\n", _res.ndots);
+#endif
+ } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
+#ifdef DEBUG
+ if (!(_res.options & RES_DEBUG)) {
+ printf(";; res_setoptions(\"%s\", \"%s\")..\n",
+ options, source);
+ _res.options |= RES_DEBUG;
+ }
+ printf(";;\tdebug\n");
+#endif
+ } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
+ _res.options |= RES_USE_INET6;
+ } else {
+ /* XXX - print a warning here? */
+ }
+ /* 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;
+{
+ register 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()
+{
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+ return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
+}
diff --git a/lib/libc/net/res_mkquery.c b/lib/libc/net/res_mkquery.c
new file mode 100644
index 0000000..cfc9d33
--- /dev/null
+++ b/lib/libc/net/res_mkquery.c
@@ -0,0 +1,186 @@
+/*
+ * ++Copyright++ 1985, 1993
+ * -
+ * 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.
+ * 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--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: res_mkquery.c,v 8.5 1996/08/27 08:33:28 vixie Exp ";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+
+#include "res_config.h"
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+
+
+/*
+ * Form all types of queries.
+ * Returns the size of the result or -1.
+ */
+int
+res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
+ int op; /* opcode of query */
+ const char *dname; /* domain name */
+ int class, 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 */
+{
+ register HEADER *hp;
+ register u_char *cp;
+ register int n;
+ u_char *dnptrs[20], **dpp, **lastdnptr;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_mkquery(%d, %s, %d, %d)\n",
+ op, dname, class, type);
+#endif
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return (-1);
+ bzero(buf, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = htons(++_res.id);
+ hp->opcode = op;
+ hp->rd = (_res.options & RES_RECURSE) != 0;
+ hp->rcode = NOERROR;
+ cp = buf + HFIXEDSZ;
+ buflen -= HFIXEDSZ;
+ 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 ((buflen -= QFIXEDSZ) < 0)
+ return (-1);
+ if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ buflen -= n;
+ __putshort(type, cp);
+ cp += INT16SZ;
+ __putshort(class, cp);
+ cp += INT16SZ;
+ hp->qdcount = htons(1);
+ if (op == QUERY || data == NULL)
+ break;
+ /*
+ * Make an additional record for completion domain.
+ */
+ buflen -= RRFIXEDSZ;
+ n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ buflen -= n;
+ __putshort(T_NULL, cp);
+ cp += INT16SZ;
+ __putshort(class, cp);
+ cp += INT16SZ;
+ __putlong(0, cp);
+ cp += INT32SZ;
+ __putshort(0, cp);
+ cp += INT16SZ;
+ hp->arcount = htons(1);
+ break;
+
+ case IQUERY:
+ /*
+ * Initialize answer section
+ */
+ if (buflen < 1 + RRFIXEDSZ + datalen)
+ return (-1);
+ *cp++ = '\0'; /* no domain name */
+ __putshort(type, cp);
+ cp += INT16SZ;
+ __putshort(class, cp);
+ cp += INT16SZ;
+ __putlong(0, cp);
+ cp += INT32SZ;
+ __putshort(datalen, cp);
+ cp += INT16SZ;
+ if (datalen) {
+ bcopy(data, cp, datalen);
+ cp += datalen;
+ }
+ hp->ancount = htons(1);
+ break;
+
+ default:
+ return (-1);
+ }
+ return (cp - buf);
+}
diff --git a/lib/libc/net/res_query.c b/lib/libc/net/res_query.c
new file mode 100644
index 0000000..8110895
--- /dev/null
+++ b/lib/libc/net/res_query.c
@@ -0,0 +1,401 @@
+/*
+ * ++Copyright++ 1988, 1993
+ * -
+ * 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. 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--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid = "From: Id: res_query.c,v 8.10 1997/06/01 20:34:37 vixie Exp";
+static char rcsid[] = "$Id: res_query.c,v 1.13 1997/03/24 06:11:44 imp Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "res_config.h"
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+const char *hostalias __P((const char *));
+int h_errno;
+
+/*
+ * 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_query(name, class, type, answer, anslen)
+ const char *name; /* domain name */
+ int class, type; /* class and type of query */
+ u_char *answer; /* buffer to put answer */
+ int anslen; /* size of answer buffer */
+{
+ u_char buf[MAXPACKET];
+ register HEADER *hp = (HEADER *) answer;
+ int n;
+
+ hp->rcode = NOERROR; /* default */
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_query(%s, %d, %d)\n", name, class, type);
+#endif
+
+ n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
+ buf, sizeof(buf));
+ if (n <= 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_query: mkquery failed\n");
+#endif
+ h_errno = NO_RECOVERY;
+ return (n);
+ }
+ n = res_send(buf, n, answer, anslen);
+ if (n < 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_query: send error\n");
+#endif
+ h_errno = TRY_AGAIN;
+ return (n);
+ }
+
+ if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; rcode = %d, ancount=%d\n", hp->rcode,
+ ntohs(hp->ancount));
+#endif
+ switch (hp->rcode) {
+ case NXDOMAIN:
+ h_errno = HOST_NOT_FOUND;
+ break;
+ case SERVFAIL:
+ h_errno = TRY_AGAIN;
+ break;
+ case NOERROR:
+ h_errno = NO_DATA;
+ break;
+ case FORMERR:
+ case NOTIMP:
+ case REFUSED:
+ default:
+ h_errno = 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_search(name, class, type, answer, anslen)
+ const char *name; /* domain name */
+ int class, type; /* class and type of query */
+ u_char *answer; /* buffer to put answer */
+ int anslen; /* size of answer */
+{
+ register const char *cp, * const *domain;
+ HEADER *hp = (HEADER *) answer;
+ u_int dots;
+ int trailing_dot, ret, saved_herrno;
+ int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+ errno = 0;
+ h_errno = 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 = __hostalias(name)) != NULL)
+ return (res_query(cp, class, type, answer, anslen));
+
+ /*
+ * If there are dots in the name already, let's just give it a try
+ * 'as is'. The threshold can be set with the "ndots" option.
+ */
+ saved_herrno = -1;
+ if (dots >= _res.ndots) {
+ ret = res_querydomain(name, NULL, class, type, answer, anslen);
+ if (ret > 0)
+ return (ret);
+ saved_herrno = 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++) {
+
+ ret = res_querydomain(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) {
+ h_errno = TRY_AGAIN;
+ return (-1);
+ }
+
+ switch (h_errno) {
+ case NO_DATA:
+ got_nodata++;
+ /* FALLTHROUGH */
+ case HOST_NOT_FOUND:
+ /* keep trying */
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL) {
+ /* try next search element, if any */
+ got_servfail++;
+ 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++;
+ }
+ }
+
+ /* if we have not already tried the name "as is", do that now.
+ * note that we do this regardless of how many dots were in the
+ * name or whether it ends with a dot.
+ */
+ if (!tried_as_is) {
+ ret = res_querydomain(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.
+ */
+ if (saved_herrno != -1)
+ h_errno = saved_herrno;
+ else if (got_nodata)
+ h_errno = NO_DATA;
+ else if (got_servfail)
+ h_errno = 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_querydomain(name, domain, class, type, answer, anslen)
+ const char *name, *domain;
+ int class, 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;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_querydomain(%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) {
+ h_errno = 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) {
+ h_errno = NO_RECOVERY;
+ return (-1);
+ }
+ sprintf(nbuf, "%s.%s", name, domain);
+ }
+ return (res_query(longname, class, type, answer, anslen));
+}
+
+const char *
+hostalias(name)
+ register const char *name;
+{
+ register char *cp1, *cp2;
+ FILE *fp;
+ char *file;
+ char buf[BUFSIZ];
+ static char abuf[MAXDNAME];
+
+ if (_res.options & RES_NOALIASES)
+ return (NULL);
+ /* XXX issetguid() would be better here, but we don't have that. */
+ if (getuid() != geteuid() || getgid() != getegid())
+ 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(*cp1); ++cp1)
+ ;
+ if (!*cp1)
+ break;
+ *cp1 = '\0';
+ if (!strcasecmp(buf, name)) {
+ while (isspace(*++cp1))
+ ;
+ if (!*cp1)
+ break;
+ for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
+ ;
+ abuf[sizeof(abuf) - 1] = *cp2 = '\0';
+ strncpy(abuf, cp1, sizeof(abuf) - 1);
+ fclose(fp);
+ return (abuf);
+ }
+ }
+ fclose(fp);
+ return (NULL);
+}
diff --git a/lib/libc/net/res_send.c b/lib/libc/net/res_send.c
new file mode 100644
index 0000000..9061ec6
--- /dev/null
+++ b/lib/libc/net/res_send.c
@@ -0,0 +1,767 @@
+/*
+ * ++Copyright++ 1985, 1989, 1993
+ * -
+ * 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.
+ * 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--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: res_send.c,v 8.13 1997/06/01 20:34:37 vixie Exp";
+static char rcsid[] = "$Id: res_send.c,v 1.17 1997/06/27 13:00:51 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Send query to name server and wait for reply.
+ */
+
+#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/inet.h>
+
+#include "res_config.h"
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <netdb.h>
+#include <errno.h>
+#include <resolv.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int s = -1; /* socket used for communications */
+static int connected = 0; /* is the socket connected */
+static int vc = 0; /* is the socket a virtual ciruit? */
+
+#define CAN_RECONNECT 1
+
+#ifndef DEBUG
+# define Dprint(cond, args) /*empty*/
+# define DprintQ(cond, args, query, size) /*empty*/
+# define Aerror(file, string, error, address) /*empty*/
+# define Perror(file, string, error) /*empty*/
+#else
+# define Dprint(cond, args) if (cond) {fprintf args;} else {}
+# define DprintQ(cond, args, query, size) if (cond) {\
+ fprintf args;\
+ __fp_nquery(query, size, stdout);\
+ } else {}
+ static void
+ Aerror(file, string, error, address)
+ FILE *file;
+ char *string;
+ int error;
+ struct sockaddr_in address;
+ {
+ int save = errno;
+
+ if (_res.options & RES_DEBUG) {
+ fprintf(file, "res_send: %s ([%s].%u): %s\n",
+ string,
+ inet_ntoa(address.sin_addr),
+ ntohs(address.sin_port),
+ strerror(error));
+ }
+ errno = save;
+ }
+ static void
+ Perror(file, string, error)
+ FILE *file;
+ char *string;
+ int error;
+ {
+ int save = errno;
+
+ if (_res.options & RES_DEBUG) {
+ fprintf(file, "res_send: %s: %s\n",
+ string, strerror(error));
+ }
+ errno = save;
+ }
+#endif
+
+static res_send_qhook Qhook = NULL;
+static res_send_rhook Rhook = NULL;
+
+void
+res_send_setqhook(hook)
+ res_send_qhook hook;
+{
+
+ Qhook = hook;
+}
+
+void
+res_send_setrhook(hook)
+ res_send_rhook hook;
+{
+
+ Rhook = hook;
+}
+
+/* int
+ * res_isourserver(ina)
+ * looks up "ina" in _res.ns_addr_list[]
+ * returns:
+ * 0 : not found
+ * >0 : found
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_isourserver(inp)
+ const struct sockaddr_in *inp;
+{
+ struct sockaddr_in ina;
+ register int ns, ret;
+
+ ina = *inp;
+ ret = 0;
+ for (ns = 0; ns < _res.nscount; ns++) {
+ register const struct sockaddr_in *srv = &_res.nsaddr_list[ns];
+
+ if (srv->sin_family == ina.sin_family &&
+ srv->sin_port == ina.sin_port &&
+ (srv->sin_addr.s_addr == INADDR_ANY ||
+ srv->sin_addr.s_addr == ina.sin_addr.s_addr)) {
+ ret++;
+ break;
+ }
+ }
+ return (ret);
+}
+
+/* int
+ * res_nameinquery(name, type, class, buf, eom)
+ * look for (name,type,class) in the query section of packet (buf,eom)
+ * returns:
+ * -1 : format error
+ * 0 : not found
+ * >0 : found
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_nameinquery(name, type, class, buf, eom)
+ const char *name;
+ register int type, class;
+ const u_char *buf, *eom;
+{
+ register const u_char *cp = buf + HFIXEDSZ;
+ int qdcount = ntohs(((HEADER*)buf)->qdcount);
+
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ register int n, ttype, tclass;
+
+ n = dn_expand(buf, eom, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ttype = _getshort(cp); cp += INT16SZ;
+ tclass = _getshort(cp); cp += INT16SZ;
+ if (ttype == type &&
+ tclass == class &&
+ strcasecmp(tname, name) == 0)
+ return (1);
+ }
+ return (0);
+}
+
+/* int
+ * res_queriesmatch(buf1, eom1, buf2, eom2)
+ * is there a 1:1 mapping of (name,type,class)
+ * in (buf1,eom1) and (buf2,eom2)?
+ * returns:
+ * -1 : format error
+ * 0 : not a 1:1 mapping
+ * >0 : is a 1:1 mapping
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_queriesmatch(buf1, eom1, buf2, eom2)
+ const u_char *buf1, *eom1;
+ const u_char *buf2, *eom2;
+{
+ register const u_char *cp = buf1 + HFIXEDSZ;
+ int qdcount = ntohs(((HEADER*)buf1)->qdcount);
+
+ if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
+ return (0);
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ register int n, ttype, tclass;
+
+ n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ttype = _getshort(cp); cp += INT16SZ;
+ tclass = _getshort(cp); cp += INT16SZ;
+ if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
+ return (0);
+ }
+ return (1);
+}
+
+int
+res_send(buf, buflen, ans, anssiz)
+ const u_char *buf;
+ int buflen;
+ u_char *ans;
+ int anssiz;
+{
+ HEADER *hp = (HEADER *) buf;
+ HEADER *anhp = (HEADER *) ans;
+ int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
+ register int n;
+ u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+ DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
+ (stdout, ";; res_send()\n"), buf, buflen);
+ v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
+ gotsomewhere = 0;
+ connreset = 0;
+ terrno = ETIMEDOUT;
+ badns = 0;
+
+ /*
+ * Send request, RETRY times, or until successful
+ */
+ for (try = 0; try < _res.retry; try++) {
+ for (ns = 0; ns < _res.nscount; ns++) {
+ struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
+ same_ns:
+ if (badns & (1 << ns)) {
+ res_close();
+ goto next_ns;
+ }
+
+ if (Qhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*Qhook)(&nsap, &buf, &buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ done = 1;
+ break;
+ case res_nextns:
+ res_close();
+ goto next_ns;
+ case res_done:
+ return (resplen);
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ return (-1);
+ }
+ } while (!done);
+ }
+
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; Querying server (# %d) address = %s\n",
+ ns + 1, inet_ntoa(nsap->sin_addr)));
+
+ if (v_circuit) {
+ int truncated;
+ struct iovec iov[2];
+ u_short len;
+ u_char *cp;
+
+ /*
+ * Use virtual circuit;
+ * at most one attempt per server.
+ */
+ try = _res.retry;
+ truncated = 0;
+ if ((s < 0) || (!vc)) {
+ if (s >= 0)
+ res_close();
+
+ s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ terrno = errno;
+ Perror(stderr, "socket(vc)", errno);
+ return (-1);
+ }
+ errno = 0;
+ if (connect(s, (struct sockaddr *)nsap,
+ sizeof(struct sockaddr)) < 0) {
+ terrno = errno;
+ Aerror(stderr, "connect/vc",
+ errno, *nsap);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ vc = 1;
+ }
+ /*
+ * Send length & message
+ */
+ putshort((u_short)buflen, (u_char*)&len);
+ iov[0].iov_base = (caddr_t)&len;
+ iov[0].iov_len = INT16SZ;
+ iov[1].iov_base = (caddr_t)buf;
+ iov[1].iov_len = buflen;
+ if (writev(s, iov, 2) != (INT16SZ + buflen)) {
+ terrno = errno;
+ Perror(stderr, "write failed", errno);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ /*
+ * Receive length & response
+ */
+read_len:
+ cp = ans;
+ len = INT16SZ;
+ while ((n = read(s, (char *)cp, (int)len)) > 0) {
+ cp += n;
+ if ((len -= n) <= 0)
+ break;
+ }
+ if (n <= 0) {
+ terrno = errno;
+ Perror(stderr, "read failed", errno);
+ res_close();
+ /*
+ * 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_close();
+ goto same_ns;
+ }
+ res_close();
+ goto next_ns;
+ }
+ resplen = _getshort(ans);
+ if (resplen > anssiz) {
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; response truncated\n")
+ );
+ truncated = 1;
+ len = anssiz;
+ } else
+ len = resplen;
+ cp = ans;
+ while (len != 0 &&
+ (n = read(s, (char *)cp, (int)len)) > 0) {
+ cp += n;
+ len -= n;
+ }
+ if (n <= 0) {
+ terrno = errno;
+ Perror(stderr, "read(vc)", errno);
+ res_close();
+ goto next_ns;
+ }
+ if (truncated) {
+ /*
+ * Flush rest of answer
+ * so connection stays in synch.
+ */
+ anhp->tc = 1;
+ len = resplen - anssiz;
+ while (len != 0) {
+ char junk[PACKETSZ];
+
+ n = (len > sizeof(junk)
+ ? sizeof(junk)
+ : len);
+ if ((n = read(s, junk, n)) > 0)
+ len -= n;
+ else
+ break;
+ }
+ }
+ /*
+ * 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. Anyway drop the packet and
+ * wait for the correct one.
+ */
+ if (hp->id != anhp->id) {
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer (unexpected):\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto read_len;
+ }
+ } else {
+ /*
+ * Use datagrams.
+ */
+ struct timeval timeout;
+ fd_set dsmask, *dsmaskp;
+ int dsmasklen;
+ struct sockaddr_in from;
+ int fromlen;
+
+ if ((s < 0) || vc) {
+ if (vc)
+ res_close();
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+#if !CAN_RECONNECT
+ bad_dg_sock:
+#endif
+ terrno = errno;
+ Perror(stderr, "socket(dg)", errno);
+ return (-1);
+ }
+ connected = 0;
+ }
+ /*
+ * 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.
+ * If we have sent queries to at least two servers,
+ * however, we don't want to remain connected,
+ * as we wish to receive answers from the first
+ * server to respond.
+ */
+ if (_res.nscount == 1 || (try == 0 && ns == 0)) {
+ /*
+ * Connect only if we are sure we won't
+ * receive a response from another server.
+ */
+ if (!connected) {
+ if (connect(s, (struct sockaddr *)nsap,
+ sizeof(struct sockaddr)
+ ) < 0) {
+ Aerror(stderr,
+ "connect(dg)",
+ errno, *nsap);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ connected = 1;
+ }
+ if (send(s, (char*)buf, buflen, 0) != buflen) {
+ Perror(stderr, "send", errno);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ } else {
+ /*
+ * Disconnect if we want to listen
+ * for responses from more than one server.
+ */
+ if (connected) {
+#if CAN_RECONNECT
+ struct sockaddr_in no_addr;
+
+ no_addr.sin_family = AF_INET;
+ no_addr.sin_addr.s_addr = INADDR_ANY;
+ no_addr.sin_port = 0;
+ (void) connect(s,
+ (struct sockaddr *)
+ &no_addr,
+ sizeof(no_addr));
+#else
+ int s1 = socket(PF_INET, SOCK_DGRAM,0);
+ if (s1 < 0)
+ goto bad_dg_sock;
+ (void) dup2(s1, s);
+ (void) close(s1);
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; new DG socket\n"))
+#endif
+ connected = 0;
+ errno = 0;
+ }
+ if (sendto(s, (char*)buf, buflen, 0,
+ (struct sockaddr *)nsap,
+ sizeof(struct sockaddr))
+ != buflen) {
+ Aerror(stderr, "sendto", errno, *nsap);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ }
+
+ /*
+ * Wait for reply
+ */
+ timeout.tv_sec = (_res.retrans << try);
+ if (try > 0)
+ timeout.tv_sec /= _res.nscount;
+ if ((long) timeout.tv_sec <= 0)
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ wait:
+ dsmasklen = howmany(s+1, NFDBITS) * sizeof(fd_mask);
+ if (dsmasklen > sizeof(fd_set)) {
+ dsmaskp = (fd_set *)malloc(dsmasklen);
+ if (dsmaskp == NULL) {
+ res_close();
+ goto next_ns;
+ }
+ } else
+ dsmaskp = &dsmask;
+ /* only zero what we need */
+ bzero((char *)dsmaskp, dsmasklen);
+ FD_SET(s, dsmaskp);
+ n = select(s+1, dsmaskp, (fd_set *)NULL,
+ (fd_set *)NULL, &timeout);
+ if (dsmaskp != &dsmask)
+ free(dsmaskp);
+ if (n < 0) {
+ if (errno == EINTR)
+ goto wait;
+ Perror(stderr, "select", errno);
+ res_close();
+ goto next_ns;
+ }
+ if (n == 0) {
+ /*
+ * timeout
+ */
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; timeout\n"));
+ gotsomewhere = 1;
+ res_close();
+ goto next_ns;
+ }
+ errno = 0;
+ fromlen = sizeof(struct sockaddr_in);
+ resplen = recvfrom(s, (char*)ans, anssiz, 0,
+ (struct sockaddr *)&from, &fromlen);
+ if (resplen <= 0) {
+ Perror(stderr, "recvfrom", errno);
+ res_close();
+ goto next_ns;
+ }
+ gotsomewhere = 1;
+ if (hp->id != anhp->id) {
+ /*
+ * response from old query, ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer:\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto wait;
+ }
+#if CHECK_SRVR_ADDR
+ if (!(_res.options & RES_INSECURE1) &&
+ !res_isourserver(&from)) {
+ /*
+ * response from wrong server? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; not our server:\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto wait;
+ }
+#endif
+ if (!(_res.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((_res.options & RES_DEBUG) ||
+ (_res.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(_res.options & RES_DEBUG,
+ (stdout, "server rejected query:\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ badns |= (1 << ns);
+ res_close();
+ /* don't retry if called from dig */
+ if (!_res.pfcode)
+ goto next_ns;
+ }
+ if (!(_res.options & RES_IGNTC) && anhp->tc) {
+ /*
+ * get rest of answer;
+ * use TCP with same server.
+ */
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; truncated answer\n"));
+ v_circuit = 1;
+ res_close();
+ goto same_ns;
+ }
+ } /*if vc/dg*/
+ Dprint((_res.options & RES_DEBUG) ||
+ ((_res.pfcode & RES_PRF_REPLY) &&
+ (_res.pfcode & RES_PRF_HEAD1)),
+ (stdout, ";; got answer:\n"));
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ""),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ /*
+ * If using virtual circuits, we assume that the first server
+ * is preferred over the rest (i.e. it is on the local
+ * machine) and only keep that one open.
+ * 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 && (!(_res.options & RES_USEVC) || ns != 0)) ||
+ !(_res.options & RES_STAYOPEN)) {
+ res_close();
+ }
+ if (Rhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*Rhook)(nsap, buf, buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ case res_done:
+ done = 1;
+ break;
+ case res_nextns:
+ res_close();
+ goto next_ns;
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ return (-1);
+ }
+ } while (!done);
+
+ }
+ return (resplen);
+ next_ns: ;
+ } /*foreach ns*/
+ } /*foreach retry*/
+ res_close();
+ if (!v_circuit)
+ if (!gotsomewhere)
+ errno = ECONNREFUSED; /* no nameservers found */
+ else
+ errno = ETIMEDOUT; /* no answer obtained */
+ else
+ errno = terrno;
+ return (-1);
+}
+
+/*
+ * 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_close()
+{
+ if (s >= 0) {
+ (void) close(s);
+ s = -1;
+ connected = 0;
+ vc = 0;
+ }
+}
diff --git a/lib/libc/net/res_stubs.c b/lib/libc/net/res_stubs.c
new file mode 100644
index 0000000..e156608
--- /dev/null
+++ b/lib/libc/net/res_stubs.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 1996 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.
+ *
+ * $Id: res_stubs.c,v 1.5 1997/02/22 15:00:36 peter Exp $
+ */
+
+/*
+ * This file is for FreeBSD-3.0 that has a bind-4.9.5-P1 derived
+ * resolver in the libc. It provides aliases for functions that
+ * have moved since 4.9.4-P1.
+ *
+ * I'll save everybody the trouble and say it now: *THIS IS A HACK*!
+ *
+ * Yes, many of these are private functions to the resolver, but some are
+ * needed as there is no other way to provide the functionality and they've
+ * turned up all over the place. :-(
+ */
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+__weak_reference(__sym_ston, sym_ston);
+__weak_reference(__sym_ntos, sym_ntos);
+__weak_reference(__sym_ntop, sym_ntop);
+__weak_reference(__fp_resstat, fp_resstat);
+__weak_reference(__p_query, p_query);
+__weak_reference(__p_fqnname, p_fqnname);
+__weak_reference(__p_secstodate, p_secstodate);
+__weak_reference(__dn_count_labels, dn_count_labels);
+__weak_reference(__dn_comp, dn_comp);
+__weak_reference(__res_close, _res_close);
+#ifdef BIND_RES_POSIX3
+__weak_reference(__dn_expand, dn_expand);
+__weak_reference(__res_init, res_init);
+__weak_reference(__res_query, res_query);
+__weak_reference(__res_search, res_search);
+__weak_reference(__res_querydomain, res_querydomain);
+__weak_reference(__res_mkquery, res_mkquery);
+__weak_reference(__res_send, res_send);
+#else
+__weak_reference(res_send, __res_send);
+#endif
diff --git a/lib/libc/net/resolver.3 b/lib/libc/net/resolver.3
index 4014c72..6d210c3 100644
--- a/lib/libc/net/resolver.3
+++ b/lib/libc/net/resolver.3
@@ -48,50 +48,56 @@
.Fd #include <netinet/in.h>
.Fd #include <arpa/nameser.h>
.Fd #include <resolv.h>
+.Ft int
.Fo res_query
-.Fa "char *dname"
+.Fa "const char *dname"
.Fa "int class"
.Fa "int type"
.Fa "u_char *answer"
.Fa "int anslen"
.Fc
+.Ft int
.Fo res_search
-.Fa "char *dname"
+.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 "char *dname"
+.Fa "const char *dname"
.Fa "int class"
.Fa "int type"
-.Fa "char *data"
+.Fa "const u_char *data"
.Fa "int datalen"
-.Fa "struct rrec *newrr"
-.Fa "char *buf"
+.Fa "const u_char *newrr_in"
+.Fa "u_char *buf"
.Fa "int buflen"
.Fc
+.Ft int
.Fo res_send
-.Fa "char *msg"
+.Fa "const char *msg"
.Fa "int msglen"
.Fa "char *answer"
.Fa "int anslen"
.Fc
+.Ft int
.Fn res_init
.Fo dn_comp
-.Fa "char *exp_dn"
+.Fa "const char *exp_dn"
.Fa "char *comp_dn"
.Fa "int length"
.Fa "char **dnptrs"
.Fa "char **lastdnptr"
.Fc
+.Ft int
.Fo dn_expand
-.Fa "u_char *msg"
-.Fa "u_char *eomorig"
-.Fa "u_char *comp_dn"
-.Fa "u_char *exp_dn"
+.Fa "const u_char *msg"
+.Fa "const u_char *eomorig"
+.Fa "const u_char *comp_dn"
+.Fa "char *exp_dn"
.Fa "int length"
.Fc
.Sh DESCRIPTION
@@ -163,6 +169,10 @@ will search for host names in the current domain and in parent domains; see
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.
.El
.Pp
The
@@ -179,6 +189,24 @@ 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
+.Em 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
+.Em _res
+structure or are inherited from the configuration file's
+.Em 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
@@ -304,9 +332,9 @@ see
.El
.Sh SEE ALSO
.Xr gethostbyname 3 ,
-.Xr named 8 ,
.Xr resolver 5 ,
.Xr hostname 7 ,
+.Xr named 8
.Pp
.%T RFC1032 ,
.%T RFC1033 ,
diff --git a/lib/libc/nls/Makefile.inc b/lib/libc/nls/Makefile.inc
new file mode 100644
index 0000000..6d2acea
--- /dev/null
+++ b/lib/libc/nls/Makefile.inc
@@ -0,0 +1,11 @@
+# from $NetBSD: Makefile.inc,v 1.7 1995/02/27 13:06:20 cgd Exp $
+# $Id$
+
+.PATH: ${.CURDIR}/../libc/nls
+
+SRCS+= catclose.c catgets.c catopen.c msgcat.c
+
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN3+= nls/catclose.3 nls/catgets.3 nls/catopen.3
+.endif
diff --git a/lib/libc/nls/catclose.3 b/lib/libc/nls/catclose.3
new file mode 100644
index 0000000..e4757bd
--- /dev/null
+++ b/lib/libc/nls/catclose.3
@@ -0,0 +1,54 @@
+.\" $Id$
+.\"
+.\" 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.
+.\"
+.Dd May 29, 1994
+.Dt CATCLOSE 3
+.Os
+.Sh NAME
+.Nm catclose
+.Nd close message catalog
+.Sh SYNOPSIS
+.Fd #include <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 SEE ALSO
+.Xr catgets 3 ,
+.Xr catopen 3
+.Sh STANDARDS
+The
+.Fn catclose
+function conforms to
+.St -xpg3 .
+
diff --git a/lib/libc/nls/catclose.c b/lib/libc/nls/catclose.c
new file mode 100644
index 0000000..341f664
--- /dev/null
+++ b/lib/libc/nls/catclose.c
@@ -0,0 +1,25 @@
+/* $Id$ */
+
+/*
+ * Written by J.T. Conklin, 10/05/94
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+
+#ifdef __indr_reference
+__indr_reference(_catclose,catclose);
+#else
+
+#include <nl_types.h>
+
+extern int _catclose __P((nl_catd));
+
+int
+catclose(catd)
+ nl_catd catd;
+{
+ return _catclose(catd);
+}
+
+#endif
diff --git a/lib/libc/nls/catgets.3 b/lib/libc/nls/catgets.3
new file mode 100644
index 0000000..b50f8a4
--- /dev/null
+++ b/lib/libc/nls/catgets.3
@@ -0,0 +1,66 @@
+.\" $Id$
+.\"
+.\" 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.
+.\"
+.Dd May 29, 1994
+.Dt CATGETS 3
+.Os
+.Sh NAME
+.Nm catgets
+.Nd retrieve string from message catalog
+.Sh SYNOPSIS
+.Fd #include <nl_types.h>
+.Ft char *
+.Fn catgets "nl_catd catd" "int set_id" "int msg_id" "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 VALUE
+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 SEE ALSO
+.Xr catclose 3 ,
+.Xr catopen 3
+.Sh STANDARDS
+The
+.Fn catgets
+function conforms to \fBxpg3\fR.
diff --git a/lib/libc/nls/catgets.c b/lib/libc/nls/catgets.c
new file mode 100644
index 0000000..c29cf64
--- /dev/null
+++ b/lib/libc/nls/catgets.c
@@ -0,0 +1,28 @@
+/* $Id$ */
+
+/*
+ * Written by J.T. Conklin, 10/05/94
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+
+#ifdef __indr_reference
+__indr_reference(_catgets,catgets);
+#else
+
+#include <nl_types.h>
+
+extern char * _catgets __P((nl_catd, int, int, char *));
+
+char *
+catgets(catd, set_id, msg_id, s)
+ nl_catd catd;
+ int set_id;
+ int msg_id;
+ char *s;
+{
+ return _catgets(catd, set_id, msg_id, s);
+}
+
+#endif
diff --git a/lib/libc/nls/catopen.3 b/lib/libc/nls/catopen.3
new file mode 100644
index 0000000..a792ebd
--- /dev/null
+++ b/lib/libc/nls/catopen.3
@@ -0,0 +1,82 @@
+.\" $Id$
+.\"
+.\" 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.
+.\"
+.Dd May 29, 1994
+.Dt CATOPEN 3
+.Os
+.Sh NAME
+.Nm catopen
+.Nd open message catalog
+.Sh SYNOPSIS
+.Fd #include <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
+.Fa name
+substituted for %N.
+.Pp
+The
+.Fa oflag
+argument is reserved for future use and should be set to zero.
+.Sh RETURN VALUE
+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 ENOMEM
+Insufficient memory is available.
+.El
+.Sh SEE ALSO
+.Xr catclose 3 ,
+.Xr catgets 3
+.Sh STANDARDS
+The
+.Fn catopen
+function conforms to
+.St -xpg3 .
diff --git a/lib/libc/nls/catopen.c b/lib/libc/nls/catopen.c
new file mode 100644
index 0000000..5dfb727
--- /dev/null
+++ b/lib/libc/nls/catopen.c
@@ -0,0 +1,26 @@
+/* $Id$ */
+
+/*
+ * Written by J.T. Conklin, 10/05/94
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+
+#ifdef __indr_reference
+__indr_reference(_catopen,catopen);
+#else
+
+#include <nl_types.h>
+
+extern nl_catd _catopen __P((__const char *, int));
+
+nl_catd
+catopen(name, oflag)
+ __const char *name;
+ int oflag;
+{
+ return _catopen(name, oflag);
+}
+
+#endif
diff --git a/lib/libc/nls/msgcat.c b/lib/libc/nls/msgcat.c
new file mode 100644
index 0000000..c90cefb
--- /dev/null
+++ b/lib/libc/nls/msgcat.c
@@ -0,0 +1,428 @@
+/* $Id: msgcat.c,v 1.10 1997/05/10 04:28:17 ache Exp $ */
+
+/***********************************************************
+Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
+
+ 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
+
+******************************************************************/
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$NetBSD: msgcat.c,v 1.11 1995/02/27 13:06:51 cgd Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* Edit History
+
+03/06/91 4 schulert remove working directory from nlspath
+01/18/91 2 hamilton #if not rescanned
+01/12/91 3 schulert conditionally use prototypes
+11/03/90 1 hamilton Alphalpha->Alfalfa & OmegaMail->Poste
+10/15/90 2 schulert > #include <unistd.h> if MIPS
+08/13/90 1 schulert move from ua to omu
+*/
+
+/*
+ * We need a better way of handling errors than printing text. I need
+ * to add an error handling routine.
+ */
+
+#include "nl_types.h"
+#include "msgcat.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef True
+# define True ~0
+# define False 0
+#endif
+
+/* take care of sysv diffs */
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+#ifndef FD_CLOEXEC
+#define FD_CLOEXEC 1
+#endif
+
+#define NLERR ((nl_catd) -1)
+
+static nl_catd loadCat();
+static nl_catd loadSet();
+
+nl_catd _catopen( name, type)
+__const char *name;
+int type;
+{
+ char path[MAXPATHLEN];
+ __const char *catpath = NULL;
+ char *nlspath;
+ char *lang;
+ long len;
+ char *base, *cptr, *pathP;
+ struct stat sbuf;
+
+ if (!name || !*name) return(NLERR);
+
+ if (strchr(name, '/')) {
+ catpath = name;
+ if (stat(catpath, &sbuf)) return(0);
+ } else {
+ if ((lang = (char *) getenv("LANG")) == NULL)
+ lang = "C";
+ if ((nlspath = (char *) getenv("NLSPATH")) == NULL || issetugid())
+ nlspath = "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L:/usr/local/share/nls/%L/%N.cat:/usr/local/share/nls/%N/%L";
+
+ len = strlen(nlspath);
+ base = cptr = (char *) malloc(len + 2);
+ if (!base) return(NLERR);
+ strcpy(cptr, nlspath);
+ cptr[len] = ':';
+ cptr[len+1] = '\0';
+
+ for (nlspath = cptr; *cptr; ++cptr) {
+ if (*cptr == ':') {
+ *cptr = '\0';
+ for (pathP = path; *nlspath; ++nlspath) {
+ if (*nlspath == '%') {
+ if (*(nlspath + 1) == 'L') {
+ ++nlspath;
+ strcpy(pathP, lang);
+ pathP += strlen(lang);
+ } else if (*(nlspath + 1) == 'N') {
+ ++nlspath;
+ strcpy(pathP, name);
+ pathP += strlen(name);
+ } else *(pathP++) = *nlspath;
+ } else *(pathP++) = *nlspath;
+ }
+ *pathP = '\0';
+ if (stat(path, &sbuf) == 0) {
+ catpath = path;
+ break;
+ }
+ nlspath = cptr+1;
+ }
+ }
+ free(base);
+
+ if (!catpath) return(0);
+ }
+
+ return(loadCat(catpath, type));
+}
+
+/*
+ * We've got an odd situation here. The odds are real good that the
+ * number we are looking for is almost the same as the index. We could
+ * use the index, check the difference and do something intelligent, but
+ * I haven't quite figured out what's intelligent.
+ *
+ * Here's a start.
+ * Take an id N. If there are > N items in the list, then N cannot
+ * be more than N items from the start, since otherwise there would
+ * have to be duplicate items. So we can safely set the top to N+1
+ * (after taking into account that ids start at 1, and arrays at 0)
+ *
+ * Let's say we are at position P, and we are looking for N, but have
+ * V. If N > V, then the furthest away that N could be is
+ * P + (N-V). So we can safely set hi to P+(N-V)+1. For example:
+ * We are looking for 10, but have 8
+ * 8 ? ? ? ?
+ * >=9 >=10 >=11
+ *
+ */
+static MCSetT *MCGetSet( cat, setId)
+MCCatT *cat;
+int setId;
+{
+ MCSetT *set;
+ long lo, hi, cur, dir;
+
+ if (!cat || setId <= 0) return(NULL);
+
+ lo = 0;
+ if (setId - 1 < cat->numSets) {
+ cur = setId - 1;
+ hi = setId;
+ } else {
+ hi = cat->numSets;
+ cur = (hi - lo) / 2;
+ }
+
+ while (True) {
+ set = cat->sets + cur;
+ if (set->setId == setId) break;
+ if (set->setId < setId) {
+ lo = cur+1;
+ if (hi > cur + (setId - set->setId) + 1) hi = cur+(setId-set->setId)+1;
+ dir = 1;
+ } else {
+ hi = cur;
+ dir = -1;
+ }
+ if (lo >= hi) return(NULL);
+ if (hi - lo == 1) cur += dir;
+ else cur += ((hi - lo) / 2) * dir;
+ }
+ if (set->invalid) loadSet(cat, set);
+ return(set);
+}
+
+
+static MCMsgT *MCGetMsg( set, msgId)
+MCSetT *set;
+int msgId;
+{
+ MCMsgT *msg;
+ long lo, hi, cur, dir;
+
+ if (!set || set->invalid || msgId <= 0) return(NULL);
+
+ lo = 0;
+ if (msgId - 1 < set->numMsgs) {
+ cur = msgId - 1;
+ hi = msgId;
+ } else {
+ hi = set->numMsgs;
+ cur = (hi - lo) / 2;
+ }
+
+ while (True) {
+ msg = set->u.msgs + cur;
+ if (msg->msgId == msgId) break;
+ if (msg->msgId < msgId) {
+ lo = cur+1;
+ if (hi > cur + (msgId - msg->msgId) + 1) hi = cur+(msgId-msg->msgId)+1;
+ dir = 1;
+ } else {
+ hi = cur;
+ dir = -1;
+ }
+ if (lo >= hi) return(NULL);
+ if (hi - lo == 1) cur += dir;
+ else cur += ((hi - lo) / 2) * dir;
+ }
+ return(msg);
+}
+
+char *_catgets( catd, setId, msgId, dflt)
+nl_catd catd;
+int setId;
+int msgId;
+char *dflt;
+{
+ MCMsgT *msg;
+ MCCatT *cat = (MCCatT *) catd;
+ char *cptr;
+
+ msg = MCGetMsg(MCGetSet(cat, setId), msgId);
+ if (msg) cptr = msg->msg.str;
+ else cptr = dflt;
+ return(cptr);
+}
+
+
+int _catclose( catd)
+nl_catd catd;
+{
+ MCCatT *cat = (MCCatT *) catd;
+ MCSetT *set;
+ int i;
+
+ if (!cat) return -1;
+
+ if (cat->loadType != MCLoadAll) close(cat->fd);
+ for (i = 0; i < cat->numSets; ++i) {
+ set = cat->sets + i;
+ if (!set->invalid) {
+ free(set->data.str);
+ free(set->u.msgs);
+ }
+ }
+ free(cat->sets);
+ free(cat);
+
+ return 0;
+}
+
+/*
+ * Internal routines
+ */
+
+/* Note that only malloc failures are allowed to return an error */
+#define ERRNAME "Message Catalog System"
+#define CORRUPT() {fprintf(stderr, "%s: corrupt file.\n", ERRNAME); free(cat); return(0);}
+#define NOSPACE() {fprintf(stderr, "%s: no more memory.\n", ERRNAME); free(cat); return(NLERR);}
+
+static nl_catd loadCat( catpath, type)
+__const char *catpath;
+int type;
+{
+ MCHeaderT header;
+ MCCatT *cat;
+ MCSetT *set;
+ long i, j;
+ off_t nextSet;
+
+ cat = (MCCatT *) malloc(sizeof(MCCatT));
+ if (!cat) return(NLERR);
+ cat->loadType = type;
+
+ if ((cat->fd = open(catpath, O_RDONLY)) < 0) {
+ free(cat);
+ return(0);
+ }
+
+ (void)fcntl(cat->fd, F_SETFD, FD_CLOEXEC);
+
+ if (read(cat->fd, &header, sizeof(header)) != sizeof(header)) CORRUPT();
+
+ if (strncmp(header.magic, MCMagic, MCMagicLen) != 0) CORRUPT();
+
+ if (header.majorVer != MCMajorVer) {
+ free(cat);
+ fprintf(stderr, "%s: %s is version %ld, we need %ld.\n", ERRNAME,
+ catpath, header.majorVer, MCMajorVer);
+ return(0);
+ }
+
+ if (header.numSets <= 0) {
+ free(cat);
+ fprintf(stderr, "%s: %s has %ld sets!\n", ERRNAME, catpath,
+ header.numSets);
+ return(0);
+ }
+
+ cat->numSets = header.numSets;
+ cat->sets = (MCSetT *) malloc(sizeof(MCSetT) * header.numSets);
+ if (!cat->sets) NOSPACE();
+
+ nextSet = header.firstSet;
+ for (i = 0; i < cat->numSets; ++i) {
+ if (lseek(cat->fd, nextSet, 0) == -1) {
+ for (j = 0; j < i; j++) {
+ set = cat->sets + j;
+ if (!set->invalid) {
+ free(set->data.str);
+ free(set->u.msgs);
+ }
+ }
+ free(cat->sets);
+ CORRUPT();
+ }
+
+ /* read in the set header */
+ set = cat->sets + i;
+ if (read(cat->fd, set, sizeof(*set)) != sizeof(*set)) {
+ for (j = 0; j < i; j++) {
+ set = cat->sets + j;
+ if (!set->invalid) {
+ free(set->data.str);
+ free(set->u.msgs);
+ }
+ }
+ free(cat->sets);
+ CORRUPT();
+ }
+
+ /* if it's invalid, skip over it (and backup 'i') */
+
+ if (set->invalid) {
+ --i;
+ nextSet = set->nextSet;
+ continue;
+ }
+
+ if (cat->loadType == MCLoadAll) {
+ nl_catd res;
+
+ if ((res = loadSet(cat, set)) <= 0) {
+ for (j = 0; j < i; j++) {
+ set = cat->sets + j;
+ if (!set->invalid) {
+ free(set->data.str);
+ free(set->u.msgs);
+ }
+ }
+ free(cat->sets);
+ if (res == -1) NOSPACE();
+ CORRUPT();
+ }
+ } else set->invalid = True;
+ nextSet = set->nextSet;
+ }
+ if (cat->loadType == MCLoadAll) {
+ close(cat->fd);
+ cat->fd = -1;
+ }
+ return((nl_catd) cat);
+}
+
+static nl_catd loadSet( cat, set)
+MCCatT *cat;
+MCSetT *set;
+{
+ MCMsgT *msg;
+ int i;
+
+ /* Get the data */
+ if (lseek(cat->fd, set->data.off, 0) == -1) return(0);
+ if ((set->data.str = (char *) malloc(set->dataLen)) == NULL) return(-1);
+ if (read(cat->fd, set->data.str, set->dataLen) != set->dataLen) {
+ free(set->data.str); return(0);
+ }
+
+ /* Get the messages */
+ if (lseek(cat->fd, set->u.firstMsg, 0) == -1) {
+ free(set->data.str); return(0);
+ }
+ if ((set->u.msgs = (MCMsgT *) malloc(sizeof(MCMsgT) * set->numMsgs)) == NULL) {
+ free(set->data.str); return(-1);
+ }
+
+ for (i = 0; i < set->numMsgs; ++i) {
+ msg = set->u.msgs + i;
+ if (read(cat->fd, msg, sizeof(*msg)) != sizeof(*msg)) {
+ free(set->u.msgs); free(set->data.str); return(0);
+ }
+ if (msg->invalid) {
+ --i;
+ continue;
+ }
+ msg->msg.str = (char *) (set->data.str + msg->msg.off);
+ }
+ set->invalid = False;
+ return(1);
+}
diff --git a/lib/libc/nls/msgcat.h b/lib/libc/nls/msgcat.h
new file mode 100644
index 0000000..9df7a82
--- /dev/null
+++ b/lib/libc/nls/msgcat.h
@@ -0,0 +1,170 @@
+/* $Id$ */
+
+/* -*-c++-*- */
+
+#ifndef __msgcath
+
+
+/***********************************************************
+Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
+
+ 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/types.h>
+
+/*
+ * On disk data structures
+ */
+
+/* Edit History
+
+02/25/91 2 nazgul Byte order flags, upped the version number
+11/03/90 1 hamilton Alphalpha->Alfalfa & OmegaMail->Poste
+08/13/90 1 schulert move from ua to omu
+*/
+
+/* For or'd constants */
+#define MCMakeId(s,m) (unsigned long) ( ((unsigned short)s << (sizeof(short)*8)) \
+ | (unsigned short)m )
+#define MCSetId(id) (unsigned int) ( id >> (sizeof(short) * 8) )
+#define MCMsgId(id) (unsigned int) ( (id << (sizeof(short) * 8)) \
+ >> (sizeof(short) * 8) )
+#undef S
+#undef UI
+#undef UL
+
+#define MCMagicLen 8
+#define MCMagic "*nazgul*"
+#define MCLastMsg 0
+#define MCLastSet 0
+
+#define MCMajorVer 1L
+#define MCMinorVer 0
+
+/*
+ * Critical note here. Sets and Messages *MUST* be stored in ascending
+ * order. There are stored that way (by specification) in the original
+ * data file, however in the process of merging in new stuff you might
+ * mix that up. Don't! The catget stuff does a binary search and will
+ * totally lose it if these aren't in order (not contiguous mind you, just
+ * in order. If this turns out to be a major problem this could be enhanced
+ * by adding a 'sorted' flag to the db, and sorting msgs and sets at load
+ * time if things aren't sorted, but I'd like not to have to do that.
+ */
+
+/*
+ * I have tried here to define data structures which can be used
+ * while the catalog is on disk, and at runtime.
+ * This is rather dangerous of course, but I think it can be done without
+ * overly increasing the memory usage, and it makes loading and storing
+ * somewhat simpler and less prone to accidents. I have also tried to
+ * define on disk data structures which can be updated in place, so that
+ * with a very large catalog (e.g. all system errors) you don't have to
+ * load everything in memory in order to add or update one set. With
+ * this in mind there are "invalid" flags which allow items to be
+ * invalidated and thus not loaded at runtime. Note however that although
+ * I pay attention to these when I load the DB, I do not currently use
+ * them in gencat (it just reads everything into memory), so there is
+ * no guarantee that this will all work.
+ */
+
+/* These should be publicly available */
+
+#define MCLoadBySet 0 /* Load entire sets as they are used */
+#define MCLoadAll 1 /* Load entire DB on catopen */
+
+/*
+ * MCOffsetT - Union to handle both disk and runtime pointers
+ */
+typedef union {
+ off_t off;
+ char *str;
+ void *ptr;
+ struct _MCMsgT *msg;
+ struct _MCSetT *set;
+} MCOffsetT;
+
+/*
+ * MCMsgT - Message structure (disk and runtime)
+ */
+typedef struct _MCMsgT {
+ long msgId; /* Id of this message */
+ MCOffsetT msg; /* Relative offset on disk or pointer in memory */
+ long invalid; /* Valid on disk, loaded in memory */
+} MCMsgT;
+
+/*
+ * MCSetT - Set structure (disk and runtime)
+ */
+typedef struct _MCSetT {
+ long setId; /* Id of this set */
+ off_t nextSet; /* Offset of next set on disk */
+ union {
+ off_t firstMsg; /* Offset to first Msg (while on disk) */
+ MCMsgT *msgs; /* Pointer to array of msgs (in mem, loaded) */
+ } u;
+ MCOffsetT data; /* Offset to data, or pointer to data */
+ long dataLen; /* Length of data area on disk */
+ long numMsgs; /* Number of messages */
+ long invalid; /* Valid on disk, loaded in memory */
+} MCSetT;
+
+/*
+ * MCCatT - Runtime catalog pointer
+ */
+typedef struct {
+ long loadType; /* How to load the messages (see MSLoadType) */
+ int fd; /* File descriptor of catalog (if load-on-demand) */
+ long numSets; /* Number of sets */
+ MCSetT *sets; /* Pointer to the sets */
+ off_t firstSet; /* Offset of first set on disk */
+} MCCatT;
+
+/*
+ * MCHeaderT - Disk file header
+ */
+typedef struct {
+ char magic[MCMagicLen]; /* Magic cookie "*nazgul*" */
+ long majorVer; /* ++ on incompatible changes */
+ long minorVer; /* ++ on compatible changes */
+ long flags; /* Informational flags */
+ long numSets; /* Number of valid Sets */
+ off_t firstSet; /* Offset of first set on disk */
+} MCHeaderT;
+
+/* Some flags */
+#define MC68KByteOrder 0x01
+#define MCn86ByteOrder 0x02
+
+
+
+
+#endif
diff --git a/lib/libc/quad/Makefile.inc b/lib/libc/quad/Makefile.inc
index 6273574..8aca699 100644
--- a/lib/libc/quad/Makefile.inc
+++ b/lib/libc/quad/Makefile.inc
@@ -1,10 +1,20 @@
-# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
+
+# Quad support, if needed
+
+.if ${MACHINE} == "i386"
+
+SRCS+= cmpdi2.c divdi3.c moddi3.c qdivrem.c ucmpdi2.c udivdi3.c umoddi3.c
+
+.else
-# Quad support
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
-.PATH: ${.CURDIR}/${MACHINE}/quad ${.CURDIR}/quad
+.endif
+
+.PATH: ${.CURDIR}/../libc/${MACHINE}/quad ${.CURDIR}/../libc/quad
diff --git a/lib/libc/quad/muldi3.c b/lib/libc/quad/muldi3.c
index a8d7cfc..5e2331f 100644
--- a/lib/libc/quad/muldi3.c
+++ b/lib/libc/quad/muldi3.c
@@ -49,7 +49,7 @@ static char sccsid[] = "@(#)muldi3.c 8.1 (Berkeley) 6/4/93";
*
* u = 2^n u1 * u0 (n = number of bits in `u_long', usu. 32)
*
- * and
+ * and
*
* v = 2^n v1 * v0
*
diff --git a/lib/libc/quad/qdivrem.c b/lib/libc/quad/qdivrem.c
index 34b94ce..56f91ec 100644
--- a/lib/libc/quad/qdivrem.c
+++ b/lib/libc/quad/qdivrem.c
@@ -198,7 +198,7 @@ __qdivrem(uq, vq, arq)
v2 = v[2]; /* for D3 */
do {
register 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
diff --git a/lib/libc/quad/quad.h b/lib/libc/quad/quad.h
index bc6a2f8..873a1f6 100644
--- a/lib/libc/quad/quad.h
+++ b/lib/libc/quad/quad.h
@@ -35,6 +35,7 @@
* SUCH DAMAGE.
*
* @(#)quad.h 8.1 (Berkeley) 6/4/93
+ * $Id$
*/
/*
@@ -95,7 +96,11 @@ union uu {
#define LHALF(x) ((x) & ((1 << HALF_BITS) - 1))
#define LHUP(x) ((x) << HALF_BITS)
-extern u_quad_t __qdivrem __P((u_quad_t u, u_quad_t v, u_quad_t *rem));
+quad_t __divdi3 __P((quad_t a, quad_t b));
+quad_t __moddi3 __P((quad_t a, quad_t b));
+u_quad_t __qdivrem __P((u_quad_t u, u_quad_t v, u_quad_t *rem));
+u_quad_t __udivdi3 __P((u_quad_t a, u_quad_t b));
+u_quad_t __umoddi3 __P((u_quad_t a, u_quad_t b));
/*
* XXX
diff --git a/lib/libc/regex/Makefile.inc b/lib/libc/regex/Makefile.inc
index f9853f3..d8c6092 100644
--- a/lib/libc/regex/Makefile.inc
+++ b/lib/libc/regex/Makefile.inc
@@ -1,14 +1,18 @@
-# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id$
# regex sources
-.PATH: ${.CURDIR}/regex
+.PATH: ${.CURDIR}/../libc/regex
CFLAGS+=-DPOSIX_MISTAKE
SRCS+= regcomp.c regerror.c regexec.c regfree.c
-MAN3+= regex.0
-MAN7+= re_format.0
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN3+= regex/regex.3
+MAN7+= regex/re_format.7
MLINKS+=regex.3 regcomp.3 regex.3 regexec.3 regex.3 regerror.3
MLINKS+=regexec.3 regfree.3
+.endif
diff --git a/lib/libc/regex/cclass.h b/lib/libc/regex/cclass.h
index a29a92e..581909c 100644
--- a/lib/libc/regex/cclass.h
+++ b/lib/libc/regex/cclass.h
@@ -37,34 +37,26 @@
* @(#)cclass.h 8.3 (Berkeley) 3/20/94
*/
+
+typedef enum {CALNUM, CALPHA, CBLANK, CCNTRL, CDIGIT, CGRAPH,
+ CLOWER, CPRINT, CPUNCT, CSPACE, CUPPER, CXDIGIT} citype;
+
/* character-class table */
static struct cclass {
char *name;
- char *chars;
- char *multis;
+ citype fidx;
} cclasses[] = {
- "alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-0123456789", "",
- "alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
- "",
- "blank", " \t", "",
- "cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\
-\25\26\27\30\31\32\33\34\35\36\37\177", "",
- "digit", "0123456789", "",
- "graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- "",
- "lower", "abcdefghijklmnopqrstuvwxyz",
- "",
- "print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ",
- "",
- "punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- "",
- "space", "\t\n\v\f\r ", "",
- "upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
- "",
- "xdigit", "0123456789ABCDEFabcdef",
- "",
- NULL, 0, ""
+ {"alnum", CALNUM},
+ {"alpha", CALPHA},
+ {"blank", CBLANK},
+ {"cntrl", CCNTRL},
+ {"digit", CDIGIT},
+ {"graph", CGRAPH},
+ {"lower", CLOWER},
+ {"print", CPRINT},
+ {"punct", CPUNCT},
+ {"space", CSPACE},
+ {"upper", CUPPER},
+ {"xdigit", CXDIGIT},
+ {NULL, }
};
diff --git a/lib/libc/regex/cname.h b/lib/libc/regex/cname.h
index c1632eb..72bbe5e 100644
--- a/lib/libc/regex/cname.h
+++ b/lib/libc/regex/cname.h
@@ -42,100 +42,100 @@ 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,
+ {"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
index 02c841a..be569b1 100644
--- a/lib/libc/regex/engine.c
+++ b/lib/libc/regex/engine.c
@@ -148,8 +148,8 @@ int eflags;
struct match mv;
register struct match *m = &mv;
register char *dp;
- const register sopno gf = g->firststate+1; /* +1 for OEND */
- const register sopno gl = g->laststate;
+ register const sopno gf = g->firststate+1; /* +1 for OEND */
+ register const sopno gl = g->laststate;
char *start;
char *stop;
@@ -686,6 +686,7 @@ sopno lev; /* PLUS nesting level */
/* "can't happen" */
assert(nope);
/* NOTREACHED */
+ return "shut up gcc";
}
/*
@@ -1028,7 +1029,7 @@ FILE *d;
fprintf(d, "\n");
}
-/*
+/*
- at - print current situation
== #ifdef REDEBUG
== static void at(struct match *m, char *title, char *start, char *stop, \
@@ -1071,7 +1072,7 @@ int ch;
{
static char pbuf[10];
- if (isprint(ch) || ch == ' ')
+ if (isprint((uch)ch) || ch == ' ')
sprintf(pbuf, "%c", ch);
else
sprintf(pbuf, "\\%o", ch);
diff --git a/lib/libc/regex/regcomp.c b/lib/libc/regex/regcomp.c
index feb24ec..8bb1355 100644
--- a/lib/libc/regex/regcomp.c
+++ b/lib/libc/regex/regcomp.c
@@ -49,6 +49,8 @@ static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94";
#include <stdlib.h>
#include <regex.h>
+#include "collate.h"
+
#include "utils.h"
#include "regex2.h"
@@ -103,9 +105,11 @@ static int freezeset __P((struct parse *p, cset *cs));
static int firstch __P((struct parse *p, cset *cs));
static int nch __P((struct parse *p, cset *cs));
static void mcadd __P((struct parse *p, cset *cs, char *cp));
+#if used
static void mcsub __P((cset *cs, char *cp));
static int mcin __P((cset *cs, char *cp));
static char *mcfind __P((cset *cs, char *cp));
+#endif
static void mcinvert __P((struct parse *p, cset *cs));
static void mccase __P((struct parse *p, cset *cs));
static int isinsets __P((struct re_guts *g, int c));
@@ -295,7 +299,7 @@ int stop; /* character this ERE should end at */
conc = HERE();
while (MORE() && (c = PEEK()) != '|' && c != stop)
p_ere_exp(p);
- REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */
+ (void)REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */
if (!EAT('|'))
break; /* NOTE BREAK OUT */
@@ -342,7 +346,7 @@ register struct parse *p;
pos = HERE();
switch (c) {
case '(':
- REQUIRE(MORE(), REG_EPAREN);
+ (void)REQUIRE(MORE(), REG_EPAREN);
p->g->nsub++;
subno = p->g->nsub;
if (subno < NPAREN)
@@ -355,7 +359,7 @@ register struct parse *p;
assert(p->pend[subno] != 0);
}
EMIT(ORPAREN, subno);
- MUSTEAT(')', REG_EPAREN);
+ (void)MUSTEAT(')', REG_EPAREN);
break;
#ifndef POSIX_MISTAKE
case ')': /* happens only if no current unmatched ( */
@@ -398,12 +402,12 @@ register struct parse *p;
p_bracket(p);
break;
case '\\':
- REQUIRE(MORE(), REG_EESCAPE);
+ (void)REQUIRE(MORE(), REG_EESCAPE);
c = GETNEXT();
ordinary(p, c);
break;
case '{': /* okay as ordinary except if digit follows */
- REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT);
+ (void)REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT);
/* FALLTHROUGH */
default:
ordinary(p, c);
@@ -419,7 +423,7 @@ register struct parse *p;
return; /* no repetition, we're done */
NEXT();
- REQUIRE(!wascaret, REG_BADRPT);
+ (void)REQUIRE(!wascaret, REG_BADRPT);
switch (c) {
case '*': /* implemented as +? */
/* this case does not require the (y|) trick, noKLUDGE */
@@ -446,7 +450,7 @@ register struct parse *p;
if (EAT(',')) {
if (isdigit(PEEK())) {
count2 = p_count(p);
- REQUIRE(count <= count2, REG_BADBR);
+ (void)REQUIRE(count <= count2, REG_BADBR);
} else /* single number with comma */
count2 = INFINITY;
} else /* just a single number */
@@ -455,7 +459,7 @@ register struct parse *p;
if (!EAT('}')) { /* error heuristics */
while (MORE() && PEEK() != '}')
NEXT();
- REQUIRE(MORE(), REG_EBRACE);
+ (void)REQUIRE(MORE(), REG_EBRACE);
SETERROR(REG_BADBR);
}
break;
@@ -478,7 +482,7 @@ static void
p_str(p)
register struct parse *p;
{
- REQUIRE(MORE(), REG_EMPTY);
+ (void)REQUIRE(MORE(), REG_EMPTY);
while (MORE())
ordinary(p, GETNEXT());
}
@@ -521,7 +525,7 @@ register int end2; /* second terminating character */
p->g->neol++;
}
- REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */
+ (void)REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */
}
/*
@@ -546,7 +550,7 @@ int starordinary; /* is a leading * an ordinary character? */
assert(MORE()); /* caller should have ensured this */
c = GETNEXT();
if (c == '\\') {
- REQUIRE(MORE(), REG_EESCAPE);
+ (void)REQUIRE(MORE(), REG_EESCAPE);
c = BACKSL | (unsigned char)GETNEXT();
}
switch (c) {
@@ -576,7 +580,7 @@ int starordinary; /* is a leading * an ordinary character? */
assert(p->pend[subno] != 0);
}
EMIT(ORPAREN, subno);
- REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
+ (void)REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
break;
case BACKSL|')': /* should not get here -- must be user */
case BACKSL|'}':
@@ -606,7 +610,7 @@ int starordinary; /* is a leading * an ordinary character? */
p->g->backrefs = 1;
break;
case '*':
- REQUIRE(starordinary, REG_BADRPT);
+ (void)REQUIRE(starordinary, REG_BADRPT);
/* FALLTHROUGH */
default:
ordinary(p, c &~ BACKSL);
@@ -624,7 +628,7 @@ int starordinary; /* is a leading * an ordinary character? */
if (EAT(',')) {
if (MORE() && isdigit(PEEK())) {
count2 = p_count(p);
- REQUIRE(count <= count2, REG_BADBR);
+ (void)REQUIRE(count <= count2, REG_BADBR);
} else /* single number with comma */
count2 = INFINITY;
} else /* just a single number */
@@ -633,7 +637,7 @@ int starordinary; /* is a leading * an ordinary character? */
if (!EATTWO('\\', '}')) { /* error heuristics */
while (MORE() && !SEETWO('\\', '}'))
NEXT();
- REQUIRE(MORE(), REG_EBRACE);
+ (void)REQUIRE(MORE(), REG_EBRACE);
SETERROR(REG_BADBR);
}
} else if (c == (unsigned char)'$') /* $ (but not \$) ends it */
@@ -658,7 +662,7 @@ register struct parse *p;
ndigits++;
}
- REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
+ (void)REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
return(count);
}
@@ -673,7 +677,6 @@ static void
p_bracket(p)
register struct parse *p;
{
- register char c;
register cset *cs = allocset(p);
register int invert = 0;
@@ -699,7 +702,7 @@ register struct parse *p;
p_b_term(p, cs);
if (EAT('-'))
CHadd(cs, '-');
- MUSTEAT(']', REG_EBRACK);
+ (void)MUSTEAT(']', REG_EBRACK);
if (p->error != 0) /* don't mess things up further */
return;
@@ -770,21 +773,21 @@ register cset *cs;
switch (c) {
case ':': /* character class */
NEXT2();
- REQUIRE(MORE(), REG_EBRACK);
+ (void)REQUIRE(MORE(), REG_EBRACK);
c = PEEK();
- REQUIRE(c != '-' && c != ']', REG_ECTYPE);
+ (void)REQUIRE(c != '-' && c != ']', REG_ECTYPE);
p_b_cclass(p, cs);
- REQUIRE(MORE(), REG_EBRACK);
- REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
+ (void)REQUIRE(MORE(), REG_EBRACK);
+ (void)REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
break;
case '=': /* equivalence class */
NEXT2();
- REQUIRE(MORE(), REG_EBRACK);
+ (void)REQUIRE(MORE(), REG_EBRACK);
c = PEEK();
- REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
+ (void)REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
p_b_eclass(p, cs);
- REQUIRE(MORE(), REG_EBRACK);
- REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
+ (void)REQUIRE(MORE(), REG_EBRACK);
+ (void)REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
break;
default: /* symbol, ordinary character, or range */
/* xxx revision needed for multichar stuff */
@@ -798,10 +801,23 @@ register cset *cs;
finish = p_b_symbol(p);
} else
finish = start;
-/* xxx what about signed chars here... */
- REQUIRE(start <= finish, REG_ERANGE);
- for (i = start; i <= finish; i++)
- CHadd(cs, i);
+ if (start == finish)
+ CHadd(cs, start);
+ else {
+ if (__collate_load_error) {
+ (void)REQUIRE((uch)start <= (uch)finish, REG_ERANGE);
+ for (i = (uch)start; i <= (uch)finish; i++)
+ CHadd(cs, i);
+ } else {
+ (void)REQUIRE(__collate_range_cmp(start, finish) <= 0, REG_ERANGE);
+ for (i = CHAR_MIN; i <= CHAR_MAX; i++) {
+ if ( __collate_range_cmp(start, i) <= 0
+ && __collate_range_cmp(i, finish) <= 0
+ )
+ CHadd(cs, i);
+ }
+ }
+ }
break;
}
}
@@ -815,13 +831,12 @@ p_b_cclass(p, cs)
register struct parse *p;
register cset *cs;
{
+ register int c;
register char *sp = p->next;
register struct cclass *cp;
register size_t len;
- register char *u;
- register char c;
- while (MORE() && isalpha(PEEK()))
+ while (MORE() && isalpha((uch)PEEK()))
NEXT();
len = p->next - sp;
for (cp = cclasses; cp->name != NULL; cp++)
@@ -833,11 +848,72 @@ register cset *cs;
return;
}
- u = cp->chars;
- while ((c = *u++) != '\0')
- CHadd(cs, c);
+ switch (cp->fidx) {
+ case CALNUM:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (isalnum((uch)c))
+ CHadd(cs, c);
+ break;
+ case CALPHA:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (isalpha((uch)c))
+ CHadd(cs, c);
+ break;
+ case CBLANK:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (isblank((uch)c))
+ CHadd(cs, c);
+ break;
+ case CCNTRL:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (iscntrl((uch)c))
+ CHadd(cs, c);
+ break;
+ case CDIGIT:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (isdigit((uch)c))
+ CHadd(cs, c);
+ break;
+ case CGRAPH:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (isgraph((uch)c))
+ CHadd(cs, c);
+ break;
+ case CLOWER:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (islower((uch)c))
+ CHadd(cs, c);
+ break;
+ case CPRINT:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (isprint((uch)c))
+ CHadd(cs, c);
+ break;
+ case CPUNCT:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (ispunct((uch)c))
+ CHadd(cs, c);
+ break;
+ case CSPACE:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (isspace((uch)c))
+ CHadd(cs, c);
+ break;
+ case CUPPER:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (isupper((uch)c))
+ CHadd(cs, c);
+ break;
+ case CXDIGIT:
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (isxdigit((uch)c))
+ CHadd(cs, c);
+ break;
+ }
+#if 0
for (u = cp->multis; *u != '\0'; u += strlen(u) + 1)
MCadd(p, cs, u);
+#endif
}
/*
@@ -867,13 +943,13 @@ register struct parse *p;
{
register char value;
- REQUIRE(MORE(), REG_EBRACK);
+ (void)REQUIRE(MORE(), REG_EBRACK);
if (!EATTWO('[', '.'))
return(GETNEXT());
/* collating symbol */
value = p_b_coll_elem(p, '.');
- REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
+ (void)REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
return(value);
}
@@ -889,7 +965,6 @@ int endc; /* name ended by endc,']' */
register char *sp = p->next;
register struct cname *cp;
register int len;
- register char c;
while (MORE() && !SEETWO(endc, ']'))
NEXT();
@@ -915,6 +990,7 @@ static char /* if no counterpart, return ch */
othercase(ch)
int ch;
{
+ ch = (unsigned char)ch;
assert(isalpha(ch));
if (isupper(ch))
return(tolower(ch));
@@ -939,6 +1015,7 @@ int ch;
register char *oldend = p->end;
char bracket[3];
+ ch = (unsigned char)ch;
assert(othercase(ch) != ch); /* p_bracket() would recurse */
p->next = bracket;
p->end = bracket+2;
@@ -962,7 +1039,7 @@ register int ch;
{
register cat_t *cap = p->g->categories;
- if ((p->g->cflags&REG_ICASE) && isalpha(ch) && othercase(ch) != ch)
+ if ((p->g->cflags&REG_ICASE) && isalpha((unsigned char)ch) && othercase(ch) != ch)
bothcases(p, ch);
else {
EMIT(OCHAR, (unsigned char)ch);
@@ -1174,7 +1251,7 @@ freezeset(p, cs)
register struct parse *p;
register cset *cs;
{
- register uch h = cs->hash;
+ register short h = cs->hash;
register int i;
register cset *top = &p->g->sets[p->g->ncsets];
register cset *cs2;
@@ -1213,7 +1290,7 @@ register cset *cs;
for (i = 0; i < css; i++)
if (CHIN(cs, i))
- return((char)i);
+ return((unsigned char)i);
assert(never);
return(0); /* arbitrary */
}
@@ -1264,6 +1341,7 @@ register char *cp;
cs->multis[cs->smultis - 1] = '\0';
}
+#if used
/*
- mcsub - subtract a collating element from a cset
== static void mcsub(register cset *cs, register char *cp);
@@ -1321,6 +1399,7 @@ register char *cp;
return(p);
return(NULL);
}
+#endif
/*
- mcinvert - invert the list of collating elements in a cset
diff --git a/lib/libc/regex/regerror.c b/lib/libc/regex/regerror.c
index a8d0945..1ed6771 100644
--- a/lib/libc/regex/regerror.c
+++ b/lib/libc/regex/regerror.c
@@ -88,23 +88,23 @@ static struct rerr {
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",
- 0, "", "*** unknown regexp error code ***",
+ {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"},
+ {0, "", "*** unknown regexp error code ***"}
};
/*
@@ -131,7 +131,7 @@ size_t errbuf_size;
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);
@@ -166,8 +166,6 @@ const regex_t *preg;
char *localbuf;
{
register struct rerr *r;
- register size_t siz;
- register char *p;
for (r = rerrs; r->code != 0; r++)
if (strcmp(r->name, preg->re_endp) == 0)
diff --git a/lib/libc/regex/regex.3 b/lib/libc/regex/regex.3
index 66a7285..a107eea 100644
--- a/lib/libc/regex/regex.3
+++ b/lib/libc/regex/regex.3
@@ -483,7 +483,9 @@ REG_INVARG invalid argument, e.g. negative-length string
.fi
.SH HISTORY
Originally written by Henry Spencer.
-Altered for inclusion in the 4.4BSD distribution.
+Altered for inclusion in the
+.Bx 4.4
+distribution.
.SH BUGS
This is an alpha release with known defects.
Please report problems.
diff --git a/lib/libc/regex/regex2.h b/lib/libc/regex/regex2.h
index 64b6212..9560e05 100644
--- a/lib/libc/regex/regex2.h
+++ b/lib/libc/regex/regex2.h
@@ -121,13 +121,13 @@ typedef long sopno;
typedef struct {
uch *ptr; /* -> uch [csetsize] */
uch mask; /* bit within array */
- uch hash; /* hash code */
+ short hash; /* hash code */
size_t smultis;
char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */
} cset;
/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */
-#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c))
-#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c))
+#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (uch)(c))
+#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (uch)(c))
#define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask)
#define MCadd(p, cs, cp) mcadd(p, cs, cp) /* regcomp() internal fns */
#define MCsub(p, cs, cp) mcsub(p, cs, cp)
@@ -170,4 +170,4 @@ struct re_guts {
/* misc utilities */
#define OUT (CHAR_MAX+1) /* a non-character value */
-#define ISWORD(c) (isalnum(c) || (c) == '_')
+#define ISWORD(c) (isalnum((uch)(c)) || (c) == '_')
diff --git a/lib/libc/rpc/DISCLAIMER b/lib/libc/rpc/DISCLAIMER
new file mode 100644
index 0000000..1a66d5f
--- /dev/null
+++ b/lib/libc/rpc/DISCLAIMER
@@ -0,0 +1,28 @@
+/*
+ * 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/Makefile.inc b/lib/libc/rpc/Makefile.inc
new file mode 100644
index 0000000..5c96968
--- /dev/null
+++ b/lib/libc/rpc/Makefile.inc
@@ -0,0 +1,120 @@
+# @(#)Makefile 5.11 (Berkeley) 9/6/90
+
+.PATH: ${.CURDIR}/../libc/rpc ${.CURDIR}/.
+SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c \
+ clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \
+ clnt_udp.c rpc_dtablesize.c get_myaddress.c getrpcent.c getrpcport.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 \
+ svc.c svc_auth.c svc_auth_unix.c svc_raw.c svc_run.c svc_simple.c \
+ svc_tcp.c svc_udp.c
+
+SRCS+= clnt_unix.c svc_unix.c
+
+SRCS+= auth_des.c authdes_prot.c auth_time.c des_soft.c des_crypt.c \
+ key_call.c key_prot_xdr.c netname.c netnamer.c rpcdname.c rtime.c \
+ svc_auth_des.c crypt_clnt.c crypt_xdr.c crypt_client.c
+
+CFLAGS+= -DBROKEN_DES
+
+CLEANFILES= crypt_clnt.c crypt_xdr.c crypt.h
+
+RPCDIR= ${DESTDIR}/usr/include/rpcsvc
+RPCGEN= 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
+
+# Only build man pages with libc.
+.if ${LIB} == "c"
+#
+# XXX -- rstat.1 and rstat_svc.8 shouldn't really be here
+# but there's no rstat command, don't know why, so I'm
+# leaving them here in case they're needed sometime later.
+# Paul.
+#
+
+# MAN1+= rpc/rstat.1
+MAN3+= rpc/bindresvport.3 rpc/getrpcent.3 rpc/getrpcport.3 rpc/rpc.3
+MAN5+= rpc/rpc.5
+MAN8+= rpc/rstat_svc.8
+
+MAN3+= rpc/rpc_secure.3 rpc/publickey.3 rpc/rtime.3 rpc/des_crypt.3
+MAN5+= rpc/publickey.5
+
+MLINKS+= getrpcent.3 getrpcbyname.3 \
+ getrpcent.3 getrpcbynumber.3 \
+ getrpcent.3 endrpcent.3 \
+ getrpcent.3 setrpcent.3 \
+ rpc.3 auth_destroy.3 \
+ rpc.3 authnone_create.3 \
+ rpc.3 authunix_create.3 \
+ rpc.3 authunix_create_default.3 \
+ rpc.3 callrpc.3 \
+ rpc.3 clnt_broadcast.3 \
+ rpc.3 clnt_call.3 \
+ rpc.3 clnt_control.3 \
+ rpc.3 clnt_create.3 \
+ rpc.3 clnt_destroy.3 \
+ rpc.3 clnt_freeres.3 \
+ rpc.3 clnt_geterr.3 \
+ rpc.3 clnt_pcreateerror.3 \
+ rpc.3 clnt_perrno.3 \
+ rpc.3 clnt_perror.3 \
+ rpc.3 clnt_spcreateerror.3 \
+ rpc.3 clnt_sperrno.3 \
+ rpc.3 clnt_sperror.3 \
+ rpc.3 clntraw_create.3 \
+ rpc.3 clnttcp_create.3 \
+ rpc.3 clntudp_bufcreate.3 \
+ rpc.3 clntudp_create.3 \
+ rpc.3 get_myaddress.3 \
+ rpc.3 pmap_getmaps.3 \
+ rpc.3 pmap_getport.3 \
+ rpc.3 pmap_rmtcall.3 \
+ rpc.3 pmap_set.3 \
+ rpc.3 pmap_unset.3 \
+ rpc.3 regsterrpc.3 \
+ rpc.3 rpc_createerr.3 \
+ rpc.3 svc_destroy.3 \
+ rpc.3 svc_fds.3 \
+ rpc.3 svc_fdset.3 \
+ rpc.3 svc_getargs.3 \
+ rpc.3 svc_getcaller.3 \
+ rpc.3 svc_getreg.3 \
+ rpc.3 svc_getregset.3 \
+ rpc.3 svc_register.3 \
+ rpc.3 svc_run.3 \
+ rpc.3 svc_sendreply.3 \
+ rpc.3 svc_unregister.3 \
+ rpc.3 svcerr_auth.3 \
+ rpc.3 svcerr_decode.3 \
+ rpc.3 svcerr_noproc.3 \
+ rpc.3 svcerr_noprog.3 \
+ rpc.3 svcerr_progvers.3 \
+ rpc.3 svcerr_systemerr.3 \
+ rpc.3 svcerr_weakauth.3 \
+ rpc.3 svcfd_create.3 \
+ rpc.3 svcraw_create.3 \
+ rpc.3 svctcp_create.3 \
+ rpc.3 svcudp_bufcreate.3 \
+ rpc.3 xdr_accepted_reply.3 \
+ rpc.3 xdr_authunix_parms.3 \
+ rpc.3 xdr_callhdr.3 \
+ rpc.3 xdr_callmsg.3 \
+ rpc.3 xdr_opaque_auth.3 \
+ rpc.3 xdr_pmap.3 \
+ rpc.3 xdr_pmaplist.3 \
+ rpc.3 xdr_rejected_reply.3 \
+ rpc.3 xdr_replymsg.3 \
+ rpc.3 xprt_register.3 \
+ rpc.3 xprt_unregister.3 \
+
+MLINKS+=getrpcent.3 getrpcbyname.3 getrpcent.3 getrpcbynumber.3
+.endif
diff --git a/lib/libc/rpc/PSD.doc/nfs.rfc.ms b/lib/libc/rpc/PSD.doc/nfs.rfc.ms
new file mode 100644
index 0000000..0c9a899
--- /dev/null
+++ b/lib/libc/rpc/PSD.doc/nfs.rfc.ms
@@ -0,0 +1,1372 @@
+.\"
+.\" Must use -- tbl -- with this one
+.\"
+.\" @(#)nfs.rfc.ms 2.2 88/08/05 4.0 RPCSRC
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'Network File System: Version 2 Protocol Specification''Page %'
+.EH 'Page %''Network File System: Version 2 Protocol Specification'
+.if \\n%=1 .bp
+.SH
+\&Network File System: Version 2 Protocol Specification
+.IX NFS "" "" "" PAGE MAJOR
+.IX "Network File System" "" "" "" PAGE MAJOR
+.IX NFS "version-2 protocol specification"
+.IX "Network File System" "version-2 protocol specification"
+.LP
+.NH 0
+\&Status of this Standard
+.LP
+Note: This document specifies a protocol that Sun Microsystems, Inc.,
+and others are using. It specifies it in standard ARPA RFC form.
+.NH 1
+\&Introduction
+.IX NFS introduction
+.LP
+The Sun Network Filesystem (NFS) protocol provides transparent remote
+access to shared filesystems over local area networks. The NFS
+protocol is designed to be machine, operating system, network architecture,
+and transport protocol independent. This independence is
+achieved through the use of Remote Procedure Call (RPC) primitives
+built on top of an External Data Representation (XDR). Implementations
+exist for a variety of machines, from personal computers to
+supercomputers.
+.LP
+The supporting mount protocol allows the server to hand out remote
+access privileges to a restricted set of clients. It performs the
+operating system-specific functions that allow, for example, to
+attach remote directory trees to some local file system.
+.NH 2
+\&Remote Procedure Call
+.IX "Remote Procedure Call"
+.LP
+Sun's remote procedure call specification provides a procedure-
+oriented interface to remote services. Each server supplies a
+program that is a set of procedures. NFS is one such "program".
+The combination of host address, program number, and procedure
+number specifies one remote service procedure. RPC does not depend
+on services provided by specific protocols, so it can be used with
+any underlying transport protocol. See the
+.I "Remote Procedure Calls: Protocol Specification"
+chapter of this manual.
+.NH 2
+\&External Data Representation
+.IX "External Data Representation"
+.LP
+The External Data Representation (XDR) standard provides a common
+way of representing a set of data types over a network.
+The NFS
+Protocol Specification is written using the RPC data description
+language.
+For more information, see the
+.I " External Data Representation Standard: Protocol Specification."
+Sun provides implementations of XDR and
+RPC, but NFS does not require their use. Any software that
+provides equivalent functionality can be used, and if the encoding
+is exactly the same it can interoperate with other implementations
+of NFS.
+.NH 2
+\&Stateless Servers
+.IX "stateless servers"
+.IX servers stateless
+.LP
+The NFS protocol is stateless. That is, a server does not need to
+maintain any extra state information about any of its clients in
+order to function correctly. Stateless servers have a distinct
+advantage over stateful servers in the event of a failure. With
+stateless servers, a client need only retry a request until the
+server responds; it does not even need to know that the server has
+crashed, or the network temporarily went down. The client of a
+stateful server, on the other hand, needs to either detect a server
+crash and rebuild the server's state when it comes back up, or
+cause client operations to fail.
+.LP
+This may not sound like an important issue, but it affects the
+protocol in some unexpected ways. We feel that it is worth a bit
+of extra complexity in the protocol to be able to write very simple
+servers that do not require fancy crash recovery.
+.LP
+On the other hand, NFS deals with objects such as files and
+directories that inherently have state -- what good would a file be
+if it did not keep its contents intact? The goal is to not
+introduce any extra state in the protocol itself. Another way to
+simplify recovery is by making operations "idempotent" whenever
+possible (so that they can potentially be repeated).
+.NH 1
+\&NFS Protocol Definition
+.IX NFS "protocol definition"
+.IX NFS protocol
+.LP
+Servers have been known to change over time, and so can the
+protocol that they use. So RPC provides a version number with each
+RPC request. This RFC describes version two of the NFS protocol.
+Even in the second version, there are various obsolete procedures
+and parameters, which will be removed in later versions. An RFC
+for version three of the NFS protocol is currently under
+preparation.
+.NH 2
+\&File System Model
+.IX filesystem model
+.LP
+NFS assumes a file system that is hierarchical, with directories as
+all but the bottom-level files. Each entry in a directory (file,
+directory, device, etc.) has a string name. Different operating
+systems may have restrictions on the depth of the tree or the names
+used, as well as using different syntax to represent the "pathname",
+which is the concatenation of all the "components" (directory and
+file names) in the name. A "file system" is a tree on a single
+server (usually a single disk or physical partition) with a specified
+"root". Some operating systems provide a "mount" operation to make
+all file systems appear as a single tree, while others maintain a
+"forest" of file systems. Files are unstructured streams of
+uninterpreted bytes. Version 3 of NFS uses a slightly more general
+file system model.
+.LP
+NFS looks up one component of a pathname at a time. It may not be
+obvious why it does not just take the whole pathname, traipse down
+the directories, and return a file handle when it is done. There are
+several good reasons not to do this. First, pathnames need
+separators between the directory components, and different operating
+systems use different separators. We could define a Network Standard
+Pathname Representation, but then every pathname would have to be
+parsed and converted at each end. Other issues are discussed in
+\fINFS Implementation Issues\fP below.
+.LP
+Although files and directories are similar objects in many ways,
+different procedures are used to read directories and files. This
+provides a network standard format for representing directories. The
+same argument as above could have been used to justify a procedure
+that returns only one directory entry per call. The problem is
+efficiency. Directories can contain many entries, and a remote call
+to return each would be just too slow.
+.NH 2
+\&RPC Information
+.IX NFS "RPC information"
+.IP \fIAuthentication\fP
+The NFS service uses
+.I AUTH_UNIX ,
+.I AUTH_DES ,
+or
+.I AUTH_SHORT
+style
+authentication, except in the NULL procedure where
+.I AUTH_NONE
+is also allowed.
+.IP "\fITransport Protocols\fP"
+NFS currently is supported on UDP/IP only.
+.IP "\fIPort Number\fP"
+The NFS protocol currently uses the UDP port number 2049. This is
+not an officially assigned port, so later versions of the protocol
+use the \*QPortmapping\*U facility of RPC.
+.NH 2
+\&Sizes of XDR Structures
+.IX "XDR structure sizes"
+.LP
+These are the sizes, given in decimal bytes, of various XDR
+structures used in the protocol:
+.DS
+/* \fIThe maximum number of bytes of data in a READ or WRITE request\fP */
+const MAXDATA = 8192;
+
+/* \fIThe maximum number of bytes in a pathname argument\fP */
+const MAXPATHLEN = 1024;
+
+/* \fIThe maximum number of bytes in a file name argument\fP */
+const MAXNAMLEN = 255;
+
+/* \fIThe size in bytes of the opaque "cookie" passed by READDIR\fP */
+const COOKIESIZE = 4;
+
+/* \fIThe size in bytes of the opaque file handle\fP */
+const FHSIZE = 32;
+.DE
+.NH 2
+\&Basic Data Types
+.IX "NFS data types"
+.IX NFS "basic data types"
+.LP
+The following XDR definitions are basic structures and types used
+in other structures described further on.
+.KS
+.NH 3
+\&stat
+.IX "NFS data types" stat "" \fIstat\fP
+.DS
+enum stat {
+ NFS_OK = 0,
+ NFSERR_PERM=1,
+ NFSERR_NOENT=2,
+ NFSERR_IO=5,
+ NFSERR_NXIO=6,
+ NFSERR_ACCES=13,
+ NFSERR_EXIST=17,
+ NFSERR_NODEV=19,
+ NFSERR_NOTDIR=20,
+ NFSERR_ISDIR=21,
+ NFSERR_FBIG=27,
+ NFSERR_NOSPC=28,
+ NFSERR_ROFS=30,
+ NFSERR_NAMETOOLONG=63,
+ NFSERR_NOTEMPTY=66,
+ NFSERR_DQUOT=69,
+ NFSERR_STALE=70,
+ NFSERR_WFLUSH=99
+};
+.DE
+.KE
+.LP
+The
+.I stat
+type is returned with every procedure's results. A
+value of
+.I NFS_OK
+indicates that the call completed successfully and
+the results are valid. The other values indicate some kind of
+error occurred on the server side during the servicing of the
+procedure. The error values are derived from UNIX error numbers.
+.IP \fBNFSERR_PERM\fP:
+Not owner. The caller does not have correct ownership
+to perform the requested operation.
+.IP \fBNFSERR_NOENT\fP:
+No such file or directory. The file or directory
+specified does not exist.
+.IP \fBNFSERR_IO\fP:
+Some sort of hard error occurred when the operation was
+in progress. This could be a disk error, for example.
+.IP \fBNFSERR_NXIO\fP:
+No such device or address.
+.IP \fBNFSERR_ACCES\fP:
+Permission denied. The caller does not have the
+correct permission to perform the requested operation.
+.IP \fBNFSERR_EXIST\fP:
+File exists. The file specified already exists.
+.IP \fBNFSERR_NODEV\fP:
+No such device.
+.IP \fBNFSERR_NOTDIR\fP:
+Not a directory. The caller specified a
+non-directory in a directory operation.
+.IP \fBNFSERR_ISDIR\fP:
+Is a directory. The caller specified a directory in
+a non- directory operation.
+.IP \fBNFSERR_FBIG\fP:
+File too large. The operation caused a file to grow
+beyond the server's limit.
+.IP \fBNFSERR_NOSPC\fP:
+No space left on device. The operation caused the
+server's filesystem to reach its limit.
+.IP \fBNFSERR_ROFS\fP:
+Read-only filesystem. Write attempted on a read-only filesystem.
+.IP \fBNFSERR_NAMETOOLONG\fP:
+File name too long. The file name in an operation was too long.
+.IP \fBNFSERR_NOTEMPTY\fP:
+Directory not empty. Attempted to remove a
+directory that was not empty.
+.IP \fBNFSERR_DQUOT\fP:
+Disk quota exceeded. The client's disk quota on the
+server has been exceeded.
+.IP \fBNFSERR_STALE\fP:
+The "fhandle" given in the arguments was invalid.
+That is, the file referred to by that file handle no longer exists,
+or access to it has been revoked.
+.IP \fBNFSERR_WFLUSH\fP:
+The server's write cache used in the
+.I WRITECACHE
+call got flushed to disk.
+.LP
+.KS
+.NH 3
+\&ftype
+.IX "NFS data types" ftype "" \fIftype\fP
+.DS
+enum ftype {
+ NFNON = 0,
+ NFREG = 1,
+ NFDIR = 2,
+ NFBLK = 3,
+ NFCHR = 4,
+ NFLNK = 5
+};
+.DE
+.KE
+The enumeration
+.I ftype
+gives the type of a file. The type
+.I NFNON
+indicates a non-file,
+.I NFREG
+is a regular file,
+.I NFDIR
+is a directory,
+.I NFBLK
+is a block-special device,
+.I NFCHR
+is a character-special device, and
+.I NFLNK
+is a symbolic link.
+.KS
+.NH 3
+\&fhandle
+.IX "NFS data types" fhandle "" \fIfhandle\fP
+.DS
+typedef opaque fhandle[FHSIZE];
+.DE
+.KE
+The
+.I fhandle
+is the file handle passed between the server and the client.
+All file operations are done using file handles to refer to a file or
+directory. The file handle can contain whatever information the server
+needs to distinguish an individual file.
+.KS
+.NH 3
+\&timeval
+.IX "NFS data types" timeval "" \fItimeval\fP
+.DS
+struct timeval {
+ unsigned int seconds;
+ unsigned int useconds;
+};
+.DE
+.KE
+The
+.I timeval
+structure is the number of seconds and microseconds
+since midnight January 1, 1970, Greenwich Mean Time. It is used to
+pass time and date information.
+.KS
+.NH 3
+\&fattr
+.IX "NFS data types" fattr "" \fIfattr\fP
+.DS
+struct fattr {
+ ftype type;
+ unsigned int mode;
+ unsigned int nlink;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int size;
+ unsigned int blocksize;
+ unsigned int rdev;
+ unsigned int blocks;
+ unsigned int fsid;
+ unsigned int fileid;
+ timeval atime;
+ timeval mtime;
+ timeval ctime;
+};
+.DE
+.KE
+The
+.I fattr
+structure contains the attributes of a file; "type" is the type of
+the file; "nlink" is the number of hard links to the file (the number
+of different names for the same file); "uid" is the user
+identification number of the owner of the file; "gid" is the group
+identification number of the group of the file; "size" is the size in
+bytes of the file; "blocksize" is the size in bytes of a block of the
+file; "rdev" is the device number of the file if it is type
+.I NFCHR
+or
+.I NFBLK ;
+"blocks" is the number of blocks the file takes up on disk; "fsid" is
+the file system identifier for the filesystem containing the file;
+"fileid" is a number that uniquely identifies the file within its
+filesystem; "atime" is the time when the file was last accessed for
+either read or write; "mtime" is the time when the file data was last
+modified (written); and "ctime" is the time when the status of the
+file was last changed. Writing to the file also changes "ctime" if
+the size of the file changes.
+.LP
+"mode" is the access mode encoded as a set of bits. Notice that the
+file type is specified both in the mode bits and in the file type.
+This is really a bug in the protocol and will be fixed in future
+versions. The descriptions given below specify the bit positions
+using octal numbers.
+.TS
+box tab (&) ;
+cfI cfI
+lfL l .
+Bit&Description
+_
+0040000&This is a directory; "type" field should be NFDIR.
+0020000&This is a character special file; "type" field should be NFCHR.
+0060000&This is a block special file; "type" field should be NFBLK.
+0100000&This is a regular file; "type" field should be NFREG.
+0120000&This is a symbolic link file; "type" field should be NFLNK.
+0140000&This is a named socket; "type" field should be NFNON.
+0004000&Set user id on execution.
+0002000&Set group id on execution.
+0001000&Save swapped text even after use.
+0000400&Read permission for owner.
+0000200&Write permission for owner.
+0000100&Execute and search permission for owner.
+0000040&Read permission for group.
+0000020&Write permission for group.
+0000010&Execute and search permission for group.
+0000004&Read permission for others.
+0000002&Write permission for others.
+0000001&Execute and search permission for others.
+.TE
+.KS
+Notes:
+.IP
+The bits are the same as the mode bits returned by the
+.I stat(2)
+system call in the UNIX system. The file type is specified both in
+the mode bits and in the file type. This is fixed in future
+versions.
+.IP
+The "rdev" field in the attributes structure is an operating system
+specific device specifier. It will be removed and generalized in
+the next revision of the protocol.
+.KE
+.LP
+.KS
+.NH 3
+\&sattr
+.IX "NFS data types" sattr "" \fIsattr\fP
+.DS
+struct sattr {
+ unsigned int mode;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int size;
+ timeval atime;
+ timeval mtime;
+};
+.DE
+.KE
+The
+.I sattr
+structure contains the file attributes which can be set
+from the client. The fields are the same as for
+.I fattr
+above. A "size" of zero means the file should be truncated.
+A value of -1 indicates a field that should be ignored.
+.LP
+.KS
+.NH 3
+\&filename
+.IX "NFS data types" filename "" \fIfilename\fP
+.DS
+typedef string filename<MAXNAMLEN>;
+.DE
+.KE
+The type
+.I filename
+is used for passing file names or pathname components.
+.LP
+.KS
+.NH 3
+\&path
+.IX "NFS data types" path "" \fIpath\fP
+.DS
+typedef string path<MAXPATHLEN>;
+.DE
+.KE
+The type
+.I path
+is a pathname. The server considers it as a string
+with no internal structure, but to the client it is the name of a
+node in a filesystem tree.
+.LP
+.KS
+.NH 3
+\&attrstat
+.IX "NFS data types" attrstat "" \fIattrstat\fP
+.DS
+union attrstat switch (stat status) {
+ case NFS_OK:
+ fattr attributes;
+ default:
+ void;
+};
+.DE
+.KE
+The
+.I attrstat
+structure is a common procedure result. It contains
+a "status" and, if the call succeeded, it also contains the
+attributes of the file on which the operation was done.
+.LP
+.KS
+.NH 3
+\&diropargs
+.IX "NFS data types" diropargs "" \fIdiropargs\fP
+.DS
+struct diropargs {
+ fhandle dir;
+ filename name;
+};
+.DE
+.KE
+The
+.I diropargs
+structure is used in directory operations. The
+"fhandle" "dir" is the directory in which to find the file "name".
+A directory operation is one in which the directory is affected.
+.LP
+.KS
+.NH 3
+\&diropres
+.IX "NFS data types" diropres "" \fIdiropres\fP
+.DS
+union diropres switch (stat status) {
+ case NFS_OK:
+ struct {
+ fhandle file;
+ fattr attributes;
+ } diropok;
+ default:
+ void;
+};
+.DE
+.KE
+The results of a directory operation are returned in a
+.I diropres
+structure. If the call succeeded, a new file handle "file" and the
+"attributes" associated with that file are returned along with the
+"status".
+.NH 2
+\&Server Procedures
+.IX "NFS server procedures" "" "" "" PAGE MAJOR
+.LP
+The protocol definition is given as a set of procedures with
+arguments and results defined using the RPC language. A brief
+description of the function of each procedure should provide enough
+information to allow implementation.
+.LP
+All of the procedures in the NFS protocol are assumed to be
+synchronous. When a procedure returns to the client, the client
+can assume that the operation has completed and any data associated
+with the request is now on stable storage. For example, a client
+.I WRITE
+request may cause the server to update data blocks,
+filesystem information blocks (such as indirect blocks), and file
+attribute information (size and modify times). When the
+.I WRITE
+returns to the client, it can assume that the write is safe, even
+in case of a server crash, and it can discard the data written.
+This is a very important part of the statelessness of the server.
+If the server waited to flush data from remote requests, the client
+would have to save those requests so that it could resend them in
+case of a server crash.
+.ie t .DS
+.el .DS L
+
+.ft I
+/*
+* Remote file service routines
+*/
+.ft CW
+program NFS_PROGRAM {
+ version NFS_VERSION {
+ void NFSPROC_NULL(void) = 0;
+ attrstat NFSPROC_GETATTR(fhandle) = 1;
+ attrstat NFSPROC_SETATTR(sattrargs) = 2;
+ void NFSPROC_ROOT(void) = 3;
+ diropres NFSPROC_LOOKUP(diropargs) = 4;
+ readlinkres NFSPROC_READLINK(fhandle) = 5;
+ readres NFSPROC_READ(readargs) = 6;
+ void NFSPROC_WRITECACHE(void) = 7;
+ attrstat NFSPROC_WRITE(writeargs) = 8;
+ diropres NFSPROC_CREATE(createargs) = 9;
+ stat NFSPROC_REMOVE(diropargs) = 10;
+ stat NFSPROC_RENAME(renameargs) = 11;
+ stat NFSPROC_LINK(linkargs) = 12;
+ stat NFSPROC_SYMLINK(symlinkargs) = 13;
+ diropres NFSPROC_MKDIR(createargs) = 14;
+ stat NFSPROC_RMDIR(diropargs) = 15;
+ readdirres NFSPROC_READDIR(readdirargs) = 16;
+ statfsres NFSPROC_STATFS(fhandle) = 17;
+ } = 2;
+} = 100003;
+.DE
+.KS
+.NH 3
+\&Do Nothing
+.IX "NFS server procedures" NFSPROC_NULL() "" \fINFSPROC_NULL()\fP
+.DS
+void
+NFSPROC_NULL(void) = 0;
+.DE
+.KE
+This procedure does no work. It is made available in all RPC
+services to allow server response testing and timing.
+.KS
+.NH 3
+\&Get File Attributes
+.IX "NFS server procedures" NFSPROC_GETATTR() "" \fINFSPROC_GETATTR()\fP
+.DS
+attrstat
+NFSPROC_GETATTR (fhandle) = 1;
+.DE
+.KE
+If the reply status is
+.I NFS_OK ,
+then the reply attributes contains
+the attributes for the file given by the input fhandle.
+.KS
+.NH 3
+\&Set File Attributes
+.IX "NFS server procedures" NFSPROC_SETATTR() "" \fINFSPROC_SETATTR()\fP
+.DS
+struct sattrargs {
+ fhandle file;
+ sattr attributes;
+ };
+
+attrstat
+NFSPROC_SETATTR (sattrargs) = 2;
+.DE
+.KE
+The "attributes" argument contains fields which are either -1 or
+are the new value for the attributes of "file". If the reply
+status is
+.I NFS_OK ,
+then the reply attributes have the attributes of
+the file after the "SETATTR" operation has completed.
+.LP
+Note: The use of -1 to indicate an unused field in "attributes" is
+changed in the next version of the protocol.
+.KS
+.NH 3
+\&Get Filesystem Root
+.IX "NFS server procedures" NFSPROC_ROOT "" \fINFSPROC_ROOT\fP
+.DS
+void
+NFSPROC_ROOT(void) = 3;
+.DE
+.KE
+Obsolete. This procedure is no longer used because finding the
+root file handle of a filesystem requires moving pathnames between
+client and server. To do this right we would have to define a
+network standard representation of pathnames. Instead, the
+function of looking up the root file handle is done by the
+.I MNTPROC_MNT()
+procedure. (See the
+.I "Mount Protocol Definition"
+later in this chapter for details).
+.KS
+.NH 3
+\&Look Up File Name
+.IX "NFS server procedures" NFSPROC_LOOKUP() "" \fINFSPROC_LOOKUP()\fP
+.DS
+diropres
+NFSPROC_LOOKUP(diropargs) = 4;
+.DE
+.KE
+If the reply "status" is
+.I NFS_OK ,
+then the reply "file" and reply
+"attributes" are the file handle and attributes for the file "name"
+in the directory given by "dir" in the argument.
+.KS
+.NH 3
+\&Read From Symbolic Link
+.IX "NFS server procedures" NFSPROC_READLINK() "" \fINFSPROC_READLINK()\fP
+.DS
+union readlinkres switch (stat status) {
+ case NFS_OK:
+ path data;
+ default:
+ void;
+};
+
+readlinkres
+NFSPROC_READLINK(fhandle) = 5;
+.DE
+.KE
+If "status" has the value
+.I NFS_OK ,
+then the reply "data" is the data in
+the symbolic link given by the file referred to by the fhandle argument.
+.LP
+Note: since NFS always parses pathnames on the client, the
+pathname in a symbolic link may mean something different (or be
+meaningless) on a different client or on the server if a different
+pathname syntax is used.
+.KS
+.NH 3
+\&Read From File
+.IX "NFS server procedures" NFSPROC_READ "" \fINFSPROC_READ\fP
+.DS
+struct readargs {
+ fhandle file;
+ unsigned offset;
+ unsigned count;
+ unsigned totalcount;
+};
+
+union readres switch (stat status) {
+ case NFS_OK:
+ fattr attributes;
+ opaque data<NFS_MAXDATA>;
+ default:
+ void;
+};
+
+readres
+NFSPROC_READ(readargs) = 6;
+.DE
+.KE
+Returns up to "count" bytes of "data" from the file given by
+"file", starting at "offset" bytes from the beginning of the file.
+The first byte of the file is at offset zero. The file attributes
+after the read takes place are returned in "attributes".
+.LP
+Note: The argument "totalcount" is unused, and is removed in the
+next protocol revision.
+.KS
+.NH 3
+\&Write to Cache
+.IX "NFS server procedures" NFSPROC_WRITECACHE() "" \fINFSPROC_WRITECACHE()\fP
+.DS
+void
+NFSPROC_WRITECACHE(void) = 7;
+.DE
+.KE
+To be used in the next protocol revision.
+.KS
+.NH 3
+\&Write to File
+.IX "NFS server procedures" NFSPROC_WRITE() "" \fINFSPROC_WRITE()\fP
+.DS
+struct writeargs {
+ fhandle file;
+ unsigned beginoffset;
+ unsigned offset;
+ unsigned totalcount;
+ opaque data<NFS_MAXDATA>;
+};
+
+attrstat
+NFSPROC_WRITE(writeargs) = 8;
+.DE
+.KE
+Writes "data" beginning "offset" bytes from the beginning of
+"file". The first byte of the file is at offset zero. If the
+reply "status" is NFS_OK, then the reply "attributes" contains the
+attributes of the file after the write has completed. The write
+operation is atomic. Data from this call to
+.I WRITE
+will not be mixed with data from another client's calls.
+.LP
+Note: The arguments "beginoffset" and "totalcount" are ignored and
+are removed in the next protocol revision.
+.KS
+.NH 3
+\&Create File
+.IX "NFS server procedures" NFSPROC_CREATE() "" \fINFSPROC_CREATE()\fP
+.DS
+struct createargs {
+ diropargs where;
+ sattr attributes;
+};
+
+diropres
+NFSPROC_CREATE(createargs) = 9;
+.DE
+.KE
+The file "name" is created in the directory given by "dir". The
+initial attributes of the new file are given by "attributes". A
+reply "status" of NFS_OK indicates that the file was created, and
+reply "file" and reply "attributes" are its file handle and
+attributes. Any other reply "status" means that the operation
+failed and no file was created.
+.LP
+Note: This routine should pass an exclusive create flag, meaning
+"create the file only if it is not already there".
+.KS
+.NH 3
+\&Remove File
+.IX "NFS server procedures" NFSPROC_REMOVE() "" \fINFSPROC_REMOVE()\fP
+.DS
+stat
+NFSPROC_REMOVE(diropargs) = 10;
+.DE
+.KE
+The file "name" is removed from the directory given by "dir". A
+reply of NFS_OK means the directory entry was removed.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Rename File
+.IX "NFS server procedures" NFSPROC_RENAME() "" \fINFSPROC_RENAME()\fP
+.DS
+struct renameargs {
+ diropargs from;
+ diropargs to;
+};
+
+stat
+NFSPROC_RENAME(renameargs) = 11;
+.DE
+.KE
+The existing file "from.name" in the directory given by "from.dir"
+is renamed to "to.name" in the directory given by "to.dir". If the
+reply is
+.I NFS_OK ,
+the file was renamed. The
+RENAME
+operation is
+atomic on the server; it cannot be interrupted in the middle.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Create Link to File
+.IX "NFS server procedures" NFSPROC_LINK() "" \fINFSPROC_LINK()\fP
+.DS
+struct linkargs {
+ fhandle from;
+ diropargs to;
+};
+
+stat
+NFSPROC_LINK(linkargs) = 12;
+.DE
+.KE
+Creates the file "to.name" in the directory given by "to.dir",
+which is a hard link to the existing file given by "from". If the
+return value is
+.I NFS_OK ,
+a link was created. Any other return value
+indicates an error, and the link was not created.
+.LP
+A hard link should have the property that changes to either of the
+linked files are reflected in both files. When a hard link is made
+to a file, the attributes for the file should have a value for
+"nlink" that is one greater than the value before the link.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Create Symbolic Link
+.IX "NFS server procedures" NFSPROC_SYMLINK() "" \fINFSPROC_SYMLINK()\fP
+.DS
+struct symlinkargs {
+ diropargs from;
+ path to;
+ sattr attributes;
+};
+
+stat
+NFSPROC_SYMLINK(symlinkargs) = 13;
+.DE
+.KE
+Creates the file "from.name" with ftype
+.I NFLNK
+in the directory
+given by "from.dir". The new file contains the pathname "to" and
+has initial attributes given by "attributes". If the return value
+is
+.I NFS_OK ,
+a link was created. Any other return value indicates an
+error, and the link was not created.
+.LP
+A symbolic link is a pointer to another file. The name given in
+"to" is not interpreted by the server, only stored in the newly
+created file. When the client references a file that is a symbolic
+link, the contents of the symbolic link are normally transparently
+reinterpreted as a pathname to substitute. A
+.I READLINK
+operation returns the data to the client for interpretation.
+.LP
+Note: On UNIX servers the attributes are never used, since
+symbolic links always have mode 0777.
+.KS
+.NH 3
+\&Create Directory
+.IX "NFS server procedures" NFSPROC_MKDIR() "" \fINFSPROC_MKDIR()\fP
+.DS
+diropres
+NFSPROC_MKDIR (createargs) = 14;
+.DE
+.KE
+The new directory "where.name" is created in the directory given by
+"where.dir". The initial attributes of the new directory are given
+by "attributes". A reply "status" of NFS_OK indicates that the new
+directory was created, and reply "file" and reply "attributes" are
+its file handle and attributes. Any other reply "status" means
+that the operation failed and no directory was created.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Remove Directory
+.IX "NFS server procedures" NFSPROC_RMDIR() "" \fINFSPROC_RMDIR()\fP
+.DS
+stat
+NFSPROC_RMDIR(diropargs) = 15;
+.DE
+.KE
+The existing empty directory "name" in the directory given by "dir"
+is removed. If the reply is
+.I NFS_OK ,
+the directory was removed.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Read From Directory
+.IX "NFS server procedures" NFSPROC_READDIR() "" \fINFSPROC_READDIR()\fP
+.DS
+struct readdirargs {
+ fhandle dir;
+ nfscookie cookie;
+ unsigned count;
+};
+
+struct entry {
+ unsigned fileid;
+ filename name;
+ nfscookie cookie;
+ entry *nextentry;
+};
+
+union readdirres switch (stat status) {
+ case NFS_OK:
+ struct {
+ entry *entries;
+ bool eof;
+ } readdirok;
+ default:
+ void;
+};
+
+readdirres
+NFSPROC_READDIR (readdirargs) = 16;
+.DE
+.KE
+Returns a variable number of directory entries, with a total size
+of up to "count" bytes, from the directory given by "dir". If the
+returned value of "status" is
+.I NFS_OK ,
+then it is followed by a
+variable number of "entry"s. Each "entry" contains a "fileid"
+which consists of a unique number to identify the file within a
+filesystem, the "name" of the file, and a "cookie" which is an
+opaque pointer to the next entry in the directory. The cookie is
+used in the next
+.I READDIR
+call to get more entries starting at a
+given point in the directory. The special cookie zero (all bits
+zero) can be used to get the entries starting at the beginning of
+the directory. The "fileid" field should be the same number as the
+"fileid" in the the attributes of the file. (See the
+.I "Basic Data Types"
+section.)
+The "eof" flag has a value of
+.I TRUE
+if there are no more entries in the directory.
+.KS
+.NH 3
+\&Get Filesystem Attributes
+.IX "NFS server procedures" NFSPROC_STATFS() "" \fINFSPROC_STATFS()\fP
+.DS
+union statfsres (stat status) {
+ case NFS_OK:
+ struct {
+ unsigned tsize;
+ unsigned bsize;
+ unsigned blocks;
+ unsigned bfree;
+ unsigned bavail;
+ } info;
+ default:
+ void;
+};
+
+statfsres
+NFSPROC_STATFS(fhandle) = 17;
+.DE
+.KE
+If the reply "status" is
+.I NFS_OK ,
+then the reply "info" gives the
+attributes for the filesystem that contains file referred to by the
+input fhandle. The attribute fields contain the following values:
+.IP tsize:
+The optimum transfer size of the server in bytes. This is
+the number of bytes the server would like to have in the
+data part of READ and WRITE requests.
+.IP bsize:
+The block size in bytes of the filesystem.
+.IP blocks:
+The total number of "bsize" blocks on the filesystem.
+.IP bfree:
+The number of free "bsize" blocks on the filesystem.
+.IP bavail:
+The number of "bsize" blocks available to non-privileged users.
+.LP
+Note: This call does not work well if a filesystem has variable
+size blocks.
+.NH 1
+\&NFS Implementation Issues
+.IX NFS implementation
+.LP
+The NFS protocol is designed to be operating system independent, but
+since this version was designed in a UNIX environment, many
+operations have semantics similar to the operations of the UNIX file
+system. This section discusses some of the implementation-specific
+semantic issues.
+.NH 2
+\&Server/Client Relationship
+.IX NFS "server/client relationship"
+.LP
+The NFS protocol is designed to allow servers to be as simple and
+general as possible. Sometimes the simplicity of the server can be a
+problem, if the client wants to implement complicated filesystem
+semantics.
+.LP
+For example, some operating systems allow removal of open files. A
+process can open a file and, while it is open, remove it from the
+directory. The file can be read and written as long as the process
+keeps it open, even though the file has no name in the filesystem.
+It is impossible for a stateless server to implement these semantics.
+The client can do some tricks such as renaming the file on remove,
+and only removing it on close. We believe that the server provides
+enough functionality to implement most file system semantics on the
+client.
+.LP
+Every NFS client can also potentially be a server, and remote and
+local mounted filesystems can be freely intermixed. This leads to
+some interesting problems when a client travels down the directory
+tree of a remote filesystem and reaches the mount point on the server
+for another remote filesystem. Allowing the server to follow the
+second remote mount would require loop detection, server lookup, and
+user revalidation. Instead, we decided not to let clients cross a
+server's mount point. When a client does a LOOKUP on a directory on
+which the server has mounted a filesystem, the client sees the
+underlying directory instead of the mounted directory. A client can
+do remote mounts that match the server's mount points to maintain the
+server's view.
+.LP
+.NH 2
+\&Pathname Interpretation
+.IX NFS "pathname interpretation"
+.LP
+There are a few complications to the rule that pathnames are always
+parsed on the client. For example, symbolic links could have
+different interpretations on different clients. Another common
+problem for non-UNIX implementations is the special interpretation of
+the pathname ".." to mean the parent of a given directory. The next
+revision of the protocol uses an explicit flag to indicate the parent
+instead.
+.NH 2
+\&Permission Issues
+.IX NFS "permission issues"
+.LP
+The NFS protocol, strictly speaking, does not define the permission
+checking used by servers. However, it is expected that a server
+will do normal operating system permission checking using
+.I AUTH_UNIX
+style authentication as the basis of its protection mechanism. The
+server gets the client's effective "uid", effective "gid", and groups
+on each call and uses them to check permission. There are various
+problems with this method that can been resolved in interesting ways.
+.LP
+Using "uid" and "gid" implies that the client and server share the
+same "uid" list. Every server and client pair must have the same
+mapping from user to "uid" and from group to "gid". Since every
+client can also be a server, this tends to imply that the whole
+network shares the same "uid/gid" space.
+.I AUTH_DES
+(and the next
+revision of the NFS protocol) uses string names instead of numbers,
+but there are still complex problems to be solved.
+.LP
+Another problem arises due to the usually stateful open operation.
+Most operating systems check permission at open time, and then check
+that the file is open on each read and write request. With stateless
+servers, the server has no idea that the file is open and must do
+permission checking on each read and write call. On a local
+filesystem, a user can open a file and then change the permissions so
+that no one is allowed to touch it, but will still be able to write
+to the file because it is open. On a remote filesystem, by contrast,
+the write would fail. To get around this problem, the server's
+permission checking algorithm should allow the owner of a file to
+access it regardless of the permission setting.
+.LP
+A similar problem has to do with paging in from a file over the
+network. The operating system usually checks for execute permission
+before opening a file for demand paging, and then reads blocks from
+the open file. The file may not have read permission, but after it
+is opened it doesn't matter. An NFS server can not tell the
+difference between a normal file read and a demand page-in read. To
+make this work, the server allows reading of files if the "uid" given
+in the call has execute or read permission on the file.
+.LP
+In most operating systems, a particular user (on the user ID zero)
+has access to all files no matter what permission and ownership they
+have. This "super-user" permission may not be allowed on the server,
+since anyone who can become super-user on their workstation could
+gain access to all remote files. The UNIX server by default maps
+user id 0 to -2 before doing its access checking. This works except
+for NFS root filesystems, where super-user access cannot be avoided.
+.NH 2
+\&Setting RPC Parameters
+.IX NFS "setting RPC parameters"
+.LP
+Various file system parameters and options should be set at mount
+time. The mount protocol is described in the appendix below. For
+example, "Soft" mounts as well as "Hard" mounts are usually both
+provided. Soft mounted file systems return errors when RPC
+operations fail (after a given number of optional retransmissions),
+while hard mounted file systems continue to retransmit forever.
+Clients and servers may need to keep caches of recent operations to
+help avoid problems with non-idempotent operations.
+.NH 1
+\&Mount Protocol Definition
+.IX "mount protocol" "" "" "" PAGE MAJOR
+.sp 1
+.NH 2
+\&Introduction
+.IX "mount protocol" introduction
+.LP
+The mount protocol is separate from, but related to, the NFS
+protocol. It provides operating system specific services to get the
+NFS off the ground -- looking up server path names, validating user
+identity, and checking access permissions. Clients use the mount
+protocol to get the first file handle, which allows them entry into a
+remote filesystem.
+.LP
+The mount protocol is kept separate from the NFS protocol to make it
+easy to plug in new access checking and validation methods without
+changing the NFS server protocol.
+.LP
+Notice that the protocol definition implies stateful servers because
+the server maintains a list of client's mount requests. The mount
+list information is not critical for the correct functioning of
+either the client or the server. It is intended for advisory use
+only, for example, to warn possible clients when a server is going
+down.
+.LP
+Version one of the mount protocol is used with version two of the NFS
+protocol. The only connecting point is the
+.I fhandle
+structure, which is the same for both protocols.
+.NH 2
+\&RPC Information
+.IX "mount protocol" "RPC information"
+.IP \fIAuthentication\fP
+The mount service uses
+.I AUTH_UNIX
+and
+.I AUTH_DES
+style authentication only.
+.IP "\fITransport Protocols\fP"
+The mount service is currently supported on UDP/IP only.
+.IP "\fIPort Number\fP"
+Consult the server's portmapper, described in the chapter
+.I "Remote Procedure Calls: Protocol Specification",
+to find the port number on which the mount service is registered.
+.NH 2
+\&Sizes of XDR Structures
+.IX "mount protocol" "XDR structure sizes"
+.LP
+These are the sizes, given in decimal bytes, of various XDR
+structures used in the protocol:
+.DS
+/* \fIThe maximum number of bytes in a pathname argument\fP */
+const MNTPATHLEN = 1024;
+
+/* \fIThe maximum number of bytes in a name argument\fP */
+const MNTNAMLEN = 255;
+
+/* \fIThe size in bytes of the opaque file handle\fP */
+const FHSIZE = 32;
+.DE
+.NH 2
+\&Basic Data Types
+.IX "mount protocol" "basic data types"
+.IX "mount data types"
+.LP
+This section presents the data types used by the mount protocol.
+In many cases they are similar to the types used in NFS.
+.KS
+.NH 3
+\&fhandle
+.IX "mount data types" fhandle "" \fIfhandle\fP
+.DS
+typedef opaque fhandle[FHSIZE];
+.DE
+.KE
+The type
+.I fhandle
+is the file handle that the server passes to the
+client. All file operations are done using file handles to refer
+to a file or directory. The file handle can contain whatever
+information the server needs to distinguish an individual file.
+.LP
+This is the same as the "fhandle" XDR definition in version 2 of
+the NFS protocol; see
+.I "Basic Data Types"
+in the definition of the NFS protocol, above.
+.KS
+.NH 3
+\&fhstatus
+.IX "mount data types" fhstatus "" \fIfhstatus\fP
+.DS
+union fhstatus switch (unsigned status) {
+ case 0:
+ fhandle directory;
+ default:
+ void;
+};
+.DE
+.KE
+The type
+.I fhstatus
+is a union. If a "status" of zero is returned,
+the call completed successfully, and a file handle for the
+"directory" follows. A non-zero status indicates some sort of
+error. In this case the status is a UNIX error number.
+.KS
+.NH 3
+\&dirpath
+.IX "mount data types" dirpath "" \fIdirpath\fP
+.DS
+typedef string dirpath<MNTPATHLEN>;
+.DE
+.KE
+The type
+.I dirpath
+is a server pathname of a directory.
+.KS
+.NH 3
+\&name
+.IX "mount data types" name "" \fIname\fP
+.DS
+typedef string name<MNTNAMLEN>;
+.DE
+.KE
+The type
+.I name
+is an arbitrary string used for various names.
+.NH 2
+\&Server Procedures
+.IX "mount server procedures"
+.LP
+The following sections define the RPC procedures supplied by a
+mount server.
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Protocol description for the mount program
+*/
+.ft CW
+
+program MOUNTPROG {
+.ft I
+/*
+* Version 1 of the mount protocol used with
+* version 2 of the NFS protocol.
+*/
+.ft CW
+ version MOUNTVERS {
+ void MOUNTPROC_NULL(void) = 0;
+ fhstatus MOUNTPROC_MNT(dirpath) = 1;
+ mountlist MOUNTPROC_DUMP(void) = 2;
+ void MOUNTPROC_UMNT(dirpath) = 3;
+ void MOUNTPROC_UMNTALL(void) = 4;
+ exportlist MOUNTPROC_EXPORT(void) = 5;
+ } = 1;
+} = 100005;
+.DE
+.KS
+.NH 3
+\&Do Nothing
+.IX "mount server procedures" MNTPROC_NULL() "" \fIMNTPROC_NULL()\fP
+.DS
+void
+MNTPROC_NULL(void) = 0;
+.DE
+.KE
+This procedure does no work. It is made available in all RPC
+services to allow server response testing and timing.
+.KS
+.NH 3
+\&Add Mount Entry
+.IX "mount server procedures" MNTPROC_MNT() "" \fIMNTPROC_MNT()\fP
+.DS
+fhstatus
+MNTPROC_MNT(dirpath) = 1;
+.DE
+.KE
+If the reply "status" is 0, then the reply "directory" contains the
+file handle for the directory "dirname". This file handle may be
+used in the NFS protocol. This procedure also adds a new entry to
+the mount list for this client mounting "dirname".
+.KS
+.NH 3
+\&Return Mount Entries
+.IX "mount server procedures" MNTPROC_DUMP() "" \fIMNTPROC_DUMP()\fP
+.DS
+struct *mountlist {
+ name hostname;
+ dirpath directory;
+ mountlist nextentry;
+};
+
+mountlist
+MNTPROC_DUMP(void) = 2;
+.DE
+.KE
+Returns the list of remote mounted filesystems. The "mountlist"
+contains one entry for each "hostname" and "directory" pair.
+.KS
+.NH 3
+\&Remove Mount Entry
+.IX "mount server procedures" MNTPROC_UMNT() "" \fIMNTPROC_UMNT()\fP
+.DS
+void
+MNTPROC_UMNT(dirpath) = 3;
+.DE
+.KE
+Removes the mount list entry for the input "dirpath".
+.KS
+.NH 3
+\&Remove All Mount Entries
+.IX "mount server procedures" MNTPROC_UMNTALL() "" \fIMNTPROC_UMNTALL()\fP
+.DS
+void
+MNTPROC_UMNTALL(void) = 4;
+.DE
+.KE
+Removes all of the mount list entries for this client.
+.KS
+.NH 3
+\&Return Export List
+.IX "mount server procedures" MNTPROC_EXPORT() "" \fIMNTPROC_EXPORT()\fP
+.DS
+struct *groups {
+ name grname;
+ groups grnext;
+};
+
+struct *exportlist {
+ dirpath filesys;
+ groups groups;
+ exportlist next;
+};
+
+exportlist
+MNTPROC_EXPORT(void) = 5;
+.DE
+.KE
+Returns a variable number of export list entries. Each entry
+contains a filesystem name and a list of groups that are allowed to
+import it. The filesystem name is in "filesys", and the group name
+is in the list "groups".
+.LP
+Note: The exportlist should contain
+more information about the status of the filesystem, such as a
+read-only flag.
diff --git a/lib/libc/rpc/PSD.doc/rpc.prog.ms b/lib/libc/rpc/PSD.doc/rpc.prog.ms
new file mode 100644
index 0000000..3b02447
--- /dev/null
+++ b/lib/libc/rpc/PSD.doc/rpc.prog.ms
@@ -0,0 +1,2684 @@
+.\"
+.\" Must use -- tbl and pic -- with this one
+.\"
+.\" @(#)rpc.prog.ms 2.3 88/08/11 4.0 RPCSRC
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.IX "Network Programming" "" "" "" PAGE MAJOR
+.nr OF 0
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'Remote Procedure Call Programming Guide''Page %'
+.EH 'Page %''Remote Procedure Call Programming Guide'
+.SH
+\&Remote Procedure Call Programming Guide
+.nr OF 1
+.IX "RPC Programming Guide"
+.LP
+This document assumes a working knowledge of network theory. It is
+intended for programmers who wish to write network applications using
+remote procedure calls (explained below), and who want to understand
+the RPC mechanisms usually hidden by the
+.I rpcgen(1)
+protocol compiler.
+.I rpcgen
+is described in detail in the previous chapter, the
+.I "\fBrpcgen\fP \fIProgramming Guide\fP".
+.SH
+Note:
+.I
+.IX rpcgen "" \fIrpcgen\fP
+Before attempting to write a network application, or to convert an
+existing non-network application to run over the network, you may want to
+understand the material in this chapter. However, for most applications,
+you can circumvent the need to cope with the details presented here by using
+.I rpcgen .
+The
+.I "Generating XDR Routines"
+section of that chapter contains the complete source for a working RPC
+service\(ema remote directory listing service which uses
+.I rpcgen
+to generate XDR routines as well as client and server stubs.
+.LP
+.LP
+What are remote procedure calls? Simply put, they are the high-level
+communications paradigm used in the operating system.
+RPC presumes the existence of
+low-level networking mechanisms (such as TCP/IP and UDP/IP), and upon them
+it implements a logical client to server communications system designed
+specifically for the support of network applications. With RPC, the client
+makes a procedure call to send a data packet to the server. When the
+packet arrives, the server calls a dispatch routine, performs whatever
+service is requested, sends back the reply, and the procedure call returns
+to the client.
+.NH 0
+\&Layers of RPC
+.IX "layers of RPC"
+.IX "RPC" "layers"
+.LP
+The RPC interface can be seen as being divided into three layers.\**
+.FS
+For a complete specification of the routines in the remote procedure
+call Library, see the
+.I rpc(3N)
+manual page.
+.FE
+.LP
+.I "The Highest Layer:"
+.IX RPC "The Highest Layer"
+The highest layer is totally transparent to the operating system,
+machine and network upon which is is run. It's probably best to
+think of this level as a way of
+.I using
+RPC, rather than as
+a \fIpart of\fP RPC proper. Programmers who write RPC routines
+should (almost) always make this layer available to others by way
+of a simple C front end that entirely hides the networking.
+.LP
+To illustrate, at this level a program can simply make a call to
+.I rnusers (),
+a C routine which returns the number of users on a remote machine.
+The user is not explicitly aware of using RPC \(em they simply
+call a procedure, just as they would call
+.I malloc() .
+.LP
+.I "The Middle Layer:"
+.IX RPC "The Middle Layer"
+The middle layer is really \*QRPC proper.\*U Here, the user doesn't
+need to consider details about sockets, the UNIX system, or other low-level
+implementation mechanisms. They simply make remote procedure calls
+to routines on other machines. The selling point here is simplicity.
+It's this layer that allows RPC to pass the \*Qhello world\*U test \(em
+simple things should be simple. The middle-layer routines are used
+for most applications.
+.LP
+RPC calls are made with the system routines
+.I registerrpc()
+.I callrpc()
+and
+.I svc_run ().
+The first two of these are the most fundamental:
+.I registerrpc()
+obtains a unique system-wide procedure-identification number, and
+.I callrpc()
+actually executes a remote procedure call. At the middle level, a
+call to
+.I rnusers()
+is implemented by way of these two routines.
+.LP
+The middle layer is unfortunately rarely used in serious programming
+due to its inflexibility (simplicity). It does not allow timeout
+specifications or the choice of transport. It allows no UNIX
+process control or flexibility in case of errors. It doesn't support
+multiple kinds of call authentication. The programmer rarely needs
+all these kinds of control, but one or two of them is often necessary.
+.LP
+.I "The Lowest Layer:"
+.IX RPC "The Lowest Layer"
+The lowest layer does allow these details to be controlled by the
+programmer, and for that reason it is often necessary. Programs
+written at this level are also most efficient, but this is rarely a
+real issue \(em since RPC clients and servers rarely generate
+heavy network loads.
+.LP
+Although this document only discusses the interface to C,
+remote procedure calls can be made from any language.
+Even though this document discusses RPC
+when it is used to communicate
+between processes on different machines,
+it works just as well for communication
+between different processes on the same machine.
+.br
+.KS
+.NH 2
+\&The RPC Paradigm
+.IX RPC paradigm
+.LP
+Here is a diagram of the RPC paradigm:
+.LP
+\fBFigure 1-1\fI Network Communication with the Remote Reocedure Call\fR
+.LP
+.PS
+L1: arrow down 1i "client " rjust "program " rjust
+L2: line right 1.5i "\fIcallrpc\fP" "function"
+move up 1.5i; line dotted down 6i; move up 4.5i
+arrow right 1i
+L3: arrow down 1i "invoke " rjust "service " rjust
+L4: arrow right 1.5i "call" "service"
+L5: arrow down 1i " service" ljust " executes" ljust
+L6: arrow left 1.5i "\fIreturn\fP" "answer"
+L7: arrow down 1i "request " rjust "completed " rjust
+L8: line left 1i
+arrow left 1.5i "\fIreturn\fP" "reply"
+L9: arrow down 1i "program " rjust "continues " rjust
+line dashed down from L2 to L9
+line dashed down from L4 to L7
+line dashed up 1i from L3 "service " rjust "daemon " rjust
+arrow dashed down 1i from L8
+move right 1i from L3
+box invis "Machine B"
+move left 1.2i from L2; move down
+box invis "Machine A"
+.PE
+.KE
+.KS
+.NH 1
+\&Higher Layers of RPC
+.NH 2
+\&Highest Layer
+.IX "highest layer of RPC"
+.IX RPC "highest layer"
+.LP
+Imagine you're writing a program that needs to know
+how many users are logged into a remote machine.
+You can do this by calling the RPC library routine
+.I rnusers()
+as illustrated below:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int num;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: rnusers hostname\en");
+ exit(1);
+ }
+ if ((num = rnusers(argv[1])) < 0) {
+ fprintf(stderr, "error: rnusers\en");
+ exit(-1);
+ }
+ printf("%d users on %s\en", num, argv[1]);
+ exit(0);
+}
+.DE
+.KE
+RPC library routines such as
+.I rnusers()
+are in the RPC services library
+.I librpcsvc.a
+Thus, the program above should be compiled with
+.DS
+.ft CW
+% cc \fIprogram.c -lrpcsvc\fP
+.DE
+.I rnusers (),
+like the other RPC library routines, is documented in section 3R
+of the
+.I "System Interface Manual for the Sun Workstation" ,
+the same section which documents the standard Sun RPC services.
+.IX "RPC Services"
+See the
+.I intro(3R)
+manual page for an explanation of the documentation strategy
+for these services and their RPC protocols.
+.LP
+Here are some of the RPC service library routines available to the
+C programmer:
+.LP
+\fBTable 3-3\fI RPC Service Library Routines\RP
+.TS
+box tab (&) ;
+cfI cfI
+lfL l .
+Routine&Description
+_
+.sp.5
+rnusers&Return number of users on remote machine
+rusers&Return information about users on remote machine
+havedisk&Determine if remote machine has disk
+rstats&Get performance data from remote kernel
+rwall&Write to specified remote machines
+yppasswd&Update user password in Yellow Pages
+.TE
+.LP
+Other RPC services \(em for example
+.I ether()
+.I mount
+.I rquota()
+and
+.I spray
+\(em are not available to the C programmer as library routines.
+They do, however,
+have RPC program numbers so they can be invoked with
+.I callrpc()
+which will be discussed in the next section. Most of them also
+have compilable
+.I rpcgen(1)
+protocol description files. (The
+.I rpcgen
+protocol compiler radically simplifies the process of developing
+network applications.
+See the \fBrpcgen\fI Programming Guide\fR
+for detailed information about
+.I rpcgen
+and
+.I rpcgen
+protocol description files).
+.KS
+.NH 2
+\&Intermediate Layer
+.IX "intermediate layer of RPC"
+.IX "RPC" "intermediate layer"
+.LP
+The simplest interface, which explicitly makes RPC calls, uses the
+functions
+.I callrpc()
+and
+.I registerrpc()
+Using this method, the number of remote users can be gotten as follows:
+.ie t .DS
+.el .DS L
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ unsigned long nusers;
+ int stat;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: nusers hostname\en");
+ exit(-1);
+ }
+ if (stat = callrpc(argv[1],
+ RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM,
+ xdr_void, 0, xdr_u_long, &nusers) != 0) {
+ clnt_perrno(stat);
+ exit(1);
+ }
+ printf("%d users on %s\en", nusers, argv[1]);
+ exit(0);
+}
+.DE
+.KE
+Each RPC procedure is uniquely defined by a program number,
+version number, and procedure number. The program number
+specifies a group of related remote procedures, each of
+which has a different procedure number. Each program also
+has a version number, so when a minor change is made to a
+remote service (adding a new procedure, for example), a new
+program number doesn't have to be assigned. When you want
+to call a procedure to find the number of remote users, you
+look up the appropriate program, version and procedure numbers
+in a manual, just as you look up the name of a memory allocator
+when you want to allocate memory.
+.LP
+The simplest way of making remote procedure calls is with the the RPC
+library routine
+.I callrpc()
+It has eight parameters. The first is the name of the remote server
+machine. The next three parameters are the program, version, and procedure
+numbers\(emtogether they identify the procedure to be called.
+The fifth and sixth parameters are an XDR filter and an argument to
+be encoded and passed to the remote procedure.
+The final two parameters are a filter for decoding the results
+returned by the remote procedure and a pointer to the place where
+the procedure's results are to be stored. Multiple arguments and
+results are handled by embedding them in structures. If
+.I callrpc()
+completes successfully, it returns zero; else it returns a nonzero
+value. The return codes (of type
+.IX "enum clnt_stat (in RPC programming)" "" "\fIenum clnt_stat\fP (in RPC programming)"
+cast into an integer) are found in
+.I <rpc/clnt.h> .
+.LP
+Since data types may be represented differently on different machines,
+.I callrpc()
+needs both the type of the RPC argument, as well as
+a pointer to the argument itself (and similarly for the result). For
+.I RUSERSPROC_NUM ,
+the return value is an
+.I "unsigned long"
+so
+.I callrpc()
+has
+.I xdr_u_long()
+as its first return parameter, which says
+that the result is of type
+.I "unsigned long"
+and
+.I &nusers
+as its second return parameter,
+which is a pointer to where the long result will be placed. Since
+.I RUSERSPROC_NUM
+takes no argument, the argument parameter of
+.I callrpc()
+is
+.I xdr_void ().
+.LP
+After trying several times to deliver a message, if
+.I callrpc()
+gets no answer, it returns with an error code.
+The delivery mechanism is UDP,
+which stands for User Datagram Protocol.
+Methods for adjusting the number of retries
+or for using a different protocol require you to use the lower
+layer of the RPC library, discussed later in this document.
+The remote server procedure
+corresponding to the above might look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+.ft CW
+char *
+nuser(indata)
+ char *indata;
+{
+ unsigned long nusers;
+
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and place result in variable \fInusers\fP.
+ */
+.ft CW
+ return((char *)&nusers);
+}
+.DE
+.LP
+It takes one argument, which is a pointer to the input
+of the remote procedure call (ignored in our example),
+and it returns a pointer to the result.
+In the current version of C,
+character pointers are the generic pointers,
+so both the input argument and the return value are cast to
+.I "char *" .
+.LP
+Normally, a server registers all of the RPC calls it plans
+to handle, and then goes into an infinite loop waiting to service requests.
+In this example, there is only a single procedure
+to register, so the main body of the server would look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+
+char *nuser();
+
+main()
+{
+ registerrpc(RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM,
+ nuser, xdr_void, xdr_u_long);
+ svc_run(); /* \fINever returns\fP */
+ fprintf(stderr, "Error: svc_run returned!\en");
+ exit(1);
+}
+.DE
+.LP
+The
+.I registerrpc()
+routine registers a C procedure as corresponding to a
+given RPC procedure number. The first three parameters,
+.I RUSERPROG ,
+.I RUSERSVERS ,
+and
+.I RUSERSPROC_NUM
+are the program, version, and procedure numbers
+of the remote procedure to be registered;
+.I nuser()
+is the name of the local procedure that implements the remote
+procedure; and
+.I xdr_void()
+and
+.I xdr_u_long()
+are the XDR filters for the remote procedure's arguments and
+results, respectively. (Multiple arguments or multiple results
+are passed as structures).
+.LP
+Only the UDP transport mechanism can use
+.I registerrpc()
+thus, it is always safe in conjunction with calls generated by
+.I callrpc() .
+.SH
+.IX "UDP 8K warning"
+Warning: the UDP transport mechanism can only deal with
+arguments and results less than 8K bytes in length.
+.LP
+.LP
+After registering the local procedure, the server program's
+main procedure calls
+.I svc_run (),
+the RPC library's remote procedure dispatcher. It is this
+function that calls the remote procedures in response to RPC
+call messages. Note that the dispatcher takes care of decoding
+remote procedure arguments and encoding results, using the XDR
+filters specified when the remote procedure was registered.
+.NH 2
+\&Assigning Program Numbers
+.IX "program number assignment"
+.IX "assigning program numbers"
+.LP
+Program numbers are assigned in groups of
+.I 0x20000000
+according to the following chart:
+.DS
+.ft CW
+ 0x0 - 0x1fffffff \fRDefined by Sun\fP
+0x20000000 - 0x3fffffff \fRDefined by user\fP
+0x40000000 - 0x5fffffff \fRTransient\fP
+0x60000000 - 0x7fffffff \fRReserved\fP
+0x80000000 - 0x9fffffff \fRReserved\fP
+0xa0000000 - 0xbfffffff \fRReserved\fP
+0xc0000000 - 0xdfffffff \fRReserved\fP
+0xe0000000 - 0xffffffff \fRReserved\fP
+.ft R
+.DE
+Sun Microsystems administers the first group of numbers, which
+should be identical for all Sun customers. If a customer
+develops an application that might be of general interest, that
+application should be given an assigned number in the first
+range. The second group of numbers is reserved for specific
+customer applications. This range is intended primarily for
+debugging new programs. The third group is reserved for
+applications that generate program numbers dynamically. The
+final groups are reserved for future use, and should not be
+used.
+.LP
+To register a protocol specification, send a request by network
+mail to
+.I rpc@sun
+or write to:
+.DS
+RPC Administrator
+Sun Microsystems
+2550 Garcia Ave.
+Mountain View, CA 94043
+.DE
+Please include a compilable
+.I rpcgen
+\*Q.x\*U file describing your protocol.
+You will be given a unique program number in return.
+.IX RPC administration
+.IX administration "of RPC"
+.LP
+The RPC program numbers and protocol specifications
+of standard Sun RPC services can be
+found in the include files in
+.I "/usr/include/rpcsvc" .
+These services, however, constitute only a small subset
+of those which have been registered. The complete list of
+registered programs, as of the time when this manual was
+printed, is:
+.LP
+\fBTable 3-2\fI RPC Registered Programs\fR
+.TS H
+box tab (&) ;
+lfBI lfBI lfBI
+lfL lfL lfI .
+RPC Number&Program&Description
+_
+.TH
+.sp.5
+100000&PMAPPROG&portmapper
+100001&RSTATPROG&remote stats
+100002&RUSERSPROG&remote users
+100003&NFSPROG&nfs
+100004&YPPROG&Yellow Pages
+100005&MOUNTPROG&mount demon
+100006&DBXPROG&remote dbx
+100007&YPBINDPROG&yp binder
+100008&WALLPROG&shutdown msg
+100009&YPPASSWDPROG&yppasswd server
+100010&ETHERSTATPROG&ether stats
+100011&RQUOTAPROG&disk quotas
+100012&SPRAYPROG&spray packets
+100013&IBM3270PROG&3270 mapper
+100014&IBMRJEPROG&RJE mapper
+100015&SELNSVCPROG&selection service
+100016&RDATABASEPROG&remote database access
+100017&REXECPROG&remote execution
+100018&ALICEPROG&Alice Office Automation
+100019&SCHEDPROG&scheduling service
+100020&LOCKPROG&local lock manager
+100021&NETLOCKPROG&network lock manager
+100022&X25PROG&x.25 inr protocol
+100023&STATMON1PROG&status monitor 1
+100024&STATMON2PROG&status monitor 2
+100025&SELNLIBPROG&selection library
+100026&BOOTPARAMPROG&boot parameters service
+100027&MAZEPROG&mazewars game
+100028&YPUPDATEPROG&yp update
+100029&KEYSERVEPROG&key server
+100030&SECURECMDPROG&secure login
+100031&NETFWDIPROG&nfs net forwarder init
+100032&NETFWDTPROG&nfs net forwarder trans
+100033&SUNLINKMAP_PROG&sunlink MAP
+100034&NETMONPROG&network monitor
+100035&DBASEPROG&lightweight database
+100036&PWDAUTHPROG&password authorization
+100037&TFSPROG&translucent file svc
+100038&NSEPROG&nse server
+100039&NSE_ACTIVATE_PROG&nse activate daemon
+.sp .2i
+150001&PCNFSDPROG&pc passwd authorization
+.sp .2i
+200000&PYRAMIDLOCKINGPROG&Pyramid-locking
+200001&PYRAMIDSYS5&Pyramid-sys5
+200002&CADDS_IMAGE&CV cadds_image
+.sp .2i
+300001&ADT_RFLOCKPROG&ADT file locking
+.TE
+.NH 2
+\&Passing Arbitrary Data Types
+.IX "arbitrary data types"
+.LP
+In the previous example, the RPC call passes a single
+.I "unsigned long"
+RPC can handle arbitrary data structures, regardless of
+different machines' byte orders or structure layout conventions,
+by always converting them to a network standard called
+.I "External Data Representation"
+(XDR) before
+sending them over the wire.
+The process of converting from a particular machine representation
+to XDR format is called
+.I serializing ,
+and the reverse process is called
+.I deserializing .
+The type field parameters of
+.I callrpc()
+and
+.I registerrpc()
+can be a built-in procedure like
+.I xdr_u_long()
+in the previous example, or a user supplied one.
+XDR has these built-in type routines:
+.IX RPC "built-in routines"
+.DS
+.ft CW
+xdr_int() xdr_u_int() xdr_enum()
+xdr_long() xdr_u_long() xdr_bool()
+xdr_short() xdr_u_short() xdr_wrapstring()
+xdr_char() xdr_u_char()
+.DE
+Note that the routine
+.I xdr_string()
+exists, but cannot be used with
+.I callrpc()
+and
+.I registerrpc (),
+which only pass two parameters to their XDR routines.
+.I xdr_wrapstring()
+has only two parameters, and is thus OK. It calls
+.I xdr_string ().
+.LP
+As an example of a user-defined type routine,
+if you wanted to send the structure
+.DS
+.ft CW
+struct simple {
+ int a;
+ short b;
+} simple;
+.DE
+then you would call
+.I callrpc()
+as
+.DS
+.ft CW
+callrpc(hostname, PROGNUM, VERSNUM, PROCNUM,
+ xdr_simple, &simple ...);
+.DE
+where
+.I xdr_simple()
+is written as:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <rpc/rpc.h>
+
+xdr_simple(xdrsp, simplep)
+ XDR *xdrsp;
+ struct simple *simplep;
+{
+ if (!xdr_int(xdrsp, &simplep->a))
+ return (0);
+ if (!xdr_short(xdrsp, &simplep->b))
+ return (0);
+ return (1);
+}
+.DE
+.LP
+An XDR routine returns nonzero (true in the sense of C) if it
+completes successfully, and zero otherwise.
+A complete description of XDR is in the
+.I "XDR Protocol Specification"
+section of this manual, only few implementation examples are
+given here.
+.LP
+In addition to the built-in primitives,
+there are also the prefabricated building blocks:
+.DS
+.ft CW
+xdr_array() xdr_bytes() xdr_reference()
+xdr_vector() xdr_union() xdr_pointer()
+xdr_string() xdr_opaque()
+.DE
+To send a variable array of integers,
+you might package them up as a structure like this
+.DS
+.ft CW
+struct varintarr {
+ int *data;
+ int arrlnth;
+} arr;
+.DE
+and make an RPC call such as
+.DS
+.ft CW
+callrpc(hostname, PROGNUM, VERSNUM, PROCNUM,
+ xdr_varintarr, &arr...);
+.DE
+with
+.I xdr_varintarr()
+defined as:
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_varintarr(xdrsp, arrp)
+ XDR *xdrsp;
+ struct varintarr *arrp;
+{
+ return (xdr_array(xdrsp, &arrp->data, &arrp->arrlnth,
+ MAXLEN, sizeof(int), xdr_int));
+}
+.DE
+This routine takes as parameters the XDR handle,
+a pointer to the array, a pointer to the size of the array,
+the maximum allowable array size,
+the size of each array element,
+and an XDR routine for handling each array element.
+.KS
+.LP
+If the size of the array is known in advance, one can use
+.I xdr_vector (),
+which serializes fixed-length arrays.
+.ie t .DS
+.el .DS L
+.ft CW
+int intarr[SIZE];
+
+xdr_intarr(xdrsp, intarr)
+ XDR *xdrsp;
+ int intarr[];
+{
+ int i;
+
+ return (xdr_vector(xdrsp, intarr, SIZE, sizeof(int),
+ xdr_int));
+}
+.DE
+.KE
+.LP
+XDR always converts quantities to 4-byte multiples when serializing.
+Thus, if either of the examples above involved characters
+instead of integers, each character would occupy 32 bits.
+That is the reason for the XDR routine
+.I xdr_bytes()
+which is like
+.I xdr_array()
+except that it packs characters;
+.I xdr_bytes()
+has four parameters, similar to the first four parameters of
+.I xdr_array ().
+For null-terminated strings, there is also the
+.I xdr_string()
+routine, which is the same as
+.I xdr_bytes()
+without the length parameter.
+On serializing it gets the string length from
+.I strlen (),
+and on deserializing it creates a null-terminated string.
+.LP
+Here is a final example that calls the previously written
+.I xdr_simple()
+as well as the built-in functions
+.I xdr_string()
+and
+.I xdr_reference (),
+which chases pointers:
+.ie t .DS
+.el .DS L
+.ft CW
+struct finalexample {
+ char *string;
+ struct simple *simplep;
+} finalexample;
+
+xdr_finalexample(xdrsp, finalp)
+ XDR *xdrsp;
+ struct finalexample *finalp;
+{
+
+ if (!xdr_string(xdrsp, &finalp->string, MAXSTRLEN))
+ return (0);
+ if (!xdr_reference(xdrsp, &finalp->simplep,
+ sizeof(struct simple), xdr_simple);
+ return (0);
+ return (1);
+}
+.DE
+Note that we could as easily call
+.I xdr_simple()
+here instead of
+.I xdr_reference ().
+.NH 1
+\&Lowest Layer of RPC
+.IX "lowest layer of RPC"
+.IX "RPC" "lowest layer"
+.LP
+In the examples given so far,
+RPC takes care of many details automatically for you.
+In this section, we'll show you how you can change the defaults
+by using lower layers of the RPC library.
+It is assumed that you are familiar with sockets
+and the system calls for dealing with them.
+.LP
+There are several occasions when you may need to use lower layers of
+RPC. First, you may need to use TCP, since the higher layer uses UDP,
+which restricts RPC calls to 8K bytes of data. Using TCP permits calls
+to send long streams of data.
+For an example, see the
+.I TCP
+section below. Second, you may want to allocate and free memory
+while serializing or deserializing with XDR routines.
+There is no call at the higher level to let
+you free memory explicitly.
+For more explanation, see the
+.I "Memory Allocation with XDR"
+section below.
+Third, you may need to perform authentication
+on either the client or server side, by supplying
+credentials or verifying them.
+See the explanation in the
+.I Authentication
+section below.
+.NH 2
+\&More on the Server Side
+.IX RPC "server side"
+.LP
+The server for the
+.I nusers()
+program shown below does the same thing as the one using
+.I registerrpc()
+above, but is written using a lower layer of the RPC package:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+
+main()
+{
+ SVCXPRT *transp;
+ int nuser();
+
+ transp = svcudp_create(RPC_ANYSOCK);
+ if (transp == NULL){
+ fprintf(stderr, "can't create an RPC server\en");
+ exit(1);
+ }
+ pmap_unset(RUSERSPROG, RUSERSVERS);
+ if (!svc_register(transp, RUSERSPROG, RUSERSVERS,
+ nuser, IPPROTO_UDP)) {
+ fprintf(stderr, "can't register RUSER service\en");
+ exit(1);
+ }
+ svc_run(); /* \fINever returns\fP */
+ fprintf(stderr, "should never reach this point\en");
+}
+
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ unsigned long nusers;
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (!svc_sendreply(transp, xdr_void, 0))
+ fprintf(stderr, "can't reply to RPC call\en");
+ return;
+ case RUSERSPROC_NUM:
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and assign it to the variable \fInusers\fP
+ */
+.ft CW
+ if (!svc_sendreply(transp, xdr_u_long, &nusers))
+ fprintf(stderr, "can't reply to RPC call\en");
+ return;
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.DE
+.LP
+First, the server gets a transport handle, which is used
+for receiving and replying to RPC messages.
+.I registerrpc()
+uses
+.I svcudp_create()
+to get a UDP handle.
+If you require a more reliable protocol, call
+.I svctcp_create()
+instead.
+If the argument to
+.I svcudp_create()
+is
+.I RPC_ANYSOCK
+the RPC library creates a socket
+on which to receive and reply to RPC calls. Otherwise,
+.I svcudp_create()
+expects its argument to be a valid socket number.
+If you specify your own socket, it can be bound or unbound.
+If it is bound to a port by the user, the port numbers of
+.I svcudp_create()
+and
+.I clnttcp_create()
+(the low-level client routine) must match.
+.LP
+If the user specifies the
+.I RPC_ANYSOCK
+argument, the RPC library routines will open sockets.
+Otherwise they will expect the user to do so. The routines
+.I svcudp_create()
+and
+.I clntudp_create()
+will cause the RPC library routines to
+.I bind()
+their socket if it is not bound already.
+.LP
+A service may choose to register its port number with the
+local portmapper service. This is done is done by specifying
+a non-zero protocol number in
+.I svc_register ().
+Incidently, a client can discover the server's port number by
+consulting the portmapper on their server's machine. This can
+be done automatically by specifying a zero port number in
+.I clntudp_create()
+or
+.I clnttcp_create ().
+.LP
+After creating an
+.I SVCXPRT ,
+the next step is to call
+.I pmap_unset()
+so that if the
+.I nusers()
+server crashed earlier,
+any previous trace of it is erased before restarting.
+More precisely,
+.I pmap_unset()
+erases the entry for
+.I RUSERSPROG
+from the port mapper's tables.
+.LP
+Finally, we associate the program number for
+.I nusers()
+with the procedure
+.I nuser ().
+The final argument to
+.I svc_register()
+is normally the protocol being used,
+which, in this case, is
+.I IPPROTO_UDP
+Notice that unlike
+.I registerrpc (),
+there are no XDR routines involved
+in the registration process.
+Also, registration is done on the program,
+rather than procedure, level.
+.LP
+The user routine
+.I nuser()
+must call and dispatch the appropriate XDR routines
+based on the procedure number.
+Note that
+two things are handled by
+.I nuser()
+that
+.I registerrpc()
+handles automatically.
+The first is that procedure
+.I NULLPROC
+(currently zero) returns with no results.
+This can be used as a simple test
+for detecting if a remote program is running.
+Second, there is a check for invalid procedure numbers.
+If one is detected,
+.I svcerr_noproc()
+is called to handle the error.
+.KS
+.LP
+The user service routine serializes the results and returns
+them to the RPC caller via
+.I svc_sendreply()
+Its first parameter is the
+.I SVCXPRT
+handle, the second is the XDR routine,
+and the third is a pointer to the data to be returned.
+Not illustrated above is how a server
+handles an RPC program that receives data.
+As an example, we can add a procedure
+.I RUSERSPROC_BOOL
+which has an argument
+.I nusers (),
+and returns
+.I TRUE
+or
+.I FALSE
+depending on whether there are nusers logged on.
+It would look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+case RUSERSPROC_BOOL: {
+ int bool;
+ unsigned nuserquery;
+
+ if (!svc_getargs(transp, xdr_u_int, &nuserquery) {
+ svcerr_decode(transp);
+ return;
+ }
+.ft I
+ /*
+ * Code to set \fInusers\fP = number of users
+ */
+.ft CW
+ if (nuserquery == nusers)
+ bool = TRUE;
+ else
+ bool = FALSE;
+ if (!svc_sendreply(transp, xdr_bool, &bool)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+}
+.DE
+.KE
+.LP
+The relevant routine is
+.I svc_getargs()
+which takes an
+.I SVCXPRT
+handle, the XDR routine,
+and a pointer to where the input is to be placed as arguments.
+.NH 2
+\&Memory Allocation with XDR
+.IX "memory allocation with XDR"
+.IX XDR "memory allocation"
+.LP
+XDR routines not only do input and output,
+they also do memory allocation.
+This is why the second parameter of
+.I xdr_array()
+is a pointer to an array, rather than the array itself.
+If it is
+.I NULL ,
+then
+.I xdr_array()
+allocates space for the array and returns a pointer to it,
+putting the size of the array in the third argument.
+As an example, consider the following XDR routine
+.I xdr_chararr1()
+which deals with a fixed array of bytes with length
+.I SIZE .
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_chararr1(xdrsp, chararr)
+ XDR *xdrsp;
+ char chararr[];
+{
+ char *p;
+ int len;
+
+ p = chararr;
+ len = SIZE;
+ return (xdr_bytes(xdrsp, &p, &len, SIZE));
+}
+.DE
+If space has already been allocated in
+.I chararr ,
+it can be called from a server like this:
+.ie t .DS
+.el .DS L
+.ft CW
+char chararr[SIZE];
+
+svc_getargs(transp, xdr_chararr1, chararr);
+.DE
+If you want XDR to do the allocation,
+you would have to rewrite this routine in the following way:
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_chararr2(xdrsp, chararrp)
+ XDR *xdrsp;
+ char **chararrp;
+{
+ int len;
+
+ len = SIZE;
+ return (xdr_bytes(xdrsp, charrarrp, &len, SIZE));
+}
+.DE
+Then the RPC call might look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+char *arrptr;
+
+arrptr = NULL;
+svc_getargs(transp, xdr_chararr2, &arrptr);
+.ft I
+/*
+ * Use the result here
+ */
+.ft CW
+svc_freeargs(transp, xdr_chararr2, &arrptr);
+.DE
+Note that, after being used, the character array can be freed with
+.I svc_freeargs()
+.I svc_freeargs()
+will not attempt to free any memory if the variable indicating it
+is NULL. For example, in the the routine
+.I xdr_finalexample (),
+given earlier, if
+.I finalp->string
+was NULL, then it would not be freed. The same is true for
+.I finalp->simplep .
+.LP
+To summarize, each XDR routine is responsible
+for serializing, deserializing, and freeing memory.
+When an XDR routine is called from
+.I callrpc()
+the serializing part is used.
+When called from
+.I svc_getargs()
+the deserializer is used.
+And when called from
+.I svc_freeargs()
+the memory deallocator is used. When building simple examples like those
+in this section, a user doesn't have to worry
+about the three modes.
+See the
+.I "External Data Representation: Sun Technical Notes"
+for examples of more sophisticated XDR routines that determine
+which of the three modes they are in and adjust their behavior accordingly.
+.KS
+.NH 2
+\&The Calling Side
+.IX RPC "calling side"
+.LP
+When you use
+.I callrpc()
+you have no control over the RPC delivery
+mechanism or the socket used to transport the data.
+To illustrate the layer of RPC that lets you adjust these
+parameters, consider the following code to call the
+.I nusers
+service:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netdb.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct hostent *hp;
+ struct timeval pertry_timeout, total_timeout;
+ struct sockaddr_in server_addr;
+ int sock = RPC_ANYSOCK;
+ register CLIENT *client;
+ enum clnt_stat clnt_stat;
+ unsigned long nusers;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: nusers hostname\en");
+ exit(-1);
+ }
+ if ((hp = gethostbyname(argv[1])) == NULL) {
+ fprintf(stderr, "can't get addr for %s\en",argv[1]);
+ exit(-1);
+ }
+ pertry_timeout.tv_sec = 3;
+ pertry_timeout.tv_usec = 0;
+ bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
+ hp->h_length);
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = 0;
+ if ((client = clntudp_create(&server_addr, RUSERSPROG,
+ RUSERSVERS, pertry_timeout, &sock)) == NULL) {
+ clnt_pcreateerror("clntudp_create");
+ exit(-1);
+ }
+ total_timeout.tv_sec = 20;
+ total_timeout.tv_usec = 0;
+ clnt_stat = clnt_call(client, RUSERSPROC_NUM, xdr_void,
+ 0, xdr_u_long, &nusers, total_timeout);
+ if (clnt_stat != RPC_SUCCESS) {
+ clnt_perror(client, "rpc");
+ exit(-1);
+ }
+ clnt_destroy(client);
+ close(sock);
+ exit(0);
+}
+.vs
+.DE
+.KE
+The low-level version of
+.I callrpc()
+is
+.I clnt_call()
+which takes a
+.I CLIENT
+pointer rather than a host name. The parameters to
+.I clnt_call()
+are a
+.I CLIENT
+pointer, the procedure number,
+the XDR routine for serializing the argument,
+a pointer to the argument,
+the XDR routine for deserializing the return value,
+a pointer to where the return value will be placed,
+and the time in seconds to wait for a reply.
+.LP
+The
+.I CLIENT
+pointer is encoded with the transport mechanism.
+.I callrpc()
+uses UDP, thus it calls
+.I clntudp_create()
+to get a
+.I CLIENT
+pointer. To get TCP (Transmission Control Protocol), you would use
+.I clnttcp_create() .
+.LP
+The parameters to
+.I clntudp_create()
+are the server address, the program number, the version number,
+a timeout value (between tries), and a pointer to a socket.
+The final argument to
+.I clnt_call()
+is the total time to wait for a response.
+Thus, the number of tries is the
+.I clnt_call()
+timeout divided by the
+.I clntudp_create()
+timeout.
+.LP
+Note that the
+.I clnt_destroy()
+call
+always deallocates the space associated with the
+.I CLIENT
+handle. It closes the socket associated with the
+.I CLIENT
+handle, however, only if the RPC library opened it. It the
+socket was opened by the user, it stays open. This makes it
+possible, in cases where there are multiple client handles
+using the same socket, to destroy one handle without closing
+the socket that other handles are using.
+.LP
+To make a stream connection, the call to
+.I clntudp_create()
+is replaced with a call to
+.I clnttcp_create() .
+.DS
+.ft CW
+clnttcp_create(&server_addr, prognum, versnum, &sock,
+ inputsize, outputsize);
+.DE
+There is no timeout argument; instead, the receive and send buffer
+sizes must be specified. When the
+.I clnttcp_create()
+call is made, a TCP connection is established.
+All RPC calls using that
+.I CLIENT
+handle would use this connection.
+The server side of an RPC call using TCP has
+.I svcudp_create()
+replaced by
+.I svctcp_create() .
+.DS
+.ft CW
+transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+.DE
+The last two arguments to
+.I svctcp_create()
+are send and receive sizes respectively. If `0' is specified for
+either of these, the system chooses a reasonable default.
+.KS
+.NH 1
+\&Other RPC Features
+.IX "RPC" "miscellaneous features"
+.IX "miscellaneous RPC features"
+.LP
+This section discusses some other aspects of RPC
+that are occasionally useful.
+.NH 2
+\&Select on the Server Side
+.IX RPC select() RPC \fIselect()\fP
+.IX select() "" \fIselect()\fP "on the server side"
+.LP
+Suppose a process is processing RPC requests
+while performing some other activity.
+If the other activity involves periodically updating a data structure,
+the process can set an alarm signal before calling
+.I svc_run()
+But if the other activity
+involves waiting on a a file descriptor, the
+.I svc_run()
+call won't work.
+The code for
+.I svc_run()
+is as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+void
+svc_run()
+{
+ fd_set readfds;
+ int dtbsz = getdtablesize();
+
+ for (;;) {
+ readfds = svc_fds;
+ switch (select(dtbsz, &readfds, NULL,NULL,NULL)) {
+
+ case -1:
+ if (errno == EINTR)
+ continue;
+ perror("select");
+ return;
+ case 0:
+ break;
+ default:
+ svc_getreqset(&readfds);
+ }
+ }
+}
+.vs
+.DE
+.KE
+.LP
+You can bypass
+.I svc_run()
+and call
+.I svc_getreqset()
+yourself.
+All you need to know are the file descriptors
+of the socket(s) associated with the programs you are waiting on.
+Thus you can have your own
+.I select()
+.IX select() "" \fIselect()\fP
+that waits on both the RPC socket,
+and your own descriptors. Note that
+.I svc_fds()
+is a bit mask of all the file descriptors that RPC is using for
+services. It can change everytime that
+.I any
+RPC library routine is called, because descriptors are constantly
+being opened and closed, for example for TCP connections.
+.NH 2
+\&Broadcast RPC
+.IX "broadcast RPC"
+.IX RPC "broadcast"
+.LP
+The
+.I portmapper
+is a daemon that converts RPC program numbers
+into DARPA protocol port numbers; see the
+.I portmap
+man page. You can't do broadcast RPC without the portmapper.
+Here are the main differences between
+broadcast RPC and normal RPC calls:
+.IP 1.
+Normal RPC expects one answer, whereas
+broadcast RPC expects many answers
+(one or more answer from each responding machine).
+.IP 2.
+Broadcast RPC can only be supported by packet-oriented (connectionless)
+transport protocols like UPD/IP.
+.IP 3.
+The implementation of broadcast RPC
+treats all unsuccessful responses as garbage by filtering them out.
+Thus, if there is a version mismatch between the
+broadcaster and a remote service,
+the user of broadcast RPC never knows.
+.IP 4.
+All broadcast messages are sent to the portmap port.
+Thus, only services that register themselves with their portmapper
+are accessible via the broadcast RPC mechanism.
+.IP 5.
+Broadcast requests are limited in size to the MTU (Maximum Transfer
+Unit) of the local network. For Ethernet, the MTU is 1500 bytes.
+.KS
+.NH 3
+\&Broadcast RPC Synopsis
+.IX "broadcast RPC" synopsis
+.IX "RPC" "broadcast synopsis"
+.ie t .DS
+.el .DS L
+.ft CW
+#include <rpc/pmap_clnt.h>
+ . . .
+enum clnt_stat clnt_stat;
+ . . .
+clnt_stat = clnt_broadcast(prognum, versnum, procnum,
+ inproc, in, outproc, out, eachresult)
+ u_long prognum; /* \fIprogram number\fP */
+ u_long versnum; /* \fIversion number\fP */
+ u_long procnum; /* \fIprocedure number\fP */
+ xdrproc_t inproc; /* \fIxdr routine for args\fP */
+ caddr_t in; /* \fIpointer to args\fP */
+ xdrproc_t outproc; /* \fIxdr routine for results\fP */
+ caddr_t out; /* \fIpointer to results\fP */
+ bool_t (*eachresult)();/* \fIcall with each result gotten\fP */
+.DE
+.KE
+The procedure
+.I eachresult()
+is called each time a valid result is obtained.
+It returns a boolean that indicates
+whether or not the user wants more responses.
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t done;
+ . . .
+done = eachresult(resultsp, raddr)
+ caddr_t resultsp;
+ struct sockaddr_in *raddr; /* \fIAddr of responding machine\fP */
+.DE
+If
+.I done
+is
+.I TRUE ,
+then broadcasting stops and
+.I clnt_broadcast()
+returns successfully.
+Otherwise, the routine waits for another response.
+The request is rebroadcast
+after a few seconds of waiting.
+If no responses come back,
+the routine returns with
+.I RPC_TIMEDOUT .
+.NH 2
+\&Batching
+.IX "batching"
+.IX RPC "batching"
+.LP
+The RPC architecture is designed so that clients send a call message,
+and wait for servers to reply that the call succeeded.
+This implies that clients do not compute
+while servers are processing a call.
+This is inefficient if the client does not want or need
+an acknowledgement for every message sent.
+It is possible for clients to continue computing
+while waiting for a response,
+using RPC batch facilities.
+.LP
+RPC messages can be placed in a \*Qpipeline\*U of calls
+to a desired server; this is called batching.
+Batching assumes that:
+1) each RPC call in the pipeline requires no response from the server,
+and the server does not send a response message; and
+2) the pipeline of calls is transported on a reliable
+byte stream transport such as TCP/IP.
+Since the server does not respond to every call,
+the client can generate new calls in parallel
+with the server executing previous calls.
+Furthermore, the TCP/IP implementation can buffer up
+many call messages, and send them to the server in one
+.I write()
+system call. This overlapped execution
+greatly decreases the interprocess communication overhead of
+the client and server processes,
+and the total elapsed time of a series of calls.
+.LP
+Since the batched calls are buffered,
+the client should eventually do a nonbatched call
+in order to flush the pipeline.
+.LP
+A contrived example of batching follows.
+Assume a string rendering service (like a window system)
+has two similar calls: one renders a string and returns void results,
+while the other renders a string and remains silent.
+The service (using the TCP/IP transport) may look like:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <suntool/windows.h>
+
+void windowdispatch();
+
+main()
+{
+ SVCXPRT *transp;
+
+ transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+ if (transp == NULL){
+ fprintf(stderr, "can't create an RPC server\en");
+ exit(1);
+ }
+ pmap_unset(WINDOWPROG, WINDOWVERS);
+ if (!svc_register(transp, WINDOWPROG, WINDOWVERS,
+ windowdispatch, IPPROTO_TCP)) {
+ fprintf(stderr, "can't register WINDOW service\en");
+ exit(1);
+ }
+ svc_run(); /* \fINever returns\fP */
+ fprintf(stderr, "should never reach this point\en");
+}
+
+void
+windowdispatch(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ char *s = NULL;
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (!svc_sendreply(transp, xdr_void, 0))
+ fprintf(stderr, "can't reply to RPC call\en");
+ return;
+ case RENDERSTRING:
+ if (!svc_getargs(transp, xdr_wrapstring, &s)) {
+ fprintf(stderr, "can't decode arguments\en");
+.ft I
+ /*
+ * Tell caller he screwed up
+ */
+.ft CW
+ svcerr_decode(transp);
+ break;
+ }
+.ft I
+ /*
+ * Code here to render the string \fIs\fP
+ */
+.ft CW
+ if (!svc_sendreply(transp, xdr_void, NULL))
+ fprintf(stderr, "can't reply to RPC call\en");
+ break;
+ case RENDERSTRING_BATCHED:
+ if (!svc_getargs(transp, xdr_wrapstring, &s)) {
+ fprintf(stderr, "can't decode arguments\en");
+.ft I
+ /*
+ * We are silent in the face of protocol errors
+ */
+.ft CW
+ break;
+ }
+.ft I
+ /*
+ * Code here to render string s, but send no reply!
+ */
+.ft CW
+ break;
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+.ft I
+ /*
+ * Now free string allocated while decoding arguments
+ */
+.ft CW
+ svc_freeargs(transp, xdr_wrapstring, &s);
+}
+.DE
+Of course the service could have one procedure
+that takes the string and a boolean
+to indicate whether or not the procedure should respond.
+.LP
+In order for a client to take advantage of batching,
+the client must perform RPC calls on a TCP-based transport
+and the actual calls must have the following attributes:
+1) the result's XDR routine must be zero
+.I NULL ),
+and 2) the RPC call's timeout must be zero.
+.KS
+.LP
+Here is an example of a client that uses batching to render a
+bunch of strings; the batching is flushed when the client gets
+a null string (EOF):
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <suntool/windows.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct hostent *hp;
+ struct timeval pertry_timeout, total_timeout;
+ struct sockaddr_in server_addr;
+ int sock = RPC_ANYSOCK;
+ register CLIENT *client;
+ enum clnt_stat clnt_stat;
+ char buf[1000], *s = buf;
+
+ if ((client = clnttcp_create(&server_addr,
+ WINDOWPROG, WINDOWVERS, &sock, 0, 0)) == NULL) {
+ perror("clnttcp_create");
+ exit(-1);
+ }
+ total_timeout.tv_sec = 0;
+ total_timeout.tv_usec = 0;
+ while (scanf("%s", s) != EOF) {
+ clnt_stat = clnt_call(client, RENDERSTRING_BATCHED,
+ xdr_wrapstring, &s, NULL, NULL, total_timeout);
+ if (clnt_stat != RPC_SUCCESS) {
+ clnt_perror(client, "batched rpc");
+ exit(-1);
+ }
+ }
+
+ /* \fINow flush the pipeline\fP */
+
+ total_timeout.tv_sec = 20;
+ clnt_stat = clnt_call(client, NULLPROC, xdr_void, NULL,
+ xdr_void, NULL, total_timeout);
+ if (clnt_stat != RPC_SUCCESS) {
+ clnt_perror(client, "rpc");
+ exit(-1);
+ }
+ clnt_destroy(client);
+ exit(0);
+}
+.vs
+.DE
+.KE
+Since the server sends no message,
+the clients cannot be notified of any of the failures that may occur.
+Therefore, clients are on their own when it comes to handling errors.
+.LP
+The above example was completed to render
+all of the (2000) lines in the file
+.I /etc/termcap .
+The rendering service did nothing but throw the lines away.
+The example was run in the following four configurations:
+1) machine to itself, regular RPC;
+2) machine to itself, batched RPC;
+3) machine to another, regular RPC; and
+4) machine to another, batched RPC.
+The results are as follows:
+1) 50 seconds;
+2) 16 seconds;
+3) 52 seconds;
+4) 10 seconds.
+Running
+.I fscanf()
+on
+.I /etc/termcap
+only requires six seconds.
+These timings show the advantage of protocols
+that allow for overlapped execution,
+though these protocols are often hard to design.
+.NH 2
+\&Authentication
+.IX "authentication"
+.IX "RPC" "authentication"
+.LP
+In the examples presented so far,
+the caller never identified itself to the server,
+and the server never required an ID from the caller.
+Clearly, some network services, such as a network filesystem,
+require stronger security than what has been presented so far.
+.LP
+In reality, every RPC call is authenticated by
+the RPC package on the server, and similarly,
+the RPC client package generates and sends authentication parameters.
+Just as different transports (TCP/IP or UDP/IP)
+can be used when creating RPC clients and servers,
+different forms of authentication can be associated with RPC clients;
+the default authentication type used as a default is type
+.I none .
+.LP
+The authentication subsystem of the RPC package is open ended.
+That is, numerous types of authentication are easy to support.
+.NH 3
+\&UNIX Authentication
+.IX "UNIX Authentication"
+.IP "\fIThe Client Side\fP"
+.LP
+When a caller creates a new RPC client handle as in:
+.DS
+.ft CW
+clnt = clntudp_create(address, prognum, versnum,
+ wait, sockp)
+.DE
+the appropriate transport instance defaults
+the associate authentication handle to be
+.DS
+.ft CW
+clnt->cl_auth = authnone_create();
+.DE
+The RPC client can choose to use
+.I UNIX
+style authentication by setting
+.I clnt\->cl_auth
+after creating the RPC client handle:
+.DS
+.ft CW
+clnt->cl_auth = authunix_create_default();
+.DE
+This causes each RPC call associated with
+.I clnt
+to carry with it the following authentication credentials structure:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * UNIX style credentials.
+ */
+.ft CW
+struct authunix_parms {
+ u_long aup_time; /* \fIcredentials creation time\fP */
+ char *aup_machname; /* \fIhost name where client is\fP */
+ int aup_uid; /* \fIclient's UNIX effective uid\fP */
+ int aup_gid; /* \fIclient's current group id\fP */
+ u_int aup_len; /* \fIelement length of aup_gids\fP */
+ int *aup_gids; /* \fIarray of groups user is in\fP */
+};
+.DE
+These fields are set by
+.I authunix_create_default()
+by invoking the appropriate system calls.
+Since the RPC user created this new style of authentication,
+the user is responsible for destroying it with:
+.DS
+.ft CW
+auth_destroy(clnt->cl_auth);
+.DE
+This should be done in all cases, to conserve memory.
+.sp
+.IP "\fIThe Server Side\fP"
+.LP
+Service implementors have a harder time dealing with authentication issues
+since the RPC package passes the service dispatch routine a request
+that has an arbitrary authentication style associated with it.
+Consider the fields of a request handle passed to a service dispatch routine:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * An RPC Service request
+ */
+.ft CW
+struct svc_req {
+ u_long rq_prog; /* \fIservice program number\fP */
+ u_long rq_vers; /* \fIservice protocol vers num\fP */
+ u_long rq_proc; /* \fIdesired procedure number\fP */
+ struct opaque_auth rq_cred; /* \fIraw credentials from wire\fP */
+ caddr_t rq_clntcred; /* \fIcredentials (read only)\fP */
+};
+.DE
+The
+.I rq_cred
+is mostly opaque, except for one field of interest:
+the style or flavor of authentication credentials:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * Authentication info. Mostly opaque to the programmer.
+ */
+.ft CW
+struct opaque_auth {
+ enum_t oa_flavor; /* \fIstyle of credentials\fP */
+ caddr_t oa_base; /* \fIaddress of more auth stuff\fP */
+ u_int oa_length; /* \fInot to exceed \fIMAX_AUTH_BYTES */
+};
+.DE
+.IX RPC guarantees
+The RPC package guarantees the following
+to the service dispatch routine:
+.IP 1.
+That the request's
+.I rq_cred
+is well formed. Thus the service implementor may inspect the request's
+.I rq_cred.oa_flavor
+to determine which style of authentication the caller used.
+The service implementor may also wish to inspect the other fields of
+.I rq_cred
+if the style is not one of the styles supported by the RPC package.
+.IP 2.
+That the request's
+.I rq_clntcred
+field is either
+.I NULL
+or points to a well formed structure
+that corresponds to a supported style of authentication credentials.
+Remember that only
+.I unix
+style is currently supported, so (currently)
+.I rq_clntcred
+could be cast to a pointer to an
+.I authunix_parms
+structure. If
+.I rq_clntcred
+is
+.I NULL ,
+the service implementor may wish to inspect the other (opaque) fields of
+.I rq_cred
+in case the service knows about a new type of authentication
+that the RPC package does not know about.
+.LP
+Our remote users service example can be extended so that
+it computes results for all users except UID 16:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ struct authunix_parms *unix_cred;
+ int uid;
+ unsigned long nusers;
+
+.ft I
+ /*
+ * we don't care about authentication for null proc
+ */
+.ft CW
+ if (rqstp->rq_proc == NULLPROC) {
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+ }
+.ft I
+ /*
+ * now get the uid
+ */
+.ft CW
+ switch (rqstp->rq_cred.oa_flavor) {
+ case AUTH_UNIX:
+ unix_cred =
+ (struct authunix_parms *)rqstp->rq_clntcred;
+ uid = unix_cred->aup_uid;
+ break;
+ case AUTH_NULL:
+ default:
+ svcerr_weakauth(transp);
+ return;
+ }
+ switch (rqstp->rq_proc) {
+ case RUSERSPROC_NUM:
+.ft I
+ /*
+ * make sure caller is allowed to call this proc
+ */
+.ft CW
+ if (uid == 16) {
+ svcerr_systemerr(transp);
+ return;
+ }
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and assign it to the variable \fInusers\fP
+ */
+.ft CW
+ if (!svc_sendreply(transp, xdr_u_long, &nusers)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.vs
+.DE
+A few things should be noted here.
+First, it is customary not to check
+the authentication parameters associated with the
+.I NULLPROC
+(procedure number zero).
+Second, if the authentication parameter's type is not suitable
+for your service, you should call
+.I svcerr_weakauth() .
+And finally, the service protocol itself should return status
+for access denied; in the case of our example, the protocol
+does not have such a status, so we call the service primitive
+.I svcerr_systemerr()
+instead.
+.LP
+The last point underscores the relation between
+the RPC authentication package and the services;
+RPC deals only with
+.I authentication
+and not with individual services'
+.I "access control" .
+The services themselves must implement their own access control policies
+and reflect these policies as return statuses in their protocols.
+.NH 2
+\&DES Authentication
+.IX RPC DES
+.IX RPC authentication
+.LP
+UNIX authentication is quite easy to defeat. Instead of using
+.I authunix_create_default (),
+one can call
+.I authunix_create()
+and then modify the RPC authentication handle it returns by filling in
+whatever user ID and hostname they wish the server to think they have.
+DES authentication is thus recommended for people who want more security
+than UNIX authentication offers.
+.LP
+The details of the DES authentication protocol are complicated and
+are not explained here.
+See
+.I "Remote Procedure Calls: Protocol Specification"
+for the details.
+.LP
+In order for DES authentication to work, the
+.I keyserv(8c)
+daemon must be running on both the server and client machines. The
+users on these machines need public keys assigned by the network
+administrator in the
+.I publickey(5)
+database. And, they need to have decrypted their secret keys
+using their login password. This automatically happens when one
+logs in using
+.I login(1) ,
+or can be done manually using
+.I keylogin(1) .
+The
+.I "Network Services"
+chapter
+./" XXX
+explains more how to setup secure networking.
+.sp
+.IP "\fIClient Side\fP"
+.LP
+If a client wishes to use DES authentication, it must set its
+authentication handle appropriately. Here is an example:
+.DS
+cl->cl_auth =
+ authdes_create(servername, 60, &server_addr, NULL);
+.DE
+The first argument is the network name or \*Qnetname\*U of the owner of
+the server process. Typically, server processes are root processes
+and their netname can be derived using the following call:
+.DS
+char servername[MAXNETNAMELEN];
+
+host2netname(servername, rhostname, NULL);
+.DE
+Here,
+.I rhostname
+is the hostname of the machine the server process is running on.
+.I host2netname()
+fills in
+.I servername
+to contain this root process's netname. If the
+server process was run by a regular user, one could use the call
+.I user2netname()
+instead. Here is an example for a server process with the same user
+ID as the client:
+.DS
+char servername[MAXNETNAMELEN];
+
+user2netname(servername, getuid(), NULL);
+.DE
+The last argument to both of these calls,
+.I user2netname()
+and
+.I host2netname (),
+is the name of the naming domain where the server is located. The
+.I NULL
+used here means \*Quse the local domain name.\*U
+.LP
+The second argument to
+.I authdes_create()
+is a lifetime for the credential. Here it is set to sixty
+seconds. What that means is that the credential will expire 60
+seconds from now. If some mischievous user tries to reuse the
+credential, the server RPC subsystem will recognize that it has
+expired and not grant any requests. If the same mischievous user
+tries to reuse the credential within the sixty second lifetime,
+he will still be rejected because the server RPC subsystem
+remembers which credentials it has already seen in the near past,
+and will not grant requests to duplicates.
+.LP
+The third argument to
+.I authdes_create()
+is the address of the host to synchronize with. In order for DES
+authentication to work, the server and client must agree upon the
+time. Here we pass the address of the server itself, so the
+client and server will both be using the same time: the server's
+time. The argument can be
+.I NULL ,
+which means \*Qdon't bother synchronizing.\*U You should only do this
+if you are sure the client and server are already synchronized.
+.LP
+The final argument to
+.I authdes_create()
+is the address of a DES encryption key to use for encrypting
+timestamps and data. If this argument is
+.I NULL ,
+as it is in this example, a random key will be chosen. The client
+may find out the encryption key being used by consulting the
+.I ah_key
+field of the authentication handle.
+.sp
+.IP "\fIServer Side\fP"
+.LP
+The server side is a lot simpler than the client side. Here is the
+previous example rewritten to use
+.I AUTH_DES
+instead of
+.I AUTH_UNIX :
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <sys/time.h>
+#include <rpc/auth_des.h>
+ . . .
+ . . .
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ struct authdes_cred *des_cred;
+ int uid;
+ int gid;
+ int gidlen;
+ int gidlist[10];
+.ft I
+ /*
+ * we don't care about authentication for null proc
+ */
+.ft CW
+
+ if (rqstp->rq_proc == NULLPROC) {
+ /* \fIsame as before\fP */
+ }
+
+.ft I
+ /*
+ * now get the uid
+ */
+.ft CW
+ switch (rqstp->rq_cred.oa_flavor) {
+ case AUTH_DES:
+ des_cred =
+ (struct authdes_cred *) rqstp->rq_clntcred;
+ if (! netname2user(des_cred->adc_fullname.name,
+ &uid, &gid, &gidlen, gidlist))
+ {
+ fprintf(stderr, "unknown user: %s\n",
+ des_cred->adc_fullname.name);
+ svcerr_systemerr(transp);
+ return;
+ }
+ break;
+ case AUTH_NULL:
+ default:
+ svcerr_weakauth(transp);
+ return;
+ }
+
+.ft I
+ /*
+ * The rest is the same as before
+ */
+.ft CW
+.vs
+.DE
+Note the use of the routine
+.I netname2user (),
+the inverse of
+.I user2netname ():
+it takes a network ID and converts to a unix ID.
+.I netname2user ()
+also supplies the group IDs which we don't use in this example,
+but which may be useful to other UNIX programs.
+.NH 2
+\&Using Inetd
+.IX inetd "" "using \fIinetd\fP"
+.LP
+An RPC server can be started from
+.I inetd
+The only difference from the usual code is that the service
+creation routine should be called in the following form:
+.ie t .DS
+.el .DS L
+.ft CW
+transp = svcudp_create(0); /* \fIFor UDP\fP */
+transp = svctcp_create(0,0,0); /* \fIFor listener TCP sockets\fP */
+transp = svcfd_create(0,0,0); /* \fIFor connected TCP sockets\fP */
+.DE
+since
+.I inet
+passes a socket as file descriptor 0.
+Also,
+.I svc_register()
+should be called as
+.ie t .DS
+.el .DS L
+.ft CW
+svc_register(transp, PROGNUM, VERSNUM, service, 0);
+.DE
+with the final flag as 0,
+since the program would already be registered by
+.I inetd
+Remember that if you want to exit
+from the server process and return control to
+.I inet
+you need to explicitly exit, since
+.I svc_run()
+never returns.
+.LP
+The format of entries in
+.I /etc/inetd.conf
+for RPC services is in one of the following two forms:
+.ie t .DS
+.el .DS L
+.ft CW
+p_name/version dgram rpc/udp wait/nowait user server args
+p_name/version stream rpc/tcp wait/nowait user server args
+.DE
+where
+.I p_name
+is the symbolic name of the program as it appears in
+.I rpc(5) ,
+.I server
+is the program implementing the server,
+and
+.I program
+and
+.I version
+are the program and version numbers of the service.
+For more information, see
+.I inetd.conf(5) .
+.LP
+If the same program handles multiple versions,
+then the version number can be a range,
+as in this example:
+.ie t .DS
+.el .DS L
+.ft CW
+rstatd/1-2 dgram rpc/udp wait root /usr/etc/rpc.rstatd
+.DE
+.NH 1
+\&More Examples
+.sp 1
+.NH 2
+\&Versions
+.IX "versions"
+.IX "RPC" "versions"
+.LP
+By convention, the first version number of program
+.I PROG
+is
+.I PROGVERS_ORIG
+and the most recent version is
+.I PROGVERS
+Suppose there is a new version of the
+.I user
+program that returns an
+.I "unsigned short"
+rather than a
+.I long .
+If we name this version
+.I RUSERSVERS_SHORT
+then a server that wants to support both versions
+would do a double register.
+.ie t .DS
+.el .DS L
+.ft CW
+if (!svc_register(transp, RUSERSPROG, RUSERSVERS_ORIG,
+ nuser, IPPROTO_TCP)) {
+ fprintf(stderr, "can't register RUSER service\en");
+ exit(1);
+}
+if (!svc_register(transp, RUSERSPROG, RUSERSVERS_SHORT,
+ nuser, IPPROTO_TCP)) {
+ fprintf(stderr, "can't register RUSER service\en");
+ exit(1);
+}
+.DE
+Both versions can be handled by the same C procedure:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ unsigned long nusers;
+ unsigned short nusers2;
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+ case RUSERSPROC_NUM:
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and assign it to the variable \fInusers\fP
+ */
+.ft CW
+ nusers2 = nusers;
+ switch (rqstp->rq_vers) {
+ case RUSERSVERS_ORIG:
+ if (!svc_sendreply(transp, xdr_u_long,
+ &nusers)) {
+ fprintf(stderr,"can't reply to RPC call\en");
+ }
+ break;
+ case RUSERSVERS_SHORT:
+ if (!svc_sendreply(transp, xdr_u_short,
+ &nusers2)) {
+ fprintf(stderr,"can't reply to RPC call\en");
+ }
+ break;
+ }
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.vs
+.DE
+.KS
+.NH 2
+\&TCP
+.IX "TCP"
+.LP
+Here is an example that is essentially
+.I rcp.
+The initiator of the RPC
+.I snd
+call takes its standard input and sends it to the server
+.I rcv
+which prints it on standard output.
+The RPC call uses TCP.
+This also illustrates an XDR procedure that behaves differently
+on serialization than on deserialization.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * The xdr routine:
+ * on decode, read from wire, write onto fp
+ * on encode, read from fp, write onto wire
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+xdr_rcp(xdrs, fp)
+ XDR *xdrs;
+ FILE *fp;
+{
+ unsigned long size;
+ char buf[BUFSIZ], *p;
+
+ if (xdrs->x_op == XDR_FREE)/* nothing to free */
+ return 1;
+ while (1) {
+ if (xdrs->x_op == XDR_ENCODE) {
+ if ((size = fread(buf, sizeof(char), BUFSIZ,
+ fp)) == 0 && ferror(fp)) {
+ fprintf(stderr, "can't fread\en");
+ return (1);
+ }
+ }
+ p = buf;
+ if (!xdr_bytes(xdrs, &p, &size, BUFSIZ))
+ return 0;
+ if (size == 0)
+ return 1;
+ if (xdrs->x_op == XDR_DECODE) {
+ if (fwrite(buf, sizeof(char), size,
+ fp) != size) {
+ fprintf(stderr, "can't fwrite\en");
+ return (1);
+ }
+ }
+ }
+}
+.vs
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * The sender routines
+ */
+.ft CW
+#include <stdio.h>
+#include <netdb.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int xdr_rcp();
+ int err;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s servername\en", argv[0]);
+ exit(-1);
+ }
+ if ((err = callrpctcp(argv[1], RCPPROG, RCPPROC,
+ RCPVERS, xdr_rcp, stdin, xdr_void, 0) != 0)) {
+ clnt_perrno(err);
+ fprintf(stderr, "can't make RPC call\en");
+ exit(1);
+ }
+ exit(0);
+}
+
+callrpctcp(host, prognum, procnum, versnum,
+ inproc, in, outproc, out)
+ char *host, *in, *out;
+ xdrproc_t inproc, outproc;
+{
+ struct sockaddr_in server_addr;
+ int socket = RPC_ANYSOCK;
+ enum clnt_stat clnt_stat;
+ struct hostent *hp;
+ register CLIENT *client;
+ struct timeval total_timeout;
+
+ if ((hp = gethostbyname(host)) == NULL) {
+ fprintf(stderr, "can't get addr for '%s'\en", host);
+ return (-1);
+ }
+ bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
+ hp->h_length);
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = 0;
+ if ((client = clnttcp_create(&server_addr, prognum,
+ versnum, &socket, BUFSIZ, BUFSIZ)) == NULL) {
+ perror("rpctcp_create");
+ return (-1);
+ }
+ total_timeout.tv_sec = 20;
+ total_timeout.tv_usec = 0;
+ clnt_stat = clnt_call(client, procnum,
+ inproc, in, outproc, out, total_timeout);
+ clnt_destroy(client);
+ return (int)clnt_stat;
+}
+.vs
+.DE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * The receiving routines
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+main()
+{
+ register SVCXPRT *transp;
+ int rcp_service(), xdr_rcp();
+
+ if ((transp = svctcp_create(RPC_ANYSOCK,
+ BUFSIZ, BUFSIZ)) == NULL) {
+ fprintf("svctcp_create: error\en");
+ exit(1);
+ }
+ pmap_unset(RCPPROG, RCPVERS);
+ if (!svc_register(transp,
+ RCPPROG, RCPVERS, rcp_service, IPPROTO_TCP)) {
+ fprintf(stderr, "svc_register: error\en");
+ exit(1);
+ }
+ svc_run(); /* \fInever returns\fP */
+ fprintf(stderr, "svc_run should never return\en");
+}
+
+rcp_service(rqstp, transp)
+ register struct svc_req *rqstp;
+ register SVCXPRT *transp;
+{
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (svc_sendreply(transp, xdr_void, 0) == 0) {
+ fprintf(stderr, "err: rcp_service");
+ return (1);
+ }
+ return;
+ case RCPPROC_FP:
+ if (!svc_getargs(transp, xdr_rcp, stdout)) {
+ svcerr_decode(transp);
+ return;
+ }
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "can't reply\en");
+ return;
+ }
+ return (0);
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.vs
+.DE
+.NH 2
+\&Callback Procedures
+.IX RPC "callback procedures"
+.LP
+Occasionally, it is useful to have a server become a client,
+and make an RPC call back to the process which is its client.
+An example is remote debugging,
+where the client is a window system program,
+and the server is a debugger running on the remote machine.
+Most of the time,
+the user clicks a mouse button at the debugging window,
+which converts this to a debugger command,
+and then makes an RPC call to the server
+(where the debugger is actually running),
+telling it to execute that command.
+However, when the debugger hits a breakpoint, the roles are reversed,
+and the debugger wants to make an rpc call to the window program,
+so that it can inform the user that a breakpoint has been reached.
+.LP
+In order to do an RPC callback,
+you need a program number to make the RPC call on.
+Since this will be a dynamically generated program number,
+it should be in the transient range,
+.I "0x40000000 - 0x5fffffff" .
+The routine
+.I gettransient()
+returns a valid program number in the transient range,
+and registers it with the portmapper.
+It only talks to the portmapper running on the same machine as the
+.I gettransient()
+routine itself. The call to
+.I pmap_set()
+is a test and set operation,
+in that it indivisibly tests whether a program number
+has already been registered,
+and if it has not, then reserves it. On return, the
+.I sockp
+argument will contain a socket that can be used
+as the argument to an
+.I svcudp_create()
+or
+.I svctcp_create()
+call.
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+
+gettransient(proto, vers, sockp)
+ int proto, vers, *sockp;
+{
+ static int prognum = 0x40000000;
+ int s, len, socktype;
+ struct sockaddr_in addr;
+
+ switch(proto) {
+ case IPPROTO_UDP:
+ socktype = SOCK_DGRAM;
+ break;
+ case IPPROTO_TCP:
+ socktype = SOCK_STREAM;
+ break;
+ default:
+ fprintf(stderr, "unknown protocol type\en");
+ return 0;
+ }
+ if (*sockp == RPC_ANYSOCK) {
+ if ((s = socket(AF_INET, socktype, 0)) < 0) {
+ perror("socket");
+ return (0);
+ }
+ *sockp = s;
+ }
+ else
+ s = *sockp;
+ addr.sin_addr.s_addr = 0;
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ len = sizeof(addr);
+.ft I
+ /*
+ * may be already bound, so don't check for error
+ */
+.ft CW
+ bind(s, &addr, len);
+ if (getsockname(s, &addr, &len)< 0) {
+ perror("getsockname");
+ return (0);
+ }
+ while (!pmap_set(prognum++, vers, proto,
+ ntohs(addr.sin_port))) continue;
+ return (prognum-1);
+}
+.vs
+.DE
+.SH
+Note:
+.I
+The call to
+.I ntohs()
+is necessary to ensure that the port number in
+.I "addr.sin_port" ,
+which is in
+.I network
+byte order, is passed in
+.I host
+byte order (as
+.I pmap_set()
+expects). See the
+.I byteorder(3N)
+man page for more details on the conversion of network
+addresses from network to host byte order.
+.KS
+.LP
+The following pair of programs illustrate how to use the
+.I gettransient()
+routine.
+The client makes an RPC call to the server,
+passing it a transient program number.
+Then the client waits around to receive a callback
+from the server at that program number.
+The server registers the program
+.I EXAMPLEPROG
+so that it can receive the RPC call
+informing it of the callback program number.
+Then at some random time (on receiving an
+.I ALRM
+signal in this example), it sends a callback RPC call,
+using the program number it received earlier.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * client
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+int callback();
+char hostname[256];
+
+main()
+{
+ int x, ans, s;
+ SVCXPRT *xprt;
+
+ gethostname(hostname, sizeof(hostname));
+ s = RPC_ANYSOCK;
+ x = gettransient(IPPROTO_UDP, 1, &s);
+ fprintf(stderr, "client gets prognum %d\en", x);
+ if ((xprt = svcudp_create(s)) == NULL) {
+ fprintf(stderr, "rpc_server: svcudp_create\en");
+ exit(1);
+ }
+.ft I
+ /* protocol is 0 - gettransient does registering
+ */
+.ft CW
+ (void)svc_register(xprt, x, 1, callback, 0);
+ ans = callrpc(hostname, EXAMPLEPROG, EXAMPLEVERS,
+ EXAMPLEPROC_CALLBACK, xdr_int, &x, xdr_void, 0);
+ if ((enum clnt_stat) ans != RPC_SUCCESS) {
+ fprintf(stderr, "call: ");
+ clnt_perrno(ans);
+ fprintf(stderr, "\en");
+ }
+ svc_run();
+ fprintf(stderr, "Error: svc_run shouldn't return\en");
+}
+
+callback(rqstp, transp)
+ register struct svc_req *rqstp;
+ register SVCXPRT *transp;
+{
+ switch (rqstp->rq_proc) {
+ case 0:
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "err: exampleprog\en");
+ return (1);
+ }
+ return (0);
+ case 1:
+ if (!svc_getargs(transp, xdr_void, 0)) {
+ svcerr_decode(transp);
+ return (1);
+ }
+ fprintf(stderr, "client got callback\en");
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "err: exampleprog");
+ return (1);
+ }
+ }
+}
+.vs
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * server
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/signal.h>
+
+char *getnewprog();
+char hostname[256];
+int docallback();
+int pnum; /* \fIprogram number for callback routine\fP */
+
+main()
+{
+ gethostname(hostname, sizeof(hostname));
+ registerrpc(EXAMPLEPROG, EXAMPLEVERS,
+ EXAMPLEPROC_CALLBACK, getnewprog, xdr_int, xdr_void);
+ fprintf(stderr, "server going into svc_run\en");
+ signal(SIGALRM, docallback);
+ alarm(10);
+ svc_run();
+ fprintf(stderr, "Error: svc_run shouldn't return\en");
+}
+
+char *
+getnewprog(pnump)
+ char *pnump;
+{
+ pnum = *(int *)pnump;
+ return NULL;
+}
+
+docallback()
+{
+ int ans;
+
+ ans = callrpc(hostname, pnum, 1, 1, xdr_void, 0,
+ xdr_void, 0);
+ if (ans != 0) {
+ fprintf(stderr, "server: ");
+ clnt_perrno(ans);
+ fprintf(stderr, "\en");
+ }
+}
+.vs
+.DE
diff --git a/lib/libc/rpc/PSD.doc/rpc.rfc.ms b/lib/libc/rpc/PSD.doc/rpc.rfc.ms
new file mode 100644
index 0000000..af9c2df
--- /dev/null
+++ b/lib/libc/rpc/PSD.doc/rpc.rfc.ms
@@ -0,0 +1,1302 @@
+.\"
+.\" Must use -- tbl -- with this one
+.\"
+.\" @(#)rpc.rfc.ms 2.2 88/08/05 4.0 RPCSRC
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'Remote Procedure Calls: Protocol Specification''Page %'
+.EH 'Page %''Remote Procedure Calls: Protocol Specification'
+.if \\n%=1 .bp
+.SH
+\&Remote Procedure Calls: Protocol Specification
+.LP
+.NH 0
+\&Status of this Memo
+.LP
+Note: This chapter specifies a protocol that Sun Microsystems, Inc.,
+and others are using.
+It has been designated RFC1050 by the ARPA Network
+Information Center.
+.LP
+.NH 1
+\&Introduction
+.LP
+This chapter specifies a message protocol used in implementing
+Sun's Remote Procedure Call (RPC) package. (The message protocol is
+specified with the External Data Representation (XDR) language.
+See the
+.I "External Data Representation Standard: Protocol Specification"
+for the details. Here, we assume that the reader is familiar
+with XDR and do not attempt to justify it or its uses). The paper
+by Birrell and Nelson [1] is recommended as an excellent background
+to and justification of RPC.
+.NH 2
+\&Terminology
+.LP
+This chapter discusses servers, services, programs, procedures,
+clients, and versions. A server is a piece of software where network
+services are implemented. A network service is a collection of one
+or more remote programs. A remote program implements one or more
+remote procedures; the procedures, their parameters, and results are
+documented in the specific program's protocol specification (see the
+\fIPort Mapper Program Protocol\fP\, below, for an example). Network
+clients are pieces of software that initiate remote procedure calls
+to services. A server may support more than one version of a remote
+program in order to be forward compatible with changing protocols.
+.LP
+For example, a network file service may be composed of two programs.
+One program may deal with high-level applications such as file system
+access control and locking. The other may deal with low-level file
+IO and have procedures like "read" and "write". A client machine of
+the network file service would call the procedures associated with
+the two programs of the service on behalf of some user on the client
+machine.
+.NH 2
+\&The RPC Model
+.LP
+The remote procedure call model is similar to the local procedure
+call model. In the local case, the caller places arguments to a
+procedure in some well-specified location (such as a result
+register). It then transfers control to the procedure, and
+eventually gains back control. At that point, the results of the
+procedure are extracted from the well-specified location, and the
+caller continues execution.
+.LP
+The remote procedure call is similar, in that one thread of control
+logically winds through two processes\(emone is the caller's process,
+the other is a server's process. That is, the caller process sends a
+call message to the server process and waits (blocks) for a reply
+message. The call message contains the procedure's parameters, among
+other things. The reply message contains the procedure's results,
+among other things. Once the reply message is received, the results
+of the procedure are extracted, and caller's execution is resumed.
+.LP
+On the server side, a process is dormant awaiting the arrival of a
+call message. When one arrives, the server process extracts the
+procedure's parameters, computes the results, sends a reply message,
+and then awaits the next call message.
+.LP
+Note that in this model, only one of the two processes is active at
+any given time. However, this model is only given as an example.
+The RPC protocol makes no restrictions on the concurrency model
+implemented, and others are possible. For example, an implementation
+may choose to have RPC calls be asynchronous, so that the client may
+do useful work while waiting for the reply from the server. Another
+possibility is to have the server create a task to process an
+incoming request, so that the server can be free to receive other
+requests.
+.NH 2
+\&Transports and Semantics
+.LP
+The RPC protocol is independent of transport protocols. That is, RPC
+does not care how a message is passed from one process to another.
+The protocol deals only with specification and interpretation of
+messages.
+.LP
+It is important to point out that RPC does not try to implement any
+kind of reliability and that the application must be aware of the
+type of transport protocol underneath RPC. If it knows it is running
+on top of a reliable transport such as TCP/IP[6], then most of the
+work is already done for it. On the other hand, if it is running on
+top of an unreliable transport such as UDP/IP[7], it must implement
+is own retransmission and time-out policy as the RPC layer does not
+provide this service.
+.LP
+Because of transport independence, the RPC protocol does not attach
+specific semantics to the remote procedures or their execution.
+Semantics can be inferred from (but should be explicitly specified
+by) the underlying transport protocol. For example, consider RPC
+running on top of an unreliable transport such as UDP/IP. If an
+application retransmits RPC messages after short time-outs, the only
+thing it can infer if it receives no reply is that the procedure was
+executed zero or more times. If it does receive a reply, then it can
+infer that the procedure was executed at least once.
+.LP
+A server may wish to remember previously granted requests from a
+client and not regrant them in order to insure some degree of
+execute-at-most-once semantics. A server can do this by taking
+advantage of the transaction ID that is packaged with every RPC
+request. The main use of this transaction is by the client RPC layer
+in matching replies to requests. However, a client application may
+choose to reuse its previous transaction ID when retransmitting a
+request. The server application, knowing this fact, may choose to
+remember this ID after granting a request and not regrant requests
+with the same ID in order to achieve some degree of
+execute-at-most-once semantics. The server is not allowed to examine
+this ID in any other way except as a test for equality.
+.LP
+On the other hand, if using a reliable transport such as TCP/IP, the
+application can infer from a reply message that the procedure was
+executed exactly once, but if it receives no reply message, it cannot
+assume the remote procedure was not executed. Note that even if a
+connection-oriented protocol like TCP is used, an application still
+needs time-outs and reconnection to handle server crashes.
+.LP
+There are other possibilities for transports besides datagram- or
+connection-oriented protocols. For example, a request-reply protocol
+such as VMTP[2] is perhaps the most natural transport for RPC.
+.SH
+.I
+NOTE: At Sun, RPC is currently implemented on top of both TCP/IP
+and UDP/IP transports.
+.LP
+.NH 2
+\&Binding and Rendezvous Independence
+.LP
+The act of binding a client to a service is NOT part of the remote
+procedure call specification. This important and necessary function
+is left up to some higher-level software. (The software may use RPC
+itself\(emsee the \fIPort Mapper Program Protocol\fP\, below).
+.LP
+Implementors should think of the RPC protocol as the jump-subroutine
+instruction ("JSR") of a network; the loader (binder) makes JSR
+useful, and the loader itself uses JSR to accomplish its task.
+Likewise, the network makes RPC useful, using RPC to accomplish this
+task.
+.NH 2
+\&Authentication
+.LP
+The RPC protocol provides the fields necessary for a client to
+identify itself to a service and vice-versa. Security and access
+control mechanisms can be built on top of the message authentication.
+Several different authentication protocols can be supported. A field
+in the RPC header indicates which protocol is being used. More
+information on specific authentication protocols can be found in the
+\fIAuthentication Protocols\fP\,
+below.
+.KS
+.NH 1
+\&RPC Protocol Requirements
+.LP
+The RPC protocol must provide for the following:
+.IP 1.
+Unique specification of a procedure to be called.
+.IP 2.
+Provisions for matching response messages to request messages.
+.KE
+.IP 3.
+Provisions for authenticating the caller to service and vice-versa.
+.LP
+Besides these requirements, features that detect the following are
+worth supporting because of protocol roll-over errors, implementation
+bugs, user error, and network administration:
+.IP 1.
+RPC protocol mismatches.
+.IP 2.
+Remote program protocol version mismatches.
+.IP 3.
+Protocol errors (such as misspecification of a procedure's parameters).
+.IP 4.
+Reasons why remote authentication failed.
+.IP 5.
+Any other reasons why the desired procedure was not called.
+.NH 2
+\&Programs and Procedures
+.LP
+The RPC call message has three unsigned fields: remote program
+number, remote program version number, and remote procedure number.
+The three fields uniquely identify the procedure to be called.
+Program numbers are administered by some central authority (like
+Sun). Once an implementor has a program number, he can implement his
+remote program; the first implementation would most likely have the
+version number of 1. Because most new protocols evolve into better,
+stable, and mature protocols, a version field of the call message
+identifies which version of the protocol the caller is using.
+Version numbers make speaking old and new protocols through the same
+server process possible.
+.LP
+The procedure number identifies the procedure to be called. These
+numbers are documented in the specific program's protocol
+specification. For example, a file service's protocol specification
+may state that its procedure number 5 is "read" and procedure number
+12 is "write".
+.LP
+Just as remote program protocols may change over several versions,
+the actual RPC message protocol could also change. Therefore, the
+call message also has in it the RPC version number, which is always
+equal to two for the version of RPC described here.
+.LP
+The reply message to a request message has enough information to
+distinguish the following error conditions:
+.IP 1.
+The remote implementation of RPC does speak protocol version 2.
+The lowest and highest supported RPC version numbers are returned.
+.IP 2.
+The remote program is not available on the remote system.
+.IP 3.
+The remote program does not support the requested version number.
+The lowest and highest supported remote program version numbers are
+returned.
+.IP 4.
+The requested procedure number does not exist. (This is usually a
+caller side protocol or programming error.)
+.IP 5.
+The parameters to the remote procedure appear to be garbage from the
+server's point of view. (Again, this is usually caused by a
+disagreement about the protocol between client and service.)
+.NH 2
+\&Authentication
+.LP
+Provisions for authentication of caller to service and vice-versa are
+provided as a part of the RPC protocol. The call message has two
+authentication fields, the credentials and verifier. The reply
+message has one authentication field, the response verifier. The RPC
+protocol specification defines all three fields to be the following
+opaque type:
+.DS
+.ft CW
+.vs 11
+enum auth_flavor {
+ AUTH_NULL = 0,
+ AUTH_UNIX = 1,
+ AUTH_SHORT = 2,
+ AUTH_DES = 3
+ /* \fIand more to be defined\fP */
+};
+
+struct opaque_auth {
+ auth_flavor flavor;
+ opaque body<400>;
+};
+.DE
+.LP
+In simple English, any
+.I opaque_auth
+structure is an
+.I auth_flavor
+enumeration followed by bytes which are opaque to the RPC protocol
+implementation.
+.LP
+The interpretation and semantics of the data contained within the
+authentication fields is specified by individual, independent
+authentication protocol specifications. (See
+\fIAuthentication Protocols\fP\,
+below, for definitions of the various authentication protocols.)
+.LP
+If authentication parameters were rejected, the response message
+contains information stating why they were rejected.
+.NH 2
+\&Program Number Assignment
+.LP
+Program numbers are given out in groups of
+.I 0x20000000
+(decimal 536870912) according to the following chart:
+.TS
+box tab (&) ;
+lfI lfI
+rfL cfI .
+Program Numbers&Description
+_
+.sp .5
+0 - 1fffffff&Defined by Sun
+20000000 - 3fffffff&Defined by user
+40000000 - 5fffffff&Transient
+60000000 - 7fffffff&Reserved
+80000000 - 9fffffff&Reserved
+a0000000 - bfffffff&Reserved
+c0000000 - dfffffff&Reserved
+e0000000 - ffffffff&Reserved
+.TE
+.LP
+The first group is a range of numbers administered by Sun
+Microsystems and should be identical for all sites. The second range
+is for applications peculiar to a particular site. This range is
+intended primarily for debugging new programs. When a site develops
+an application that might be of general interest, that application
+should be given an assigned number in the first range. The third
+group is for applications that generate program numbers dynamically.
+The final groups are reserved for future use, and should not be used.
+.NH 2
+\&Other Uses of the RPC Protocol
+.LP
+The intended use of this protocol is for calling remote procedures.
+That is, each call message is matched with a response message.
+However, the protocol itself is a message-passing protocol with which
+other (non-RPC) protocols can be implemented. Sun currently uses, or
+perhaps abuses, the RPC message protocol for the following two
+(non-RPC) protocols: batching (or pipelining) and broadcast RPC.
+These two protocols are discussed but not defined below.
+.NH 3
+\&Batching
+.LP
+Batching allows a client to send an arbitrarily large sequence of
+call messages to a server; batching typically uses reliable byte
+stream protocols (like TCP/IP) for its transport. In the case of
+batching, the client never waits for a reply from the server, and the
+server does not send replies to batch requests. A sequence of batch
+calls is usually terminated by a legitimate RPC in order to flush the
+pipeline (with positive acknowledgement).
+.NH 3
+\&Broadcast RPC
+.LP
+In broadcast RPC-based protocols, the client sends a broadcast packet
+to the network and waits for numerous replies. Broadcast RPC uses
+unreliable, packet-based protocols (like UDP/IP) as its transports.
+Servers that support broadcast protocols only respond when the
+request is successfully processed, and are silent in the face of
+errors. Broadcast RPC uses the Port Mapper RPC service to achieve
+its semantics. See the \fIPort Mapper Program Protocol\fP\, below,
+for more information.
+.KS
+.NH 1
+\&The RPC Message Protocol
+.LP
+This section defines the RPC message protocol in the XDR data
+description language. The message is defined in a top-down style.
+.ie t .DS
+.el .DS L
+.ft CW
+enum msg_type {
+ CALL = 0,
+ REPLY = 1
+};
+
+.ft I
+/*
+* A reply to a call message can take on two forms:
+* The message was either accepted or rejected.
+*/
+.ft CW
+enum reply_stat {
+ MSG_ACCEPTED = 0,
+ MSG_DENIED = 1
+};
+
+.ft I
+/*
+* Given that a call message was accepted, the following is the
+* status of an attempt to call a remote procedure.
+*/
+.ft CW
+enum accept_stat {
+ SUCCESS = 0, /* \fIRPC executed successfully \fP*/
+ PROG_UNAVAIL = 1, /* \fIremote hasn't exported program \fP*/
+ PROG_MISMATCH = 2, /* \fIremote can't support version # \fP*/
+ PROC_UNAVAIL = 3, /* \fIprogram can't support procedure \fP*/
+ GARBAGE_ARGS = 4 /* \fIprocedure can't decode params \fP*/
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Reasons why a call message was rejected:
+*/
+.ft CW
+enum reject_stat {
+ RPC_MISMATCH = 0, /* \fIRPC version number != 2 \fP*/
+ AUTH_ERROR = 1 /* \fIremote can't authenticate caller \fP*/
+};
+
+.ft I
+/*
+* Why authentication failed:
+*/
+.ft CW
+enum auth_stat {
+ AUTH_BADCRED = 1, /* \fIbad credentials \fP*/
+ AUTH_REJECTEDCRED = 2, /* \fIclient must begin new session \fP*/
+ AUTH_BADVERF = 3, /* \fIbad verifier \fP*/
+ AUTH_REJECTEDVERF = 4, /* \fIverifier expired or replayed \fP*/
+ AUTH_TOOWEAK = 5 /* \fIrejected for security reasons \fP*/
+};
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* The RPC message:
+* All messages start with a transaction identifier, xid,
+* followed by a two-armed discriminated union. The union's
+* discriminant is a msg_type which switches to one of the two
+* types of the message. The xid of a \fIREPLY\fP message always
+* matches that of the initiating \fICALL\fP message. NB: The xid
+* field is only used for clients matching reply messages with
+* call messages or for servers detecting retransmissions; the
+* service side cannot treat this id as any type of sequence
+* number.
+*/
+.ft CW
+struct rpc_msg {
+ unsigned int xid;
+ union switch (msg_type mtype) {
+ case CALL:
+ call_body cbody;
+ case REPLY:
+ reply_body rbody;
+ } body;
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Body of an RPC request call:
+* In version 2 of the RPC protocol specification, rpcvers must
+* be equal to 2. The fields prog, vers, and proc specify the
+* remote program, its version number, and the procedure within
+* the remote program to be called. After these fields are two
+* authentication parameters: cred (authentication credentials)
+* and verf (authentication verifier). The two authentication
+* parameters are followed by the parameters to the remote
+* procedure, which are specified by the specific program
+* protocol.
+*/
+.ft CW
+struct call_body {
+ unsigned int rpcvers; /* \fImust be equal to two (2) \fP*/
+ unsigned int prog;
+ unsigned int vers;
+ unsigned int proc;
+ opaque_auth cred;
+ opaque_auth verf;
+ /* \fIprocedure specific parameters start here \fP*/
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Body of a reply to an RPC request:
+* The call message was either accepted or rejected.
+*/
+.ft CW
+union reply_body switch (reply_stat stat) {
+ case MSG_ACCEPTED:
+ accepted_reply areply;
+ case MSG_DENIED:
+ rejected_reply rreply;
+} reply;
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Reply to an RPC request that was accepted by the server:
+* there could be an error even though the request was accepted.
+* The first field is an authentication verifier that the server
+* generates in order to validate itself to the caller. It is
+* followed by a union whose discriminant is an enum
+* accept_stat. The \fISUCCESS\fP arm of the union is protocol
+* specific. The \fIPROG_UNAVAIL\fP, \fIPROC_UNAVAIL\fP, and \fIGARBAGE_ARGP\fP
+* arms of the union are void. The \fIPROG_MISMATCH\fP arm specifies
+* the lowest and highest version numbers of the remote program
+* supported by the server.
+*/
+.ft CW
+struct accepted_reply {
+ opaque_auth verf;
+ union switch (accept_stat stat) {
+ case SUCCESS:
+ opaque results[0];
+ /* \fIprocedure-specific results start here\fP */
+ case PROG_MISMATCH:
+ struct {
+ unsigned int low;
+ unsigned int high;
+ } mismatch_info;
+ default:
+.ft I
+ /*
+ * Void. Cases include \fIPROG_UNAVAIL, PROC_UNAVAIL\fP,
+ * and \fIGARBAGE_ARGS\fP.
+ */
+.ft CW
+ void;
+ } reply_data;
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Reply to an RPC request that was rejected by the server:
+* The request can be rejected for two reasons: either the
+* server is not running a compatible version of the RPC
+* protocol (\fIRPC_MISMATCH\fP), or the server refuses to
+* authenticate the caller (\fIAUTH_ERROR\fP). In case of an RPC
+* version mismatch, the server returns the lowest and highest
+* supported RPC version numbers. In case of refused
+* authentication, failure status is returned.
+*/
+.ft CW
+union rejected_reply switch (reject_stat stat) {
+ case RPC_MISMATCH:
+ struct {
+ unsigned int low;
+ unsigned int high;
+ } mismatch_info;
+ case AUTH_ERROR:
+ auth_stat stat;
+};
+.DE
+.NH 1
+\&Authentication Protocols
+.LP
+As previously stated, authentication parameters are opaque, but
+open-ended to the rest of the RPC protocol. This section defines
+some "flavors" of authentication implemented at (and supported by)
+Sun. Other sites are free to invent new authentication types, with
+the same rules of flavor number assignment as there is for program
+number assignment.
+.NH 2
+\&Null Authentication
+.LP
+Often calls must be made where the caller does not know who he is or
+the server does not care who the caller is. In this case, the flavor
+value (the discriminant of the \fIopaque_auth\fP's union) of the RPC
+message's credentials, verifier, and response verifier is
+.I AUTH_NULL .
+The bytes of the opaque_auth's body are undefined.
+It is recommended that the opaque length be zero.
+.NH 2
+\&UNIX Authentication
+.LP
+The caller of a remote procedure may wish to identify himself as he
+is identified on a UNIX system. The value of the credential's
+discriminant of an RPC call message is
+.I AUTH_UNIX .
+The bytes of
+the credential's opaque body encode the following structure:
+.DS
+.ft CW
+struct auth_unix {
+ unsigned int stamp;
+ string machinename<255>;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int gids<10>;
+};
+.DE
+The
+.I stamp
+is an arbitrary ID which the caller machine may
+generate. The
+.I machinename
+is the name of the caller's machine (like "krypton"). The
+.I uid
+is the caller's effective user ID. The
+.I gid
+is the caller's effective group ID. The
+.I gids
+is a
+counted array of groups which contain the caller as a member. The
+verifier accompanying the credentials should be of
+.I AUTH_NULL
+(defined above).
+.LP
+The value of the discriminant of the response verifier received in
+the reply message from the server may be
+.I AUTH_NULL
+or
+.I AUTH_SHORT .
+In the case of
+.I AUTH_SHORT ,
+the bytes of the response verifier's string encode an opaque
+structure. This new opaque structure may now be passed to the server
+instead of the original
+.I AUTH_UNIX
+flavor credentials. The server keeps a cache which maps shorthand
+opaque structures (passed back by way of an
+.I AUTH_SHORT
+style response verifier) to the original credentials of the caller.
+The caller can save network bandwidth and server cpu cycles by using
+the new credentials.
+.LP
+The server may flush the shorthand opaque structure at any time. If
+this happens, the remote procedure call message will be rejected due
+to an authentication error. The reason for the failure will be
+.I AUTH_REJECTEDCRED .
+At this point, the caller may wish to try the original
+.I AUTH_UNIX
+style of credentials.
+.KS
+.NH 2
+\&DES Authentication
+.LP
+UNIX authentication suffers from two major problems:
+.IP 1.
+The naming is too UNIX-system oriented.
+.IP 2.
+There is no verifier, so credentials can easily be faked.
+.LP
+DES authentication attempts to fix these two problems.
+.KE
+.NH 3
+\&Naming
+.LP
+The first problem is handled by addressing the caller by a simple
+string of characters instead of by an operating system specific
+integer. This string of characters is known as the "netname" or
+network name of the caller. The server is not allowed to interpret
+the contents of the caller's name in any other way except to
+identify the caller. Thus, netnames should be unique for every
+caller in the internet.
+.LP
+It is up to each operating system's implementation of DES
+authentication to generate netnames for its users that insure this
+uniqueness when they call upon remote servers. Operating systems
+already know how to distinguish users local to their systems. It is
+usually a simple matter to extend this mechanism to the network.
+For example, a UNIX user at Sun with a user ID of 515 might be
+assigned the following netname: "unix.515@sun.com". This netname
+contains three items that serve to insure it is unique. Going
+backwards, there is only one naming domain called "sun.com" in the
+internet. Within this domain, there is only one UNIX user with
+user ID 515. However, there may be another user on another
+operating system, for example VMS, within the same naming domain
+that, by coincidence, happens to have the same user ID. To insure
+that these two users can be distinguished we add the operating
+system name. So one user is "unix.515@sun.com" and the other is
+"vms.515@sun.com".
+.LP
+The first field is actually a naming method rather than an
+operating system name. It just happens that today there is almost
+a one-to-one correspondence between naming methods and operating
+systems. If the world could agree on a naming standard, the first
+field could be the name of that standard, instead of an operating
+system name.
+.LP
+.NH 3
+\&DES Authentication Verifiers
+.LP
+Unlike UNIX authentication, DES authentication does have a verifier
+so the server can validate the client's credential (and
+vice-versa). The contents of this verifier is primarily an
+encrypted timestamp. The server can decrypt this timestamp, and if
+it is close to what the real time is, then the client must have
+encrypted it correctly. The only way the client could encrypt it
+correctly is to know the "conversation key" of the RPC session. And
+if the client knows the conversation key, then it must be the real
+client.
+.LP
+The conversation key is a DES [5] key which the client generates
+and notifies the server of in its first RPC call. The conversation
+key is encrypted using a public key scheme in this first
+transaction. The particular public key scheme used in DES
+authentication is Diffie-Hellman [3] with 192-bit keys. The
+details of this encryption method are described later.
+.LP
+The client and the server need the same notion of the current time
+in order for all of this to work. If network time synchronization
+cannot be guaranteed, then client can synchronize with the server
+before beginning the conversation, perhaps by consulting the
+Internet Time Server (TIME[4]).
+.LP
+The way a server determines if a client timestamp is valid is
+somewhat complicated. For any other transaction but the first, the
+server just checks for two things:
+.IP 1.
+the timestamp is greater than the one previously seen from the
+same client.
+.IP 2.
+the timestamp has not expired.
+.LP
+A timestamp is expired if the server's time is later than the sum
+of the client's timestamp plus what is known as the client's
+"window". The "window" is a number the client passes (encrypted)
+to the server in its first transaction. You can think of it as a
+lifetime for the credential.
+.LP
+This explains everything but the first transaction. In the first
+transaction, the server checks only that the timestamp has not
+expired. If this was all that was done though, then it would be
+quite easy for the client to send random data in place of the
+timestamp with a fairly good chance of succeeding. As an added
+check, the client sends an encrypted item in the first transaction
+known as the "window verifier" which must be equal to the window
+minus 1, or the server will reject the credential.
+.LP
+The client too must check the verifier returned from the server to
+be sure it is legitimate. The server sends back to the client the
+encrypted timestamp it received from the client, minus one second.
+If the client gets anything different than this, it will reject it.
+.LP
+.NH 3
+\&Nicknames and Clock Synchronization
+.LP
+After the first transaction, the server's DES authentication
+subsystem returns in its verifier to the client an integer
+"nickname" which the client may use in its further transactions
+instead of passing its netname, encrypted DES key and window every
+time. The nickname is most likely an index into a table on the
+server which stores for each client its netname, decrypted DES key
+and window.
+.LP
+Though they originally were synchronized, the client's and server's
+clocks can get out of sync again. When this happens the client RPC
+subsystem most likely will get back
+.I RPC_AUTHERROR
+at which point it should resynchronize.
+.LP
+A client may still get the
+.I RPC_AUTHERROR
+error even though it is
+synchronized with the server. The reason is that the server's
+nickname table is a limited size, and it may flush entries whenever
+it wants. A client should resend its original credential in this
+case and the server will give it a new nickname. If a server
+crashes, the entire nickname table gets flushed, and all clients
+will have to resend their original credentials.
+.KS
+.NH 3
+\&DES Authentication Protocol (in XDR language)
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* There are two kinds of credentials: one in which the client uses
+* its full network name, and one in which it uses its "nickname"
+* (just an unsigned integer) given to it by the server. The
+* client must use its fullname in its first transaction with the
+* server, in which the server will return to the client its
+* nickname. The client may use its nickname in all further
+* transactions with the server. There is no requirement to use the
+* nickname, but it is wise to use it for performance reasons.
+*/
+.ft CW
+enum authdes_namekind {
+ ADN_FULLNAME = 0,
+ ADN_NICKNAME = 1
+};
+
+.ft I
+/*
+* A 64-bit block of encrypted DES data
+*/
+.ft CW
+typedef opaque des_block[8];
+
+.ft I
+/*
+* Maximum length of a network user's name
+*/
+.ft CW
+const MAXNETNAMELEN = 255;
+
+.ft I
+/*
+* A fullname contains the network name of the client, an encrypted
+* conversation key and the window. The window is actually a
+* lifetime for the credential. If the time indicated in the
+* verifier timestamp plus the window has past, then the server
+* should expire the request and not grant it. To insure that
+* requests are not replayed, the server should insist that
+* timestamps are greater than the previous one seen, unless it is
+* the first transaction. In the first transaction, the server
+* checks instead that the window verifier is one less than the
+* window.
+*/
+.ft CW
+struct authdes_fullname {
+string name<MAXNETNAMELEN>; /* \fIname of client \f(CW*/
+des_block key; /* \fIPK encrypted conversation key \f(CW*/
+unsigned int window; /* \fIencrypted window \f(CW*/
+};
+
+.ft I
+/*
+* A credential is either a fullname or a nickname
+*/
+.ft CW
+union authdes_cred switch (authdes_namekind adc_namekind) {
+ case ADN_FULLNAME:
+ authdes_fullname adc_fullname;
+ case ADN_NICKNAME:
+ unsigned int adc_nickname;
+};
+
+.ft I
+/*
+* A timestamp encodes the time since midnight, January 1, 1970.
+*/
+.ft CW
+struct timestamp {
+ unsigned int seconds; /* \fIseconds \fP*/
+ unsigned int useconds; /* \fIand microseconds \fP*/
+};
+
+.ft I
+/*
+* Verifier: client variety
+* The window verifier is only used in the first transaction. In
+* conjunction with a fullname credential, these items are packed
+* into the following structure before being encrypted:
+*
+* \f(CWstruct {\fP
+* \f(CWadv_timestamp; \fP-- one DES block
+* \f(CWadc_fullname.window; \fP-- one half DES block
+* \f(CWadv_winverf; \fP-- one half DES block
+* \f(CW}\fP
+* This structure is encrypted using CBC mode encryption with an
+* input vector of zero. All other encryptions of timestamps use
+* ECB mode encryption.
+*/
+.ft CW
+struct authdes_verf_clnt {
+ timestamp adv_timestamp; /* \fIencrypted timestamp \fP*/
+ unsigned int adv_winverf; /* \fIencrypted window verifier \fP*/
+};
+
+.ft I
+/*
+* Verifier: server variety
+* The server returns (encrypted) the same timestamp the client
+* gave it minus one second. It also tells the client its nickname
+* to be used in future transactions (unencrypted).
+*/
+.ft CW
+struct authdes_verf_svr {
+timestamp adv_timeverf; /* \fIencrypted verifier \fP*/
+unsigned int adv_nickname; /* \fInew nickname for client \fP*/
+};
+.DE
+.KE
+.NH 3
+\&Diffie-Hellman Encryption
+.LP
+In this scheme, there are two constants,
+.I BASE
+and
+.I MODULUS .
+The
+particular values Sun has chosen for these for the DES
+authentication protocol are:
+.ie t .DS
+.el .DS L
+.ft CW
+const BASE = 3;
+const MODULUS =
+ "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b"; /* \fIhex \fP*/
+.DE
+.ft R
+The way this scheme works is best explained by an example. Suppose
+there are two people "A" and "B" who want to send encrypted
+messages to each other. So, A and B both generate "secret" keys at
+random which they do not reveal to anyone. Let these keys be
+represented as SK(A) and SK(B). They also publish in a public
+directory their "public" keys. These keys are computed as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+PK(A) = ( BASE ** SK(A) ) mod MODULUS
+PK(B) = ( BASE ** SK(B) ) mod MODULUS
+.DE
+.ft R
+The "**" notation is used here to represent exponentiation. Now,
+both A and B can arrive at the "common" key between them,
+represented here as CK(A, B), without revealing their secret keys.
+.LP
+A computes:
+.ie t .DS
+.el .DS L
+.ft CW
+CK(A, B) = ( PK(B) ** SK(A)) mod MODULUS
+.DE
+.ft R
+while B computes:
+.ie t .DS
+.el .DS L
+.ft CW
+CK(A, B) = ( PK(A) ** SK(B)) mod MODULUS
+.DE
+.ft R
+These two can be shown to be equivalent:
+.ie t .DS
+.el .DS L
+.ft CW
+(PK(B) ** SK(A)) mod MODULUS = (PK(A) ** SK(B)) mod MODULUS
+.DE
+.ft R
+We drop the "mod MODULUS" parts and assume modulo arithmetic to
+simplify things:
+.ie t .DS
+.el .DS L
+.ft CW
+PK(B) ** SK(A) = PK(A) ** SK(B)
+.DE
+.ft R
+Then, replace PK(B) by what B computed earlier and likewise for
+PK(A).
+.ie t .DS
+.el .DS L
+.ft CW
+((BASE ** SK(B)) ** SK(A) = (BASE ** SK(A)) ** SK(B)
+.DE
+.ft R
+which leads to:
+.ie t .DS
+.el .DS L
+.ft CW
+BASE ** (SK(A) * SK(B)) = BASE ** (SK(A) * SK(B))
+.DE
+.ft R
+This common key CK(A, B) is not used to encrypt the timestamps used
+in the protocol. Rather, it is used only to encrypt a conversation
+key which is then used to encrypt the timestamps. The reason for
+doing this is to use the common key as little as possible, for fear
+that it could be broken. Breaking the conversation key is a far
+less serious offense, since conversations are relatively
+short-lived.
+.LP
+The conversation key is encrypted using 56-bit DES keys, yet the
+common key is 192 bits. To reduce the number of bits, 56 bits are
+selected from the common key as follows. The middle-most 8-bytes
+are selected from the common key, and then parity is added to the
+lower order bit of each byte, producing a 56-bit key with 8 bits of
+parity.
+.KS
+.NH 1
+\&Record Marking Standard
+.LP
+When RPC messages are passed on top of a byte stream protocol (like
+TCP/IP), it is necessary, or at least desirable, to delimit one
+message from another in order to detect and possibly recover from
+user protocol errors. This is called record marking (RM). Sun uses
+this RM/TCP/IP transport for passing RPC messages on TCP streams.
+One RPC message fits into one RM record.
+.LP
+A record is composed of one or more record fragments. A record
+fragment is a four-byte header followed by 0 to (2**31) - 1 bytes of
+fragment data. The bytes encode an unsigned binary number; as with
+XDR integers, the byte order is from highest to lowest. The number
+encodes two values\(ema boolean which indicates whether the fragment
+is the last fragment of the record (bit value 1 implies the fragment
+is the last fragment) and a 31-bit unsigned binary value which is the
+length in bytes of the fragment's data. The boolean value is the
+highest-order bit of the header; the length is the 31 low-order bits.
+(Note that this record specification is NOT in XDR standard form!)
+.KE
+.KS
+.NH 1
+\&The RPC Language
+.LP
+Just as there was a need to describe the XDR data-types in a formal
+language, there is also need to describe the procedures that operate
+on these XDR data-types in a formal language as well. We use the RPC
+Language for this purpose. It is an extension to the XDR language.
+The following example is used to describe the essence of the
+language.
+.NH 2
+\&An Example Service Described in the RPC Language
+.LP
+Here is an example of the specification of a simple ping program.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+* Simple ping program
+*/
+.ft CW
+program PING_PROG {
+ /* \fILatest and greatest version\fP */
+ version PING_VERS_PINGBACK {
+ void
+ PINGPROC_NULL(void) = 0;
+
+.ft I
+ /*
+ * Ping the caller, return the round-trip time
+ * (in microseconds). Returns -1 if the operation
+ * timed out.
+ */
+.ft CW
+ int
+ PINGPROC_PINGBACK(void) = 1;
+} = 2;
+
+.ft I
+/*
+* Original version
+*/
+.ft CW
+version PING_VERS_ORIG {
+ void
+ PINGPROC_NULL(void) = 0;
+ } = 1;
+} = 1;
+
+const PING_VERS = 2; /* \fIlatest version \fP*/
+.vs
+.DE
+.KE
+.LP
+The first version described is
+.I PING_VERS_PINGBACK
+with two procedures,
+.I PINGPROC_NULL
+and
+.I PINGPROC_PINGBACK .
+.I PINGPROC_NULL
+takes no arguments and returns no results, but it is useful for
+computing round-trip times from the client to the server and back
+again. By convention, procedure 0 of any RPC protocol should have
+the same semantics, and never require any kind of authentication.
+The second procedure is used for the client to have the server do a
+reverse ping operation back to the client, and it returns the amount
+of time (in microseconds) that the operation used. The next version,
+.I PING_VERS_ORIG ,
+is the original version of the protocol
+and it does not contain
+.I PINGPROC_PINGBACK
+procedure. It is useful
+for compatibility with old client programs, and as this program
+matures it may be dropped from the protocol entirely.
+.KS
+.NH 2
+\&The RPC Language Specification
+.LP
+The RPC language is identical to the XDR language, except for the
+added definition of a
+.I program-def
+described below.
+.DS
+.ft CW
+program-def:
+ "program" identifier "{"
+ version-def
+ version-def *
+ "}" "=" constant ";"
+
+version-def:
+ "version" identifier "{"
+ procedure-def
+ procedure-def *
+ "}" "=" constant ";"
+
+procedure-def:
+ type-specifier identifier "(" type-specifier ")"
+ "=" constant ";"
+.DE
+.KE
+.NH 2
+\&Syntax Notes
+.IP 1.
+The following keywords are added and cannot be used as
+identifiers: "program" and "version";
+.IP 2.
+A version name cannot occur more than once within the scope of
+a program definition. Nor can a version number occur more than once
+within the scope of a program definition.
+.IP 3.
+A procedure name cannot occur more than once within the scope
+of a version definition. Nor can a procedure number occur more than
+once within the scope of version definition.
+.IP 4.
+Program identifiers are in the same name space as constant and
+type identifiers.
+.IP 5.
+Only unsigned constants can be assigned to programs, versions
+and procedures.
+.NH 1
+\&Port Mapper Program Protocol
+.LP
+The port mapper program maps RPC program and version numbers to
+transport-specific port numbers. This program makes dynamic binding
+of remote programs possible.
+.LP
+This is desirable because the range of reserved port numbers is very
+small and the number of potential remote programs is very large. By
+running only the port mapper on a reserved port, the port numbers of
+other remote programs can be ascertained by querying the port mapper.
+.LP
+The port mapper also aids in broadcast RPC. A given RPC program will
+usually have different port number bindings on different machines, so
+there is no way to directly broadcast to all of these programs. The
+port mapper, however, does have a fixed port number. So, to
+broadcast to a given program, the client actually sends its message
+to the port mapper located at the broadcast address. Each port
+mapper that picks up the broadcast then calls the local service
+specified by the client. When the port mapper gets the reply from
+the local service, it sends the reply on back to the client.
+.KS
+.NH 2
+\&Port Mapper Protocol Specification (in RPC Language)
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+const PMAP_PORT = 111; /* \fIportmapper port number \fP*/
+
+.ft I
+/*
+* A mapping of (program, version, protocol) to port number
+*/
+.ft CW
+struct mapping {
+ unsigned int prog;
+ unsigned int vers;
+ unsigned int prot;
+ unsigned int port;
+};
+
+.ft I
+/*
+* Supported values for the "prot" field
+*/
+.ft CW
+const IPPROTO_TCP = 6; /* \fIprotocol number for TCP/IP \fP*/
+const IPPROTO_UDP = 17; /* \fIprotocol number for UDP/IP \fP*/
+
+.ft I
+/*
+* A list of mappings
+*/
+.ft CW
+struct *pmaplist {
+ mapping map;
+ pmaplist next;
+};
+.vs
+.DE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+* Arguments to callit
+*/
+.ft CW
+struct call_args {
+ unsigned int prog;
+ unsigned int vers;
+ unsigned int proc;
+ opaque args<>;
+};
+
+.ft I
+/*
+* Results of callit
+*/
+.ft CW
+struct call_result {
+ unsigned int port;
+ opaque res<>;
+};
+.vs
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+* Port mapper procedures
+*/
+.ft CW
+program PMAP_PROG {
+ version PMAP_VERS {
+ void
+ PMAPPROC_NULL(void) = 0;
+
+ bool
+ PMAPPROC_SET(mapping) = 1;
+
+ bool
+ PMAPPROC_UNSET(mapping) = 2;
+
+ unsigned int
+ PMAPPROC_GETPORT(mapping) = 3;
+
+ pmaplist
+ PMAPPROC_DUMP(void) = 4;
+
+ call_result
+ PMAPPROC_CALLIT(call_args) = 5;
+ } = 2;
+} = 100000;
+.vs
+.DE
+.NH 2
+\&Port Mapper Operation
+.LP
+The portmapper program currently supports two protocols (UDP/IP and
+TCP/IP). The portmapper is contacted by talking to it on assigned
+port number 111 (SUNRPC [8]) on either of these protocols. The
+following is a description of each of the portmapper procedures:
+.IP \fBPMAPPROC_NULL:\fP
+This procedure does no work. By convention, procedure zero of any
+protocol takes no parameters and returns no results.
+.IP \fBPMAPPROC_SET:\fP
+When a program first becomes available on a machine, it registers
+itself with the port mapper program on the same machine. The program
+passes its program number "prog", version number "vers", transport
+protocol number "prot", and the port "port" on which it awaits
+service request. The procedure returns a boolean response whose
+value is
+.I TRUE
+if the procedure successfully established the mapping and
+.I FALSE
+otherwise. The procedure refuses to establish
+a mapping if one already exists for the tuple "(prog, vers, prot)".
+.IP \fBPMAPPROC_UNSET:\fP
+When a program becomes unavailable, it should unregister itself with
+the port mapper program on the same machine. The parameters and
+results have meanings identical to those of
+.I PMAPPROC_SET .
+The protocol and port number fields of the argument are ignored.
+.IP \fBPMAPPROC_GETPORT:\fP
+Given a program number "prog", version number "vers", and transport
+protocol number "prot", this procedure returns the port number on
+which the program is awaiting call requests. A port value of zeros
+means the program has not been registered. The "port" field of the
+argument is ignored.
+.IP \fBPMAPPROC_DUMP:\fP
+This procedure enumerates all entries in the port mapper's database.
+The procedure takes no parameters and returns a list of program,
+version, protocol, and port values.
+.IP \fBPMAPPROC_CALLIT:\fP
+This procedure allows a caller to call another remote procedure on
+the same machine without knowing the remote procedure's port number.
+It is intended for supporting broadcasts to arbitrary remote programs
+via the well-known port mapper's port. The parameters "prog",
+"vers", "proc", and the bytes of "args" are the program number,
+version number, procedure number, and parameters of the remote
+procedure.
+.LP
+.B Note:
+.RS
+.IP 1.
+This procedure only sends a response if the procedure was
+successfully executed and is silent (no response) otherwise.
+.IP 2.
+The port mapper communicates with the remote program using UDP/IP
+only.
+.RE
+.LP
+The procedure returns the remote program's port number, and the bytes
+of results are the results of the remote procedure.
+.bp
+.NH 1
+\&References
+.LP
+[1] Birrell, Andrew D. & Nelson, Bruce Jay; "Implementing Remote
+Procedure Calls"; XEROX CSL-83-7, October 1983.
+.LP
+[2] Cheriton, D.; "VMTP: Versatile Message Transaction Protocol",
+Preliminary Version 0.3; Stanford University, January 1987.
+.LP
+[3] Diffie & Hellman; "New Directions in Cryptography"; IEEE
+Transactions on Information Theory IT-22, November 1976.
+.LP
+[4] Harrenstien, K.; "Time Server", RFC 738; Information Sciences
+Institute, October 1977.
+.LP
+[5] National Bureau of Standards; "Data Encryption Standard"; Federal
+Information Processing Standards Publication 46, January 1977.
+.LP
+[6] Postel, J.; "Transmission Control Protocol - DARPA Internet
+Program Protocol Specification", RFC 793; Information Sciences
+Institute, September 1981.
+.LP
+[7] Postel, J.; "User Datagram Protocol", RFC 768; Information Sciences
+Institute, August 1980.
+.LP
+[8] Reynolds, J. & Postel, J.; "Assigned Numbers", RFC 923; Information
+Sciences Institute, October 1984.
diff --git a/lib/libc/rpc/PSD.doc/rpcgen.ms b/lib/libc/rpc/PSD.doc/rpcgen.ms
new file mode 100644
index 0000000..b4e50e5
--- /dev/null
+++ b/lib/libc/rpc/PSD.doc/rpcgen.ms
@@ -0,0 +1,1299 @@
+.\"
+.\" Must use -- tbl -- for this one
+.\"
+.\" @(#)rpcgen.ms 2.2 88/08/04 4.0 RPCSRC
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH '\fBrpcgen\fP Programming Guide''Page %'
+.EH 'Page %''\fBrpcgen\fP Programming Guide'
+.if \\n%=1 .bp
+.SH
+\&\fBrpcgen\fP Programming Guide
+.NH 0
+\&The \fBrpcgen\fP Protocol Compiler
+.IX rpcgen "" \fIrpcgen\fP "" PAGE MAJOR
+.LP
+.IX RPC "" "" \fIrpcgen\fP
+The details of programming applications to use Remote Procedure Calls
+can be overwhelming. Perhaps most daunting is the writing of the XDR
+routines necessary to convert procedure arguments and results into
+their network format and vice-versa.
+.LP
+Fortunately,
+.I rpcgen(1)
+exists to help programmers write RPC applications simply and directly.
+.I rpcgen
+does most of the dirty work, allowing programmers to debug
+the main features of their application, instead of requiring them to
+spend most of their time debugging their network interface code.
+.LP
+.I rpcgen
+is a compiler. It accepts a remote program interface definition written
+in a language, called RPC Language, which is similar to C. It produces a C
+language output which includes stub versions of the client routines, a
+server skeleton, XDR filter routines for both parameters and results, and a
+header file that contains common definitions. The client stubs interface
+with the RPC library and effectively hide the network from their callers.
+The server stub similarly hides the network from the server procedures that
+are to be invoked by remote clients.
+.I rpcgen 's
+output files can be compiled and linked in the usual way. The developer
+writes server procedures\(emin any language that observes Sun calling
+conventions\(emand links them with the server skeleton produced by
+.I rpcgen
+to get an executable server program. To use a remote program, a programmer
+writes an ordinary main program that makes local procedure calls to the
+client stubs produced by
+.I rpcgen .
+Linking this program with
+.I rpcgen 's
+stubs creates an executable program. (At present the main program must be
+written in C).
+.I rpcgen
+options can be used to suppress stub generation and to specify the transport
+to be used by the server stub.
+.LP
+Like all compilers,
+.I rpcgen
+reduces development time
+that would otherwise be spent coding and debugging low-level routines.
+All compilers, including
+.I rpcgen ,
+do this at a small cost in efficiency
+and flexibility. However, many compilers allow escape hatches for
+programmers to mix low-level code with high-level code.
+.I rpcgen
+is no exception. In speed-critical applications, hand-written routines
+can be linked with the
+.I rpcgen
+output without any difficulty. Also, one may proceed by using
+.I rpcgen
+output as a starting point, and then rewriting it as necessary.
+(If you need a discussion of RPC programming without
+.I rpcgen ,
+see the
+.I "Remote Procedure Call Programming Guide)\.
+.NH 1
+\&Converting Local Procedures into Remote Procedures
+.IX rpcgen "local procedures" \fIrpcgen\fP
+.IX rpcgen "remote procedures" \fIrpcgen\fP
+.LP
+Assume an application that runs on a single machine, one which we want
+to convert to run over the network. Here we will demonstrate such a
+conversion by way of a simple example\(ema program that prints a
+message to the console:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * printmsg.c: print a message on the console
+ */
+.ft CW
+#include <stdio.h>
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *message;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <message>\en", argv[0]);
+ exit(1);
+ }
+ message = argv[1];
+
+ if (!printmessage(message)) {
+ fprintf(stderr, "%s: couldn't print your message\en",
+ argv[0]);
+ exit(1);
+ }
+ printf("Message Delivered!\en");
+ exit(0);
+}
+.ft I
+/*
+ * Print a message to the console.
+ * Return a boolean indicating whether the message was actually printed.
+ */
+.ft CW
+printmessage(msg)
+ char *msg;
+{
+ FILE *f;
+
+ f = fopen("/dev/console", "w");
+ if (f == NULL) {
+ return (0);
+ }
+ fprintf(f, "%s\en", msg);
+ fclose(f);
+ return(1);
+}
+.DE
+.LP
+And then, of course:
+.ie t .DS
+.el .DS L
+.ft CW
+example% \fBcc printmsg.c -o printmsg\fP
+example% \fBprintmsg "Hello, there."\fP
+Message delivered!
+example%
+.DE
+.LP
+If
+.I printmessage()
+was turned into a remote procedure,
+then it could be called from anywhere in the network.
+Ideally, one would just like to stick a keyword like
+.I remote
+in front of a
+procedure to turn it into a remote procedure. Unfortunately,
+we have to live within the constraints of the C language, since
+it existed long before RPC did. But even without language
+support, it's not very difficult to make a procedure remote.
+.LP
+In general, it's necessary to figure out what the types are for
+all procedure inputs and outputs. In this case, we have a
+procedure
+.I printmessage()
+which takes a string as input, and returns an integer
+as output. Knowing this, we can write a protocol specification in RPC
+language that describes the remote version of
+.I printmessage ().
+Here it is:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * msg.x: Remote message printing protocol
+ */
+.ft CW
+
+program MESSAGEPROG {
+ version MESSAGEVERS {
+ int PRINTMESSAGE(string) = 1;
+ } = 1;
+} = 99;
+.DE
+.LP
+Remote procedures are part of remote programs, so we actually declared
+an entire remote program here which contains the single procedure
+.I PRINTMESSAGE .
+This procedure was declared to be in version 1 of the
+remote program. No null procedure (procedure 0) is necessary because
+.I rpcgen
+generates it automatically.
+.LP
+Notice that everything is declared with all capital letters. This is
+not required, but is a good convention to follow.
+.LP
+Notice also that the argument type is \*Qstring\*U and not \*Qchar *\*U. This
+is because a \*Qchar *\*U in C is ambiguous. Programmers usually intend it
+to mean a null-terminated string of characters, but it could also
+represent a pointer to a single character or a pointer to an array of
+characters. In RPC language, a null-terminated string is
+unambiguously called a \*Qstring\*U.
+.LP
+There are just two more things to write. First, there is the remote
+procedure itself. Here's the definition of a remote procedure
+to implement the
+.I PRINTMESSAGE
+procedure we declared above:
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * msg_proc.c: implementation of the remote procedure "printmessage"
+ */
+.ft CW
+
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIalways needed\fP */
+#include "msg.h" /* \fIneed this too: msg.h will be generated by rpcgen\fP */
+
+.ft I
+/*
+ * Remote verson of "printmessage"
+ */
+.ft CW
+int *
+printmessage_1(msg)
+ char **msg;
+{
+ static int result; /* \fImust be static!\fP */
+ FILE *f;
+
+ f = fopen("/dev/console", "w");
+ if (f == NULL) {
+ result = 0;
+ return (&result);
+ }
+ fprintf(f, "%s\en", *msg);
+ fclose(f);
+ result = 1;
+ return (&result);
+}
+.vs
+.DE
+.LP
+Notice here that the declaration of the remote procedure
+.I printmessage_1()
+differs from that of the local procedure
+.I printmessage()
+in three ways:
+.IP 1.
+It takes a pointer to a string instead of a string itself. This
+is true of all remote procedures: they always take pointers to their
+arguments rather than the arguments themselves.
+.IP 2.
+It returns a pointer to an integer instead of an integer itself. This is
+also generally true of remote procedures: they always return a pointer
+to their results.
+.IP 3.
+It has an \*Q_1\*U appended to its name. In general, all remote
+procedures called by
+.I rpcgen
+are named by the following rule: the name in the program definition
+(here
+.I PRINTMESSAGE )
+is converted to all
+lower-case letters, an underbar (\*Q_\*U) is appended to it, and
+finally the version number (here 1) is appended.
+.LP
+The last thing to do is declare the main client program that will call
+the remote procedure. Here it is:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * rprintmsg.c: remote version of "printmsg.c"
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIalways needed\fP */
+#include "msg.h" /* \fIneed this too: msg.h will be generated by rpcgen\fP */
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ CLIENT *cl;
+ int *result;
+ char *server;
+ char *message;
+
+ if (argc < 3) {
+ fprintf(stderr, "usage: %s host message\en", argv[0]);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Save values of command line arguments
+ */
+.ft CW
+ server = argv[1];
+ message = argv[2];
+
+.ft I
+ /*
+ * Create client "handle" used for calling \fIMESSAGEPROG\fP on the
+ * server designated on the command line. We tell the RPC package
+ * to use the "tcp" protocol when contacting the server.
+ */
+.ft CW
+ cl = clnt_create(server, MESSAGEPROG, MESSAGEVERS, "tcp");
+ if (cl == NULL) {
+.ft I
+ /*
+ * Couldn't establish connection with server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_pcreateerror(server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Call the remote procedure "printmessage" on the server
+ */
+.ft CW
+ result = printmessage_1(&message, cl);
+ if (result == NULL) {
+.ft I
+ /*
+ * An error occurred while calling the server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_perror(cl, server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Okay, we successfully called the remote procedure.
+ */
+.ft CW
+ if (*result == 0) {
+.ft I
+ /*
+ * Server was unable to print our message.
+ * Print error message and die.
+ */
+.ft CW
+ fprintf(stderr, "%s: %s couldn't print your message\en",
+ argv[0], server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * The message got printed on the server's console
+ */
+.ft CW
+ printf("Message delivered to %s!\en", server);
+}
+.DE
+There are two things to note here:
+.IP 1.
+.IX "client handle, used by rpcgen" "" "client handle, used by \fIrpcgen\fP"
+First a client \*Qhandle\*U is created using the RPC library routine
+.I clnt_create ().
+This client handle will be passed to the stub routines
+which call the remote procedure.
+.IP 2.
+The remote procedure
+.I printmessage_1()
+is called exactly the same way as it is declared in
+.I msg_proc.c
+except for the inserted client handle as the first argument.
+.LP
+Here's how to put all of the pieces together:
+.ie t .DS
+.el .DS L
+.ft CW
+example% \fBrpcgen msg.x\fP
+example% \fBcc rprintmsg.c msg_clnt.c -o rprintmsg\fP
+example% \fBcc msg_proc.c msg_svc.c -o msg_server\fP
+.DE
+Two programs were compiled here: the client program
+.I rprintmsg
+and the server program
+.I msg_server .
+Before doing this though,
+.I rpcgen
+was used to fill in the missing pieces.
+.LP
+Here is what
+.I rpcgen
+did with the input file
+.I msg.x :
+.IP 1.
+It created a header file called
+.I msg.h
+that contained
+.I #define 's
+for
+.I MESSAGEPROG ,
+.I MESSAGEVERS
+and
+.I PRINTMESSAGE
+for use in the other modules.
+.IP 2.
+It created client \*Qstub\*U routines in the
+.I msg_clnt.c
+file. In this case there is only one, the
+.I printmessage_1()
+that was referred to from the
+.I printmsg
+client program. The name of the output file for
+client stub routines is always formed in this way: if the name of the
+input file is
+.I FOO.x ,
+the client stubs output file is called
+.I FOO_clnt.c .
+.IP 3.
+It created the server program which calls
+.I printmessage_1()
+in
+.I msg_proc.c .
+This server program is named
+.I msg_svc.c .
+The rule for naming the server output file is similar to the
+previous one: for an input file called
+.I FOO.x ,
+the output server file is named
+.I FOO_svc.c .
+.LP
+Now we're ready to have some fun. First, copy the server to a
+remote machine and run it. For this example, the
+machine is called \*Qmoon\*U. Server processes are run in the
+background, because they never exit.
+.ie t .DS
+.el .DS L
+.ft CW
+moon% \fBmsg_server &\fP
+.DE
+Then on our local machine (\*Qsun\*U) we can print a message on \*Qmoon\*Us
+console.
+.ie t .DS
+.el .DS L
+.ft CW
+sun% \fBprintmsg moon "Hello, moon."\fP
+.DE
+The message will get printed to \*Qmoon\*Us console. You can print a
+message on anybody's console (including your own) with this program if
+you are able to copy the server to their machine and run it.
+.NH 1
+\&Generating XDR Routines
+.IX RPC "generating XDR routines"
+.LP
+The previous example only demonstrated the automatic generation of
+client and server RPC code.
+.I rpcgen
+may also be used to generate XDR routines, that is, the routines
+necessary to convert local data
+structures into network format and vice-versa. This example presents
+a complete RPC service\(ema remote directory listing service, which uses
+.I rpcgen
+not only to generate stub routines, but also to generate the XDR
+routines. Here is the protocol description file:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * dir.x: Remote directory listing protocol
+ */
+.ft CW
+const MAXNAMELEN = 255; /* \fImaximum length of a directory entry\fP */
+
+typedef string nametype<MAXNAMELEN>; /* \fIa directory entry\fP */
+
+typedef struct namenode *namelist; /* \fIa link in the listing\fP */
+
+.ft I
+/*
+ * A node in the directory listing
+ */
+.ft CW
+struct namenode {
+ nametype name; /* \fIname of directory entry\fP */
+ namelist next; /* \fInext entry\fP */
+};
+
+.ft I
+/*
+ * The result of a READDIR operation.
+ */
+.ft CW
+union readdir_res switch (int errno) {
+case 0:
+ namelist list; /* \fIno error: return directory listing\fP */
+default:
+ void; /* \fIerror occurred: nothing else to return\fP */
+};
+
+.ft I
+/*
+ * The directory program definition
+ */
+.ft CW
+program DIRPROG {
+ version DIRVERS {
+ readdir_res
+ READDIR(nametype) = 1;
+ } = 1;
+} = 76;
+.DE
+.SH
+Note:
+.I
+Types (like
+.I readdir_res
+in the example above) can be defined using
+the \*Qstruct\*U, \*Qunion\*U and \*Qenum\*U keywords, but those keywords
+should not be used in subsequent declarations of variables of those types.
+For example, if you define a union \*Qfoo\*U, you should declare using
+only \*Qfoo\*U and not \*Qunion foo\*U. In fact,
+.I rpcgen
+compiles
+RPC unions into C structures and it is an error to declare them using the
+\*Qunion\*U keyword.
+.LP
+Running
+.I rpcgen
+on
+.I dir.x
+creates four output files. Three are the same as before: header file,
+client stub routines and server skeleton. The fourth are the XDR routines
+necessary for converting the data types we declared into XDR format and
+vice-versa. These are output in the file
+.I dir_xdr.c .
+.LP
+Here is the implementation of the
+.I READDIR
+procedure.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * dir_proc.c: remote readdir implementation
+ */
+.ft CW
+#include <rpc/rpc.h>
+#include <sys/dir.h>
+#include "dir.h"
+
+extern int errno;
+extern char *malloc();
+extern char *strdup();
+
+readdir_res *
+readdir_1(dirname)
+ nametype *dirname;
+{
+ DIR *dirp;
+ struct direct *d;
+ namelist nl;
+ namelist *nlp;
+ static readdir_res res; /* \fImust be static\fP! */
+
+.ft I
+ /*
+ * Open directory
+ */
+.ft CW
+ dirp = opendir(*dirname);
+ if (dirp == NULL) {
+ res.errno = errno;
+ return (&res);
+ }
+
+.ft I
+ /*
+ * Free previous result
+ */
+.ft CW
+ xdr_free(xdr_readdir_res, &res);
+
+.ft I
+ /*
+ * Collect directory entries.
+ * Memory allocated here will be freed by \fIxdr_free\fP
+ * next time \fIreaddir_1\fP is called
+ */
+.ft CW
+ nlp = &res.readdir_res_u.list;
+ while (d = readdir(dirp)) {
+ nl = *nlp = (namenode *) malloc(sizeof(namenode));
+ nl->name = strdup(d->d_name);
+ nlp = &nl->next;
+ }
+ *nlp = NULL;
+
+.ft I
+ /*
+ * Return the result
+ */
+.ft CW
+ res.errno = 0;
+ closedir(dirp);
+ return (&res);
+}
+.vs
+.DE
+Finally, there is the client side program to call the server:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * rls.c: Remote directory listing client
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIalways need this\fP */
+#include "dir.h" /* \fIwill be generated by rpcgen\fI */
+
+extern int errno;
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ CLIENT *cl;
+ char *server;
+ char *dir;
+ readdir_res *result;
+ namelist nl;
+
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s host directory\en",
+ argv[0]);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Remember what our command line arguments refer to
+ */
+.ft CW
+ server = argv[1];
+ dir = argv[2];
+
+.ft I
+ /*
+ * Create client "handle" used for calling \fIMESSAGEPROG\fP on the
+ * server designated on the command line. We tell the RPC package
+ * to use the "tcp" protocol when contacting the server.
+ */
+.ft CW
+ cl = clnt_create(server, DIRPROG, DIRVERS, "tcp");
+ if (cl == NULL) {
+.ft I
+ /*
+ * Couldn't establish connection with server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_pcreateerror(server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Call the remote procedure \fIreaddir\fP on the server
+ */
+.ft CW
+ result = readdir_1(&dir, cl);
+ if (result == NULL) {
+.ft I
+ /*
+ * An error occurred while calling the server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_perror(cl, server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Okay, we successfully called the remote procedure.
+ */
+.ft CW
+ if (result->errno != 0) {
+.ft I
+ /*
+ * A remote system error occurred.
+ * Print error message and die.
+ */
+.ft CW
+ errno = result->errno;
+ perror(dir);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Successfully got a directory listing.
+ * Print it out.
+ */
+.ft CW
+ for (nl = result->readdir_res_u.list; nl != NULL;
+ nl = nl->next) {
+ printf("%s\en", nl->name);
+ }
+ exit(0);
+}
+.DE
+Compile everything, and run.
+.DS
+.ft CW
+sun% \fBrpcgen dir.x\fP
+sun% \fBcc rls.c dir_clnt.c dir_xdr.c -o rls\fP
+sun% \fBcc dir_svc.c dir_proc.c dir_xdr.c -o dir_svc\fP
+
+sun% \fBdir_svc &\fP
+
+moon% \fBrls sun /usr/pub\fP
+\&.
+\&..
+ascii
+eqnchar
+greek
+kbd
+marg8
+tabclr
+tabs
+tabs4
+moon%
+.DE
+.LP
+.IX "debugging with rpcgen" "" "debugging with \fIrpcgen\fP"
+A final note about
+.I rpcgen :
+The client program and the server procedure can be tested together
+as a single program by simply linking them with each other rather
+than with the client and server stubs. The procedure calls will be
+executed as ordinary local procedure calls and the program can be
+debugged with a local debugger such as
+.I dbx .
+When the program is working, the client program can be linked to
+the client stub produced by
+.I rpcgen
+and the server procedures can be linked to the server stub produced
+by
+.I rpcgen .
+.SH
+.I NOTE :
+\fIIf you do this, you may want to comment out calls to RPC library
+routines, and have client-side routines call server routines
+directly.\fP
+.LP
+.NH 1
+\&The C-Preprocessor
+.IX rpcgen "C-preprocessor" \fIrpcgen\fP
+.LP
+The C-preprocessor is run on all input files before they are
+compiled, so all the preprocessor directives are legal within a \*Q.x\*U
+file. Four symbols may be defined, depending upon which output file is
+getting generated. The symbols are:
+.TS
+box tab (&);
+lfI lfI
+lfL l .
+Symbol&Usage
+_
+RPC_HDR&for header-file output
+RPC_XDR&for XDR routine output
+RPC_SVC&for server-skeleton output
+RPC_CLNT&for client stub output
+.TE
+.LP
+Also,
+.I rpcgen
+does a little preprocessing of its own. Any line that
+begins with a percent sign is passed directly into the output file,
+without any interpretation of the line. Here is a simple example that
+demonstrates the preprocessing features.
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * time.x: Remote time protocol
+ */
+.ft CW
+program TIMEPROG {
+ version TIMEVERS {
+ unsigned int TIMEGET(void) = 1;
+ } = 1;
+} = 44;
+
+#ifdef RPC_SVC
+%int *
+%timeget_1()
+%{
+% static int thetime;
+%
+% thetime = time(0);
+% return (&thetime);
+%}
+#endif
+.DE
+The '%' feature is not generally recommended, as there is no guarantee
+that the compiler will stick the output where you intended.
+.NH 1
+\&\fBrpcgen\fP Programming Notes
+.IX rpcgen "other operations" \fIrpcgen\fP
+.sp
+.NH 2
+\&Timeout Changes
+.IX rpcgen "timeout changes" \fIrpcgen\fP
+.LP
+RPC sets a default timeout of 25 seconds for RPC calls when
+.I clnt_create()
+is used. This timeout may be changed using
+.I clnt_control()
+Here is a small code fragment to demonstrate use of
+.I clnt_control ():
+.ID
+struct timeval tv;
+CLIENT *cl;
+.sp .5
+cl = clnt_create("somehost", SOMEPROG, SOMEVERS, "tcp");
+if (cl == NULL) {
+ exit(1);
+}
+tv.tv_sec = 60; /* \fIchange timeout to 1 minute\fP */
+tv.tv_usec = 0;
+clnt_control(cl, CLSET_TIMEOUT, &tv);
+.DE
+.NH 2
+\&Handling Broadcast on the Server Side
+.IX "broadcast RPC"
+.IX rpcgen "broadcast RPC" \fIrpcgen\fP
+.LP
+When a procedure is known to be called via broadcast RPC,
+it is usually wise for the server to not reply unless it can provide
+some useful information to the client. This prevents the network
+from getting flooded by useless replies.
+.LP
+To prevent the server from replying, a remote procedure can
+return NULL as its result, and the server code generated by
+.I rpcgen
+will detect this and not send out a reply.
+.LP
+Here is an example of a procedure that replies only if it
+thinks it is an NFS server:
+.ID
+void *
+reply_if_nfsserver()
+{
+ char notnull; /* \fIjust here so we can use its address\fP */
+.sp .5
+ if (access("/etc/exports", F_OK) < 0) {
+ return (NULL); /* \fIprevent RPC from replying\fP */
+ }
+.ft I
+ /*
+ * return non-null pointer so RPC will send out a reply
+ */
+.ft L
+ return ((void *)&notnull);
+}
+.DE
+Note that if procedure returns type \*Qvoid *\*U, they must return a non-NULL
+pointer if they want RPC to reply for them.
+.NH 2
+\&Other Information Passed to Server Procedures
+.LP
+Server procedures will often want to know more about an RPC call
+than just its arguments. For example, getting authentication information
+is important to procedures that want to implement some level of security.
+This extra information is actually supplied to the server procedure as a
+second argument. Here is an example to demonstrate its use. What we've
+done here is rewrite the previous
+.I printmessage_1()
+procedure to only allow root users to print a message to the console.
+.ID
+int *
+printmessage_1(msg, rq)
+ char **msg;
+ struct svc_req *rq;
+{
+ static in result; /* \fIMust be static\fP */
+ FILE *f;
+ struct suthunix_parms *aup;
+.sp .5
+ aup = (struct authunix_parms *)rq->rq_clntcred;
+ if (aup->aup_uid != 0) {
+ result = 0;
+ return (&result);
+ }
+.sp
+.ft I
+ /*
+ * Same code as before.
+ */
+.ft L
+}
+.DE
+.NH 1
+\&RPC Language
+.IX RPCL
+.IX rpcgen "RPC Language" \fIrpcgen\fP
+.LP
+RPC language is an extension of XDR language. The sole extension is
+the addition of the
+.I program
+type. For a complete description of the XDR language syntax, see the
+.I "External Data Representation Standard: Protocol Specification"
+chapter. For a description of the RPC extensions to the XDR language,
+see the
+.I "Remote Procedure Calls: Protocol Specification"
+chapter.
+.LP
+However, XDR language is so close to C that if you know C, you know most
+of it already. We describe here the syntax of the RPC language,
+showing a few examples along the way. We also show how the various
+RPC and XDR type definitions get compiled into C type definitions in
+the output header file.
+.KS
+.NH 2
+Definitions
+\&
+.IX rpcgen definitions \fIrpcgen\fP
+.LP
+An RPC language file consists of a series of definitions.
+.DS L
+.ft CW
+ definition-list:
+ definition ";"
+ definition ";" definition-list
+.DE
+.KE
+It recognizes five types of definitions.
+.DS L
+.ft CW
+ definition:
+ enum-definition
+ struct-definition
+ union-definition
+ typedef-definition
+ const-definition
+ program-definition
+.DE
+.NH 2
+Structures
+\&
+.IX rpcgen structures \fIrpcgen\fP
+.LP
+An XDR struct is declared almost exactly like its C counterpart. It
+looks like the following:
+.DS L
+.ft CW
+ struct-definition:
+ "struct" struct-ident "{"
+ declaration-list
+ "}"
+
+ declaration-list:
+ declaration ";"
+ declaration ";" declaration-list
+.DE
+As an example, here is an XDR structure to a two-dimensional
+coordinate, and the C structure that it gets compiled into in the
+output header file.
+.DS
+.ft CW
+ struct coord { struct coord {
+ int x; --> int x;
+ int y; int y;
+ }; };
+ typedef struct coord coord;
+.DE
+The output is identical to the input, except for the added
+.I typedef
+at the end of the output. This allows one to use \*Qcoord\*U instead of
+\*Qstruct coord\*U when declaring items.
+.NH 2
+Unions
+\&
+.IX rpcgen unions \fIrpcgen\fP
+.LP
+XDR unions are discriminated unions, and look quite different from C
+unions. They are more analogous to Pascal variant records than they
+are to C unions.
+.DS L
+.ft CW
+ union-definition:
+ "union" union-ident "switch" "(" declaration ")" "{"
+ case-list
+ "}"
+
+ case-list:
+ "case" value ":" declaration ";"
+ "default" ":" declaration ";"
+ "case" value ":" declaration ";" case-list
+.DE
+Here is an example of a type that might be returned as the result of a
+\*Qread data\*U operation. If there is no error, return a block of data.
+Otherwise, don't return anything.
+.DS L
+.ft CW
+ union read_result switch (int errno) {
+ case 0:
+ opaque data[1024];
+ default:
+ void;
+ };
+.DE
+It gets compiled into the following:
+.DS L
+.ft CW
+ struct read_result {
+ int errno;
+ union {
+ char data[1024];
+ } read_result_u;
+ };
+ typedef struct read_result read_result;
+.DE
+Notice that the union component of the output struct has the name as
+the type name, except for the trailing \*Q_u\*U.
+.NH 2
+Enumerations
+\&
+.IX rpcgen enumerations \fIrpcgen\fP
+.LP
+XDR enumerations have the same syntax as C enumerations.
+.DS L
+.ft CW
+ enum-definition:
+ "enum" enum-ident "{"
+ enum-value-list
+ "}"
+
+ enum-value-list:
+ enum-value
+ enum-value "," enum-value-list
+
+ enum-value:
+ enum-value-ident
+ enum-value-ident "=" value
+.DE
+Here is a short example of an XDR enum, and the C enum that it gets
+compiled into.
+.DS L
+.ft CW
+ enum colortype { enum colortype {
+ RED = 0, RED = 0,
+ GREEN = 1, --> GREEN = 1,
+ BLUE = 2 BLUE = 2,
+ }; };
+ typedef enum colortype colortype;
+.DE
+.NH 2
+Typedef
+\&
+.IX rpcgen typedef \fIrpcgen\fP
+.LP
+XDR typedefs have the same syntax as C typedefs.
+.DS L
+.ft CW
+ typedef-definition:
+ "typedef" declaration
+.DE
+Here is an example that defines a
+.I fname_type
+used for declaring
+file name strings that have a maximum length of 255 characters.
+.DS L
+.ft CW
+typedef string fname_type<255>; --> typedef char *fname_type;
+.DE
+.NH 2
+Constants
+\&
+.IX rpcgen constants \fIrpcgen\fP
+.LP
+XDR constants symbolic constants that may be used wherever a
+integer constant is used, for example, in array size specifications.
+.DS L
+.ft CW
+ const-definition:
+ "const" const-ident "=" integer
+.DE
+For example, the following defines a constant
+.I DOZEN
+equal to 12.
+.DS L
+.ft CW
+ const DOZEN = 12; --> #define DOZEN 12
+.DE
+.NH 2
+Programs
+\&
+.IX rpcgen programs \fIrpcgen\fP
+.LP
+RPC programs are declared using the following syntax:
+.DS L
+.ft CW
+ program-definition:
+ "program" program-ident "{"
+ version-list
+ "}" "=" value
+
+ version-list:
+ version ";"
+ version ";" version-list
+
+ version:
+ "version" version-ident "{"
+ procedure-list
+ "}" "=" value
+
+ procedure-list:
+ procedure ";"
+ procedure ";" procedure-list
+
+ procedure:
+ type-ident procedure-ident "(" type-ident ")" "=" value
+.DE
+For example, here is the time protocol, revisited:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * time.x: Get or set the time. Time is represented as number of seconds
+ * since 0:00, January 1, 1970.
+ */
+.ft CW
+program TIMEPROG {
+ version TIMEVERS {
+ unsigned int TIMEGET(void) = 1;
+ void TIMESET(unsigned) = 2;
+ } = 1;
+} = 44;
+.DE
+This file compiles into #defines in the output header file:
+.ie t .DS
+.el .DS L
+.ft CW
+#define TIMEPROG 44
+#define TIMEVERS 1
+#define TIMEGET 1
+#define TIMESET 2
+.DE
+.NH 2
+Declarations
+\&
+.IX rpcgen declarations \fIrpcgen\fP
+.LP
+In XDR, there are only four kinds of declarations.
+.DS L
+.ft CW
+ declaration:
+ simple-declaration
+ fixed-array-declaration
+ variable-array-declaration
+ pointer-declaration
+.DE
+\fB1) Simple declarations\fP are just like simple C declarations.
+.DS L
+.ft CW
+ simple-declaration:
+ type-ident variable-ident
+.DE
+Example:
+.DS L
+.ft CW
+ colortype color; --> colortype color;
+.DE
+\fB2) Fixed-length Array Declarations\fP are just like C array declarations:
+.DS L
+.ft CW
+ fixed-array-declaration:
+ type-ident variable-ident "[" value "]"
+.DE
+Example:
+.DS L
+.ft CW
+ colortype palette[8]; --> colortype palette[8];
+.DE
+\fB3) Variable-Length Array Declarations\fP have no explicit syntax
+in C, so XDR invents its own using angle-brackets.
+.DS L
+.ft CW
+variable-array-declaration:
+ type-ident variable-ident "<" value ">"
+ type-ident variable-ident "<" ">"
+.DE
+The maximum size is specified between the angle brackets. The size may
+be omitted, indicating that the array may be of any size.
+.DS L
+.ft CW
+ int heights<12>; /* \fIat most 12 items\fP */
+ int widths<>; /* \fIany number of items\fP */
+.DE
+Since variable-length arrays have no explicit syntax in C, these
+declarations are actually compiled into \*Qstruct\*Us. For example, the
+\*Qheights\*U declaration gets compiled into the following struct:
+.DS L
+.ft CW
+ struct {
+ u_int heights_len; /* \fI# of items in array\fP */
+ int *heights_val; /* \fIpointer to array\fP */
+ } heights;
+.DE
+Note that the number of items in the array is stored in the \*Q_len\*U
+component and the pointer to the array is stored in the \*Q_val\*U
+component. The first part of each of these component's names is the
+same as the name of the declared XDR variable.
+.LP
+\fB4) Pointer Declarations\fP are made in
+XDR exactly as they are in C. You can't
+really send pointers over the network, but you can use XDR pointers
+for sending recursive data types such as lists and trees. The type is
+actually called \*Qoptional-data\*U, not \*Qpointer\*U, in XDR language.
+.DS L
+.ft CW
+ pointer-declaration:
+ type-ident "*" variable-ident
+.DE
+Example:
+.DS L
+.ft CW
+ listitem *next; --> listitem *next;
+.DE
+.NH 2
+\&Special Cases
+.IX rpcgen "special cases" \fIrpcgen\fP
+.LP
+There are a few exceptions to the rules described above.
+.LP
+.B Booleans:
+C has no built-in boolean type. However, the RPC library does a
+boolean type called
+.I bool_t
+that is either
+.I TRUE
+or
+.I FALSE .
+Things declared as type
+.I bool
+in XDR language are compiled into
+.I bool_t
+in the output header file.
+.LP
+Example:
+.DS L
+.ft CW
+ bool married; --> bool_t married;
+.DE
+.B Strings:
+C has no built-in string type, but instead uses the null-terminated
+\*Qchar *\*U convention. In XDR language, strings are declared using the
+\*Qstring\*U keyword, and compiled into \*Qchar *\*Us in the output header
+file. The maximum size contained in the angle brackets specifies the
+maximum number of characters allowed in the strings (not counting the
+.I NULL
+character). The maximum size may be left off, indicating a string
+of arbitrary length.
+.LP
+Examples:
+.DS L
+.ft CW
+ string name<32>; --> char *name;
+ string longname<>; --> char *longname;
+.DE
+.B "Opaque Data:"
+Opaque data is used in RPC and XDR to describe untyped data, that is,
+just sequences of arbitrary bytes. It may be declared either as a
+fixed or variable length array.
+.DS L
+Examples:
+.ft CW
+ opaque diskblock[512]; --> char diskblock[512];
+
+ opaque filedata<1024>; --> struct {
+ u_int filedata_len;
+ char *filedata_val;
+ } filedata;
+.DE
+.B Voids:
+In a void declaration, the variable is not named. The declaration is
+just \*Qvoid\*U and nothing else. Void declarations can only occur in two
+places: union definitions and program definitions (as the argument or
+result of a remote procedure).
diff --git a/lib/libc/rpc/PSD.doc/xdr.nts.ms b/lib/libc/rpc/PSD.doc/xdr.nts.ms
new file mode 100644
index 0000000..6c2d482
--- /dev/null
+++ b/lib/libc/rpc/PSD.doc/xdr.nts.ms
@@ -0,0 +1,1966 @@
+.\"
+.\" Must use -- eqn -- with this one
+.\"
+.\" @(#)xdr.nts.ms 2.2 88/08/05 4.0 RPCSRC
+.EQ
+delim $$
+.EN
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'External Data Representation: Sun Technical Notes''Page %'
+.EH 'Page %''External Data Representation: Sun Technical Notes'
+.if \\n%=1 .bp
+.SH
+\&External Data Representation: Sun Technical Notes
+.IX XDR "Sun technical notes"
+.LP
+This chapter contains technical notes on Sun's implementation of the
+External Data Representation (XDR) standard, a set of library routines
+that allow a C programmer to describe arbitrary data structures in a
+machinex-independent fashion.
+For a formal specification of the XDR
+standard, see the
+.I "External Data Representation Standard: Protocol Specification".
+XDR is the backbone of Sun's Remote Procedure Call package, in the
+sense that data for remote procedure calls is transmitted using the
+standard. XDR library routines should be used to transmit data
+that is accessed (read or written) by more than one type of machine.\**
+.FS
+.IX XDR "system routines"
+For a compete specification of the system External Data Representation
+routines, see the
+.I xdr(3N)
+manual page.
+.FE
+.LP
+This chapter contains a short tutorial overview of the XDR library
+routines, a guide to accessing currently available XDR streams, and
+information on defining new streams and data types. XDR was designed
+to work across different languages, operating systems, and machine
+architectures. Most users (particularly RPC users) will only need
+the information in the
+.I "Number Filters",
+.I "Floating Point Filters",
+and
+.I "Enumeration Filters"
+sections.
+Programmers wishing to implement RPC and XDR on new machines
+will be interested in the rest of the chapter, as well as the
+.I "External Data Representaiton Standard: Protocol Specification",
+which will be their primary reference.
+.SH
+Note:
+.I
+.I rpcgen
+can be used to write XDR routines even in cases where no RPC calls are
+being made.
+.LP
+On Sun systems,
+C programs that want to use XDR routines
+must include the file
+.I <rpc/rpc.h> ,
+which contains all the necessary interfaces to the XDR system.
+Since the C library
+.I libc.a
+contains all the XDR routines,
+compile as normal.
+.DS
+example% \fBcc\0\fIprogram\fP.c\fI
+.DE
+.ne 3i
+.NH 0
+\&Justification
+.IX XDR justification
+.LP
+Consider the following two programs,
+.I writer :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+.sp.5
+main() /* \fIwriter.c\fP */
+{
+ long i;
+.sp.5
+ for (i = 0; i < 8; i++) {
+ if (fwrite((char *)&i, sizeof(i), 1, stdout) != 1) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ }
+ exit(0);
+}
+.DE
+and
+.I reader :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+.sp.5
+main() /* \fIreader.c\fP */
+{
+ long i, j;
+.sp.5
+ for (j = 0; j < 8; j++) {
+ if (fread((char *)&i, sizeof (i), 1, stdin) != 1) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ printf("%ld ", i);
+ }
+ printf("\en");
+ exit(0);
+}
+.DE
+The two programs appear to be portable, because (a) they pass
+.I lint
+checking, and (b) they exhibit the same behavior when executed
+on two different hardware architectures, a Sun and a VAX.
+.LP
+Piping the output of the
+.I writer
+program to the
+.I reader
+program gives identical results on a Sun or a VAX.
+.DS
+.ft CW
+sun% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+sun%
+
+
+vax% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+vax%
+.DE
+With the advent of local area networks and 4.2BSD came the concept
+of \*Qnetwork pipes\*U \(em a process produces data on one machine,
+and a second process consumes data on another machine.
+A network pipe can be constructed with
+.I writer
+and
+.I reader .
+Here are the results if the first produces data on a Sun,
+and the second consumes data on a VAX.
+.DS
+.ft CW
+sun% \fBwriter | rsh vax reader\fP
+0 16777216 33554432 50331648 67108864 83886080 100663296
+117440512
+sun%
+.DE
+Identical results can be obtained by executing
+.I writer
+on the VAX and
+.I reader
+on the Sun. These results occur because the byte ordering
+of long integers differs between the VAX and the Sun,
+even though word size is the same.
+Note that $16777216$ is $2 sup 24$ \(em
+when four bytes are reversed, the 1 winds up in the 24th bit.
+.LP
+Whenever data is shared by two or more machine types, there is
+a need for portable data. Programs can be made data-portable by
+replacing the
+.I read()
+and
+.I write()
+calls with calls to an XDR library routine
+.I xdr_long() ,
+a filter that knows the standard representation
+of a long integer in its external form.
+Here are the revised versions of
+.I writer :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIxdr is a sub-library of rpc\fP */
+.sp.5
+main() /* \fIwriter.c\fP */
+{
+ XDR xdrs;
+ long i;
+.sp.5
+ xdrstdio_create(&xdrs, stdout, XDR_ENCODE);
+ for (i = 0; i < 8; i++) {
+ if (!xdr_long(&xdrs, &i)) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ }
+ exit(0);
+}
+.DE
+and
+.I reader :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIxdr is a sub-library of rpc\fP */
+.sp.5
+main() /* \fIreader.c\fP */
+{
+ XDR xdrs;
+ long i, j;
+.sp.5
+ xdrstdio_create(&xdrs, stdin, XDR_DECODE);
+ for (j = 0; j < 8; j++) {
+ if (!xdr_long(&xdrs, &i)) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ printf("%ld ", i);
+ }
+ printf("\en");
+ exit(0);
+}
+.DE
+The new programs were executed on a Sun,
+on a VAX, and from a Sun to a VAX;
+the results are shown below.
+.DS
+.ft CW
+sun% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+sun%
+
+vax% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+vax%
+
+sun% \fBwriter | rsh vax reader\fP
+0 1 2 3 4 5 6 7
+sun%
+.DE
+.SH
+Note:
+.I
+.IX XDR "portable data"
+Integers are just the tip of the portable-data iceberg. Arbitrary
+data structures present portability problems, particularly with
+respect to alignment and pointers. Alignment on word boundaries
+may cause the size of a structure to vary from machine to machine.
+And pointers, which are very convenient to use, have no meaning
+outside the machine where they are defined.
+.LP
+.NH 1
+\&A Canonical Standard
+.IX XDR "canonical standard"
+.LP
+XDR's approach to standardizing data representations is
+.I canonical .
+That is, XDR defines a single byte order (Big Endian), a single
+floating-point representation (IEEE), and so on. Any program running on
+any machine can use XDR to create portable data by translating its
+local representation to the XDR standard representations; similarly, any
+program running on any machine can read portable data by translating the
+XDR standard representaions to its local equivalents. The single standard
+completely decouples programs that create or send portable data from those
+that use or receive portable data. The advent of a new machine or a new
+language has no effect upon the community of existing portable data creators
+and users. A new machine joins this community by being \*Qtaught\*U how to
+convert the standard representations and its local representations; the
+local representations of other machines are irrelevant. Conversely, to
+existing programs running on other machines, the local representations of
+the new machine are also irrelevant; such programs can immediately read
+portable data produced by the new machine because such data conforms to the
+canonical standards that they already understand.
+.LP
+There are strong precedents for XDR's canonical approach. For example,
+TCP/IP, UDP/IP, XNS, Ethernet, and, indeed, all protocols below layer five
+of the ISO model, are canonical protocols. The advantage of any canonical
+approach is simplicity; in the case of XDR, a single set of conversion
+routines is written once and is never touched again. The canonical approach
+has a disadvantage, but it is unimportant in real-world data transfer
+applications. Suppose two Little-Endian machines are transferring integers
+according to the XDR standard. The sending machine converts the integers
+from Little-Endian byte order to XDR (Big-Endian) byte order; the receiving
+machine performs the reverse conversion. Because both machines observe the
+same byte order, their conversions are unnecessary. The point, however, is
+not necessity, but cost as compared to the alternative.
+.LP
+The time spent converting to and from a canonical representation is
+insignificant, especially in networking applications. Most of the time
+required to prepare a data structure for transfer is not spent in conversion
+but in traversing the elements of the data structure. To transmit a tree,
+for example, each leaf must be visited and each element in a leaf record must
+be copied to a buffer and aligned there; storage for the leaf may have to be
+deallocated as well. Similarly, to receive a tree, storage must be
+allocated for each leaf, data must be moved from the buffer to the leaf and
+properly aligned, and pointers must be constructed to link the leaves
+together. Every machine pays the cost of traversing and copying data
+structures whether or not conversion is required. In networking
+applications, communications overhead\(emthe time required to move the data
+down through the sender's protocol layers, across the network and up through
+the receiver's protocol layers\(emdwarfs conversion overhead.
+.NH 1
+\&The XDR Library
+.IX "XDR" "library"
+.LP
+The XDR library not only solves data portability problems, it also
+allows you to write and read arbitrary C constructs in a consistent,
+specified, well-documented manner. Thus, it can make sense to use the
+library even when the data is not shared among machines on a network.
+.LP
+The XDR library has filter routines for
+strings (null-terminated arrays of bytes),
+structures, unions, and arrays, to name a few.
+Using more primitive routines,
+you can write your own specific XDR routines
+to describe arbitrary data structures,
+including elements of arrays, arms of unions,
+or objects pointed at from other structures.
+The structures themselves may contain arrays of arbitrary elements,
+or pointers to other structures.
+.LP
+Let's examine the two programs more closely.
+There is a family of XDR stream creation routines
+in which each member treats the stream of bits differently.
+In our example, data is manipulated using standard I/O routines,
+so we use
+.I xdrstdio_create ().
+.IX xdrstdio_create() "" "\fIxdrstdio_create()\fP"
+The parameters to XDR stream creation routines
+vary according to their function.
+In our example,
+.I xdrstdio_create()
+takes a pointer to an XDR structure that it initializes,
+a pointer to a
+.I FILE
+that the input or output is performed on, and the operation.
+The operation may be
+.I XDR_ENCODE
+for serializing in the
+.I writer
+program, or
+.I XDR_DECODE
+for deserializing in the
+.I reader
+program.
+.LP
+Note: RPC users never need to create XDR streams;
+the RPC system itself creates these streams,
+which are then passed to the users.
+.LP
+The
+.I xdr_long()
+.IX xdr_long() "" "\fIxdr_long()\fP"
+primitive is characteristic of most XDR library
+primitives and all client XDR routines.
+First, the routine returns
+.I FALSE
+(0) if it fails, and
+.I TRUE
+(1) if it succeeds.
+Second, for each data type,
+.I xxx ,
+there is an associated XDR routine of the form:
+.DS
+.ft CW
+xdr_xxx(xdrs, xp)
+ XDR *xdrs;
+ xxx *xp;
+{
+}
+.DE
+In our case,
+.I xxx
+is long, and the corresponding XDR routine is
+a primitive,
+.I xdr_long() .
+The client could also define an arbitrary structure
+.I xxx
+in which case the client would also supply the routine
+.I xdr_xxx (),
+describing each field by calling XDR routines
+of the appropriate type.
+In all cases the first parameter,
+.I xdrs
+can be treated as an opaque handle,
+and passed to the primitive routines.
+.LP
+XDR routines are direction independent;
+that is, the same routines are called to serialize or deserialize data.
+This feature is critical to software engineering of portable data.
+The idea is to call the same routine for either operation \(em
+this almost guarantees that serialized data can also be deserialized.
+One routine is used by both producer and consumer of networked data.
+This is implemented by always passing the address
+of an object rather than the object itself \(em
+only in the case of deserialization is the object modified.
+This feature is not shown in our trivial example,
+but its value becomes obvious when nontrivial data structures
+are passed among machines.
+If needed, the user can obtain the
+direction of the XDR operation.
+See the
+.I "XDR Operation Directions"
+section below for details.
+.LP
+Let's look at a slightly more complicated example.
+Assume that a person's gross assets and liabilities
+are to be exchanged among processes.
+Also assume that these values are important enough
+to warrant their own data type:
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers {
+ long g_assets;
+ long g_liabilities;
+};
+.DE
+The corresponding XDR routine describing this structure would be:
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t /* \fITRUE is success, FALSE is failure\fP */
+xdr_gnumbers(xdrs, gp)
+ XDR *xdrs;
+ struct gnumbers *gp;
+{
+ if (xdr_long(xdrs, &gp->g_assets) &&
+ xdr_long(xdrs, &gp->g_liabilities))
+ return(TRUE);
+ return(FALSE);
+}
+.DE
+Note that the parameter
+.I xdrs
+is never inspected or modified;
+it is only passed on to the subcomponent routines.
+It is imperative to inspect the return value of each XDR routine call,
+and to give up immediately and return
+.I FALSE
+if the subroutine fails.
+.LP
+This example also shows that the type
+.I bool_t
+is declared as an integer whose only values are
+.I TRUE
+(1) and
+.I FALSE
+(0). This document uses the following definitions:
+.ie t .DS
+.el .DS L
+.ft CW
+#define bool_t int
+#define TRUE 1
+#define FALSE 0
+.DE
+.LP
+Keeping these conventions in mind,
+.I xdr_gnumbers()
+can be rewritten as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_gnumbers(xdrs, gp)
+ XDR *xdrs;
+ struct gnumbers *gp;
+{
+ return(xdr_long(xdrs, &gp->g_assets) &&
+ xdr_long(xdrs, &gp->g_liabilities));
+}
+.DE
+This document uses both coding styles.
+.NH 1
+\&XDR Library Primitives
+.IX "library primitives for XDR"
+.IX XDR "library primitives"
+.LP
+This section gives a synopsis of each XDR primitive.
+It starts with basic data types and moves on to constructed data types.
+Finally, XDR utilities are discussed.
+The interface to these primitives
+and utilities is defined in the include file
+.I <rpc/xdr.h> ,
+automatically included by
+.I <rpc/rpc.h> .
+.NH 2
+\&Number Filters
+.IX "XDR library" "number filters"
+.LP
+The XDR library provides primitives to translate between numbers
+and their corresponding external representations.
+Primitives cover the set of numbers in:
+.DS
+.ft CW
+[signed, unsigned] * [short, int, long]
+.DE
+.ne 2i
+Specifically, the eight primitives are:
+.DS
+.ft CW
+bool_t xdr_char(xdrs, cp)
+ XDR *xdrs;
+ char *cp;
+.sp.5
+bool_t xdr_u_char(xdrs, ucp)
+ XDR *xdrs;
+ unsigned char *ucp;
+.sp.5
+bool_t xdr_int(xdrs, ip)
+ XDR *xdrs;
+ int *ip;
+.sp.5
+bool_t xdr_u_int(xdrs, up)
+ XDR *xdrs;
+ unsigned *up;
+.sp.5
+bool_t xdr_long(xdrs, lip)
+ XDR *xdrs;
+ long *lip;
+.sp.5
+bool_t xdr_u_long(xdrs, lup)
+ XDR *xdrs;
+ u_long *lup;
+.sp.5
+bool_t xdr_short(xdrs, sip)
+ XDR *xdrs;
+ short *sip;
+.sp.5
+bool_t xdr_u_short(xdrs, sup)
+ XDR *xdrs;
+ u_short *sup;
+.DE
+The first parameter,
+.I xdrs ,
+is an XDR stream handle.
+The second parameter is the address of the number
+that provides data to the stream or receives data from it.
+All routines return
+.I TRUE
+if they complete successfully, and
+.I FALSE
+otherwise.
+.NH 2
+\&Floating Point Filters
+.IX "XDR library" "floating point filters"
+.LP
+The XDR library also provides primitive routines
+for C's floating point types:
+.DS
+.ft CW
+bool_t xdr_float(xdrs, fp)
+ XDR *xdrs;
+ float *fp;
+.sp.5
+bool_t xdr_double(xdrs, dp)
+ XDR *xdrs;
+ double *dp;
+.DE
+The first parameter,
+.I xdrs
+is an XDR stream handle.
+The second parameter is the address
+of the floating point number that provides data to the stream
+or receives data from it.
+Both routines return
+.I TRUE
+if they complete successfully, and
+.I FALSE
+otherwise.
+.LP
+Note: Since the numbers are represented in IEEE floating point,
+routines may fail when decoding a valid IEEE representation
+into a machine-specific representation, or vice-versa.
+.NH 2
+\&Enumeration Filters
+.IX "XDR library" "enumeration filters"
+.LP
+The XDR library provides a primitive for generic enumerations.
+The primitive assumes that a C
+.I enum
+has the same representation inside the machine as a C integer.
+The boolean type is an important instance of the
+.I enum .
+The external representation of a boolean is always
+.I TRUE
+(1) or
+.I FALSE
+(0).
+.DS
+.ft CW
+#define bool_t int
+#define FALSE 0
+#define TRUE 1
+.sp.5
+#define enum_t int
+.sp.5
+bool_t xdr_enum(xdrs, ep)
+ XDR *xdrs;
+ enum_t *ep;
+.sp.5
+bool_t xdr_bool(xdrs, bp)
+ XDR *xdrs;
+ bool_t *bp;
+.DE
+The second parameters
+.I ep
+and
+.I bp
+are addresses of the associated type that provides data to, or
+receives data from, the stream
+.I xdrs .
+.NH 2
+\&No Data
+.IX "XDR library" "no data"
+.LP
+Occasionally, an XDR routine must be supplied to the RPC system,
+even when no data is passed or required.
+The library provides such a routine:
+.DS
+.ft CW
+bool_t xdr_void(); /* \fIalways returns TRUE\fP */
+.DE
+.NH 2
+\&Constructed Data Type Filters
+.IX "XDR library" "constructed data type filters"
+.LP
+Constructed or compound data type primitives
+require more parameters and perform more complicated functions
+then the primitives discussed above.
+This section includes primitives for
+strings, arrays, unions, and pointers to structures.
+.LP
+Constructed data type primitives may use memory management.
+In many cases, memory is allocated when deserializing data with
+.I XDR_DECODE
+Therefore, the XDR package must provide means to deallocate memory.
+This is done by an XDR operation,
+.I XDR_FREE
+To review, the three XDR directional operations are
+.I XDR_ENCODE ,
+.I XDR_DECODE
+and
+.I XDR_FREE .
+.NH 3
+\&Strings
+.IX "XDR library" "strings"
+.LP
+In C, a string is defined as a sequence of bytes
+terminated by a null byte,
+which is not considered when calculating string length.
+However, when a string is passed or manipulated,
+a pointer to it is employed.
+Therefore, the XDR library defines a string to be a
+.I "char *"
+and not a sequence of characters.
+The external representation of a string is drastically different
+from its internal representation.
+Externally, strings are represented as
+sequences of ASCII characters,
+while internally, they are represented with character pointers.
+Conversion between the two representations
+is accomplished with the routine
+.I xdr_string ():
+.IX xdr_string() "" \fIxdr_string()\fP
+.DS
+.ft CW
+bool_t xdr_string(xdrs, sp, maxlength)
+ XDR *xdrs;
+ char **sp;
+ u_int maxlength;
+.DE
+The first parameter
+.I xdrs
+is the XDR stream handle.
+The second parameter
+.I sp
+is a pointer to a string (type
+.I "char **" .
+The third parameter
+.I maxlength
+specifies the maximum number of bytes allowed during encoding or decoding.
+its value is usually specified by a protocol. For example, a protocol
+specification may say that a file name may be no longer than 255 characters.
+.LP
+The routine returns
+.I FALSE
+if the number of characters exceeds
+.I maxlength ,
+and
+.I TRUE
+if it doesn't.
+.SH
+Keep
+.I maxlength
+small. If it is too big you can blow the heap, since
+.I xdr_string()
+will call
+.I malloc()
+for space.
+.LP
+The behavior of
+.I xdr_string()
+.IX xdr_string() "" \fIxdr_string()\fP
+is similar to the behavior of other routines
+discussed in this section. The direction
+.I XDR_ENCODE
+is easiest to understand. The parameter
+.I sp
+points to a string of a certain length;
+if the string does not exceed
+.I maxlength ,
+the bytes are serialized.
+.LP
+The effect of deserializing a string is subtle.
+First the length of the incoming string is determined;
+it must not exceed
+.I maxlength .
+Next
+.I sp
+is dereferenced; if the the value is
+.I NULL ,
+then a string of the appropriate length is allocated and
+.I *sp
+is set to this string.
+If the original value of
+.I *sp
+is non-null, then the XDR package assumes
+that a target area has been allocated,
+which can hold strings no longer than
+.I maxlength .
+In either case, the string is decoded into the target area.
+The routine then appends a null character to the string.
+.LP
+In the
+.I XDR_FREE
+operation, the string is obtained by dereferencing
+.I sp .
+If the string is not
+.I NULL ,
+it is freed and
+.I *sp
+is set to
+.I NULL .
+In this operation,
+.I xdr_string()
+ignores the
+.I maxlength
+parameter.
+.NH 3
+\&Byte Arrays
+.IX "XDR library" "byte arrays"
+.LP
+Often variable-length arrays of bytes are preferable to strings.
+Byte arrays differ from strings in the following three ways:
+1) the length of the array (the byte count) is explicitly
+located in an unsigned integer,
+2) the byte sequence is not terminated by a null character, and
+3) the external representation of the bytes is the same as their
+internal representation.
+The primitive
+.I xdr_bytes()
+.IX xdr_bytes() "" \fIxdr_bytes()\fP
+converts between the internal and external
+representations of byte arrays:
+.DS
+.ft CW
+bool_t xdr_bytes(xdrs, bpp, lp, maxlength)
+ XDR *xdrs;
+ char **bpp;
+ u_int *lp;
+ u_int maxlength;
+.DE
+The usage of the first, second and fourth parameters
+are identical to the first, second and third parameters of
+.I xdr_string (),
+respectively.
+The length of the byte area is obtained by dereferencing
+.I lp
+when serializing;
+.I *lp
+is set to the byte length when deserializing.
+.NH 3
+\&Arrays
+.IX "XDR library" "arrays"
+.LP
+The XDR library package provides a primitive
+for handling arrays of arbitrary elements.
+The
+.I xdr_bytes()
+routine treats a subset of generic arrays,
+in which the size of array elements is known to be 1,
+and the external description of each element is built-in.
+The generic array primitive,
+.I xdr_array() ,
+.IX xdr_array() "" \fIxdr_array()\fP
+requires parameters identical to those of
+.I xdr_bytes()
+plus two more:
+the size of array elements,
+and an XDR routine to handle each of the elements.
+This routine is called to encode or decode
+each element of the array.
+.DS
+.ft CW
+bool_t
+xdr_array(xdrs, ap, lp, maxlength, elementsiz, xdr_element)
+ XDR *xdrs;
+ char **ap;
+ u_int *lp;
+ u_int maxlength;
+ u_int elementsiz;
+ bool_t (*xdr_element)();
+.DE
+The parameter
+.I ap
+is the address of the pointer to the array.
+If
+.I *ap
+is
+.I NULL
+when the array is being deserialized,
+XDR allocates an array of the appropriate size and sets
+.I *ap
+to that array.
+The element count of the array is obtained from
+.I *lp
+when the array is serialized;
+.I *lp
+is set to the array length when the array is deserialized.
+The parameter
+.I maxlength
+is the maximum number of elements that the array is allowed to have;
+.I elementsiz
+is the byte size of each element of the array
+(the C function
+.I sizeof()
+can be used to obtain this value).
+The
+.I xdr_element()
+.IX xdr_element() "" \fIxdr_element()\fP
+routine is called to serialize, deserialize, or free
+each element of the array.
+.br
+.LP
+Before defining more constructed data types, it is appropriate to
+present three examples.
+.LP
+.I "Example A:"
+.br
+A user on a networked machine can be identified by
+(a) the machine name, such as
+.I krypton :
+see the
+.I gethostname
+man page; (b) the user's UID: see the
+.I geteuid
+man page; and (c) the group numbers to which the user belongs:
+see the
+.I getgroups
+man page. A structure with this information and its associated
+XDR routine could be coded like this:
+.ie t .DS
+.el .DS L
+.ft CW
+struct netuser {
+ char *nu_machinename;
+ int nu_uid;
+ u_int nu_glen;
+ int *nu_gids;
+};
+#define NLEN 255 /* \fImachine names < 256 chars\fP */
+#define NGRPS 20 /* \fIuser can't be in > 20 groups\fP */
+.sp.5
+bool_t
+xdr_netuser(xdrs, nup)
+ XDR *xdrs;
+ struct netuser *nup;
+{
+ return(xdr_string(xdrs, &nup->nu_machinename, NLEN) &&
+ xdr_int(xdrs, &nup->nu_uid) &&
+ xdr_array(xdrs, &nup->nu_gids, &nup->nu_glen,
+ NGRPS, sizeof (int), xdr_int));
+}
+.DE
+.LP
+.I "Example B:"
+.br
+A party of network users could be implemented
+as an array of
+.I netuser
+structure.
+The declaration and its associated XDR routines
+are as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+struct party {
+ u_int p_len;
+ struct netuser *p_nusers;
+};
+#define PLEN 500 /* \fImax number of users in a party\fP */
+.sp.5
+bool_t
+xdr_party(xdrs, pp)
+ XDR *xdrs;
+ struct party *pp;
+{
+ return(xdr_array(xdrs, &pp->p_nusers, &pp->p_len, PLEN,
+ sizeof (struct netuser), xdr_netuser));
+}
+.DE
+.LP
+.I "Example C:"
+.br
+The well-known parameters to
+.I main ,
+.I argc
+and
+.I argv
+can be combined into a structure.
+An array of these structures can make up a history of commands.
+The declarations and XDR routines might look like:
+.ie t .DS
+.el .DS L
+.ft CW
+struct cmd {
+ u_int c_argc;
+ char **c_argv;
+};
+#define ALEN 1000 /* \fIargs cannot be > 1000 chars\fP */
+#define NARGC 100 /* \fIcommands cannot have > 100 args\fP */
+
+struct history {
+ u_int h_len;
+ struct cmd *h_cmds;
+};
+#define NCMDS 75 /* \fIhistory is no more than 75 commands\fP */
+
+bool_t
+xdr_wrap_string(xdrs, sp)
+ XDR *xdrs;
+ char **sp;
+{
+ return(xdr_string(xdrs, sp, ALEN));
+}
+.DE
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_cmd(xdrs, cp)
+ XDR *xdrs;
+ struct cmd *cp;
+{
+ return(xdr_array(xdrs, &cp->c_argv, &cp->c_argc, NARGC,
+ sizeof (char *), xdr_wrap_string));
+}
+.DE
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_history(xdrs, hp)
+ XDR *xdrs;
+ struct history *hp;
+{
+ return(xdr_array(xdrs, &hp->h_cmds, &hp->h_len, NCMDS,
+ sizeof (struct cmd), xdr_cmd));
+}
+.DE
+The most confusing part of this example is that the routine
+.I xdr_wrap_string()
+is needed to package the
+.I xdr_string()
+routine, because the implementation of
+.I xdr_array()
+only passes two parameters to the array element description routine;
+.I xdr_wrap_string()
+supplies the third parameter to
+.I xdr_string ().
+.LP
+By now the recursive nature of the XDR library should be obvious.
+Let's continue with more constructed data types.
+.NH 3
+\&Opaque Data
+.IX "XDR library" "opaque data"
+.LP
+In some protocols, handles are passed from a server to client.
+The client passes the handle back to the server at some later time.
+Handles are never inspected by clients;
+they are obtained and submitted.
+That is to say, handles are opaque.
+The
+.I xdr_opaque()
+.IX xdr_opaque() "" \fIxdr_opaque()\fP
+primitive is used for describing fixed sized, opaque bytes.
+.DS
+.ft CW
+bool_t xdr_opaque(xdrs, p, len)
+ XDR *xdrs;
+ char *p;
+ u_int len;
+.DE
+The parameter
+.I p
+is the location of the bytes;
+.I len
+is the number of bytes in the opaque object.
+By definition, the actual data
+contained in the opaque object are not machine portable.
+.NH 3
+\&Fixed Sized Arrays
+.IX "XDR library" "fixed sized arrays"
+.LP
+The XDR library provides a primitive,
+.I xdr_vector (),
+for fixed-length arrays.
+.ie t .DS
+.el .DS L
+.ft CW
+#define NLEN 255 /* \fImachine names must be < 256 chars\fP */
+#define NGRPS 20 /* \fIuser belongs to exactly 20 groups\fP */
+.sp.5
+struct netuser {
+ char *nu_machinename;
+ int nu_uid;
+ int nu_gids[NGRPS];
+};
+.sp.5
+bool_t
+xdr_netuser(xdrs, nup)
+ XDR *xdrs;
+ struct netuser *nup;
+{
+ int i;
+.sp.5
+ if (!xdr_string(xdrs, &nup->nu_machinename, NLEN))
+ return(FALSE);
+ if (!xdr_int(xdrs, &nup->nu_uid))
+ return(FALSE);
+ if (!xdr_vector(xdrs, nup->nu_gids, NGRPS, sizeof(int),
+ xdr_int)) {
+ return(FALSE);
+ }
+ return(TRUE);
+}
+.DE
+.NH 3
+\&Discriminated Unions
+.IX "XDR library" "discriminated unions"
+.LP
+The XDR library supports discriminated unions.
+A discriminated union is a C union and an
+.I enum_t
+value that selects an \*Qarm\*U of the union.
+.DS
+.ft CW
+struct xdr_discrim {
+ enum_t value;
+ bool_t (*proc)();
+};
+.sp.5
+bool_t xdr_union(xdrs, dscmp, unp, arms, defaultarm)
+ XDR *xdrs;
+ enum_t *dscmp;
+ char *unp;
+ struct xdr_discrim *arms;
+ bool_t (*defaultarm)(); /* \fImay equal NULL\fP */
+.DE
+First the routine translates the discriminant of the union located at
+.I *dscmp .
+The discriminant is always an
+.I enum_t .
+Next the union located at
+.I *unp
+is translated.
+The parameter
+.I arms
+is a pointer to an array of
+.I xdr_discrim
+structures.
+Each structure contains an ordered pair of
+.I [value,proc] .
+If the union's discriminant is equal to the associated
+.I value ,
+then the
+.I proc
+is called to translate the union.
+The end of the
+.I xdr_discrim
+structure array is denoted by a routine of value
+.I NULL
+(0). If the discriminant is not found in the
+.I arms
+array, then the
+.I defaultarm
+procedure is called if it is non-null;
+otherwise the routine returns
+.I FALSE .
+.LP
+.I "Example D:"
+Suppose the type of a union may be integer,
+character pointer (a string), or a
+.I gnumbers
+structure.
+Also, assume the union and its current type
+are declared in a structure.
+The declaration is:
+.ie t .DS
+.el .DS L
+.ft CW
+enum utype { INTEGER=1, STRING=2, GNUMBERS=3 };
+.sp.5
+struct u_tag {
+ enum utype utype; /* \fIthe union's discriminant\fP */
+ union {
+ int ival;
+ char *pval;
+ struct gnumbers gn;
+ } uval;
+};
+.DE
+The following constructs and XDR procedure (de)serialize
+the discriminated union:
+.ie t .DS
+.el .DS L
+.ft CW
+struct xdr_discrim u_tag_arms[4] = {
+ { INTEGER, xdr_int },
+ { GNUMBERS, xdr_gnumbers }
+ { STRING, xdr_wrap_string },
+ { __dontcare__, NULL }
+ /* \fIalways terminate arms with a NULL xdr_proc\fP */
+}
+.sp.5
+bool_t
+xdr_u_tag(xdrs, utp)
+ XDR *xdrs;
+ struct u_tag *utp;
+{
+ return(xdr_union(xdrs, &utp->utype, &utp->uval,
+ u_tag_arms, NULL));
+}
+.DE
+The routine
+.I xdr_gnumbers()
+was presented above in
+.I "The XDR Library"
+section.
+.I xdr_wrap_string()
+was presented in example C.
+The default
+.I arm
+parameter to
+.I xdr_union()
+(the last parameter) is
+.I NULL
+in this example. Therefore the value of the union's discriminant
+may legally take on only values listed in the
+.I u_tag_arms
+array. This example also demonstrates that
+the elements of the arm's array do not need to be sorted.
+.LP
+It is worth pointing out that the values of the discriminant
+may be sparse, though in this example they are not.
+It is always good
+practice to assign explicitly integer values to each element of the
+discriminant's type.
+This practice both documents the external
+representation of the discriminant and guarantees that different
+C compilers emit identical discriminant values.
+.LP
+Exercise: Implement
+.I xdr_union()
+using the other primitives in this section.
+.NH 3
+\&Pointers
+.IX "XDR library" "pointers"
+.LP
+In C it is often convenient to put pointers
+to another structure within a structure.
+The
+.I xdr_reference()
+.IX xdr_reference() "" \fIxdr_reference()\fP
+primitive makes it easy to serialize, deserialize, and free
+these referenced structures.
+.DS
+.ft CW
+bool_t xdr_reference(xdrs, pp, size, proc)
+ XDR *xdrs;
+ char **pp;
+ u_int ssize;
+ bool_t (*proc)();
+.DE
+.LP
+Parameter
+.I pp
+is the address of
+the pointer to the structure;
+parameter
+.I ssize
+is the size in bytes of the structure (use the C function
+.I sizeof()
+to obtain this value); and
+.I proc
+is the XDR routine that describes the structure.
+When decoding data, storage is allocated if
+.I *pp
+is
+.I NULL .
+.LP
+There is no need for a primitive
+.I xdr_struct()
+to describe structures within structures,
+because pointers are always sufficient.
+.LP
+Exercise: Implement
+.I xdr_reference()
+using
+.I xdr_array ().
+Warning:
+.I xdr_reference()
+and
+.I xdr_array()
+are NOT interchangeable external representations of data.
+.LP
+.I "Example E:"
+Suppose there is a structure containing a person's name
+and a pointer to a
+.I gnumbers
+structure containing the person's gross assets and liabilities.
+The construct is:
+.DS
+.ft CW
+struct pgn {
+ char *name;
+ struct gnumbers *gnp;
+};
+.DE
+The corresponding XDR routine for this structure is:
+.DS
+.ft CW
+bool_t
+xdr_pgn(xdrs, pp)
+ XDR *xdrs;
+ struct pgn *pp;
+{
+ if (xdr_string(xdrs, &pp->name, NLEN) &&
+ xdr_reference(xdrs, &pp->gnp,
+ sizeof(struct gnumbers), xdr_gnumbers))
+ return(TRUE);
+ return(FALSE);
+}
+.DE
+.IX "pointer semantics and XDR"
+.I "Pointer Semantics and XDR"
+.LP
+In many applications, C programmers attach double meaning to
+the values of a pointer. Typically the value
+.I NULL
+(or zero) means data is not needed,
+yet some application-specific interpretation applies.
+In essence, the C programmer is encoding
+a discriminated union efficiently
+by overloading the interpretation of the value of a pointer.
+For instance, in example E a
+.I NULL
+pointer value for
+.I gnp
+could indicate that
+the person's assets and liabilities are unknown.
+That is, the pointer value encodes two things:
+whether or not the data is known;
+and if it is known, where it is located in memory.
+Linked lists are an extreme example of the use
+of application-specific pointer interpretation.
+.LP
+The primitive
+.I xdr_reference()
+.IX xdr_reference() "" \fIxdr_reference()\fP
+cannot and does not attach any special
+meaning to a null-value pointer during serialization.
+That is, passing an address of a pointer whose value is
+.I NULL
+to
+.I xdr_reference()
+when serialing data will most likely cause a memory fault and, on the UNIX
+system, a core dump.
+.LP
+.I xdr_pointer()
+correctly handles
+.I NULL
+pointers. For more information about its use, see
+the
+.I "Linked Lists"
+topics below.
+.LP
+.I Exercise:
+After reading the section on
+.I "Linked Lists" ,
+return here and extend example E so that
+it can correctly deal with
+.I NULL
+pointer values.
+.LP
+.I Exercise:
+Using the
+.I xdr_union (),
+.I xdr_reference()
+and
+.I xdr_void()
+primitives, implement a generic pointer handling primitive
+that implicitly deals with
+.I NULL
+pointers. That is, implement
+.I xdr_pointer ().
+.NH 2
+\&Non-filter Primitives
+.IX "XDR" "non-filter primitives"
+.LP
+XDR streams can be manipulated with
+the primitives discussed in this section.
+.DS
+.ft CW
+u_int xdr_getpos(xdrs)
+ XDR *xdrs;
+.sp.5
+bool_t xdr_setpos(xdrs, pos)
+ XDR *xdrs;
+ u_int pos;
+.sp.5
+xdr_destroy(xdrs)
+ XDR *xdrs;
+.DE
+The routine
+.I xdr_getpos()
+.IX xdr_getpos() "" \fIxdr_getpos()\fP
+returns an unsigned integer
+that describes the current position in the data stream.
+Warning: In some XDR streams, the returned value of
+.I xdr_getpos()
+is meaningless;
+the routine returns a \-1 in this case
+(though \-1 should be a legitimate value).
+.LP
+The routine
+.I xdr_setpos()
+.IX xdr_setpos() "" \fIxdr_setpos()\fP
+sets a stream position to
+.I pos .
+Warning: In some XDR streams, setting a position is impossible;
+in such cases,
+.I xdr_setpos()
+will return
+.I FALSE .
+This routine will also fail if the requested position is out-of-bounds.
+The definition of bounds varies from stream to stream.
+.LP
+The
+.I xdr_destroy()
+.IX xdr_destroy() "" \fIxdr_destroy()\fP
+primitive destroys the XDR stream.
+Usage of the stream
+after calling this routine is undefined.
+.NH 2
+\&XDR Operation Directions
+.IX XDR "operation directions"
+.IX "direction of XDR operations"
+.LP
+At times you may wish to optimize XDR routines by taking
+advantage of the direction of the operation \(em
+.I XDR_ENCODE
+.I XDR_DECODE
+or
+.I XDR_FREE
+The value
+.I xdrs->x_op
+always contains the direction of the XDR operation.
+Programmers are not encouraged to take advantage of this information.
+Therefore, no example is presented here. However, an example in the
+.I "Linked Lists"
+topic below, demonstrates the usefulness of the
+.I xdrs->x_op
+field.
+.NH 2
+\&XDR Stream Access
+.IX "XDR" "stream access"
+.LP
+An XDR stream is obtained by calling the appropriate creation routine.
+These creation routines take arguments that are tailored to the
+specific properties of the stream.
+.LP
+Streams currently exist for (de)serialization of data to or from
+standard I/O
+.I FILE
+streams, TCP/IP connections and UNIX files, and memory.
+.NH 3
+\&Standard I/O Streams
+.IX "XDR" "standard I/O streams"
+.LP
+XDR streams can be interfaced to standard I/O using the
+.I xdrstdio_create()
+.IX xdrstdio_create() "" \fIxdrstdio_create()\fP
+routine as follows:
+.DS
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIxdr streams part of rpc\fP */
+.sp.5
+void
+xdrstdio_create(xdrs, fp, x_op)
+ XDR *xdrs;
+ FILE *fp;
+ enum xdr_op x_op;
+.DE
+The routine
+.I xdrstdio_create()
+initializes an XDR stream pointed to by
+.I xdrs .
+The XDR stream interfaces to the standard I/O library.
+Parameter
+.I fp
+is an open file, and
+.I x_op
+is an XDR direction.
+.NH 3
+\&Memory Streams
+.IX "XDR" "memory streams"
+.LP
+Memory streams allow the streaming of data into or out of
+a specified area of memory:
+.DS
+.ft CW
+#include <rpc/rpc.h>
+.sp.5
+void
+xdrmem_create(xdrs, addr, len, x_op)
+ XDR *xdrs;
+ char *addr;
+ u_int len;
+ enum xdr_op x_op;
+.DE
+The routine
+.I xdrmem_create()
+.IX xdrmem_create() "" \fIxdrmem_create()\fP
+initializes an XDR stream in local memory.
+The memory is pointed to by parameter
+.I addr ;
+parameter
+.I len
+is the length in bytes of the memory.
+The parameters
+.I xdrs
+and
+.I x_op
+are identical to the corresponding parameters of
+.I xdrstdio_create ().
+Currently, the UDP/IP implementation of RPC uses
+.I xdrmem_create ().
+Complete call or result messages are built in memory before calling the
+.I sendto()
+system routine.
+.NH 3
+\&Record (TCP/IP) Streams
+.IX "XDR" "record (TCP/IP) streams"
+.LP
+A record stream is an XDR stream built on top of
+a record marking standard that is built on top of the
+UNIX file or 4.2 BSD connection interface.
+.DS
+.ft CW
+#include <rpc/rpc.h> /* \fIxdr streams part of rpc\fP */
+.sp.5
+xdrrec_create(xdrs,
+ sendsize, recvsize, iohandle, readproc, writeproc)
+ XDR *xdrs;
+ u_int sendsize, recvsize;
+ char *iohandle;
+ int (*readproc)(), (*writeproc)();
+.DE
+The routine
+.I xdrrec_create()
+provides an XDR stream interface that allows for a bidirectional,
+arbitrarily long sequence of records.
+The contents of the records are meant to be data in XDR form.
+The stream's primary use is for interfacing RPC to TCP connections.
+However, it can be used to stream data into or out of normal
+UNIX files.
+.LP
+The parameter
+.I xdrs
+is similar to the corresponding parameter described above.
+The stream does its own data buffering similar to that of standard I/O.
+The parameters
+.I sendsize
+and
+.I recvsize
+determine the size in bytes of the output and input buffers, respectively;
+if their values are zero (0), then predetermined defaults are used.
+When a buffer needs to be filled or flushed, the routine
+.I readproc()
+or
+.I writeproc()
+is called, respectively.
+The usage and behavior of these
+routines are similar to the UNIX system calls
+.I read()
+and
+.I write ().
+However,
+the first parameter to each of these routines is the opaque parameter
+.I iohandle .
+The other two parameters
+.I buf ""
+and
+.I nbytes )
+and the results
+(byte count) are identical to the system routines.
+If
+.I xxx
+is
+.I readproc()
+or
+.I writeproc (),
+then it has the following form:
+.DS
+.ft CW
+.ft I
+/*
+ * returns the actual number of bytes transferred.
+ * -1 is an error
+ */
+.ft CW
+int
+xxx(iohandle, buf, len)
+ char *iohandle;
+ char *buf;
+ int nbytes;
+.DE
+The XDR stream provides means for delimiting records in the byte stream.
+The implementation details of delimiting records in a stream are
+discussed in the
+.I "Advanced Topics"
+topic below.
+The primitives that are specific to record streams are as follows:
+.DS
+.ft CW
+bool_t
+xdrrec_endofrecord(xdrs, flushnow)
+ XDR *xdrs;
+ bool_t flushnow;
+.sp.5
+bool_t
+xdrrec_skiprecord(xdrs)
+ XDR *xdrs;
+.sp.5
+bool_t
+xdrrec_eof(xdrs)
+ XDR *xdrs;
+.DE
+The routine
+.I xdrrec_endofrecord()
+.IX xdrrec_endofrecord() "" \fIxdrrec_endofrecord()\fP
+causes the current outgoing data to be marked as a record.
+If the parameter
+.I flushnow
+is
+.I TRUE ,
+then the stream's
+.I writeproc
+will be called; otherwise,
+.I writeproc
+will be called when the output buffer has been filled.
+.LP
+The routine
+.I xdrrec_skiprecord()
+.IX xdrrec_skiprecord() "" \fIxdrrec_skiprecord()\fP
+causes an input stream's position to be moved past
+the current record boundary and onto the
+beginning of the next record in the stream.
+.LP
+If there is no more data in the stream's input buffer,
+then the routine
+.I xdrrec_eof()
+.IX xdrrec_eof() "" \fIxdrrec_eof()\fP
+returns
+.I TRUE .
+That is not to say that there is no more data
+in the underlying file descriptor.
+.NH 2
+\&XDR Stream Implementation
+.IX "XDR" "stream implementation"
+.IX "stream implementation in XDR"
+.LP
+This section provides the abstract data types needed
+to implement new instances of XDR streams.
+.NH 3
+\&The XDR Object
+.IX "XDR" "object"
+.LP
+The following structure defines the interface to an XDR stream:
+.ie t .DS
+.el .DS L
+.ft CW
+enum xdr_op { XDR_ENCODE=0, XDR_DECODE=1, XDR_FREE=2 };
+.sp.5
+typedef struct {
+ enum xdr_op x_op; /* \fIoperation; fast added param\fP */
+ struct xdr_ops {
+ bool_t (*x_getlong)(); /* \fIget long from stream\fP */
+ bool_t (*x_putlong)(); /* \fIput long to stream\fP */
+ bool_t (*x_getbytes)(); /* \fIget bytes from stream\fP */
+ bool_t (*x_putbytes)(); /* \fIput bytes to stream\fP */
+ u_int (*x_getpostn)(); /* \fIreturn stream offset\fP */
+ bool_t (*x_setpostn)(); /* \fIreposition offset\fP */
+ caddr_t (*x_inline)(); /* \fIptr to buffered data\fP */
+ VOID (*x_destroy)(); /* \fIfree private area\fP */
+ } *x_ops;
+ caddr_t x_public; /* \fIusers' data\fP */
+ caddr_t x_private; /* \fIpointer to private data\fP */
+ caddr_t x_base; /* \fIprivate for position info\fP */
+ int x_handy; /* \fIextra private word\fP */
+} XDR;
+.DE
+The
+.I x_op
+field is the current operation being performed on the stream.
+This field is important to the XDR primitives,
+but should not affect a stream's implementation.
+That is, a stream's implementation should not depend
+on this value.
+The fields
+.I x_private ,
+.I x_base ,
+and
+.I x_handy
+are private to the particular
+stream's implementation.
+The field
+.I x_public
+is for the XDR client and should never be used by
+the XDR stream implementations or the XDR primitives.
+.I x_getpostn() ,
+.I x_setpostn()
+and
+.I x_destroy()
+are macros for accessing operations. The operation
+.I x_inline()
+takes two parameters:
+an XDR *, and an unsigned integer, which is a byte count.
+The routine returns a pointer to a piece of
+the stream's internal buffer.
+The caller can then use the buffer segment for any purpose.
+From the stream's point of view, the bytes in the
+buffer segment have been consumed or put.
+The routine may return
+.I NULL
+if it cannot return a buffer segment of the requested size.
+(The
+.I x_inline()
+routine is for cycle squeezers.
+Use of the resulting buffer is not data-portable.
+Users are encouraged not to use this feature.)
+.LP
+The operations
+.I x_getbytes()
+and
+.I x_putbytes()
+blindly get and put sequences of bytes
+from or to the underlying stream;
+they return
+.I TRUE
+if they are successful, and
+.I FALSE
+otherwise. The routines have identical parameters (replace
+.I xxx ):
+.DS
+.ft CW
+bool_t
+xxxbytes(xdrs, buf, bytecount)
+ XDR *xdrs;
+ char *buf;
+ u_int bytecount;
+.DE
+The operations
+.I x_getlong()
+and
+.I x_putlong()
+receive and put
+long numbers from and to the data stream.
+It is the responsibility of these routines
+to translate the numbers between the machine representation
+and the (standard) external representation.
+The UNIX primitives
+.I htonl()
+and
+.I ntohl()
+can be helpful in accomplishing this.
+The higher-level XDR implementation assumes that
+signed and unsigned long integers contain the same number of bits,
+and that nonnegative integers
+have the same bit representations as unsigned integers.
+The routines return
+.I TRUE
+if they succeed, and
+.I FALSE
+otherwise. They have identical parameters:
+.DS
+.ft CW
+bool_t
+xxxlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+.DE
+Implementors of new XDR streams must make an XDR structure
+(with new operation routines) available to clients,
+using some kind of create routine.
+.NH 1
+\&Advanced Topics
+.IX XDR "advanced topics"
+.LP
+This section describes techniques for passing data structures that
+are not covered in the preceding sections. Such structures include
+linked lists (of arbitrary lengths). Unlike the simpler examples
+covered in the earlier sections, the following examples are written
+using both the XDR C library routines and the XDR data description
+language.
+The
+.I "External Data Representation Standard: Protocol Specification"
+describes this
+language in complete detail.
+.NH 2
+\&Linked Lists
+.IX XDR "linked lists"
+.LP
+The last example in the
+.I Pointers
+topic earlier in this chapter
+presented a C data structure and its associated XDR
+routines for a individual's gross assets and liabilities.
+The example is duplicated below:
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers {
+ long g_assets;
+ long g_liabilities;
+};
+.sp.5
+bool_t
+xdr_gnumbers(xdrs, gp)
+ XDR *xdrs;
+ struct gnumbers *gp;
+{
+ if (xdr_long(xdrs, &(gp->g_assets)))
+ return(xdr_long(xdrs, &(gp->g_liabilities)));
+ return(FALSE);
+}
+.DE
+.LP
+Now assume that we wish to implement a linked list of such information.
+A data structure could be constructed as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers_node {
+ struct gnumbers gn_numbers;
+ struct gnumbers_node *gn_next;
+};
+.sp .5
+typedef struct gnumbers_node *gnumbers_list;
+.DE
+.LP
+The head of the linked list can be thought of as the data object;
+that is, the head is not merely a convenient shorthand for a
+structure. Similarly the
+.I gn_next
+field is used to indicate whether or not the object has terminated.
+Unfortunately, if the object continues, the
+.I gn_next
+field is also the address of where it continues. The link addresses
+carry no useful information when the object is serialized.
+.LP
+The XDR data description of this linked list is described by the
+recursive declaration of
+.I gnumbers_list :
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers {
+ int g_assets;
+ int g_liabilities;
+};
+.sp .5
+struct gnumbers_node {
+ gnumbers gn_numbers;
+ gnumbers_node *gn_next;
+};
+.DE
+.LP
+In this description, the boolean indicates whether there is more data
+following it. If the boolean is
+.I FALSE ,
+then it is the last data field of the structure. If it is
+.I TRUE ,
+then it is followed by a gnumbers structure and (recursively) by a
+.I gnumbers_list .
+Note that the C declaration has no boolean explicitly declared in it
+(though the
+.I gn_next
+field implicitly carries the information), while the XDR data
+description has no pointer explicitly declared in it.
+.LP
+Hints for writing the XDR routines for a
+.I gnumbers_list
+follow easily from the XDR description above. Note how the primitive
+.I xdr_pointer()
+is used to implement the XDR union above.
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_gnumbers_node(xdrs, gn)
+ XDR *xdrs;
+ gnumbers_node *gn;
+{
+ return(xdr_gnumbers(xdrs, &gn->gn_numbers) &&
+ xdr_gnumbers_list(xdrs, &gp->gn_next));
+}
+.sp .5
+bool_t
+xdr_gnumbers_list(xdrs, gnp)
+ XDR *xdrs;
+ gnumbers_list *gnp;
+{
+ return(xdr_pointer(xdrs, gnp,
+ sizeof(struct gnumbers_node),
+ xdr_gnumbers_node));
+}
+.DE
+.LP
+The unfortunate side effect of XDR'ing a list with these routines
+is that the C stack grows linearly with respect to the number of
+node in the list. This is due to the recursion. The following
+routine collapses the above two mutually recursive into a single,
+non-recursive one.
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_gnumbers_list(xdrs, gnp)
+ XDR *xdrs;
+ gnumbers_list *gnp;
+{
+ bool_t more_data;
+ gnumbers_list *nextp;
+.sp .5
+ for (;;) {
+ more_data = (*gnp != NULL);
+ if (!xdr_bool(xdrs, &more_data)) {
+ return(FALSE);
+ }
+ if (! more_data) {
+ break;
+ }
+ if (xdrs->x_op == XDR_FREE) {
+ nextp = &(*gnp)->gn_next;
+ }
+ if (!xdr_reference(xdrs, gnp,
+ sizeof(struct gnumbers_node), xdr_gnumbers)) {
+
+ return(FALSE);
+ }
+ gnp = (xdrs->x_op == XDR_FREE) ?
+ nextp : &(*gnp)->gn_next;
+ }
+ *gnp = NULL;
+ return(TRUE);
+}
+.DE
+.LP
+The first task is to find out whether there is more data or not,
+so that this boolean information can be serialized. Notice that
+this statement is unnecessary in the
+.I XDR_DECODE
+case, since the value of more_data is not known until we
+deserialize it in the next statement.
+.LP
+The next statement XDR's the more_data field of the XDR union.
+Then if there is truly no more data, we set this last pointer to
+.I NULL
+to indicate the end of the list, and return
+.I TRUE
+because we are done. Note that setting the pointer to
+.I NULL
+is only important in the
+.I XDR_DECODE
+case, since it is already
+.I NULL
+in the
+.I XDR_ENCODE
+and
+XDR_FREE
+cases.
+.LP
+Next, if the direction is
+.I XDR_FREE ,
+the value of
+.I nextp
+is set to indicate the location of the next pointer in the list.
+We do this now because we need to dereference gnp to find the
+location of the next item in the list, and after the next
+statement the storage pointed to by
+.I gnp
+will be freed up and no be longer valid. We can't do this for all
+directions though, because in the
+.I XDR_DECODE
+direction the value of
+.I gnp
+won't be set until the next statement.
+.LP
+Next, we XDR the data in the node using the primitive
+.I xdr_reference ().
+.I xdr_reference()
+is like
+.I xdr_pointer()
+which we used before, but it does not
+send over the boolean indicating whether there is more data.
+We use it instead of
+.I xdr_pointer()
+because we have already XDR'd this information ourselves. Notice
+that the xdr routine passed is not the same type as an element
+in the list. The routine passed is
+.I xdr_gnumbers (),
+for XDR'ing gnumbers, but each element in the list is actually of
+type
+.I gnumbers_node .
+We don't pass
+.I xdr_gnumbers_node()
+because it is recursive, and instead use
+.I xdr_gnumbers()
+which XDR's all of the non-recursive part. Note that this trick
+will work only if the
+.I gn_numbers
+field is the first item in each element, so that their addresses
+are identical when passed to
+.I xdr_reference ().
+.LP
+Finally, we update
+.I gnp
+to point to the next item in the list. If the direction is
+.I XDR_FREE ,
+we set it to the previously saved value, otherwise we can
+dereference
+.I gnp
+to get the proper value. Though harder to understand than the
+recursive version, this non-recursive routine is far less likely
+to blow the C stack. It will also run more efficiently since
+a lot of procedure call overhead has been removed. Most lists
+are small though (in the hundreds of items or less) and the
+recursive version should be sufficient for them.
+.EQ
+delim off
+.EN
diff --git a/lib/libc/rpc/PSD.doc/xdr.rfc.ms b/lib/libc/rpc/PSD.doc/xdr.rfc.ms
new file mode 100644
index 0000000..d4baff5
--- /dev/null
+++ b/lib/libc/rpc/PSD.doc/xdr.rfc.ms
@@ -0,0 +1,1058 @@
+.\"
+.\" Must use -- tbl -- with this one
+.\"
+.\" @(#)xdr.rfc.ms 2.2 88/08/05 4.0 RPCSRC
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'External Data Representation Standard''Page %'
+.EH 'Page %''External Data Representation Standard'
+.IX "External Data Representation"
+.if \\n%=1 .bp
+.SH
+\&External Data Representation Standard: Protocol Specification
+.IX XDR RFC
+.IX XDR "protocol specification"
+.LP
+.NH 0
+\&Status of this Standard
+.nr OF 1
+.IX XDR "RFC status"
+.LP
+Note: This chapter specifies a protocol that Sun Microsystems, Inc., and
+others are using. It has been designated RFC1014 by the ARPA Network
+Information Center.
+.NH 1
+Introduction
+\&
+.LP
+XDR is a standard for the description and encoding of data. It is
+useful for transferring data between different computer
+architectures, and has been used to communicate data between such
+diverse machines as the Sun Workstation, VAX, IBM-PC, and Cray.
+XDR fits into the ISO presentation layer, and is roughly analogous in
+purpose to X.409, ISO Abstract Syntax Notation. The major difference
+between these two is that XDR uses implicit typing, while X.409 uses
+explicit typing.
+.LP
+XDR uses a language to describe data formats. The language can only
+be used only to describe data; it is not a programming language.
+This language allows one to describe intricate data formats in a
+concise manner. The alternative of using graphical representations
+(itself an informal language) quickly becomes incomprehensible when
+faced with complexity. The XDR language itself is similar to the C
+language [1], just as Courier [4] is similar to Mesa. Protocols such
+as Sun RPC (Remote Procedure Call) and the NFS (Network File System)
+use XDR to describe the format of their data.
+.LP
+The XDR standard makes the following assumption: that bytes (or
+octets) are portable, where a byte is defined to be 8 bits of data.
+A given hardware device should encode the bytes onto the various
+media in such a way that other hardware devices may decode the bytes
+without loss of meaning. For example, the Ethernet standard
+suggests that bytes be encoded in "little-endian" style [2], or least
+significant bit first.
+.NH 2
+\&Basic Block Size
+.IX XDR "basic block size"
+.IX XDR "block size"
+.LP
+The representation of all items requires a multiple of four bytes (or
+32 bits) of data. The bytes are numbered 0 through n-1. The bytes
+are read or written to some byte stream such that byte m always
+precedes byte m+1. If the n bytes needed to contain the data are not
+a multiple of four, then the n bytes are followed by enough (0 to 3)
+residual zero bytes, r, to make the total byte count a multiple of 4.
+.LP
+We include the familiar graphic box notation for illustration and
+comparison. In most illustrations, each box (delimited by a plus
+sign at the 4 corners and vertical bars and dashes) depicts a byte.
+Ellipses (...) between boxes show zero or more additional bytes where
+required.
+.ie t .DS
+.el .DS L
+\fIA Block\fP
+
+\f(CW+--------+--------+...+--------+--------+...+--------+
+| byte 0 | byte 1 |...|byte n-1| 0 |...| 0 |
++--------+--------+...+--------+--------+...+--------+
+|<-----------n bytes---------->|<------r bytes------>|
+|<-----------n+r (where (n+r) mod 4 = 0)>----------->|\fP
+
+.DE
+.NH 1
+\&XDR Data Types
+.IX XDR "data types"
+.IX "XDR data types"
+.LP
+Each of the sections that follow describes a data type defined in the
+XDR standard, shows how it is declared in the language, and includes
+a graphic illustration of its encoding.
+.LP
+For each data type in the language we show a general paradigm
+declaration. Note that angle brackets (< and >) denote
+variable length sequences of data and square brackets ([ and ]) denote
+fixed-length sequences of data. "n", "m" and "r" denote integers.
+For the full language specification and more formal definitions of
+terms such as "identifier" and "declaration", refer to
+.I "The XDR Language Specification" ,
+below.
+.LP
+For some data types, more specific examples are included.
+A more extensive example of a data description is in
+.I "An Example of an XDR Data Description"
+below.
+.NH 2
+\&Integer
+.IX XDR integer
+.LP
+An XDR signed integer is a 32-bit datum that encodes an integer in
+the range [-2147483648,2147483647]. The integer is represented in
+two's complement notation. The most and least significant bytes are
+0 and 3, respectively. Integers are declared as follows:
+.ie t .DS
+.el .DS L
+\fIInteger\fP
+
+\f(CW(MSB) (LSB)
++-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |
++-------+-------+-------+-------+
+<------------32 bits------------>\fP
+.DE
+.NH 2
+\&Unsigned Integer
+.IX XDR "unsigned integer"
+.IX XDR "integer, unsigned"
+.LP
+An XDR unsigned integer is a 32-bit datum that encodes a nonnegative
+integer in the range [0,4294967295]. It is represented by an
+unsigned binary number whose most and least significant bytes are 0
+and 3, respectively. An unsigned integer is declared as follows:
+.ie t .DS
+.el .DS L
+\fIUnsigned Integer\fP
+
+\f(CW(MSB) (LSB)
++-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |
++-------+-------+-------+-------+
+<------------32 bits------------>\fP
+.DE
+.NH 2
+\&Enumeration
+.IX XDR enumeration
+.LP
+Enumerations have the same representation as signed integers.
+Enumerations are handy for describing subsets of the integers.
+Enumerated data is declared as follows:
+.ft CW
+.DS
+enum { name-identifier = constant, ... } identifier;
+.DE
+For example, the three colors red, yellow, and blue could be
+described by an enumerated type:
+.DS
+.ft CW
+enum { RED = 2, YELLOW = 3, BLUE = 5 } colors;
+.DE
+It is an error to encode as an enum any other integer than those that
+have been given assignments in the enum declaration.
+.NH 2
+\&Boolean
+.IX XDR boolean
+.LP
+Booleans are important enough and occur frequently enough to warrant
+their own explicit type in the standard. Booleans are declared as
+follows:
+.DS
+.ft CW
+bool identifier;
+.DE
+This is equivalent to:
+.DS
+.ft CW
+enum { FALSE = 0, TRUE = 1 } identifier;
+.DE
+.NH 2
+\&Hyper Integer and Unsigned Hyper Integer
+.IX XDR "hyper integer"
+.IX XDR "integer, hyper"
+.LP
+The standard also defines 64-bit (8-byte) numbers called hyper
+integer and unsigned hyper integer. Their representations are the
+obvious extensions of integer and unsigned integer defined above.
+They are represented in two's complement notation. The most and
+least significant bytes are 0 and 7, respectively. Their
+declarations:
+.ie t .DS
+.el .DS L
+\fIHyper Integer\fP
+\fIUnsigned Hyper Integer\fP
+
+\f(CW(MSB) (LSB)
++-------+-------+-------+-------+-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |byte 4 |byte 5 |byte 6 |byte 7 |
++-------+-------+-------+-------+-------+-------+-------+-------+
+<----------------------------64 bits---------------------------->\fP
+.DE
+.NH 2
+\&Floating-point
+.IX XDR "integer, floating point"
+.IX XDR "floating-point integer"
+.LP
+The standard defines the floating-point data type "float" (32 bits or
+4 bytes). The encoding used is the IEEE standard for normalized
+single-precision floating-point numbers [3]. The following three
+fields describe the single-precision floating-point number:
+.RS
+.IP \fBS\fP:
+The sign of the number. Values 0 and 1 represent positive and
+negative, respectively. One bit.
+.IP \fBE\fP:
+The exponent of the number, base 2. 8 bits are devoted to this
+field. The exponent is biased by 127.
+.IP \fBF\fP:
+The fractional part of the number's mantissa, base 2. 23 bits
+are devoted to this field.
+.RE
+.LP
+Therefore, the floating-point number is described by:
+.DS
+(-1)**S * 2**(E-Bias) * 1.F
+.DE
+It is declared as follows:
+.ie t .DS
+.el .DS L
+\fISingle-Precision Floating-Point\fP
+
+\f(CW+-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |
+S| E | F |
++-------+-------+-------+-------+
+1|<- 8 ->|<-------23 bits------>|
+<------------32 bits------------>\fP
+.DE
+Just as the most and least significant bytes of a number are 0 and 3,
+the most and least significant bits of a single-precision floating-
+point number are 0 and 31. The beginning bit (and most significant
+bit) offsets of S, E, and F are 0, 1, and 9, respectively. Note that
+these numbers refer to the mathematical positions of the bits, and
+NOT to their actual physical locations (which vary from medium to
+medium).
+.LP
+The IEEE specifications should be consulted concerning the encoding
+for signed zero, signed infinity (overflow), and denormalized numbers
+(underflow) [3]. According to IEEE specifications, the "NaN" (not a
+number) is system dependent and should not be used externally.
+.NH 2
+\&Double-precision Floating-point
+.IX XDR "integer, double-precision floating point"
+.IX XDR "double-precision floating-point integer"
+.LP
+The standard defines the encoding for the double-precision floating-
+point data type "double" (64 bits or 8 bytes). The encoding used is
+the IEEE standard for normalized double-precision floating-point
+numbers [3]. The standard encodes the following three fields, which
+describe the double-precision floating-point number:
+.RS
+.IP \fBS\fP:
+The sign of the number. Values 0 and 1 represent positive and
+negative, respectively. One bit.
+.IP \fBE\fP:
+The exponent of the number, base 2. 11 bits are devoted to this
+field. The exponent is biased by 1023.
+.IP \fBF\fP:
+The fractional part of the number's mantissa, base 2. 52 bits
+are devoted to this field.
+.RE
+.LP
+Therefore, the floating-point number is described by:
+.DS
+(-1)**S * 2**(E-Bias) * 1.F
+.DE
+It is declared as follows:
+.ie t .DS
+.el .DS L
+\fIDouble-Precision Floating-Point\fP
+
+\f(CW+------+------+------+------+------+------+------+------+
+|byte 0|byte 1|byte 2|byte 3|byte 4|byte 5|byte 6|byte 7|
+S| E | F |
++------+------+------+------+------+------+------+------+
+1|<--11-->|<-----------------52 bits------------------->|
+<-----------------------64 bits------------------------->\fP
+.DE
+Just as the most and least significant bytes of a number are 0 and 3,
+the most and least significant bits of a double-precision floating-
+point number are 0 and 63. The beginning bit (and most significant
+bit) offsets of S, E , and F are 0, 1, and 12, respectively. Note
+that these numbers refer to the mathematical positions of the bits,
+and NOT to their actual physical locations (which vary from medium to
+medium).
+.LP
+The IEEE specifications should be consulted concerning the encoding
+for signed zero, signed infinity (overflow), and denormalized numbers
+(underflow) [3]. According to IEEE specifications, the "NaN" (not a
+number) is system dependent and should not be used externally.
+.NH 2
+\&Fixed-length Opaque Data
+.IX XDR "fixed-length opaque data"
+.IX XDR "opaque data, fixed length"
+.LP
+At times, fixed-length uninterpreted data needs to be passed among
+machines. This data is called "opaque" and is declared as follows:
+.DS
+.ft CW
+opaque identifier[n];
+.DE
+where the constant n is the (static) number of bytes necessary to
+contain the opaque data. If n is not a multiple of four, then the n
+bytes are followed by enough (0 to 3) residual zero bytes, r, to make
+the total byte count of the opaque object a multiple of four.
+.ie t .DS
+.el .DS L
+\fIFixed-Length Opaque\fP
+
+\f(CW0 1 ...
++--------+--------+...+--------+--------+...+--------+
+| byte 0 | byte 1 |...|byte n-1| 0 |...| 0 |
++--------+--------+...+--------+--------+...+--------+
+|<-----------n bytes---------->|<------r bytes------>|
+|<-----------n+r (where (n+r) mod 4 = 0)------------>|\fP
+.DE
+.NH 2
+\&Variable-length Opaque Data
+.IX XDR "variable-length opaque data"
+.IX XDR "opaque data, variable length"
+.LP
+The standard also provides for variable-length (counted) opaque data,
+defined as a sequence of n (numbered 0 through n-1) arbitrary bytes
+to be the number n encoded as an unsigned integer (as described
+below), and followed by the n bytes of the sequence.
+.LP
+Byte m of the sequence always precedes byte m+1 of the sequence, and
+byte 0 of the sequence always follows the sequence's length (count).
+enough (0 to 3) residual zero bytes, r, to make the total byte count
+a multiple of four. Variable-length opaque data is declared in the
+following way:
+.DS
+.ft CW
+opaque identifier<m>;
+.DE
+or
+.DS
+.ft CW
+opaque identifier<>;
+.DE
+The constant m denotes an upper bound of the number of bytes that the
+sequence may contain. If m is not specified, as in the second
+declaration, it is assumed to be (2**32) - 1, the maximum length.
+The constant m would normally be found in a protocol specification.
+For example, a filing protocol may state that the maximum data
+transfer size is 8192 bytes, as follows:
+.DS
+.ft CW
+opaque filedata<8192>;
+.DE
+This can be illustrated as follows:
+.ie t .DS
+.el .DS L
+\fIVariable-Length Opaque\fP
+
+\f(CW0 1 2 3 4 5 ...
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+| length n |byte0|byte1|...| n-1 | 0 |...| 0 |
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+|<-------4 bytes------->|<------n bytes------>|<---r bytes--->|
+|<----n+r (where (n+r) mod 4 = 0)---->|\fP
+.DE
+.LP
+It is an error to encode a length greater than the maximum
+described in the specification.
+.NH 2
+\&String
+.IX XDR string
+.LP
+The standard defines a string of n (numbered 0 through n-1) ASCII
+bytes to be the number n encoded as an unsigned integer (as described
+above), and followed by the n bytes of the string. Byte m of the
+string always precedes byte m+1 of the string, and byte 0 of the
+string always follows the string's length. If n is not a multiple of
+four, then the n bytes are followed by enough (0 to 3) residual zero
+bytes, r, to make the total byte count a multiple of four. Counted
+byte strings are declared as follows:
+.DS
+.ft CW
+string object<m>;
+.DE
+or
+.DS
+.ft CW
+string object<>;
+.DE
+The constant m denotes an upper bound of the number of bytes that a
+string may contain. If m is not specified, as in the second
+declaration, it is assumed to be (2**32) - 1, the maximum length.
+The constant m would normally be found in a protocol specification.
+For example, a filing protocol may state that a file name can be no
+longer than 255 bytes, as follows:
+.DS
+.ft CW
+string filename<255>;
+.DE
+Which can be illustrated as:
+.ie t .DS
+.el .DS L
+\fIA String\fP
+
+\f(CW0 1 2 3 4 5 ...
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+| length n |byte0|byte1|...| n-1 | 0 |...| 0 |
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+|<-------4 bytes------->|<------n bytes------>|<---r bytes--->|
+|<----n+r (where (n+r) mod 4 = 0)---->|\fP
+.DE
+.LP
+It is an error to encode a length greater than the maximum
+described in the specification.
+.NH 2
+\&Fixed-length Array
+.IX XDR "fixed-length array"
+.IX XDR "array, fixed length"
+.LP
+Declarations for fixed-length arrays of homogeneous elements are in
+the following form:
+.DS
+.ft CW
+type-name identifier[n];
+.DE
+Fixed-length arrays of elements numbered 0 through n-1 are encoded by
+individually encoding the elements of the array in their natural
+order, 0 through n-1. Each element's size is a multiple of four
+bytes. Though all elements are of the same type, the elements may
+have different sizes. For example, in a fixed-length array of
+strings, all elements are of type "string", yet each element will
+vary in its length.
+.ie t .DS
+.el .DS L
+\fIFixed-Length Array\fP
+
+\f(CW+---+---+---+---+---+---+---+---+...+---+---+---+---+
+| element 0 | element 1 |...| element n-1 |
++---+---+---+---+---+---+---+---+...+---+---+---+---+
+|<--------------------n elements------------------->|\fP
+.DE
+.NH 2
+\&Variable-length Array
+.IX XDR "variable-length array"
+.IX XDR "array, variable length"
+.LP
+Counted arrays provide the ability to encode variable-length arrays
+of homogeneous elements. The array is encoded as the element count n
+(an unsigned integer) followed by the encoding of each of the array's
+elements, starting with element 0 and progressing through element n-
+1. The declaration for variable-length arrays follows this form:
+.DS
+.ft CW
+type-name identifier<m>;
+.DE
+or
+.DS
+.ft CW
+type-name identifier<>;
+.DE
+The constant m specifies the maximum acceptable element count of an
+array; if m is not specified, as in the second declaration, it is
+assumed to be (2**32) - 1.
+.ie t .DS
+.el .DS L
+\fICounted Array\fP
+
+\f(CW0 1 2 3
++--+--+--+--+--+--+--+--+--+--+--+--+...+--+--+--+--+
+| n | element 0 | element 1 |...|element n-1|
++--+--+--+--+--+--+--+--+--+--+--+--+...+--+--+--+--+
+|<-4 bytes->|<--------------n elements------------->|\fP
+.DE
+It is an error to encode a value of n that is greater than the
+maximum described in the specification.
+.NH 2
+\&Structure
+.IX XDR structure
+.LP
+Structures are declared as follows:
+.DS
+.ft CW
+struct {
+ component-declaration-A;
+ component-declaration-B;
+ \&...
+} identifier;
+.DE
+The components of the structure are encoded in the order of their
+declaration in the structure. Each component's size is a multiple of
+four bytes, though the components may be different sizes.
+.ie t .DS
+.el .DS L
+\fIStructure\fP
+
+\f(CW+-------------+-------------+...
+| component A | component B |...
++-------------+-------------+...\fP
+.DE
+.NH 2
+\&Discriminated Union
+.IX XDR "discriminated union"
+.IX XDR union discriminated
+.LP
+A discriminated union is a type composed of a discriminant followed
+by a type selected from a set of prearranged types according to the
+value of the discriminant. The type of discriminant is either "int",
+"unsigned int", or an enumerated type, such as "bool". The component
+types are called "arms" of the union, and are preceded by the value
+of the discriminant which implies their encoding. Discriminated
+unions are declared as follows:
+.DS
+.ft CW
+union switch (discriminant-declaration) {
+ case discriminant-value-A:
+ arm-declaration-A;
+ case discriminant-value-B:
+ arm-declaration-B;
+ \&...
+ default: default-declaration;
+} identifier;
+.DE
+Each "case" keyword is followed by a legal value of the discriminant.
+The default arm is optional. If it is not specified, then a valid
+encoding of the union cannot take on unspecified discriminant values.
+The size of the implied arm is always a multiple of four bytes.
+.LP
+The discriminated union is encoded as its discriminant followed by
+the encoding of the implied arm.
+.ie t .DS
+.el .DS L
+\fIDiscriminated Union\fP
+
+\f(CW0 1 2 3
++---+---+---+---+---+---+---+---+
+| discriminant | implied arm |
++---+---+---+---+---+---+---+---+
+|<---4 bytes--->|\fP
+.DE
+.NH 2
+\&Void
+.IX XDR void
+.LP
+An XDR void is a 0-byte quantity. Voids are useful for describing
+operations that take no data as input or no data as output. They are
+also useful in unions, where some arms may contain data and others do
+not. The declaration is simply as follows:
+.DS
+.ft CW
+void;
+.DE
+Voids are illustrated as follows:
+.ie t .DS
+.el .DS L
+\fIVoid\fP
+
+\f(CW ++
+ ||
+ ++
+--><-- 0 bytes\fP
+.DE
+.NH 2
+\&Constant
+.IX XDR constant
+.LP
+The data declaration for a constant follows this form:
+.DS
+.ft CW
+const name-identifier = n;
+.DE
+"const" is used to define a symbolic name for a constant; it does not
+declare any data. The symbolic constant may be used anywhere a
+regular constant may be used. For example, the following defines a
+symbolic constant DOZEN, equal to 12.
+.DS
+.ft CW
+const DOZEN = 12;
+.DE
+.NH 2
+\&Typedef
+.IX XDR typedef
+.LP
+"typedef" does not declare any data either, but serves to define new
+identifiers for declaring data. The syntax is:
+.DS
+.ft CW
+typedef declaration;
+.DE
+The new type name is actually the variable name in the declaration
+part of the typedef. For example, the following defines a new type
+called "eggbox" using an existing type called "egg":
+.DS
+.ft CW
+typedef egg eggbox[DOZEN];
+.DE
+Variables declared using the new type name have the same type as the
+new type name would have in the typedef, if it was considered a
+variable. For example, the following two declarations are equivalent
+in declaring the variable "fresheggs":
+.DS
+.ft CW
+eggbox fresheggs;
+egg fresheggs[DOZEN];
+.DE
+When a typedef involves a struct, enum, or union definition, there is
+another (preferred) syntax that may be used to define the same type.
+In general, a typedef of the following form:
+.DS
+.ft CW
+typedef <<struct, union, or enum definition>> identifier;
+.DE
+may be converted to the alternative form by removing the "typedef"
+part and placing the identifier after the "struct", "union", or
+"enum" keyword, instead of at the end. For example, here are the two
+ways to define the type "bool":
+.DS
+.ft CW
+typedef enum { /* \fIusing typedef\fP */
+ FALSE = 0,
+ TRUE = 1
+ } bool;
+
+enum bool { /* \fIpreferred alternative\fP */
+ FALSE = 0,
+ TRUE = 1
+ };
+.DE
+The reason this syntax is preferred is one does not have to wait
+until the end of a declaration to figure out the name of the new
+type.
+.NH 2
+\&Optional-data
+.IX XDR "optional data"
+.IX XDR "data, optional"
+.LP
+Optional-data is one kind of union that occurs so frequently that we
+give it a special syntax of its own for declaring it. It is declared
+as follows:
+.DS
+.ft CW
+type-name *identifier;
+.DE
+This is equivalent to the following union:
+.DS
+.ft CW
+union switch (bool opted) {
+ case TRUE:
+ type-name element;
+ case FALSE:
+ void;
+} identifier;
+.DE
+It is also equivalent to the following variable-length array
+declaration, since the boolean "opted" can be interpreted as the
+length of the array:
+.DS
+.ft CW
+type-name identifier<1>;
+.DE
+Optional-data is not so interesting in itself, but it is very useful
+for describing recursive data-structures such as linked-lists and
+trees. For example, the following defines a type "stringlist" that
+encodes lists of arbitrary length strings:
+.DS
+.ft CW
+struct *stringlist {
+ string item<>;
+ stringlist next;
+};
+.DE
+It could have been equivalently declared as the following union:
+.DS
+.ft CW
+union stringlist switch (bool opted) {
+ case TRUE:
+ struct {
+ string item<>;
+ stringlist next;
+ } element;
+ case FALSE:
+ void;
+};
+.DE
+or as a variable-length array:
+.DS
+.ft CW
+struct stringlist<1> {
+ string item<>;
+ stringlist next;
+};
+.DE
+Both of these declarations obscure the intention of the stringlist
+type, so the optional-data declaration is preferred over both of
+them. The optional-data type also has a close correlation to how
+recursive data structures are represented in high-level languages
+such as Pascal or C by use of pointers. In fact, the syntax is the
+same as that of the C language for pointers.
+.NH 2
+\&Areas for Future Enhancement
+.IX XDR futures
+.LP
+The XDR standard lacks representations for bit fields and bitmaps,
+since the standard is based on bytes. Also missing are packed (or
+binary-coded) decimals.
+.LP
+The intent of the XDR standard was not to describe every kind of data
+that people have ever sent or will ever want to send from machine to
+machine. Rather, it only describes the most commonly used data-types
+of high-level languages such as Pascal or C so that applications
+written in these languages will be able to communicate easily over
+some medium.
+.LP
+One could imagine extensions to XDR that would let it describe almost
+any existing protocol, such as TCP. The minimum necessary for this
+are support for different block sizes and byte-orders. The XDR
+discussed here could then be considered the 4-byte big-endian member
+of a larger XDR family.
+.NH 1
+\&Discussion
+.sp 2
+.NH 2
+\&Why a Language for Describing Data?
+.IX XDR language
+.LP
+There are many advantages in using a data-description language such
+as XDR versus using diagrams. Languages are more formal than
+diagrams and lead to less ambiguous descriptions of data.
+Languages are also easier to understand and allow one to think of
+other issues instead of the low-level details of bit-encoding.
+Also, there is a close analogy between the types of XDR and a
+high-level language such as C or Pascal. This makes the
+implementation of XDR encoding and decoding modules an easier task.
+Finally, the language specification itself is an ASCII string that
+can be passed from machine to machine to perform on-the-fly data
+interpretation.
+.NH 2
+\&Why Only one Byte-Order for an XDR Unit?
+.IX XDR "byte order"
+.LP
+Supporting two byte-orderings requires a higher level protocol for
+determining in which byte-order the data is encoded. Since XDR is
+not a protocol, this can't be done. The advantage of this, though,
+is that data in XDR format can be written to a magnetic tape, for
+example, and any machine will be able to interpret it, since no
+higher level protocol is necessary for determining the byte-order.
+.NH 2
+\&Why does XDR use Big-Endian Byte-Order?
+.LP
+Yes, it is unfair, but having only one byte-order means you have to
+be unfair to somebody. Many architectures, such as the Motorola
+68000 and IBM 370, support the big-endian byte-order.
+.NH 2
+\&Why is the XDR Unit Four Bytes Wide?
+.LP
+There is a tradeoff in choosing the XDR unit size. Choosing a small
+size such as two makes the encoded data small, but causes alignment
+problems for machines that aren't aligned on these boundaries. A
+large size such as eight means the data will be aligned on virtually
+every machine, but causes the encoded data to grow too big. We chose
+four as a compromise. Four is big enough to support most
+architectures efficiently, except for rare machines such as the
+eight-byte aligned Cray. Four is also small enough to keep the
+encoded data restricted to a reasonable size.
+.NH 2
+\&Why must Variable-Length Data be Padded with Zeros?
+.IX XDR "variable-length data"
+.LP
+It is desirable that the same data encode into the same thing on all
+machines, so that encoded data can be meaningfully compared or
+checksummed. Forcing the padded bytes to be zero ensures this.
+.NH 2
+\&Why is there No Explicit Data-Typing?
+.LP
+Data-typing has a relatively high cost for what small advantages it
+may have. One cost is the expansion of data due to the inserted type
+fields. Another is the added cost of interpreting these type fields
+and acting accordingly. And most protocols already know what type
+they expect, so data-typing supplies only redundant information.
+However, one can still get the benefits of data-typing using XDR. One
+way is to encode two things: first a string which is the XDR data
+description of the encoded data, and then the encoded data itself.
+Another way is to assign a value to all the types in XDR, and then
+define a universal type which takes this value as its discriminant
+and for each value, describes the corresponding data type.
+.NH 1
+\&The XDR Language Specification
+.IX XDR language
+.sp 1
+.NH 2
+\&Notational Conventions
+.IX "XDR language" notation
+.LP
+This specification uses an extended Backus-Naur Form notation for
+describing the XDR language. Here is a brief description of the
+notation:
+.IP 1.
+The characters
+.I | ,
+.I ( ,
+.I ) ,
+.I [ ,
+.I ] ,
+.I " ,
+and
+.I *
+are special.
+.IP 2.
+Terminal symbols are strings of any characters surrounded by
+double quotes.
+.IP 3.
+Non-terminal symbols are strings of non-special characters.
+.IP 4.
+Alternative items are separated by a vertical bar ("\fI|\fP").
+.IP 5.
+Optional items are enclosed in brackets.
+.IP 6.
+Items are grouped together by enclosing them in parentheses.
+.IP 7.
+A
+.I *
+following an item means 0 or more occurrences of that item.
+.LP
+For example, consider the following pattern:
+.DS L
+"a " "very" (", " " very")* [" cold " "and"] " rainy " ("day" | "night")
+.DE
+.LP
+An infinite number of strings match this pattern. A few of them
+are:
+.DS
+"a very rainy day"
+"a very, very rainy day"
+"a very cold and rainy day"
+"a very, very, very cold and rainy night"
+.DE
+.NH 2
+\&Lexical Notes
+.IP 1.
+Comments begin with '/*' and terminate with '*/'.
+.IP 2.
+White space serves to separate items and is otherwise ignored.
+.IP 3.
+An identifier is a letter followed by an optional sequence of
+letters, digits or underbar ('_'). The case of identifiers is
+not ignored.
+.IP 4.
+A constant is a sequence of one or more decimal digits,
+optionally preceded by a minus-sign ('-').
+.NH 2
+\&Syntax Information
+.IX "XDR language" syntax
+.DS
+.ft CW
+declaration:
+ type-specifier identifier
+ | type-specifier identifier "[" value "]"
+ | type-specifier identifier "<" [ value ] ">"
+ | "opaque" identifier "[" value "]"
+ | "opaque" identifier "<" [ value ] ">"
+ | "string" identifier "<" [ value ] ">"
+ | type-specifier "*" identifier
+ | "void"
+.DE
+.DS
+.ft CW
+value:
+ constant
+ | identifier
+
+type-specifier:
+ [ "unsigned" ] "int"
+ | [ "unsigned" ] "hyper"
+ | "float"
+ | "double"
+ | "bool"
+ | enum-type-spec
+ | struct-type-spec
+ | union-type-spec
+ | identifier
+.DE
+.DS
+.ft CW
+enum-type-spec:
+ "enum" enum-body
+
+enum-body:
+ "{"
+ ( identifier "=" value )
+ ( "," identifier "=" value )*
+ "}"
+.DE
+.DS
+.ft CW
+struct-type-spec:
+ "struct" struct-body
+
+struct-body:
+ "{"
+ ( declaration ";" )
+ ( declaration ";" )*
+ "}"
+.DE
+.DS
+.ft CW
+union-type-spec:
+ "union" union-body
+
+union-body:
+ "switch" "(" declaration ")" "{"
+ ( "case" value ":" declaration ";" )
+ ( "case" value ":" declaration ";" )*
+ [ "default" ":" declaration ";" ]
+ "}"
+
+constant-def:
+ "const" identifier "=" constant ";"
+.DE
+.DS
+.ft CW
+type-def:
+ "typedef" declaration ";"
+ | "enum" identifier enum-body ";"
+ | "struct" identifier struct-body ";"
+ | "union" identifier union-body ";"
+
+definition:
+ type-def
+ | constant-def
+
+specification:
+ definition *
+.DE
+.NH 3
+\&Syntax Notes
+.IX "XDR language" syntax
+.LP
+.IP 1.
+The following are keywords and cannot be used as identifiers:
+"bool", "case", "const", "default", "double", "enum", "float",
+"hyper", "opaque", "string", "struct", "switch", "typedef", "union",
+"unsigned" and "void".
+.IP 2.
+Only unsigned constants may be used as size specifications for
+arrays. If an identifier is used, it must have been declared
+previously as an unsigned constant in a "const" definition.
+.IP 3.
+Constant and type identifiers within the scope of a specification
+are in the same name space and must be declared uniquely within this
+scope.
+.IP 4.
+Similarly, variable names must be unique within the scope of
+struct and union declarations. Nested struct and union declarations
+create new scopes.
+.IP 5.
+The discriminant of a union must be of a type that evaluates to
+an integer. That is, "int", "unsigned int", "bool", an enumerated
+type or any typedefed type that evaluates to one of these is legal.
+Also, the case values must be one of the legal values of the
+discriminant. Finally, a case value may not be specified more than
+once within the scope of a union declaration.
+.NH 1
+\&An Example of an XDR Data Description
+.LP
+Here is a short XDR data description of a thing called a "file",
+which might be used to transfer files from one machine to another.
+.ie t .DS
+.el .DS L
+.ft CW
+
+const MAXUSERNAME = 32; /*\fI max length of a user name \fP*/
+const MAXFILELEN = 65535; /*\fI max length of a file \fP*/
+const MAXNAMELEN = 255; /*\fI max length of a file name \fP*/
+
+.ft I
+/*
+ * Types of files:
+ */
+.ft CW
+
+enum filekind {
+ TEXT = 0, /*\fI ascii data \fP*/
+ DATA = 1, /*\fI raw data \fP*/
+ EXEC = 2 /*\fI executable \fP*/
+};
+
+.ft I
+/*
+ * File information, per kind of file:
+ */
+.ft CW
+
+union filetype switch (filekind kind) {
+ case TEXT:
+ void; /*\fI no extra information \fP*/
+ case DATA:
+ string creator<MAXNAMELEN>; /*\fI data creator \fP*/
+ case EXEC:
+ string interpretor<MAXNAMELEN>; /*\fI program interpretor \fP*/
+};
+
+.ft I
+/*
+ * A complete file:
+ */
+.ft CW
+
+struct file {
+ string filename<MAXNAMELEN>; /*\fI name of file \fP*/
+ filetype type; /*\fI info about file \fP*/
+ string owner<MAXUSERNAME>; /*\fI owner of file \fP*/
+ opaque data<MAXFILELEN>; /*\fI file data \fP*/
+};
+.DE
+.LP
+Suppose now that there is a user named "john" who wants to store
+his lisp program "sillyprog" that contains just the data "(quit)".
+His file would be encoded as follows:
+.TS
+box tab (&) ;
+lfI lfI lfI lfI
+rfL rfL rfL l .
+Offset&Hex Bytes&ASCII&Description
+_
+0&00 00 00 09&....&Length of filename = 9
+4&73 69 6c 6c&sill&Filename characters
+8&79 70 72 6f&ypro& ... and more characters ...
+12&67 00 00 00&g...& ... and 3 zero-bytes of fill
+16&00 00 00 02&....&Filekind is EXEC = 2
+20&00 00 00 04&....&Length of interpretor = 4
+24&6c 69 73 70&lisp&Interpretor characters
+28&00 00 00 04&....&Length of owner = 4
+32&6a 6f 68 6e&john&Owner characters
+36&00 00 00 06&....&Length of file data = 6
+40&28 71 75 69&(qui&File data bytes ...
+44&74 29 00 00&t)..& ... and 2 zero-bytes of fill
+.TE
+.NH 1
+\&References
+.LP
+[1] Brian W. Kernighan & Dennis M. Ritchie, "The C Programming
+Language", Bell Laboratories, Murray Hill, New Jersey, 1978.
+.LP
+[2] Danny Cohen, "On Holy Wars and a Plea for Peace", IEEE Computer,
+October 1981.
+.LP
+[3] "IEEE Standard for Binary Floating-Point Arithmetic", ANSI/IEEE
+Standard 754-1985, Institute of Electrical and Electronics
+Engineers, August 1985.
+.LP
+[4] "Courier: The Remote Procedure Call Protocol", XEROX
+Corporation, XSIS 038112, December 1981.
diff --git a/lib/libc/rpc/README b/lib/libc/rpc/README
new file mode 100644
index 0000000..ad9d70f
--- /dev/null
+++ b/lib/libc/rpc/README
@@ -0,0 +1,233 @@
+RPCSRC 4.0 7/11/89
+
+This distribution contains Sun Microsystem's implementation of the
+RPC and XDR protocols and is compatible with 4.2BSD and 4.3BSD. Also
+included is complete documentation, utilities, RPC service
+specification files, and demonstration services in the format used by
+the RPC protocol compiler (rpcgen). See WHAT'S NEW below for
+details.
+
+NOTE ABOUT SECURE RPC:
+
+This release of RPCSRC contains most of the code needed to implement
+Secure RPC (see "DES Authentication" in the RPC Protocol Specification,
+doc/rpc.rfc.ms). Due to legal considerations, we are unable to
+distribute an implementation of DES, the Data Encryption Standard, which
+Secure RPC requires. For this reason, all of the files, documentation, and
+programs associated with Secure RPC have been placed into a separate
+directory, secure_rpc. The RPC library contained in the main body of this
+release *DOES NOT* support Secure RPC. See secure_rpc/README for more
+details. (A DES library was posted in Volume 18 of comp.sources.unix.)
+
+If you wish to report bugs found in this release, send mail to:
+
+Portable ONC/NFS
+Sun Microsystems, Inc
+MS 12-33
+2550 Garcia Avenue
+Mountain View, CA 94043
+
+or send Email to nfsnet@sun.com (the Internet) or sun!nfsnet (Usenet).
+
+ROADMAP
+
+The directory hierarchy is as follows:
+
+ demo/ Various demonstration services
+ demo/dir Remote directory lister
+ demo/msg Remote console message delivery service
+ demo/sort Remote sort service
+
+ doc/ Documentation for RPC, XDR and NFS in "-ms" format.
+
+ etc/ Utilities (rpcinfo and portmap). portmap must be
+ started by root before any other RPC network services are
+ used. SEE BELOW FOR BUGFIX TO 4.3BSD COMPILER.
+
+ man/ Manual pages for RPC library, rpcgen, and utilities.
+
+ rpc/ The RPC and XDR library. SEE BELOW
+ FOR BUGFIX TO 4.2BSD COMPILER.
+
+ rpcgen/ The RPC Language compiler (for .x files)
+
+ rpcsvc/ Service definition files for various services and the
+ server and client code for the Remote Status service.
+
+ secure_rpc/ The files in this directory are used to build a version of
+ the RPC library with DES Authentication. See the README
+ file in that directory for more details.
+
+BUILD INSTRUCTIONS
+
+Makefiles can be found in all directories except for man. The
+Makefile in the top directory will cause these others to be invoked
+(except for in the doc, man and demo directories), in turn building the
+entire release.
+
+WARNING! THE DEFAULT INSTALLATION PROCEDURES WILL INSTALL FILES
+IN /usr/include, /usr/lib, /usr/bin and /etc.
+
+The master RPC include file, rpc/rpc.h, is used by all programs and
+routines that use RPC. It includes other RPC and system include files
+needed by the RPC system. PLEASE NOTE: If your system has NFS, it
+may have been based on Sun's NFS Source. The include files installed
+by this package may duplicate include files you will find on your NFS
+system. The RPCSRC 4.0 include files are upwardly compatible to all
+NFS Source include files as of the date of this distribution (not
+including any new definitions or declarations added by your system
+vendor). HOWEVER: Please read the comments towards the end of
+rpc/rpc.h regarding rpc/netdb.h. You may need to uncomment the
+inclusion of that file if the structures it defines are already
+defined by your system's include files.
+
+After making any compiler fixes that are needed (see below), at
+the top directory, type:
+
+ make install
+
+For all installations, the Makefile macro DESTDIR is prepended to the
+installation path. It is defined to be null in the Makefiles, so
+installations are relative to root. (You will probably need root
+privileges for installing the files under the default path.) To
+install the files under some other tree (e.g., /usr/local), use the
+command:
+
+ make install DESTDIR=/usr/local
+
+This will place the include files in /usr/local/usr/include, the RPC
+library in /usr/local/usr/lib, rpcgen in /usr/local/usr/bin, and the
+utilities in /usr/local/etc. You'll have to edit the Makefiles or
+install the files by hand if you want to do anything other than this
+kind of relocation of the installation tree.
+
+The RPC library will be built and installed first. By default it is
+installed in /usr/lib as "librpclib.a". The directory
+/usr/include/rpc will also be created, and several header files will
+be installed there. ALL RPC SERVICES INCLUDE THESE HEADER FILES.
+
+The programs in etc/ link in routines from librpclib.a. If you change
+where it is installed, be sure to edit etc/'s Makefile to reflect this.
+These programs are installed in /etc. PORTMAP MUST BE RUNNING ON
+YOUR SYSTEM BEFORE YOU START ANY OTHER RPC SERVICE.
+
+rpcgen is installed in /usr/bin. This program is required to build
+the demonstration services in demo and the rstat client and server in
+rpcsvc/.
+
+The rpcsvc/ directory will install its files in the directory
+/usr/include/rpcsvc. The Remote Status service (rstat_svc) will be
+compiled and installed in /etc. If you wish to make this service
+available, you should either start this service when needed or have
+it started at boot time by invoking it in your /etc/rc.local script.
+(Be sure that portmap is started first!) Sun has modified its
+version of inetd to automatically start RPC services. (Use "make
+LIB=" when building rstat on a Sun Workstation.) The Remote Status
+client (rstat) will be installed in /usr/bin. This program queries
+the rstat_svc on a remote host and prints a system status summary
+similar to the one printed by "uptime".
+
+The documentation is not built during the "make install" command.
+Typing "make" in the doc directory will cause all of the manuals to
+be formatted using nroff into a single file. We have had a report
+that certain "troff" equivalents have trouble processing the full
+manual. If you have trouble, try building the manuals individually
+(see the Makefile).
+
+The demonstration services in the demo directory are not built by the
+top-level "make install" command. To build these, cd to the demo
+directory and enter "make". The three services will be built.
+RPCGEN MUST BE INSTALLED in a path that make can find. To run the
+services, start the portmap program as root and 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
+portmap, and to ping the service (see rpcinfo's man page). You can
+then use the corresponding client program to exercise the service.
+To build these services on a Sun workstation, you must prevent the
+Makefile from trying to link the RPC library (as these routines are
+already a part of Sun's libc). Use: "make LIB=".
+
+BUGFIX FOR 4.3BSD COMPILER
+
+The use of a 'void *' declaration for one of the arguments in
+the reply_proc() procedure in etc/rpcinfo.c will trigger a bug
+in the 4.3BSD compiler. The bug is fixed by the following change to
+the compiler file mip/manifest.h:
+
+*** manifest.h.r1.1 Thu Apr 30 13:52:25 1987
+--- manifest.h.r1.2 Mon Nov 23 18:58:17 1987
+***************
+*** 21,27 ****
+ /*
+ * Bogus type values
+ */
+! #define TNULL PTR /* pointer to UNDEF */
+ #define TVOID FTN /* function returning UNDEF (for void) */
+
+ /*
+--- 21,27 ----
+ /*
+ * Bogus type values
+ */
+! #define TNULL INCREF(MOETY) /* pointer to MOETY -- impossible type */
+ #define TVOID FTN /* function returning UNDEF (for void) */
+
+ /*
+
+If you cannot fix your compiler, change the declaration in reply_proc()
+from 'void *' to 'char *'.
+
+BUGFIX FOR 4.2BSD COMPILER
+
+Unpatched 4.2BSD compilers complain about valid C. You can make old
+compilers happy by changing some voids to ints. However, the fix to
+the 4.2 VAX compiler is as follows (to mip/trees.c):
+
+*** trees.c.r1.1 Mon May 11 13:47:58 1987
+--- trees.c.r1.2 Wed Jul 2 18:28:52 1986
+***************
+*** 1247,1253 ****
+ if(o==CAST && mt1==0)return(TYPL+TYMATCH);
+ if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
+ else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
+! else if( mt12 == 0 ) break;
+ else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
+ else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
+ break;
+--- 1261,1269 ----
+ if(o==CAST && mt1==0)return(TYPL+TYMATCH);
+ if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
+ else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
+! /* if right is TVOID and looks like a CALL, is not ok */
+! else if (mt2 == 0 && (p->in.right->in.op == CALL || p->in.right->in.op == UNARY CALL))
+! break;
+ else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
+ else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
+ break;
+
+WHAT'S NEW IN THIS RELEASE: RPCSRC 4.0
+
+The previous release was RPCSRC 3.9. As with all previous releases,
+this release is based directly on files from Sun Microsystem's
+implementation.
+
+Upgrade from RPCSRC 3.9
+
+1) RPCSRC 4.0 upgrades RPCSRC 3.9. Improvements from SunOS 4.0 have
+ been integrated into this release.
+
+Secure RPC (in the secure_rpc/ directory)
+
+2) DES Authentication routines and programs are provided.
+3) A new manual, "Secure NFS" is provided, which describes Secure RPC
+ and Secure NFS.
+4) Skeleton routines and manual pages are provided which describe the
+ DES encryption procedures required by Secure RPC. HOWEVER, NO DES
+ ROUTINE IS PROVIDED.
+
+New Functionality
+
+5) rpcinfo can now be used to de-register services from the portmapper
+ which may have terminated abnormally.
+6) A new client, rstat, is provided which queries the rstat_svc and
+ prints a status line similar to the one displayed by "uptime".
diff --git a/lib/libc/rpc/auth_des.c b/lib/libc/rpc/auth_des.c
new file mode 100644
index 0000000..3fd2bfe
--- /dev/null
+++ b/lib/libc/rpc/auth_des.c
@@ -0,0 +1,554 @@
+/*
+ * 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 <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/cdefs.h>
+#include <rpc/des_crypt.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+#include <netinet/in.h> /* XXX: just to get htonl() and ntohl() */
+#include <sys/socket.h>
+#undef NIS
+#include <rpcsvc/nis.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/* from: static char sccsid[] = "@(#)auth_des.c 2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI"; */
+static const char rcsid[] = "$Id$";
+#endif
+
+extern bool_t __rpc_get_time_offset __P(( struct timeval *, nis_server *,
+ char *, char **, struct sockaddr_in * ));
+extern int rtime __P(( struct sockaddr_in *, struct timeval *, struct timeval *));
+extern bool_t xdr_authdes_cred __P(( XDR *, struct authdes_cred * ));
+extern bool_t xdr_authdes_verf __P(( XDR *, struct authdes_verf * ));
+
+#define MILLION 1000000L
+#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)
+
+#define debug(msg) /*printf("%s\n", msg) */
+
+/*
+ * DES authenticator operations vector
+ */
+static void authdes_nextverf();
+static bool_t authdes_marshal();
+static bool_t authdes_validate();
+static bool_t authdes_refresh();
+static void authdes_destroy();
+static struct auth_ops authdes_ops = {
+ authdes_nextverf,
+ authdes_marshal,
+ authdes_validate,
+ authdes_refresh,
+ authdes_destroy
+};
+#ifdef foo
+static bool_t synchronize __P(( struct sockaddr *, struct timeval *));
+#endif
+/*
+ * 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 sockaddr 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_long 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 */
+};
+
+
+/*
+ * Create the client des authentication object
+ */
+AUTH *
+authdes_create(servername, window, syncaddr, ckey)
+ char *servername; /* network name of server */
+ u_int window; /* time to live */
+ struct sockaddr *syncaddr; /* optional addr of host to sync with */
+ des_block *ckey; /* optional conversation key to use*/
+{
+
+ AUTH *auth;
+ struct ad_private *ad;
+ char namebuf[MAXNETNAMELEN+1];
+ u_char pkey_data[1024];
+
+ if (!getpublickey(servername, pkey_data))
+ return(NULL);
+
+ /*
+ * Allocate everything now
+ */
+ auth = ALLOC(AUTH);
+ ad = ALLOC(struct ad_private);
+ (void) getnetname(namebuf);
+
+ ad->ad_fullnamelen = RNDUP(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 (auth == NULL || ad == NULL || ad->ad_fullname == NULL ||
+ ad->ad_servername == NULL) {
+ debug("authdes_create: out of memory");
+ goto failed;
+ }
+
+ /*
+ * Set up private data
+ */
+ bcopy(namebuf, ad->ad_fullname, ad->ad_fullnamelen + 1);
+ bcopy(servername, ad->ad_servername, ad->ad_servernamelen + 1);
+ bcopy(pkey_data, ad->ad_pkey, strlen(pkey_data) + 1);
+ if (syncaddr != NULL) {
+ ad->ad_syncaddr = *syncaddr;
+ ad->ad_dosync = TRUE;
+ } else {
+ ad->ad_dosync = FALSE;
+ }
+ ad->ad_window = window;
+ if (ckey == NULL) {
+ if (key_gendes(&auth->ah_key) < 0) {
+ debug("authdes_create: unable to gen conversation key");
+ return (NULL);
+ }
+ } 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)) {
+ goto failed;
+ }
+ return (auth);
+
+failed:
+ if (auth != NULL)
+ FREE(auth, sizeof(AUTH));
+ if (ad != NULL)
+ FREE(ad, sizeof(struct ad_private));
+ if (ad->ad_fullname != NULL)
+ FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
+ if (ad->ad_servername != NULL)
+ FREE(ad->ad_servername, ad->ad_servernamelen + 1);
+ return (NULL);
+}
+
+/*
+ * Slightly modified version of authdes_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_create(servername, pkey, window, timehost, ckey, srvr)
+ char *servername; /* network name of server */
+ netobj *pkey; /* public key of server */
+ u_int window; /* time to live */
+ char *timehost; /* optional hostname to sync with */
+ des_block *ckey; /* optional conversation key to use */
+ nis_server *srvr; /* optional NIS+ server struct */
+{
+ AUTH *auth;
+ struct ad_private *ad;
+ char namebuf[MAXNETNAMELEN+1];
+
+ /*
+ * Allocate everything now
+ */
+ auth = ALLOC(AUTH);
+ if (auth == NULL) {
+ debug("authdes_pk_create: out of memory");
+ return (NULL);
+ }
+ ad = ALLOC(struct ad_private);
+ if (ad == NULL) {
+ debug("authdes_pk_create: 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) {
+ debug("authdes_pk_create: out of memory");
+ goto failed;
+ }
+ if (timehost != NULL) {
+ ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1);
+ if (ad->ad_timehost == NULL) {
+ debug("authdes_pk_create: 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) {
+ debug("authdes_pk_create: unable to gen conversation 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)) {
+ 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);
+ if (ad->ad_uaddr)
+ free(ad->ad_uaddr);
+ FREE(ad, sizeof (struct ad_private));
+ }
+ return (NULL);
+}
+/*
+ * Implement the five authentication operations
+ */
+
+
+/*
+ * 1. Next Verifier
+ */
+/*ARGSUSED*/
+static void
+authdes_nextverf(auth)
+ AUTH *auth;
+{
+ /* what the heck am I supposed to do??? */
+}
+
+
+
+/*
+ * 2. Marshal
+ */
+static bool_t
+authdes_marshal(auth, xdrs)
+ AUTH *auth;
+ XDR *xdrs;
+{
+ 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;
+ long len;
+ int32_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;
+ if (ad->ad_timestamp.tv_usec >= MILLION) {
+ ad->ad_timestamp.tv_usec -= MILLION;
+ ad->ad_timestamp.tv_sec += 1;
+ }
+
+ /*
+ * XDR the timestamp and possibly some other things, then
+ * encrypt them.
+ */
+ ixdr = (int32_t *)cryptbuf;
+ IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_sec);
+ IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_usec);
+ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+ IXDR_PUT_U_LONG(ixdr, ad->ad_window);
+ IXDR_PUT_U_LONG(ixdr, ad->ad_window - 1);
+ ivec.key.high = ivec.key.low = 0;
+ status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf,
+ 2*sizeof(des_block), DES_ENCRYPT | DES_HW, (char *)&ivec);
+ } else {
+ status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf,
+ sizeof(des_block), DES_ENCRYPT | DES_HW);
+ }
+ if (DES_FAILED(status)) {
+ debug("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_LONG(ixdr, AUTH_DES);
+ IXDR_PUT_LONG(ixdr, len);
+ } else {
+ ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_cred.oa_flavor));
+ ATTEMPT(xdr_putlong(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_LONG(ixdr, AUTH_DES);
+ IXDR_PUT_LONG(ixdr, len);
+ } else {
+ ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_verf.oa_flavor));
+ ATTEMPT(xdr_putlong(xdrs, &len));
+ }
+ ATTEMPT(xdr_authdes_verf(xdrs, verf));
+ return (TRUE);
+}
+
+
+/*
+ * 3. Validate
+ */
+static bool_t
+authdes_validate(auth, rverf)
+ AUTH *auth;
+ struct opaque_auth *rverf;
+{
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+ struct authdes_verf verf;
+ int status;
+ register u_long *ixdr;
+
+ if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) {
+ return (FALSE);
+ }
+ ixdr = (u_long *)rverf->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++; /* nickname not XDR'd ! */
+
+ /*
+ * Decrypt the timestamp
+ */
+ status = ecb_crypt((char *)&auth->ah_key, (char *)&verf.adv_xtimestamp,
+ sizeof(des_block), DES_DECRYPT | DES_HW);
+
+ if (DES_FAILED(status)) {
+ debug("authdes_validate: DES decryption failure");
+ return (FALSE);
+ }
+
+ /*
+ * xdr the decrypted timestamp
+ */
+ ixdr = (u_long *)verf.adv_xtimestamp.c;
+ verf.adv_timestamp.tv_sec = IXDR_GET_LONG(ixdr) + 1;
+ verf.adv_timestamp.tv_usec = IXDR_GET_LONG(ixdr);
+
+ /*
+ * validate
+ */
+ if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp,
+ sizeof(struct timeval)) != 0) {
+ debug("authdes_validate: verifier mismatch\n");
+ 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
+ */
+static bool_t
+authdes_refresh(auth)
+ AUTH *auth;
+{
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+ struct authdes_cred *cred = &ad->ad_cred;
+ netobj pkey;
+
+ if (ad->ad_dosync &&
+#ifdef old
+ !synchronize(&ad->ad_syncaddr, &ad->ad_timediff)) {
+#else
+ !__rpc_get_time_offset(&ad->ad_timediff,ad->ad_nis_srvr,
+ ad->ad_timehost, &(ad->ad_uaddr),
+ (struct sockaddr_in *)&(ad->ad_syncaddr))) {
+#endif
+ /*
+ * Hope the clocks are synced!
+ */
+ ad->ad_timediff.tv_sec = ad->ad_timediff.tv_usec = 0;
+ ad->ad_dosync = 0;
+ debug("authdes_refresh: unable to synchronize with server");
+ }
+ ad->ad_xkey = auth->ah_key;
+ pkey.n_bytes = (char *)(ad->ad_pkey);
+ pkey.n_len = strlen((char *)ad->ad_pkey) + 1;
+ if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) {
+ debug("authdes_create: unable to encrypt conversation 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 *auth;
+{
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+
+ FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
+ FREE(ad->ad_servername, ad->ad_servernamelen + 1);
+ FREE(ad, sizeof(struct ad_private));
+ FREE(auth, sizeof(AUTH));
+}
+
+
+#ifdef old
+/*
+ * Synchronize with the server at the given address, that is,
+ * adjust timep to reflect the delta between our clocks
+ */
+static bool_t
+synchronize(syncaddr, timep)
+ struct sockaddr *syncaddr;
+ struct timeval *timep;
+{
+ struct timeval mytime;
+ struct timeval timeout;
+
+ timeout.tv_sec = RTIME_TIMEOUT;
+ timeout.tv_usec = 0;
+ if (rtime((struct sockaddr_in *)syncaddr, timep, NULL /*&timeout*/) < 0) {
+ return (FALSE);
+ }
+ (void) gettimeofday(&mytime, (struct timezone *)NULL);
+ timep->tv_sec -= mytime.tv_sec;
+ if (mytime.tv_usec > timep->tv_usec) {
+ timep->tv_sec -= 1;
+ timep->tv_usec += MILLION;
+ }
+ timep->tv_usec -= mytime.tv_usec;
+ return (TRUE);
+}
+#endif
diff --git a/lib/libc/rpc/auth_none.c b/lib/libc/rpc/auth_none.c
new file mode 100644
index 0000000..b2e2995
--- /dev/null
+++ b/lib/libc/rpc/auth_none.c
@@ -0,0 +1,136 @@
+/*
+ * 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 = "from: @(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: auth_none.c,v 1.5 1996/12/30 14:13:30 peter Exp $";
+#endif
+
+/*
+ * auth_none.c
+ * Creates a client authentication handle for passing "null"
+ * credentials and verifiers to remote systems.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdlib.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#define MAX_MARSHEL_SIZE 20
+
+/*
+ * Authenticator operations routines
+ */
+static void authnone_verf();
+static void authnone_destroy();
+static bool_t authnone_marshal();
+static bool_t authnone_validate();
+static bool_t authnone_refresh();
+
+static struct auth_ops ops = {
+ authnone_verf,
+ authnone_marshal,
+ authnone_validate,
+ authnone_refresh,
+ authnone_destroy
+};
+
+static struct authnone_private {
+ AUTH no_client;
+ char marshalled_client[MAX_MARSHEL_SIZE];
+ u_int mcnt;
+} *authnone_private;
+
+AUTH *
+authnone_create()
+{
+ register struct authnone_private *ap = authnone_private;
+ XDR xdr_stream;
+ register XDR *xdrs;
+
+ if (ap == 0) {
+ ap = (struct authnone_private *)calloc(1, sizeof (*ap));
+ if (ap == 0)
+ 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 = &ops;
+ xdrs = &xdr_stream;
+ xdrmem_create(xdrs, ap->marshalled_client, (u_int)MAX_MARSHEL_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);
+ }
+ return (&ap->no_client);
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_marshal(client, xdrs)
+ AUTH *client;
+ XDR *xdrs;
+{
+ register struct authnone_private *ap = authnone_private;
+
+ if (ap == 0)
+ return (0);
+ return ((*xdrs->x_ops->x_putbytes)(xdrs,
+ ap->marshalled_client, ap->mcnt));
+}
+
+static void
+authnone_verf()
+{
+}
+
+static bool_t
+authnone_validate()
+{
+
+ return (TRUE);
+}
+
+static bool_t
+authnone_refresh()
+{
+
+ return (FALSE);
+}
+
+static void
+authnone_destroy()
+{
+}
diff --git a/lib/libc/rpc/auth_time.c b/lib/libc/rpc/auth_time.c
new file mode 100644
index 0000000..3128e6d
--- /dev/null
+++ b/lib/libc/rpc/auth_time.c
@@ -0,0 +1,501 @@
+#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.
+ *
+ * NOTE: This code has had the crap beaten out it in order to convert
+ * it from TI-RPC back to TD-RPC for use on FreeBSD.
+ */
+#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>
+#undef NIS
+#include <rpcsvc/nis.h>
+
+/*
+ * FreeBSD currently uses RPC 4.0, which uses portmap rather than
+ * rpcbind. Consequently, we need to fake up these values here.
+ * Luckily, the RPCB_GETTIME procedure uses only base XDR data types
+ * so we don't need anything besides these magic numbers.
+ */
+#define RPCBPROG (u_long)100000
+#define RPCBVERS (u_long)3
+#define RPCBPROC_GETTIME (u_long)6
+
+#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];
+
+ 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; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
+ i++, 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));
+ eps[num_ep].uaddr = strdup(hname);
+ eps[num_ep].family = strdup("inet");
+ eps[num_ep].proto = strdup("tcp");
+ }
+
+ for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
+ i++, 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));
+ eps[num_ep].uaddr = strdup(hname);
+ eps[num_ep].family = strdup("inet");
+ eps[num_ep].proto = strdup("udp");
+ }
+
+ 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;
+ int s = RPC_ANYSOCK, len;
+ 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, xdr_void, NULL,
+ xdr_u_long, (char *)&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..32200c2
--- /dev/null
+++ b/lib/libc/rpc/auth_unix.c
@@ -0,0 +1,349 @@
+/*
+ * 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 = "from: @(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: auth_unix.c,v 1.7 1996/12/30 14:14:39 peter Exp $";
+#endif
+
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/param.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+
+/*
+ * Unix authenticator operations vector
+ */
+static void authunix_nextverf();
+static bool_t authunix_marshal();
+static bool_t authunix_validate();
+static bool_t authunix_refresh();
+static void authunix_destroy();
+
+static struct auth_ops auth_unix_ops = {
+ authunix_nextverf,
+ authunix_marshal,
+ authunix_validate,
+ authunix_refresh,
+ authunix_destroy
+};
+
+/*
+ * 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)
+
+static void marshal_new_auth();
+
+/*
+ * This goop is here because some servers refuse to accept a
+ * credential with more than some number (usually 8) supplementary
+ * groups. Blargh!
+ */
+static int authunix_maxgrouplist = 0;
+
+void
+set_rpc_maxgrouplist(int num)
+{
+ authunix_maxgrouplist = num;
+}
+
+/*
+ * 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;
+ register int len;
+ int *aup_gids;
+{
+ struct authunix_parms aup;
+ char mymem[MAX_AUTH_BYTES];
+ struct timeval now;
+ XDR xdrs;
+ register AUTH *auth;
+ register struct audata *au;
+
+ /*
+ * Allocate and set up auth handle
+ */
+ auth = (AUTH *)mem_alloc(sizeof(*auth));
+#ifndef KERNEL
+ if (auth == NULL) {
+ (void)fprintf(stderr, "authunix_create: out of memory\n");
+ return (NULL);
+ }
+#endif
+ au = (struct audata *)mem_alloc(sizeof(*au));
+#ifndef KERNEL
+ if (au == NULL) {
+ (void)fprintf(stderr, "authunix_create: out of memory\n");
+ return (NULL);
+ }
+#endif
+ auth->ah_ops = &auth_unix_ops;
+ auth->ah_private = (caddr_t)au;
+ auth->ah_verf = au->au_shcred = _null_auth;
+ au->au_shfaults = 0;
+
+ /*
+ * fill in param struct from the given params
+ */
+ (void)gettimeofday(&now, (struct timezone *)0);
+ aup.aup_time = now.tv_sec;
+ aup.aup_machname = machname;
+ aup.aup_uid = uid;
+ aup.aup_gid = gid;
+ /* GW: continuation of max group list hack */
+ if(authunix_maxgrouplist != 0) {
+ aup.aup_len = ((len < authunix_maxgrouplist) ? len
+ : authunix_maxgrouplist);
+ } else {
+ 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) {
+ (void)fprintf(stderr, "authunix_create: out of memory\n");
+ return (NULL);
+ }
+#endif
+ memcpy(au->au_origcred.oa_base, mymem, (u_int)len);
+
+ /*
+ * set auth handle to reflect new cred.
+ */
+ auth->ah_cred = au->au_origcred;
+ marshal_new_auth(auth);
+ return (auth);
+}
+
+/*
+ * Returns an auth handle with parameters determined by doing lots of
+ * syscalls.
+ */
+AUTH *
+authunix_create_default()
+{
+ register int len;
+ char machname[MAX_MACHINE_NAME + 1];
+ register int uid;
+ register int gid;
+ int gids[NGRPS];
+ int i;
+ gid_t real_gids[NGROUPS];
+
+ if (gethostname(machname, MAX_MACHINE_NAME) == -1)
+ abort();
+ machname[MAX_MACHINE_NAME] = 0;
+ uid = (int)geteuid();
+ gid = (int)getegid();
+ if ((len = getgroups(NGROUPS, real_gids)) < 0)
+ abort();
+ if(len > NGRPS) len = NGRPS; /* GW: turn `gid_t's into `int's */
+ for(i = 0; i < len; i++) {
+ gids[i] = (int)real_gids[i];
+ }
+ return (authunix_create(machname, uid, gid, len, gids));
+}
+
+/*
+ * authunix operations
+ */
+
+static void
+authunix_nextverf(auth)
+ AUTH *auth;
+{
+ /* no action necessary */
+}
+
+static bool_t
+authunix_marshal(auth, xdrs)
+ AUTH *auth;
+ XDR *xdrs;
+{
+ register struct audata *au = AUTH_PRIVATE(auth);
+
+ return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
+}
+
+static bool_t
+authunix_validate(auth, verf)
+ register AUTH *auth;
+ struct opaque_auth verf;
+{
+ register struct audata *au;
+ XDR xdrs;
+
+ 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)
+ register AUTH *auth;
+{
+ register struct audata *au = AUTH_PRIVATE(auth);
+ struct authunix_parms aup;
+ struct timeval now;
+ XDR xdrs;
+ register int stat;
+
+ 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 = (int *)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, (struct timezone *)0);
+ 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)
+ register AUTH *auth;
+{
+ register struct audata *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((caddr_t)auth, sizeof(*auth));
+}
+
+/*
+ * Marshals (pre-serializes) an auth struct.
+ * sets private data, au_marshed and au_mpos
+ */
+static void
+marshal_new_auth(auth)
+ register AUTH *auth;
+{
+ XDR xdr_stream;
+ register XDR *xdrs = &xdr_stream;
+ register struct audata *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)))) {
+ perror("auth_none.c - Fatal marshalling problem");
+ } else {
+ au->au_mpos = XDR_GETPOS(xdrs);
+ }
+ XDR_DESTROY(xdrs);
+}
diff --git a/lib/libc/rpc/authdes_prot.c b/lib/libc/rpc/authdes_prot.c
new file mode 100644
index 0000000..14679c0
--- /dev/null
+++ b/lib/libc/rpc/authdes_prot.c
@@ -0,0 +1,82 @@
+#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
+/*
+ * 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.
+ */
+
+/*
+ * authdes_prot.c, XDR routines for DES authentication
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+
+#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
+
+bool_t
+xdr_authdes_cred(xdrs, cred)
+ XDR *xdrs;
+ struct authdes_cred *cred;
+{
+ /*
+ * Unrolled xdr
+ */
+ ATTEMPT(xdr_enum(xdrs, (enum_t *)&cred->adc_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)
+ register XDR *xdrs;
+ register 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..c818ba0
--- /dev/null
+++ b/lib/libc/rpc/authunix_prot.c
@@ -0,0 +1,68 @@
+/*
+ * 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 = "from: @(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)authunix_prot.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: authunix_prot.c,v 1.2 1995/05/30 05:41:12 rgrimes Exp $";
+#endif
+
+/*
+ * authunix_prot.c
+ * XDR for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+
+/*
+ * XDR for unix authentication parameters.
+ */
+bool_t
+xdr_authunix_parms(xdrs, p)
+ register XDR *xdrs;
+ register struct authunix_parms *p;
+{
+
+ 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, (caddr_t *)&(p->aup_gids),
+ &(p->aup_len), NGRPS, sizeof(int), 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..b21d65e
--- /dev/null
+++ b/lib/libc/rpc/bindresvport.3
@@ -0,0 +1,30 @@
+.\" @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI
+.Dd November 22, 1987
+.Dt BINDRESVPORT 3
+.Os
+.Sh NAME
+.Nm bindresvport
+.Ndbind a socket to a privileged IP port
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <netinet/in.h>
+.Ft int
+.Fn bindresvport "int sd" "struct sockaddr_in **sin"
+.Sh DESCRIPTION
+.Nm Bindresvport
+is used to bind a socket descriptor to a privileged
+.Tn IP
+port, that is, a
+port number in the range 0-1023.
+The routine returns 0 if it is successful,
+otherwise -1 is returned and
+.Va errno
+set to reflect the cause of the error.
+.Pp
+Only root can bind to a privileged port; this call will fail for any
+other users.
+.Pp
+If the value of sin->sin_port is non-zero
+.Fn bindresvport
+will attempt to use that specific port. If it fails, it chooses another
+privileged port automatically.
diff --git a/lib/libc/rpc/bindresvport.c b/lib/libc/rpc/bindresvport.c
new file mode 100644
index 0000000..dea8705
--- /dev/null
+++ b/lib/libc/rpc/bindresvport.c
@@ -0,0 +1,107 @@
+/*
+ * 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 = "from: @(#)bindresvport.c 1.8 88/02/08 SMI";*/
+/*static char *sccsid = "from: @(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC";*/
+/*from: OpenBSD: bindresvport.c,v 1.7 1996/07/30 16:25:47 downsj Exp */
+static char *rcsid = "$Id: bindresvport.c,v 1.6 1996/12/30 14:12:36 peter Exp $";
+#endif
+
+/*
+ * Copyright (c) 1987 by Sun Microsystems, Inc.
+ *
+ * Portions Copyright(C) 1996, Jason Downs. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <string.h>
+
+/*
+ * Bind a socket to a privileged IP port
+ */
+int
+bindresvport(sd, sin)
+ int sd;
+ struct sockaddr_in *sin;
+{
+ int on, old, error;
+ struct sockaddr_in myaddr;
+ int sinlen = sizeof(struct sockaddr_in);
+
+ if (sin == (struct sockaddr_in *)0) {
+ sin = &myaddr;
+ memset(sin, 0, sinlen);
+ sin->sin_len = sinlen;
+ sin->sin_family = AF_INET;
+ } else if (sin->sin_family != AF_INET) {
+ errno = EPFNOSUPPORT;
+ return (-1);
+ }
+
+ if (sin->sin_port == 0) {
+ int oldlen = sizeof(old);
+ error = getsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
+ &old, &oldlen);
+ if (error < 0)
+ return(error);
+
+ on = IP_PORTRANGE_LOW;
+ error = setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
+ &on, sizeof(on));
+ if (error < 0)
+ return(error);
+ }
+
+ error = bind(sd, (struct sockaddr *)sin, sinlen);
+
+ if (sin->sin_port == 0) {
+ int saved_errno = errno;
+
+ if (error) {
+ if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
+ &old, sizeof(old)) < 0)
+ errno = saved_errno;
+ return (error);
+ }
+
+ if (sin != &myaddr) {
+ /* Hmm, what did the kernel assign... */
+ if (getsockname(sd, (struct sockaddr *)sin,
+ &sinlen) < 0)
+ errno = saved_errno;
+ return (error);
+ }
+ }
+ return (error);
+}
diff --git a/lib/libc/rpc/clnt_generic.c b/lib/libc/rpc/clnt_generic.c
new file mode 100644
index 0000000..ed754ea
--- /dev/null
+++ b/lib/libc/rpc/clnt_generic.c
@@ -0,0 +1,137 @@
+/*
+ * 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 = "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";*/
+static char *rcsid = "$Id: clnt_generic.c,v 1.5 1996/12/30 14:17:20 peter Exp $";
+#endif
+
+/*
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <netdb.h>
+#include <string.h>
+
+/*
+ * Generic client creation: takes (hostname, program-number, protocol) and
+ * returns client handle. Default options are set, which the user can
+ * change using the rpc equivalent of ioctl()'s.
+ */
+CLIENT *
+clnt_create(hostname, prog, vers, proto)
+ char *hostname;
+ u_long prog;
+ u_long vers;
+ char *proto;
+{
+ struct hostent *h;
+ struct protoent *p;
+ struct sockaddr_in sin;
+ struct sockaddr_un sun;
+ int sock;
+ static struct timeval tv;
+ CLIENT *client;
+
+ if (!strcmp(proto, "unix")) {
+ bzero((char *)&sun, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ strcpy(sun.sun_path, hostname);
+ sun.sun_len = sizeof(sun.sun_len) + sizeof(sun.sun_family) +
+ strlen(sun.sun_path) + 1;
+ sock = RPC_ANYSOCK;
+ client = clntunix_create(&sun, prog, vers, &sock, 0, 0);
+ if (client == NULL)
+ return(NULL);
+ tv.tv_sec = 25;
+ tv.tv_usec = 0;
+ clnt_control(client, CLSET_TIMEOUT, &tv);
+ return(client);
+ }
+
+ h = gethostbyname(hostname);
+ if (h == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
+ return (NULL);
+ }
+ if (h->h_addrtype != AF_INET) {
+ /*
+ * Only support INET for now
+ */
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = h->h_addrtype;
+ sin.sin_port = 0;
+ memcpy((char*)&sin.sin_addr, h->h_addr, h->h_length);
+ p = getprotobyname(proto);
+ if (p == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
+ return (NULL);
+ }
+ sock = RPC_ANYSOCK;
+ switch (p->p_proto) {
+ case IPPROTO_UDP:
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ client = clntudp_create(&sin, prog, vers, tv, &sock);
+ if (client == NULL) {
+ return (NULL);
+ }
+#if 0 /* XXX do we need this? */
+ tv.tv_sec = 25;
+ tv.tv_usec = 0;
+ clnt_control(client, CLSET_TIMEOUT, &tv);
+#endif
+ break;
+ case IPPROTO_TCP:
+ client = clnttcp_create(&sin, prog, vers, &sock, 0, 0);
+ if (client == NULL) {
+ return (NULL);
+ }
+#if 0 /* XXX do we need this? */
+ tv.tv_sec = 25;
+ tv.tv_usec = 0;
+ clnt_control(client, CLSET_TIMEOUT, &tv);
+#endif
+ break;
+ default:
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
+ return (NULL);
+ }
+ return (client);
+}
diff --git a/lib/libc/rpc/clnt_perror.c b/lib/libc/rpc/clnt_perror.c
new file mode 100644
index 0000000..79baac2
--- /dev/null
+++ b/lib/libc/rpc/clnt_perror.c
@@ -0,0 +1,254 @@
+/*
+ * 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 = "from: @(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: clnt_perror.c,v 1.6 1996/12/30 14:19:34 peter Exp $";
+#endif
+
+/*
+ * clnt_perror.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+#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>
+
+static char *auth_errmsg();
+#define CLNT_PERROR_BUFLEN 256
+
+static char *buf;
+
+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;
+ char *s;
+{
+ struct rpc_err e;
+ char *err;
+ char *str = _buf();
+ char *strstart = str;
+
+ if (str == 0)
+ return (0);
+ CLNT_GETERR(rpch, &e);
+
+ (void) sprintf(str, "%s: %s", s, clnt_sperrno(e.re_status));
+ str += strlen(str);
+
+ 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:
+ (void) snprintf(str, CLNT_PERROR_BUFLEN - (str - strstart),
+ "; errno = %s\n", strerror(e.re_errno));
+ break;
+
+ case RPC_VERSMISMATCH:
+ (void) sprintf(str,
+ "; low version = %lu, high version = %lu\n",
+ e.re_vers.low, e.re_vers.high);
+ break;
+
+ case RPC_AUTHERROR:
+ err = auth_errmsg(e.re_why);
+ (void) sprintf(str,"; why = ");
+ str += strlen(str);
+ if (err != NULL) {
+ (void) sprintf(str, "%s\n",err);
+ } else {
+ (void) sprintf(str,
+ "(unknown authentication error - %d)\n",
+ (int) e.re_why);
+ }
+ break;
+
+ case RPC_PROGVERSMISMATCH:
+ (void) sprintf(str,
+ "; low version = %lu, high version = %lu\n",
+ e.re_vers.low, e.re_vers.high);
+ break;
+
+ default: /* unknown */
+ (void) sprintf(str,
+ "; s1 = %lu, s2 = %lu\n",
+ e.re_lb.s1, e.re_lb.s2);
+ break;
+ }
+ strstart[CLNT_PERROR_BUFLEN-2] = '\n';
+ strstart[CLNT_PERROR_BUFLEN-1] = '\0';
+ return(strstart) ;
+}
+
+void
+clnt_perror(rpch, s)
+ CLIENT *rpch;
+ char *s;
+{
+ (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])))
+ 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)
+ char *s;
+{
+ char *str = _buf();
+
+ if (str == 0)
+ return(0);
+ switch (rpc_createerr.cf_stat) {
+ case RPC_PMAPFAILURE:
+ (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s,
+ clnt_sperrno(rpc_createerr.cf_stat),
+ clnt_sperrno(rpc_createerr.cf_error.re_status));
+ break;
+
+ case RPC_SYSTEMERROR:
+ (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s,
+ clnt_sperrno(rpc_createerr.cf_stat),
+ strerror(rpc_createerr.cf_error.re_errno));
+ break;
+ default:
+ (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s\n", s,
+ clnt_sperrno(rpc_createerr.cf_stat));
+ break;
+ }
+ str[CLNT_PERROR_BUFLEN-2] = '\n';
+ str[CLNT_PERROR_BUFLEN-1] = '\0';
+ return (str);
+}
+
+void
+clnt_pcreateerror(s)
+ char *s;
+{
+ (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 */
+};
+
+static char *
+auth_errmsg(stat)
+ enum auth_stat stat;
+{
+ unsigned int errnum = stat;
+
+ if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0])))
+ 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..c715ef69
--- /dev/null
+++ b/lib/libc/rpc/clnt_raw.c
@@ -0,0 +1,242 @@
+/*
+ * 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 = "from: @(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: clnt_raw.c,v 1.6 1996/12/30 14:21:36 peter Exp $";
+#endif
+
+/*
+ * 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 kernal.
+ */
+
+#include <rpc/rpc.h>
+#include <stdlib.h>
+#include <stdio.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[UDPMSGSIZE];
+ char mashl_callmsg[MCALL_MSG_SIZE];
+ u_int mcnt;
+} *clntraw_private;
+
+static enum clnt_stat clntraw_call();
+static void clntraw_abort();
+static void clntraw_geterr();
+static bool_t clntraw_freeres();
+static bool_t clntraw_control();
+static void clntraw_destroy();
+
+static struct clnt_ops client_ops = {
+ clntraw_call,
+ clntraw_abort,
+ clntraw_geterr,
+ clntraw_freeres,
+ clntraw_destroy,
+ clntraw_control
+};
+
+void svc_getreq();
+
+/*
+ * Create a client handle for memory based rpc.
+ */
+CLIENT *
+clntraw_create(prog, vers)
+ u_long prog;
+ u_long vers;
+{
+ register struct clntraw_private *clp = clntraw_private;
+ struct rpc_msg call_msg;
+ XDR *xdrs = &clp->xdr_stream;
+ CLIENT *client = &clp->client_object;
+
+ if (clp == 0) {
+ clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
+ if (clp == 0)
+ return (0);
+ clntraw_private = clp;
+ }
+ /*
+ * 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;
+ call_msg.rm_call.cb_prog = prog;
+ call_msg.rm_call.cb_vers = vers;
+ xdrmem_create(xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
+ if (! xdr_callhdr(xdrs, &call_msg)) {
+ perror("clnt_raw.c - 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 = &client_ops;
+ client->cl_auth = authnone_create();
+ return (client);
+}
+
+static enum clnt_stat
+clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
+ CLIENT *h;
+ u_long proc;
+ xdrproc_t xargs;
+ caddr_t argsp;
+ xdrproc_t xresults;
+ caddr_t resultsp;
+ struct timeval timeout;
+{
+ register struct clntraw_private *clp = clntraw_private;
+ register XDR *xdrs = &clp->xdr_stream;
+ struct rpc_msg msg;
+ enum clnt_stat status;
+ struct rpc_err error;
+
+ if (clp == 0)
+ return (RPC_FAILED);
+call_again:
+ /*
+ * send request
+ */
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ ((struct rpc_msg *)clp->mashl_callmsg)->rm_xid ++ ;
+ if ((! XDR_PUTBYTES(xdrs, clp->mashl_callmsg, clp->mcnt)) ||
+ (! XDR_PUTLONG(xdrs, (long *)&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(1);
+
+ /*
+ * 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))
+ 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))
+ 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);
+}
+
+static void
+clntraw_geterr()
+{
+}
+
+
+static bool_t
+clntraw_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ register struct clntraw_private *clp = clntraw_private;
+ register XDR *xdrs = &clp->xdr_stream;
+ bool_t rval;
+
+ if (clp == 0)
+ {
+ rval = (bool_t) RPC_FAILED;
+ return (rval);
+ }
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+static void
+clntraw_abort()
+{
+}
+
+static bool_t
+clntraw_control()
+{
+ return (FALSE);
+}
+
+static void
+clntraw_destroy()
+{
+}
diff --git a/lib/libc/rpc/clnt_simple.c b/lib/libc/rpc/clnt_simple.c
new file mode 100644
index 0000000..5bcfd47
--- /dev/null
+++ b/lib/libc/rpc/clnt_simple.c
@@ -0,0 +1,122 @@
+/*
+ * 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 = "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";*/
+static char *rcsid = "$Id: clnt_simple.c,v 1.6 1996/12/30 14:23:50 peter Exp $";
+#endif
+
+/*
+ * clnt_simple.c
+ * Simplified front end to rpc.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+static struct callrpc_private {
+ CLIENT *client;
+ int socket;
+ int oldprognum, oldversnum, valid;
+ char *oldhost;
+} *callrpc_private;
+
+int
+callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
+ char *host;
+ int prognum, versnum, procnum;
+ xdrproc_t inproc, outproc;
+ char *in, *out;
+{
+ register struct callrpc_private *crp = callrpc_private;
+ struct sockaddr_in server_addr;
+ enum clnt_stat clnt_stat;
+ struct hostent *hp;
+ struct timeval timeout, tottimeout;
+
+ if (crp == 0) {
+ crp = (struct callrpc_private *)calloc(1, sizeof (*crp));
+ if (crp == 0)
+ return (0);
+ callrpc_private = crp;
+ }
+ if (crp->oldhost == NULL) {
+ crp->oldhost = malloc(MAXHOSTNAMELEN);
+ crp->oldhost[0] = 0;
+ crp->socket = RPC_ANYSOCK;
+ }
+ if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum
+ && strcmp(crp->oldhost, host) == 0) {
+ /* reuse old client */
+ } else {
+ crp->valid = 0;
+ if (crp->socket != -1)
+ (void)close(crp->socket);
+ crp->socket = RPC_ANYSOCK;
+ if (crp->client) {
+ clnt_destroy(crp->client);
+ crp->client = NULL;
+ }
+ if ((hp = gethostbyname(host)) == NULL)
+ return ((int) RPC_UNKNOWNHOST);
+ timeout.tv_usec = 0;
+ timeout.tv_sec = 5;
+ memset(&server_addr, 0, sizeof(server_addr));
+ memcpy((char *)&server_addr.sin_addr, hp->h_addr, hp->h_length);
+ server_addr.sin_len = sizeof(struct sockaddr_in);
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = 0;
+ if ((crp->client = clntudp_create(&server_addr, (u_long)prognum,
+ (u_long)versnum, timeout, &crp->socket)) == NULL)
+ return ((int) rpc_createerr.cf_stat);
+ crp->valid = 1;
+ crp->oldprognum = prognum;
+ crp->oldversnum = versnum;
+ (void) strcpy(crp->oldhost, host);
+ }
+ tottimeout.tv_sec = 25;
+ tottimeout.tv_usec = 0;
+ clnt_stat = clnt_call(crp->client, procnum, inproc, in,
+ outproc, out, tottimeout);
+ /*
+ * if call failed, empty cache
+ */
+ if (clnt_stat != RPC_SUCCESS)
+ crp->valid = 0;
+ return ((int) clnt_stat);
+}
diff --git a/lib/libc/rpc/clnt_tcp.c b/lib/libc/rpc/clnt_tcp.c
new file mode 100644
index 0000000..cfb3746
--- /dev/null
+++ b/lib/libc/rpc/clnt_tcp.c
@@ -0,0 +1,580 @@
+/*
+ * 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 = "from: @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: clnt_tcp.c,v 1.7 1996/12/30 14:36:17 peter Exp $";
+#endif
+
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <errno.h>
+#include <rpc/pmap_clnt.h>
+
+#define MCALL_MSG_SIZE 24
+
+static int readtcp();
+static int writetcp();
+
+static enum clnt_stat clnttcp_call();
+static void clnttcp_abort();
+static void clnttcp_geterr();
+static bool_t clnttcp_freeres();
+static bool_t clnttcp_control();
+static void clnttcp_destroy();
+
+static struct clnt_ops tcp_ops = {
+ clnttcp_call,
+ clnttcp_abort,
+ clnttcp_geterr,
+ clnttcp_freeres,
+ clnttcp_destroy,
+ clnttcp_control
+};
+
+struct ct_data {
+ int ct_sock;
+ bool_t ct_closeit;
+ struct timeval ct_wait;
+ bool_t ct_waitset; /* wait set by clnt_control? */
+ struct sockaddr_in ct_addr;
+ struct rpc_err ct_error;
+ char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
+ u_int ct_mpos; /* pos after marshal */
+ XDR ct_xdrs;
+};
+
+/*
+ * Create a client handle for a tcp/ip connection.
+ * If *sockp<0, *sockp is set to a newly created TCP socket and it is
+ * connected to raddr. If *sockp non-negative then
+ * raddr is ignored. The rpc/tcp package does buffering
+ * similar to stdio, so the client must pick send and receive buffer sizes,];
+ * 0 => use the default.
+ * If raddr->sin_port is 0, then a binder on the remote machine is
+ * consulted for the right port number.
+ * NB: *sockp is copied into a private area.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
+ * something more useful.
+ */
+CLIENT *
+clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ struct sockaddr_in *raddr;
+ u_long prog;
+ u_long vers;
+ register int *sockp;
+ u_int sendsz;
+ u_int recvsz;
+{
+ CLIENT *h;
+ register struct ct_data *ct = NULL;
+ struct timeval now;
+ struct rpc_msg call_msg;
+ static u_int32_t disrupt;
+
+ if (disrupt == 0)
+ disrupt = (u_int32_t)(long)raddr;
+
+ h = (CLIENT *)mem_alloc(sizeof(*h));
+ if (h == NULL) {
+ (void)fprintf(stderr, "clnttcp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ ct = (struct ct_data *)mem_alloc(sizeof(*ct));
+ if (ct == NULL) {
+ (void)fprintf(stderr, "clnttcp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+
+ /*
+ * If no port number given ask the pmap for one
+ */
+ if (raddr->sin_port == 0) {
+ u_short port;
+ if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ mem_free((caddr_t)h, sizeof(CLIENT));
+ return ((CLIENT *)NULL);
+ }
+ raddr->sin_port = htons(port);
+ }
+
+ /*
+ * If no socket given, open one
+ */
+ if (*sockp < 0) {
+ *sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ (void)bindresvport(*sockp, (struct sockaddr_in *)0);
+ if ((*sockp < 0)
+ || (connect(*sockp, (struct sockaddr *)raddr,
+ sizeof(*raddr)) < 0)) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ if (*sockp != -1)
+ (void)close(*sockp);
+ goto fooy;
+ }
+ ct->ct_closeit = TRUE;
+ } else {
+ ct->ct_closeit = FALSE;
+ }
+
+ /*
+ * Set up private data struct
+ */
+ ct->ct_sock = *sockp;
+ ct->ct_wait.tv_usec = 0;
+ ct->ct_waitset = FALSE;
+ ct->ct_addr = *raddr;
+
+ /*
+ * Initialize call message
+ */
+ (void)gettimeofday(&now, (struct timezone *)0);
+ call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = prog;
+ call_msg.rm_call.cb_vers = vers;
+
+ /*
+ * pre-serialize the static part of the call msg and stash it away
+ */
+ xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
+ XDR_ENCODE);
+ if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
+ if (ct->ct_closeit) {
+ (void)close(*sockp);
+ }
+ goto fooy;
+ }
+ ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
+ XDR_DESTROY(&(ct->ct_xdrs));
+
+ /*
+ * Create a client handle which uses xdrrec for serialization
+ * and authnone for authentication.
+ */
+ xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
+ (caddr_t)ct, readtcp, writetcp);
+ h->cl_ops = &tcp_ops;
+ h->cl_private = (caddr_t) ct;
+ h->cl_auth = authnone_create();
+ return (h);
+
+fooy:
+ /*
+ * Something goofed, free stuff and barf
+ */
+ if (ct)
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ if (h)
+ mem_free((caddr_t)h, sizeof(CLIENT));
+ return ((CLIENT *)NULL);
+}
+
+static enum clnt_stat
+clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
+ register CLIENT *h;
+ u_long proc;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+ xdrproc_t xdr_results;
+ caddr_t results_ptr;
+ struct timeval timeout;
+{
+ register struct ct_data *ct = (struct ct_data *) h->cl_private;
+ register XDR *xdrs = &(ct->ct_xdrs);
+ struct rpc_msg reply_msg;
+ u_long x_id;
+ u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall); /* yuk */
+ register bool_t shipnow;
+ int refreshes = 2;
+
+ if (!ct->ct_waitset) {
+ ct->ct_wait = timeout;
+ }
+
+ shipnow =
+ (xdr_results == (xdrproc_t)0 && 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 ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
+ (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+ (! AUTH_MARSHALL(h->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);
+ return (ct->ct_error.re_status);
+ }
+ if (! xdrrec_endofrecord(xdrs, shipnow))
+ return (ct->ct_error.re_status = RPC_CANTSEND);
+ if (! shipnow)
+ return (RPC_SUCCESS);
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+ 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 = xdr_void;
+ if (! xdrrec_skiprecord(xdrs))
+ 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;
+ 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(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
+ ct->ct_error.re_status = RPC_AUTHERROR;
+ ct->ct_error.re_why = AUTH_INVALIDRESP;
+ } else if (! (*xdr_results)(xdrs, results_ptr)) {
+ 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(h->cl_auth))
+ goto call_again;
+ } /* end of unsuccessful completion */
+ return (ct->ct_error.re_status);
+}
+
+static void
+clnttcp_geterr(h, errp)
+ CLIENT *h;
+ struct rpc_err *errp;
+{
+ register struct ct_data *ct =
+ (struct ct_data *) h->cl_private;
+
+ *errp = ct->ct_error;
+}
+
+static bool_t
+clnttcp_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+ register XDR *xdrs = &(ct->ct_xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+static void
+clnttcp_abort()
+{
+}
+
+
+static bool_t
+clnttcp_control(cl, request, info)
+ CLIENT *cl;
+ int request;
+ char *info;
+{
+ register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+ register struct timeval *tv;
+ int len;
+
+ switch (request) {
+ case CLSET_FD_CLOSE:
+ ct->ct_closeit = TRUE;
+ break;
+ case CLSET_FD_NCLOSE:
+ ct->ct_closeit = FALSE;
+ break;
+ case CLSET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ tv = (struct timeval *)info;
+ ct->ct_wait.tv_sec = tv->tv_sec;
+ ct->ct_wait.tv_usec = tv->tv_usec;
+ ct->ct_waitset = TRUE;
+ break;
+ case CLGET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ *(struct timeval *)info = ct->ct_wait;
+ break;
+ case CLGET_SERVER_ADDR:
+ if (info == NULL)
+ return(FALSE);
+ *(struct sockaddr_in *)info = ct->ct_addr;
+ break;
+ case CLGET_FD:
+ if (info == NULL)
+ return(FALSE);
+ *(int *)info = ct->ct_sock;
+ 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
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)ct->ct_mcall);
+ break;
+ case CLSET_XID:
+ /* This will set the xid of the NEXT call */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)ct->ct_mcall = htonl(*(u_long *)info - 1);
+ /* decrement by 1 as clnttcp_call() increments once */
+ 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
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
+ 4 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_VERS:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_PROG:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the program number field is the field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
+ 3 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_PROG:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_LOCAL_ADDR:
+ len = sizeof(struct sockaddr);
+ if (getsockname(ct->ct_sock, (struct sockaddr *)info, &len) <0)
+ return(FALSE);
+ break;
+ case CLGET_RETRY_TIMEOUT:
+ case CLSET_RETRY_TIMEOUT:
+ case CLGET_SVC_ADDR:
+ case CLSET_SVC_ADDR:
+ case CLSET_PUSH_TIMOD:
+ case CLSET_POP_TIMOD:
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+static void
+clnttcp_destroy(h)
+ CLIENT *h;
+{
+ register struct ct_data *ct =
+ (struct ct_data *) h->cl_private;
+
+ if (ct->ct_closeit) {
+ (void)close(ct->ct_sock);
+ }
+ XDR_DESTROY(&(ct->ct_xdrs));
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ mem_free((caddr_t)h, sizeof(CLIENT));
+}
+
+/*
+ * 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
+readtcp(ct, buf, len)
+ register struct ct_data *ct;
+ caddr_t buf;
+ register int len;
+{
+ fd_set *fds, readfds;
+ struct timeval start, after, duration, delta, tmp, tv;
+ int r, save_errno;
+
+ if (len == 0)
+ return (0);
+
+ if (ct->ct_sock + 1 > FD_SETSIZE) {
+ int bytes = howmany(ct->ct_sock + 1, NFDBITS) * sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+ if (fds == NULL)
+ return (-1);
+ memset(fds, 0, bytes);
+ } else {
+ fds = &readfds;
+ FD_ZERO(fds);
+ }
+
+ gettimeofday(&start, NULL);
+ delta = ct->ct_wait;
+ while (TRUE) {
+ /* XXX we know the other bits are still clear */
+ FD_SET(ct->ct_sock, fds);
+ tv = delta; /* in case select writes back */
+ r = select(ct->ct_sock+1, fds, NULL, NULL, &tv);
+ save_errno = errno;
+
+ gettimeofday(&after, NULL);
+ timersub(&start, &after, &duration);
+ timersub(&delta, &duration, &tmp);
+ delta = tmp;
+ if (delta.tv_sec < 0 || !timerisset(&delta))
+ r = 0;
+
+ switch (r) {
+ case 0:
+ if (fds != &readfds)
+ free(fds);
+ ct->ct_error.re_status = RPC_TIMEDOUT;
+ return (-1);
+
+ case -1:
+ if (errno == EINTR)
+ continue;
+ if (fds != &readfds)
+ free(fds);
+ ct->ct_error.re_status = RPC_CANTRECV;
+ ct->ct_error.re_errno = save_errno;
+ return (-1);
+ }
+ break;
+ }
+ switch (len = read(ct->ct_sock, buf, 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
+writetcp(ct, buf, len)
+ struct ct_data *ct;
+ caddr_t buf;
+ int len;
+{
+ register int i, cnt;
+
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = write(ct->ct_sock, buf, cnt)) == -1) {
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTSEND;
+ return (-1);
+ }
+ }
+ return (len);
+}
diff --git a/lib/libc/rpc/clnt_udp.c b/lib/libc/rpc/clnt_udp.c
new file mode 100644
index 0000000..035ce96
--- /dev/null
+++ b/lib/libc/rpc/clnt_udp.c
@@ -0,0 +1,553 @@
+/*
+ * 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 = "from: @(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: clnt_udp.c,v 1.8 1996/12/30 14:40:34 peter Exp $";
+#endif
+
+/*
+ * clnt_udp.c, Implements a UDP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netdb.h>
+#include <errno.h>
+#include <rpc/pmap_clnt.h>
+
+/*
+ * UDP bases client side rpc operations
+ */
+static enum clnt_stat clntudp_call();
+static void clntudp_abort();
+static void clntudp_geterr();
+static bool_t clntudp_freeres();
+static bool_t clntudp_control();
+static void clntudp_destroy();
+
+static struct clnt_ops udp_ops = {
+ clntudp_call,
+ clntudp_abort,
+ clntudp_geterr,
+ clntudp_freeres,
+ clntudp_destroy,
+ clntudp_control
+};
+
+/*
+ * Private data kept per client handle
+ */
+struct cu_data {
+ int cu_sock;
+ bool_t cu_closeit;
+ struct sockaddr_in cu_raddr;
+ int cu_rlen;
+ struct timeval cu_wait;
+ struct timeval cu_total;
+ struct rpc_err cu_error;
+ XDR cu_outxdrs;
+ u_int cu_xdrpos;
+ u_int cu_sendsz;
+ char *cu_outbuf;
+ u_int cu_recvsz;
+ char cu_inbuf[1];
+};
+
+/*
+ * Create a UDP based client handle.
+ * If *sockp<0, *sockp is set to a newly created UPD socket.
+ * If raddr->sin_port is 0 a binder on the remote machine
+ * is consulted for the correct port number.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is initialized to null authentication.
+ * Caller may wish to set this something more useful.
+ *
+ * wait is the amount of time used between retransmitting a call if
+ * no response has been heard; retransmition occurs until the actual
+ * rpc call times out.
+ *
+ * sendsz and recvsz are the maximum allowable packet sizes that can be
+ * sent and received.
+ */
+CLIENT *
+clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
+ struct sockaddr_in *raddr;
+ u_long program;
+ u_long version;
+ struct timeval wait;
+ register int *sockp;
+ u_int sendsz;
+ u_int recvsz;
+{
+ CLIENT *cl;
+ register struct cu_data *cu = NULL;
+ struct timeval now;
+ struct rpc_msg call_msg;
+ static u_int32_t disrupt;
+
+ if (disrupt == 0)
+ disrupt = (u_int32_t)(long)raddr;
+
+ cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
+ if (cl == NULL) {
+ (void) fprintf(stderr, "clntudp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ sendsz = ((sendsz + 3) / 4) * 4;
+ recvsz = ((recvsz + 3) / 4) * 4;
+ cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz);
+ if (cu == NULL) {
+ (void) fprintf(stderr, "clntudp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ cu->cu_outbuf = &cu->cu_inbuf[recvsz];
+
+ (void)gettimeofday(&now, (struct timezone *)0);
+ if (raddr->sin_port == 0) {
+ u_short port;
+ if ((port =
+ pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
+ goto fooy;
+ }
+ raddr->sin_port = htons(port);
+ }
+ cl->cl_ops = &udp_ops;
+ cl->cl_private = (caddr_t)cu;
+ cu->cu_raddr = *raddr;
+ cu->cu_rlen = sizeof (cu->cu_raddr);
+ cu->cu_wait = wait;
+ cu->cu_total.tv_sec = -1;
+ cu->cu_total.tv_usec = -1;
+ cu->cu_sendsz = sendsz;
+ cu->cu_recvsz = recvsz;
+ call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = program;
+ call_msg.rm_call.cb_vers = version;
+ xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf,
+ sendsz, XDR_ENCODE);
+ if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
+ goto fooy;
+ }
+ cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
+ if (*sockp < 0) {
+ int dontblock = 1;
+
+ *sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (*sockp < 0) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ /* attempt to bind to priv port */
+ (void)bindresvport(*sockp, (struct sockaddr_in *)0);
+ /* the sockets rpc controls are non-blocking */
+ (void)ioctl(*sockp, FIONBIO, (char *) &dontblock);
+ cu->cu_closeit = TRUE;
+ } else {
+ cu->cu_closeit = FALSE;
+ }
+ cu->cu_sock = *sockp;
+ cl->cl_auth = authnone_create();
+ return (cl);
+fooy:
+ if (cu)
+ mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz);
+ if (cl)
+ mem_free((caddr_t)cl, sizeof(CLIENT));
+ return ((CLIENT *)NULL);
+}
+
+CLIENT *
+clntudp_create(raddr, program, version, wait, sockp)
+ struct sockaddr_in *raddr;
+ u_long program;
+ u_long version;
+ struct timeval wait;
+ register int *sockp;
+{
+
+ return(clntudp_bufcreate(raddr, program, version, wait, sockp,
+ UDPMSGSIZE, UDPMSGSIZE));
+}
+
+static enum clnt_stat
+clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
+ register CLIENT *cl; /* client handle */
+ u_long 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 */
+ struct timeval utimeout; /* seconds to wait before giving up */
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ register XDR *xdrs;
+ register int outlen;
+ register int inlen;
+ int fromlen;
+ fd_set *fds, readfds;
+ struct sockaddr_in from;
+ struct rpc_msg reply_msg;
+ XDR reply_xdrs;
+ struct timeval time_waited, start, after, tmp1, tmp2, tv;
+ bool_t ok;
+ int nrefreshes = 2; /* number of times to refresh cred */
+ struct timeval timeout;
+
+ if (cu->cu_total.tv_usec == -1)
+ timeout = utimeout; /* use supplied timeout */
+ else
+ timeout = cu->cu_total; /* use default timeout */
+
+ if (cu->cu_sock + 1 > FD_SETSIZE) {
+ int bytes = howmany(cu->cu_sock + 1, NFDBITS) * sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+ if (fds == NULL)
+ return (cu->cu_error.re_status = RPC_CANTSEND);
+ memset(fds, 0, bytes);
+ } else {
+ fds = &readfds;
+ FD_ZERO(fds);
+ }
+
+ timerclear(&time_waited);
+
+call_again:
+ xdrs = &(cu->cu_outxdrs);
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, cu->cu_xdrpos);
+ /*
+ * the transaction is the first thing in the out buffer
+ */
+ (*(u_short *)(cu->cu_outbuf))++;
+ if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+ (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+ (! (*xargs)(xdrs, argsp))) {
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+ }
+ outlen = (int)XDR_GETPOS(xdrs);
+
+send_again:
+ if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
+ (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) != outlen) {
+ cu->cu_error.re_errno = errno;
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_CANTSEND);
+ }
+
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (!timerisset(&timeout)) {
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+ }
+ /*
+ * 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;
+ reply_msg.acpted_rply.ar_results.where = resultsp;
+ reply_msg.acpted_rply.ar_results.proc = xresults;
+
+ gettimeofday(&start, NULL);
+ for (;;) {
+ /* XXX we know the other bits are still clear */
+ FD_SET(cu->cu_sock, fds);
+ tv = cu->cu_wait;
+ switch (select(cu->cu_sock+1, fds, NULL, NULL, &tv)) {
+
+ case 0:
+ timeradd(&time_waited, &cu->cu_wait, &tmp1);
+ time_waited = tmp1;
+ if (timercmp(&time_waited, &timeout, <))
+ goto send_again;
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+
+ case -1:
+ if (errno == EINTR) {
+ gettimeofday(&after, NULL);
+ timersub(&after, &start, &tmp1);
+ timeradd(&time_waited, &tmp1, &tmp2);
+ time_waited = tmp2;
+ if (timercmp(&time_waited, &timeout, <))
+ continue;
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+ }
+ cu->cu_error.re_errno = errno;
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_CANTRECV);
+ }
+
+ do {
+ fromlen = sizeof(struct sockaddr);
+ inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,
+ (int) cu->cu_recvsz, 0,
+ (struct sockaddr *)&from, &fromlen);
+ } while (inlen < 0 && errno == EINTR);
+ if (inlen < 0) {
+ if (errno == EWOULDBLOCK)
+ continue;
+ cu->cu_error.re_errno = errno;
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_CANTRECV);
+ }
+ if (inlen < sizeof(u_int32_t))
+ continue;
+ /* see if reply transaction id matches sent id */
+ if (*((u_int32_t *)(cu->cu_inbuf)) != *((u_int32_t *)(cu->cu_outbuf)))
+ continue;
+ /* we now assume we have the proper reply */
+ break;
+ }
+
+ /*
+ * now decode and validate the response
+ */
+ xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE);
+ ok = xdr_replymsg(&reply_xdrs, &reply_msg);
+ /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
+ if (ok) {
+ _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)) {
+ cu->cu_error.re_status = RPC_AUTHERROR;
+ cu->cu_error.re_why = AUTH_INVALIDRESP;
+ }
+ 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 (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) {
+ nrefreshes--;
+ goto call_again;
+ }
+ } /* end of unsuccessful completion */
+ } /* end of valid reply message */
+ else {
+ cu->cu_error.re_status = RPC_CANTDECODERES;
+ }
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status);
+}
+
+static void
+clntudp_geterr(cl, errp)
+ CLIENT *cl;
+ struct rpc_err *errp;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+ *errp = cu->cu_error;
+}
+
+
+static bool_t
+clntudp_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ register XDR *xdrs = &(cu->cu_outxdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+static void
+clntudp_abort(/*h*/)
+ /*CLIENT *h;*/
+{
+}
+
+
+static bool_t
+clntudp_control(cl, request, info)
+ CLIENT *cl;
+ int request;
+ char *info;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ register struct timeval *tv;
+ int len;
+
+ switch (request) {
+ case CLSET_FD_CLOSE:
+ cu->cu_closeit = TRUE;
+ break;
+ case CLSET_FD_NCLOSE:
+ cu->cu_closeit = FALSE;
+ break;
+ case CLSET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ tv = (struct timeval *)info;
+ cu->cu_total.tv_sec = tv->tv_sec;
+ cu->cu_total.tv_usec = tv->tv_usec;
+ break;
+ case CLGET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ *(struct timeval *)info = cu->cu_total;
+ break;
+ case CLSET_RETRY_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ tv = (struct timeval *)info;
+ cu->cu_wait.tv_sec = tv->tv_sec;
+ cu->cu_wait.tv_usec = tv->tv_usec;
+ break;
+ case CLGET_RETRY_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ *(struct timeval *)info = cu->cu_wait;
+ break;
+ case CLGET_SERVER_ADDR:
+ if (info == NULL)
+ return(FALSE);
+ *(struct sockaddr_in *)info = cu->cu_raddr;
+ break;
+ case CLGET_FD:
+ if (info == NULL)
+ return(FALSE);
+ *(int *)info = cu->cu_sock;
+ 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
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)cu->cu_outbuf);
+ break;
+ case CLSET_XID:
+ /* This will set the xid of the NEXT call */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)cu->cu_outbuf = htonl(*(u_long *)info - 1);
+ /* decrement by 1 as clntudp_call() increments once */
+ 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
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +
+ 4 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_VERS:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_PROG:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the program number field is the field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +
+ 3 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_PROG:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_LOCAL_ADDR:
+ len = sizeof(struct sockaddr);
+ if (getsockname(cu->cu_sock, (struct sockaddr *)info, &len) <0)
+ return(FALSE);
+ break;
+ case CLGET_SVC_ADDR:
+ case CLSET_SVC_ADDR:
+ case CLSET_PUSH_TIMOD:
+ case CLSET_POP_TIMOD:
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+static void
+clntudp_destroy(cl)
+ CLIENT *cl;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+ if (cu->cu_closeit) {
+ (void)close(cu->cu_sock);
+ }
+ XDR_DESTROY(&(cu->cu_outxdrs));
+ mem_free((caddr_t)cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz));
+ mem_free((caddr_t)cl, sizeof(CLIENT));
+}
diff --git a/lib/libc/rpc/clnt_unix.c b/lib/libc/rpc/clnt_unix.c
new file mode 100644
index 0000000..e4c4309
--- /dev/null
+++ b/lib/libc/rpc/clnt_unix.c
@@ -0,0 +1,635 @@
+/*
+ * 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 = "from: @(#)clnt_unix.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)clnt_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: clnt_unix.c,v 1.7 1996/12/30 14:36:17 peter Exp $";
+#endif
+
+/*
+ * clnt_unix.c, Implements a AF_UNIX based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * AF_UNIX 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netdb.h>
+#include <errno.h>
+#include <rpc/pmap_clnt.h>
+
+#define MCALL_MSG_SIZE 24
+
+static int readunix();
+static int writeunix();
+
+static enum clnt_stat clntunix_call();
+static void clntunix_abort();
+static void clntunix_geterr();
+static bool_t clntunix_freeres();
+static bool_t clntunix_control();
+static void clntunix_destroy();
+
+static struct clnt_ops unix_ops = {
+ clntunix_call,
+ clntunix_abort,
+ clntunix_geterr,
+ clntunix_freeres,
+ clntunix_destroy,
+ clntunix_control
+};
+
+struct ct_data {
+ int ct_sock;
+ bool_t ct_closeit;
+ struct timeval ct_wait;
+ bool_t ct_waitset; /* wait set by clnt_control? */
+ struct sockaddr_un ct_addr;
+ struct rpc_err ct_error;
+ char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
+ u_int ct_mpos; /* pos after marshal */
+ XDR ct_xdrs;
+};
+
+/*
+ * Create a client handle for a unix/ip connection.
+ * If *sockp<0, *sockp is set to a newly created TCP socket and it is
+ * connected to raddr. If *sockp non-negative then
+ * raddr is ignored. The rpc/unix package does buffering
+ * similar to stdio, so the client must pick send and receive buffer sizes,];
+ * 0 => use the default.
+ * If raddr->sin_port is 0, then a binder on the remote machine is
+ * consulted for the right port number.
+ * NB: *sockp is copied into a private area.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
+ * something more useful.
+ */
+CLIENT *
+clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ struct sockaddr_un *raddr;
+ u_long prog;
+ u_long vers;
+ register int *sockp;
+ u_int sendsz;
+ u_int recvsz;
+{
+ CLIENT *h;
+ register struct ct_data *ct = NULL;
+ struct timeval now;
+ struct rpc_msg call_msg;
+ static u_int32_t disrupt;
+ int len;
+
+ if (disrupt == 0)
+ disrupt = (u_int32_t)(long)raddr;
+
+ h = (CLIENT *)mem_alloc(sizeof(*h));
+ if (h == NULL) {
+ (void)fprintf(stderr, "clntunix_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ ct = (struct ct_data *)mem_alloc(sizeof(*ct));
+ if (ct == NULL) {
+ (void)fprintf(stderr, "clntunix_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+
+ /*
+ * If no socket given, open one
+ */
+ if (*sockp < 0) {
+ *sockp = socket(AF_UNIX, SOCK_STREAM, 0);
+ len = strlen(raddr->sun_path) + sizeof(raddr->sun_family) +
+ sizeof(raddr->sun_len) + 1;
+ raddr->sun_len = len;
+ 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 fooy;
+ }
+ ct->ct_closeit = TRUE;
+ } else {
+ ct->ct_closeit = FALSE;
+ }
+
+ /*
+ * Set up private data struct
+ */
+ ct->ct_sock = *sockp;
+ ct->ct_wait.tv_usec = 0;
+ ct->ct_waitset = FALSE;
+ ct->ct_addr = *raddr;
+
+ /*
+ * Initialize call message
+ */
+ (void)gettimeofday(&now, (struct timezone *)0);
+ call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = prog;
+ call_msg.rm_call.cb_vers = vers;
+
+ /*
+ * pre-serialize the static part of the call msg and stash it away
+ */
+ xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
+ XDR_ENCODE);
+ if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
+ if (ct->ct_closeit) {
+ (void)close(*sockp);
+ }
+ goto fooy;
+ }
+ ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
+ XDR_DESTROY(&(ct->ct_xdrs));
+
+ /*
+ * Create a client handle which uses xdrrec for serialization
+ * and authnone for authentication.
+ */
+ xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
+ (caddr_t)ct, readunix, writeunix);
+ h->cl_ops = &unix_ops;
+ h->cl_private = (caddr_t) ct;
+ h->cl_auth = authnone_create();
+ return (h);
+
+fooy:
+ /*
+ * Something goofed, free stuff and barf
+ */
+ if (ct)
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ if (h)
+ mem_free((caddr_t)h, sizeof(CLIENT));
+ return ((CLIENT *)NULL);
+}
+
+static enum clnt_stat
+clntunix_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
+ register CLIENT *h;
+ u_long proc;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+ xdrproc_t xdr_results;
+ caddr_t results_ptr;
+ struct timeval timeout;
+{
+ register struct ct_data *ct = (struct ct_data *) h->cl_private;
+ register XDR *xdrs = &(ct->ct_xdrs);
+ struct rpc_msg reply_msg;
+ u_long x_id;
+ u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall); /* yuk */
+ register bool_t shipnow;
+ int refreshes = 2;
+
+ if (!ct->ct_waitset) {
+ ct->ct_wait = timeout;
+ }
+
+ shipnow =
+ (xdr_results == (xdrproc_t)0 && 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 ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
+ (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+ (! AUTH_MARSHALL(h->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);
+ return (ct->ct_error.re_status);
+ }
+ if (! xdrrec_endofrecord(xdrs, shipnow))
+ return (ct->ct_error.re_status = RPC_CANTSEND);
+ if (! shipnow)
+ return (RPC_SUCCESS);
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+ 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 = xdr_void;
+ if (! xdrrec_skiprecord(xdrs))
+ 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;
+ 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(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
+ ct->ct_error.re_status = RPC_AUTHERROR;
+ ct->ct_error.re_why = AUTH_INVALIDRESP;
+ } else if (! (*xdr_results)(xdrs, results_ptr)) {
+ 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(h->cl_auth))
+ goto call_again;
+ } /* end of unsuccessful completion */
+ return (ct->ct_error.re_status);
+}
+
+static void
+clntunix_geterr(h, errp)
+ CLIENT *h;
+ struct rpc_err *errp;
+{
+ register struct ct_data *ct =
+ (struct ct_data *) h->cl_private;
+
+ *errp = ct->ct_error;
+}
+
+static bool_t
+clntunix_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+ register XDR *xdrs = &(ct->ct_xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+static void
+clntunix_abort()
+{
+}
+
+
+static bool_t
+clntunix_control(cl, request, info)
+ CLIENT *cl;
+ int request;
+ char *info;
+{
+ register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+ register struct timeval *tv;
+ int len;
+
+ switch (request) {
+ case CLSET_FD_CLOSE:
+ ct->ct_closeit = TRUE;
+ break;
+ case CLSET_FD_NCLOSE:
+ ct->ct_closeit = FALSE;
+ break;
+ case CLSET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ tv = (struct timeval *)info;
+ ct->ct_wait.tv_sec = tv->tv_sec;
+ ct->ct_wait.tv_usec = tv->tv_usec;
+ ct->ct_waitset = TRUE;
+ break;
+ case CLGET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ *(struct timeval *)info = ct->ct_wait;
+ break;
+ case CLGET_SERVER_ADDR:
+ if (info == NULL)
+ return(FALSE);
+ *(struct sockaddr_un *)info = ct->ct_addr;
+ break;
+ case CLGET_FD:
+ if (info == NULL)
+ return(FALSE);
+ *(int *)info = ct->ct_sock;
+ 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
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)ct->ct_mcall);
+ break;
+ case CLSET_XID:
+ /* This will set the xid of the NEXT call */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)ct->ct_mcall = htonl(*(u_long *)info - 1);
+ /* decrement by 1 as clntunix_call() increments once */
+ 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
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
+ 4 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_VERS:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_PROG:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the program number field is the field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
+ 3 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_PROG:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_LOCAL_ADDR:
+ len = sizeof(struct sockaddr);
+ if (getsockname(ct->ct_sock, (struct sockaddr *)info, &len) <0)
+ return(FALSE);
+ break;
+ case CLGET_RETRY_TIMEOUT:
+ case CLSET_RETRY_TIMEOUT:
+ case CLGET_SVC_ADDR:
+ case CLSET_SVC_ADDR:
+ case CLSET_PUSH_TIMOD:
+ case CLSET_POP_TIMOD:
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+static void
+clntunix_destroy(h)
+ CLIENT *h;
+{
+ register struct ct_data *ct =
+ (struct ct_data *) h->cl_private;
+
+ if (ct->ct_closeit) {
+ (void)close(ct->ct_sock);
+ }
+ XDR_DESTROY(&(ct->ct_xdrs));
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ mem_free((caddr_t)h, sizeof(CLIENT));
+}
+
+/*
+ * read() and write() are replaced with recvmsg()/sendmsg() so that
+ * we can pass ancillary control data. In this case, the data constists
+ * of credential information which the kernel will fill in for us.
+ * XXX: This code is specific to FreeBSD and will not work on other
+ * platforms without the requisite kernel modifications.
+ */
+struct cmessage {
+ struct cmsghdr cmsg;
+ struct cmsgcred cmcred;
+};
+
+static int __msgread(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+ struct cmessage 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 = sizeof(struct cmessage);
+ 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;
+ struct cmessage 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 = sizeof(struct cmessage);
+
+ 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 = sizeof(struct cmessage);
+ msg.msg_flags = 0;
+
+ return(sendmsg(sock, &msg, 0));
+}
+
+/*
+ * Interface between xdr serializer and unix connection.
+ * Behaves like the system calls, read & write, but keeps some error state
+ * around for the rpc level.
+ */
+static int
+readunix(ct, buf, len)
+ register struct ct_data *ct;
+ caddr_t buf;
+ register int len;
+{
+ fd_set *fds, readfds;
+ struct timeval start, after, duration, delta, tmp, tv;
+ int r, save_errno;
+
+ if (len == 0)
+ return (0);
+
+ if (ct->ct_sock + 1 > FD_SETSIZE) {
+ int bytes = howmany(ct->ct_sock + 1, NFDBITS) * sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+ if (fds == NULL)
+ return (-1);
+ memset(fds, 0, bytes);
+ } else {
+ fds = &readfds;
+ FD_ZERO(fds);
+ }
+
+ gettimeofday(&start, NULL);
+ delta = ct->ct_wait;
+ while (TRUE) {
+ /* XXX we know the other bits are still clear */
+ FD_SET(ct->ct_sock, fds);
+ tv = delta; /* in case select writes back */
+ r = select(ct->ct_sock+1, fds, NULL, NULL, &tv);
+ save_errno = errno;
+
+ gettimeofday(&after, NULL);
+ timersub(&start, &after, &duration);
+ timersub(&delta, &duration, &tmp);
+ delta = tmp;
+ if (delta.tv_sec < 0 || !timerisset(&delta))
+ r = 0;
+
+ switch (r) {
+ case 0:
+ if (fds != &readfds)
+ free(fds);
+ ct->ct_error.re_status = RPC_TIMEDOUT;
+ return (-1);
+
+ case -1:
+ if (errno == EINTR)
+ continue;
+ if (fds != &readfds)
+ free(fds);
+ ct->ct_error.re_status = RPC_CANTRECV;
+ ct->ct_error.re_errno = save_errno;
+ return (-1);
+ }
+ break;
+ }
+ switch (len = __msgread(ct->ct_sock, buf, 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
+writeunix(ct, buf, len)
+ struct ct_data *ct;
+ caddr_t buf;
+ int len;
+{
+ register int i, cnt;
+
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = __msgwrite(ct->ct_sock, buf, cnt)) == -1) {
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTSEND;
+ return (-1);
+ }
+ }
+ return (len);
+}
diff --git a/lib/libc/rpc/crypt_client.c b/lib/libc/rpc/crypt_client.c
new file mode 100644
index 0000000..cdc0c06
--- /dev/null
+++ b/lib/libc/rpc/crypt_client.c
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <rpc/des_crypt.h>
+#include <rpc/des.h>
+#include <string.h>
+#include <rpcsvc/crypt.h>
+
+#ifndef lint
+static const char rcsid[] = "$Id$";
+#endif
+
+#ifndef KEYSERVSOCK
+#define KEYSERVSOCK "/var/run/keyservsock"
+#endif
+
+int
+_des_crypt_call(buf, len, dparms)
+ char *buf;
+ int len;
+ struct desparams *dparms;
+{
+ CLIENT *clnt;
+ desresp *result_1;
+ desargs des_crypt_1_arg;
+ int stat;
+
+ clnt = clnt_create(KEYSERVSOCK, CRYPT_PROG, CRYPT_VERS, "unix");
+ if (clnt == (CLIENT *) NULL) {
+ return(DESERR_HWERROR);
+ }
+
+ 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;
+ des_crypt_1_arg.des_mode = dparms->des_mode;
+ 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) {
+ 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, xdr_desresp, (char *)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..ca0a33e
--- /dev/null
+++ b/lib/libc/rpc/des_crypt.3
@@ -0,0 +1,126 @@
+.\" @(#)des_crypt.3 2.1 88/08/11 4.0 RPCSRC; from 1.16 88/03/02 SMI;
+.TH DES_CRYPT 3 "6 October 1987"
+.SH NAME
+des_crypt, ecb_crypt, cbc_crypt, des_setparity \- fast DES encryption
+.SH SYNOPSIS
+.nf
+.B #include <des_crypt.h>
+.LP
+.B int ecb_crypt(key, data, datalen, mode)
+.B char *key;
+.B char *data;
+.B unsigned datalen;
+.B unsigned mode;
+.LP
+.B int cbc_crypt(key, data, datalen, mode, ivec)
+.B char *key;
+.B char *data;
+.B unsigned datalen;
+.B unsigned mode;
+.B char *ivec;
+.LP
+.B void des_setparity(key)
+.B char *key;
+.fi
+.SH DESCRIPTION
+.IX encryption cbc_crypt "" \fLcbc_crypt\fP
+.IX "des encryption" cbc_crypt "DES encryption" \fLcbc_crypt\fP
+.IX encryption des_setparity "" \fLdes_setparity\fP
+.IX "des encryption" des_setparity "DES encryption" \fLdes_setparity\fP
+.B ecb_crypt(\|)
+and
+.B cbc_crypt(\|)
+implement the
+.SM NBS
+.SM DES
+(Data Encryption Standard).
+These routines are faster and more general purpose than
+.BR crypt (3).
+They also are able to utilize
+.SM DES
+hardware if it is available.
+.B ecb_crypt(\|)
+encrypts in
+.SM ECB
+(Electronic Code Book)
+mode, which encrypts blocks of data independently.
+.B cbc_crypt(\|)
+encrypts in
+.SM CBC
+(Cipher Block Chaining)
+mode, which chains together
+successive blocks.
+.SM CBC
+mode protects against insertions, deletions and
+substitutions of blocks. Also, regularities in the clear text will
+not appear in the cipher text.
+.LP
+Here is how to use these routines. The first parameter,
+.IR key ,
+is the 8-byte encryption key with parity.
+To set the key's parity, which for
+.SM DES
+is in the low bit of each byte, use
+.IR des_setparity .
+The second parameter,
+.IR data ,
+contains the data to be encrypted or decrypted. The
+third parameter,
+.IR datalen ,
+is the length in bytes of
+.IR data ,
+which must be a multiple of 8. The fourth parameter,
+.IR mode ,
+is formed by
+.SM OR\s0'ing
+together some things. For the encryption direction 'or' in either
+.SM DES_ENCRYPT
+or
+.SM DES_DECRYPT\s0.
+For software versus hardware
+encryption, 'or' in either
+.SM DES_HW
+or
+.SM DES_SW\s0.
+If
+.SM DES_HW
+is specified, and there is no hardware, then the encryption is performed
+in software and the routine returns
+.SM DESERR_NOHWDEVICE\s0.
+For
+.IR cbc_crypt ,
+the parameter
+.I ivec
+is the the 8-byte initialization
+vector for the chaining. It is updated to the next initialization
+vector upon return.
+.LP
+.SH "SEE ALSO"
+.BR des (1),
+.BR crypt (3)
+.SH DIAGNOSTICS
+.PD 0
+.TP 20
+.SM DESERR_NONE
+No error.
+.TP
+.SM DESERR_NOHWDEVICE
+Encryption succeeded, but done in software instead of the requested hardware.
+.TP
+.SM DESERR_HWERR
+An error occurred in the hardware or driver.
+.TP
+.SM DESERR_BADPARAM
+Bad parameter to routine.
+.PD
+.LP
+Given a result status
+.IR stat ,
+the macro
+.SM DES_FAILED\c
+.BR ( stat )
+is false only for the first two statuses.
+.SH RESTRICTIONS
+These routines are not available in RPCSRC 4.0.
+This information is provided to describe the 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..18c9972
--- /dev/null
+++ b/lib/libc/rpc/des_crypt.c
@@ -0,0 +1,153 @@
+/*
+ * 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>
+
+#ifndef lint
+/* from: static char sccsid[] = "@(#)des_crypt.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI"; */
+static const char rcsid[] = "$Id$";
+#endif
+
+static int common_crypt __P(( char *, char *, register unsigned, unsigned, struct desparams * ));
+int (*__des_crypt_LOCAL)() = 0;
+extern _des_crypt_call __P(( char *, int, struct desparams * ));
+/*
+ * Copy 8 bytes
+ */
+#define COPY8(src, dst) { \
+ register char *a = (char *) dst; \
+ register 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) { \
+ register char *a = (char *) dst; \
+ register char *b = (char *) src; \
+ register 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;
+ register unsigned len;
+ unsigned mode;
+ register struct desparams *desp;
+{
+ register 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..01dd7f2
--- /dev/null
+++ b/lib/libc/rpc/des_soft.c
@@ -0,0 +1,67 @@
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)des_soft.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI";
+#endif
+/*
+ * 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
+ */
+/*
+ * 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/get_myaddress.c b/lib/libc/rpc/get_myaddress.c
new file mode 100644
index 0000000..a96b84b
--- /dev/null
+++ b/lib/libc/rpc/get_myaddress.c
@@ -0,0 +1,109 @@
+/*
+ * 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 = "from: @(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: get_myaddress.c,v 1.11 1997/05/28 05:05:11 wpaul Exp $";
+#endif
+
+/*
+ * get_myaddress.c
+ *
+ * Get client's IP address via ioctl. This avoids using the yellowpages.
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/*
+ * don't use gethostbyname, which would invoke yellow pages
+ *
+ * Avoid loopback interfaces. We return information from a loopback
+ * interface only if there are no other possible interfaces.
+ */
+int
+get_myaddress(addr)
+ struct sockaddr_in *addr;
+{
+ int s;
+ char buf[BUFSIZ];
+ struct ifconf ifc;
+ struct ifreq ifreq, *ifr, *end;
+ int loopback = 0, gotit = 0;
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ return(-1);
+ }
+ ifc.ifc_len = sizeof (buf);
+ ifc.ifc_buf = buf;
+ if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
+ close(s);
+ return(-1);
+ }
+again:
+ ifr = ifc.ifc_req;
+ end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+
+ while (ifr < end) {
+ ifreq = *ifr;
+ if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+ close(s);
+ return(-1);
+ }
+ if (((ifreq.ifr_flags & IFF_UP) &&
+ ifr->ifr_addr.sa_family == AF_INET) ||
+ (loopback == 1 && (ifreq.ifr_flags & IFF_LOOPBACK))) {
+ *addr = *((struct sockaddr_in *)&ifr->ifr_addr);
+ addr->sin_port = htons(PMAPPORT);
+ gotit = 1;
+ break;
+ }
+ if (ifr->ifr_addr.sa_len)
+ ifr = (struct ifreq *) ((caddr_t) ifr +
+ ifr->ifr_addr.sa_len -
+ sizeof(struct sockaddr));
+ ifr++;
+ }
+ if (gotit == 0 && loopback == 0) {
+ loopback = 1;
+ goto again;
+ }
+ (void) close(s);
+ return (0);
+}
diff --git a/lib/libc/rpc/getrpcent.3 b/lib/libc/rpc/getrpcent.3
new file mode 100644
index 0000000..d2ea355
--- /dev/null
+++ b/lib/libc/rpc/getrpcent.3
@@ -0,0 +1,96 @@
+.\" @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI
+.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 SYNOPSIS
+.Fd #include <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_aliasesxxx
+.It Fa r_name
+The name of the server for this rpc program.
+.It Fa r_aliases
+A zero terminated list of alternate names for the rpc program.
+.It Fa 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.
+The
+.Nm getrpcent
+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
+.Fn getrpcent
+function family.
+.Pp
+.Fn endrpcent
+closes the file.
+.Pp
+.Fn getrpcbyname
+and
+.Fn getrpcbynumber
+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 "SEE ALSO"
+.Xr rpc 5 ,
+.Xr rpcinfo 8 ,
+.Xr ypserv 8
+.Sh DIAGNOSTICS
+A
+.Dv NULL
+pointer is returned on
+.Dv EOF
+or error.
+.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..8266285
--- /dev/null
+++ b/lib/libc/rpc/getrpcent.c
@@ -0,0 +1,303 @@
+/*
+ * 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 = "from: @(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";*/
+static char *rcsid = "$Id: getrpcent.c,v 1.6 1996/12/30 14:42:31 peter Exp $";
+#endif
+
+/*
+ * Copyright (c) 1984 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+/*
+ * Internet version.
+ */
+struct rpcdata {
+ FILE *rpcf;
+ int stayopen;
+#define MAXALIASES 35
+ char *rpc_aliases[MAXALIASES];
+ struct rpcent rpc;
+ char line[BUFSIZ+1];
+#ifdef YP
+ char *domain;
+ char *current;
+ int currentlen;
+#endif
+} *rpcdata;
+
+#ifdef YP
+static int __yp_nomap = 0;
+extern int _yp_check(char **);
+#endif /* YP */
+
+static struct rpcent *interpret();
+struct hostent *gethostent();
+char *inet_ntoa();
+
+static char RPCDB[] = "/etc/rpc";
+
+static struct rpcdata *
+_rpcdata()
+{
+ register struct rpcdata *d = rpcdata;
+
+ if (d == 0) {
+ d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata));
+ rpcdata = d;
+ }
+ return (d);
+}
+
+struct rpcent *
+getrpcbynumber(number)
+ register int number;
+{
+ register struct rpcdata *d = _rpcdata();
+ register struct rpcent *p;
+#ifdef YP
+ int reason;
+ char adrstr[16];
+#endif
+
+ if (d == 0)
+ return (0);
+#ifdef YP
+ if (!__yp_nomap && _yp_check(&d->domain)) {
+ sprintf(adrstr, "%d", number);
+ reason = yp_match(d->domain, "rpc.bynumber", adrstr, strlen(adrstr),
+ &d->current, &d->currentlen);
+ switch(reason) {
+ case 0:
+ break;
+ case YPERR_MAP:
+ __yp_nomap = 1;
+ goto no_yp;
+ break;
+ default:
+ return(0);
+ break;
+ }
+ d->current[d->currentlen] = '\0';
+ p = interpret(d->current, d->currentlen);
+ (void) free(d->current);
+ return p;
+ }
+no_yp:
+#endif /* YP */
+ setrpcent(0);
+ while ((p = getrpcent())) {
+ if (p->r_number == number)
+ break;
+ }
+ endrpcent();
+ return (p);
+}
+
+struct rpcent *
+getrpcbyname(name)
+ char *name;
+{
+ struct rpcent *rpc = NULL;
+ char **rp;
+
+ setrpcent(0);
+ while ((rpc = getrpcent())) {
+ if (strcmp(rpc->r_name, name) == 0)
+ goto done;
+ for (rp = rpc->r_aliases; *rp != NULL; rp++) {
+ if (strcmp(*rp, name) == 0)
+ goto done;
+ }
+ }
+done:
+ endrpcent();
+ return (rpc);
+}
+
+void
+setrpcent(f)
+ int f;
+{
+ register struct rpcdata *d = _rpcdata();
+
+ if (d == 0)
+ return;
+#ifdef YP
+ if (!__yp_nomap && _yp_check(NULL)) {
+ if (d->current)
+ free(d->current);
+ d->current = NULL;
+ d->currentlen = 0;
+ return;
+ }
+ __yp_nomap = 0;
+#endif /* YP */
+ if (d->rpcf == NULL)
+ d->rpcf = fopen(RPCDB, "r");
+ else
+ rewind(d->rpcf);
+ d->stayopen |= f;
+}
+
+void
+endrpcent()
+{
+ register struct rpcdata *d = _rpcdata();
+
+ if (d == 0)
+ return;
+#ifdef YP
+ if (!__yp_nomap && _yp_check(NULL)) {
+ if (d->current && !d->stayopen)
+ free(d->current);
+ d->current = NULL;
+ d->currentlen = 0;
+ return;
+ }
+ __yp_nomap = 0;
+#endif /* YP */
+ if (d->rpcf && !d->stayopen) {
+ fclose(d->rpcf);
+ d->rpcf = NULL;
+ }
+}
+
+struct rpcent *
+getrpcent()
+{
+ register struct rpcdata *d = _rpcdata();
+#ifdef YP
+ struct rpcent *hp;
+ int reason;
+ char *val = NULL;
+ int vallen;
+#endif
+
+ if (d == 0)
+ return(NULL);
+#ifdef YP
+ if (!__yp_nomap && _yp_check(&d->domain)) {
+ if (d->current == NULL && d->currentlen == 0) {
+ reason = yp_first(d->domain, "rpc.bynumber",
+ &d->current, &d->currentlen,
+ &val, &vallen);
+ } else {
+ reason = yp_next(d->domain, "rpc.bynumber",
+ d->current, d->currentlen,
+ &d->current, &d->currentlen,
+ &val, &vallen);
+ }
+ switch(reason) {
+ case 0:
+ break;
+ case YPERR_MAP:
+ __yp_nomap = 1;
+ goto no_yp;
+ break;
+ default:
+ return(0);
+ break;
+ }
+ val[vallen] = '\0';
+ hp = interpret(val, vallen);
+ (void) free(val);
+ return hp;
+ }
+no_yp:
+#endif /* YP */
+ if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)
+ return (NULL);
+ /* -1 so there is room to append a \n below */
+ if (fgets(d->line, BUFSIZ - 1, d->rpcf) == NULL)
+ return (NULL);
+ return (interpret(d->line, strlen(d->line)));
+}
+
+static struct rpcent *
+interpret(val, len)
+ char *val;
+ int len;
+{
+ register struct rpcdata *d = _rpcdata();
+ char *p;
+ register char *cp, **q;
+
+ if (d == 0)
+ return (0);
+ (void) strncpy(d->line, val, BUFSIZ);
+ d->line[BUFSIZ] = '\0';
+ p = d->line;
+ p[len] = '\n';
+ if (*p == '#')
+ return (getrpcent());
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+ return (getrpcent());
+ *cp = '\0';
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+ return (getrpcent());
+ *cp++ = '\0';
+ /* THIS STUFF IS INTERNET SPECIFIC */
+ d->rpc.r_name = d->line;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ d->rpc.r_number = atoi(cp);
+ q = d->rpc.r_aliases = d->rpc_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &(d->rpc_aliases[MAXALIASES - 1]))
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&d->rpc);
+}
+
diff --git a/lib/libc/rpc/getrpcport.3 b/lib/libc/rpc/getrpcport.3
new file mode 100644
index 0000000..8f4ebed
--- /dev/null
+++ b/lib/libc/rpc/getrpcport.3
@@ -0,0 +1,29 @@
+.\" @(#)getrpcport.3r 2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI
+.Dd October 6, 1987
+.Dt GETRPCPORT 3
+.Os
+.Sh NAME
+.Nm getrpcport
+.Nd get RPC port number
+.Sh SYNOPSIS
+.Ft int
+.Fn getrpcport "char *host" "int prognum" "int versnum" "int proto"
+.Sh DESCRIPTION
+.Fn getrpcport
+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..04a8de2
--- /dev/null
+++ b/lib/libc/rpc/getrpcport.c
@@ -0,0 +1,63 @@
+/*
+ * 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 = "from: @(#)getrpcport.c 1.3 87/08/11 SMI";*/
+/*static char *sccsid = "from: @(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: getrpcport.c,v 1.6 1996/12/30 14:43:42 peter Exp $";
+#endif
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <netdb.h>
+#include <sys/socket.h>
+
+int
+getrpcport(host, prognum, versnum, proto)
+ char *host;
+ int prognum, versnum, proto;
+{
+ struct sockaddr_in addr;
+ struct hostent *hp;
+
+ 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;
+ memcpy((char *)&addr.sin_addr, hp->h_addr, hp->h_length);
+ return (pmap_getport(&addr, prognum, versnum, proto));
+}
diff --git a/lib/libc/rpc/key_call.c b/lib/libc/rpc/key_call.c
new file mode 100644
index 0000000..bcef22e
--- /dev/null
+++ b/lib/libc/rpc/key_call.c
@@ -0,0 +1,425 @@
+/*
+ * 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"
+
+/*
+ * 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 <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 <sys/utsname.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/fcntl.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 __P(( u_long, xdrproc_t, char *, xdrproc_t, char * ));
+
+int
+key_setsecret(secretkey)
+ const char *secretkey;
+{
+ keystatus status;
+
+ if (!key_call((u_long) KEY_SET, xdr_keybuf, (char *) secretkey,
+ xdr_keystatus, (char *)&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, xdr_void, (char *)NULL,
+ xdr_key_netstres, (char *) &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, xdr_cryptkeyarg2, (char *)&arg,
+ xdr_cryptkeyres, (char *)&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, xdr_cryptkeyarg2, (char *)&arg,
+ xdr_cryptkeyres, (char *)&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, xdr_cryptkeyarg, (char *)&arg,
+ xdr_cryptkeyres, (char *)&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, xdr_cryptkeyarg, (char *)&arg,
+ xdr_cryptkeyres, (char *)&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, xdr_void, (char *)NULL,
+ xdr_des_block, (char *)key)) {
+ return (-1);
+ }
+ return (0);
+}
+
+int
+key_setnet(arg)
+struct netstarg *arg;
+{
+ keystatus status;
+
+
+ if (!key_call((u_long) KEY_NET_PUT, xdr_key_netstarg, (char *) arg,
+ xdr_keystatus, (char *) &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, xdr_keybuf, pkey,
+ xdr_cryptkeyres, (char *)&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;
+
+#ifdef foo
+static void
+key_call_destroy(void *vp)
+{
+ register struct key_call_private *kcp = (struct key_call_private *)vp;
+
+ if (kcp) {
+ if (kcp->client)
+ clnt_destroy(kcp->client);
+ free(kcp);
+ }
+}
+#endif
+
+/*
+ * Keep the handle cached. This call may be made quite often.
+ */
+static CLIENT *
+getkeyserv_handle(vers)
+int vers;
+{
+ struct key_call_private *kcp = key_call_private_main;
+ struct timeval wait_time;
+ int fd;
+ struct sockaddr_un name;
+ int namelen = sizeof(struct sockaddr_un);
+
+#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */
+#define TOTAL_TRIES 5 /* Number of tries */
+
+ 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);
+ }
+ key_call_private_main = 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 other side closed socket, build handle again */
+ clnt_control(kcp->client, CLGET_FD, (char *)&fd);
+ if (getpeername(fd,(struct sockaddr *)&name,&namelen) == -1) {
+ auth_destroy(kcp->client->cl_auth);
+ 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 ((kcp->client == (CLIENT *) NULL))
+ /* Use the AF_UNIX transport */
+ kcp->client = clnt_create("/var/run/keyservsock", KEY_PROG,
+ vers, "unix");
+
+ 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;
+ char *arg;
+ xdrproc_t xdr_rslt;
+ char *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..8cd6b6b
--- /dev/null
+++ b/lib/libc/rpc/key_prot_xdr.c
@@ -0,0 +1,166 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include <rpc/key_prot.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
+ */
+#pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI"
+
+/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */
+
+/*
+ * 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;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_unixcred(register XDR *xdrs, unixcred *objp)
+{
+
+ if (!xdr_u_int(xdrs, &objp->uid))
+ return (FALSE);
+ if (!xdr_u_int(xdrs, &objp->gid))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->gids.gids_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;
+ }
+ 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;
+ }
+ return (TRUE);
+}
diff --git a/lib/libc/rpc/netname.c b/lib/libc/rpc/netname.c
new file mode 100644
index 0000000..3a3942b
--- /dev/null
+++ b/lib/libc/rpc/netname.c
@@ -0,0 +1,136 @@
+/*
+ * 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(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)netname.c 1.8 91/03/11 Copyr 1986 Sun Micro";
+#endif
+
+/*
+ * 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 <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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+#ifndef NGROUPS
+#define NGROUPS 16
+#endif
+
+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];
+ uid_t uid;
+ char *domain;
+{
+ char *dfltdom;
+
+#define MAXIPRINT (11) /* max length of printed integer */
+
+ if (domain == NULL) {
+ if (_rpc_get_default_domain(&dfltdom) != 0) {
+ return (0);
+ }
+ domain = dfltdom;
+ }
+ if (strlen(domain) + 1 + MAXIPRINT > MAXNETNAMELEN) {
+ return (0);
+ }
+ (void) sprintf(netname, "%s.%ld@%s", OPSYS, uid, domain);
+ return (1);
+}
+
+
+/*
+ * Convert host to network-name
+ */
+int
+host2netname(netname, host, domain)
+ char netname[MAXNETNAMELEN + 1];
+ char *host;
+ 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) > 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..41c5146
--- /dev/null
+++ b/lib/libc/rpc/netnamer.c
@@ -0,0 +1,327 @@
+/*
+ * 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(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)netnamer.c 1.13 91/03/11 Copyr 1986 Sun Micro";
+#endif
+/*
+ * 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 <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>
+
+static char *OPSYS = "unix";
+static char *NETID = "netid.byname";
+static char *NETIDFILE = "/etc/netid";
+
+static int getnetid __P(( char *, char * ));
+static int _getgroups __P(( char *, gid_t * ));
+
+#ifndef NGROUPS
+#define NGROUPS 16
+#endif
+
+/*
+ * 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;
+ struct passwd *pwd;
+ char val[1024];
+ char *val1, *val2;
+ char *domain;
+ int vallen;
+ int err;
+
+ if (getnetid(netname, val)) {
+ p = strtok(val, ":");
+ if (p == NULL)
+ return (0);
+ *uidp = (uid_t) atol(val);
+ p = strtok(NULL, "\n,");
+ *gidp = (gid_t) atol(p);
+ if (p == NULL) {
+ return (0);
+ }
+ gidlen = 0;
+ for (gidlen = 0; gidlen < NGROUPS; gidlen++) {
+ p = strtok(NULL, "\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 */
+
+ /* XXX: uid_t have different sizes on different OS's. sigh! */
+ if (sizeof (uid_t) == sizeof (short)) {
+ if (sscanf(val, "%hd", (short *)&uid) != 1)
+ return (0);
+ } else {
+ if (sscanf(val, "%ld", &uid) != 1)
+ return (0);
+ }
+ /* 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[NGROUPS];
+{
+ gid_t ngroups = 0;
+ register struct group *grp;
+ register int i;
+ register 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 == NGROUPS) {
+#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 == (FILE *) 0) {
+#ifdef YP
+ res = "+";
+ goto getnetidyp;
+#else
+ return (0);
+#endif
+ }
+ for (;;) {
+ if (fd == (FILE *) 0)
+ return (0); /* getnetidyp brings us here */
+ res = fgets(buf, 1024, fd);
+ if (res == 0) {
+ 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 = strtok(buf, "\t ");
+ if (mkey == NULL) {
+ fprintf(stderr,
+ "Bad record in %s -- %s", NETIDFILE, buf);
+ continue;
+ }
+ mval = strtok(NULL, " \t#\n");
+ 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..9901d81
--- /dev/null
+++ b/lib/libc/rpc/pmap_clnt.c
@@ -0,0 +1,149 @@
+/*
+ * 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 = "from: @(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: pmap_clnt.c,v 1.5 1996/12/30 14:46:33 peter Exp $";
+#endif
+
+/*
+ * pmap_clnt.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#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 <netinet/in.h>
+
+static struct timeval timeout = { 5, 0 };
+static struct timeval tottimeout = { 60, 0 };
+
+void clnt_perror();
+
+#ifndef PORTMAPSOCK
+#define PORTMAPSOCK "/var/run/portmapsock"
+#endif
+
+/*
+ * Set a mapping between program,version and port.
+ * Calls the pmap service remotely to do the mapping.
+ */
+bool_t
+pmap_set(program, version, protocol, port)
+ u_long program;
+ u_long version;
+ int protocol;
+ u_short port;
+{
+ struct sockaddr_in myaddress;
+ int socket = -1;
+ register CLIENT *client;
+ struct pmap parms;
+ bool_t rslt;
+ struct stat st;
+
+ /*
+ * Temporary hack for backwards compatibility. Eventually
+ * this test will go away and we'll use only the "unix" transport.
+ */
+ if (stat(PORTMAPSOCK, &st) == 0 && st.st_mode & S_IFSOCK)
+ client = clnt_create(PORTMAPSOCK, PMAPPROG, PMAPVERS, "unix");
+ else {
+ if (get_myaddress(&myaddress) != 0)
+ return (FALSE);
+ myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
+ timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ }
+
+ if (client == (CLIENT *)NULL)
+ return (FALSE);
+ parms.pm_prog = program;
+ parms.pm_vers = version;
+ parms.pm_prot = protocol;
+ parms.pm_port = port;
+ if (CLNT_CALL(client, PMAPPROC_SET, xdr_pmap, &parms, xdr_bool, &rslt,
+ tottimeout) != RPC_SUCCESS) {
+ clnt_perror(client, "Cannot register service");
+ return (FALSE);
+ }
+ CLNT_DESTROY(client);
+ if (socket != -1)
+ (void)close(socket);
+ return (rslt);
+}
+
+/*
+ * Remove the mapping between program,version and port.
+ * Calls the pmap service remotely to do the un-mapping.
+ */
+bool_t
+pmap_unset(program, version)
+ u_long program;
+ u_long version;
+{
+ struct sockaddr_in myaddress;
+ int socket = -1;
+ register CLIENT *client;
+ struct pmap parms;
+ bool_t rslt;
+ struct stat st;
+
+ /*
+ * Temporary hack for backwards compatibility. Eventually
+ * this test will go away and we'll use only the "unix" transport.
+ */
+ if (stat(PORTMAPSOCK, &st) == 0 && st.st_mode & S_IFSOCK)
+ client = clnt_create(PORTMAPSOCK, PMAPPROG, PMAPVERS, "unix");
+ else {
+ if (get_myaddress(&myaddress) != 0)
+ return (FALSE);
+ myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
+ timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ }
+ if (client == (CLIENT *)NULL)
+ return (FALSE);
+ parms.pm_prog = program;
+ parms.pm_vers = version;
+ parms.pm_port = parms.pm_prot = 0;
+ CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt,
+ tottimeout);
+ CLNT_DESTROY(client);
+ if (socket != -1)
+ (void)close(socket);
+ return (rslt);
+}
diff --git a/lib/libc/rpc/pmap_getmaps.c b/lib/libc/rpc/pmap_getmaps.c
new file mode 100644
index 0000000..d4f2774
--- /dev/null
+++ b/lib/libc/rpc/pmap_getmaps.c
@@ -0,0 +1,86 @@
+/*
+ * 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 = "from: @(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: pmap_getmaps.c,v 1.5 1996/12/30 14:48:28 peter Exp $";
+#endif
+
+/*
+ * 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 <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <net/if.h>
+#include <sys/ioctl.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 = (struct pmaplist *)NULL;
+ int socket = -1;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+ address->sin_port = htons(PMAPPORT);
+ client = clnttcp_create(address, PMAPPROG,
+ PMAPVERS, &socket, 50, 500);
+ if (client != (CLIENT *)NULL) {
+ if (CLNT_CALL(client, PMAPPROC_DUMP, xdr_void, NULL, xdr_pmaplist,
+ &head, minutetimeout) != RPC_SUCCESS) {
+ clnt_perror(client, "pmap_getmaps rpc problem");
+ }
+ CLNT_DESTROY(client);
+ }
+ if (socket != -1)
+ (void)close(socket);
+ 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..3d4c48a
--- /dev/null
+++ b/lib/libc/rpc/pmap_getport.c
@@ -0,0 +1,91 @@
+/*
+ * 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 = "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";*/
+static char *rcsid = "$Id: pmap_getport.c,v 1.4 1996/12/30 14:49:24 peter Exp $";
+#endif
+
+/*
+ * pmap_getport.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <unistd.h>
+
+static struct timeval timeout = { 5, 0 };
+static 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 socket = -1;
+ register CLIENT *client;
+ struct pmap parms;
+
+ address->sin_port = htons(PMAPPORT);
+ client = clntudp_bufcreate(address, PMAPPROG,
+ PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ if (client != (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, PMAPPROC_GETPORT, xdr_pmap, &parms,
+ 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);
+ }
+ if (socket != -1)
+ (void)close(socket);
+ 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..fcb9c99
--- /dev/null
+++ b/lib/libc/rpc/pmap_prot.c
@@ -0,0 +1,59 @@
+/*
+ * 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 = "from: @(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: pmap_prot.c,v 1.2 1995/05/30 05:41:25 rgrimes Exp $";
+#endif
+
+/*
+ * pmap_prot.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+
+
+bool_t
+xdr_pmap(xdrs, regs)
+ XDR *xdrs;
+ struct pmap *regs;
+{
+
+ 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..d81f612
--- /dev/null
+++ b/lib/libc/rpc/pmap_prot2.c
@@ -0,0 +1,118 @@
+/*
+ * 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 = "from: @(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: pmap_prot2.c,v 1.3 1996/06/10 20:13:05 jraynard Exp $";
+#endif
+
+/*
+ * pmap_prot2.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.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)
+ register XDR *xdrs;
+ register 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;
+ register int freeing = (xdrs->x_op == XDR_FREE);
+ register struct pmaplist **next = NULL;
+
+ while (TRUE) {
+ 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), xdr_pmap))
+ return (FALSE);
+ rp = (freeing) ? next : &((*rp)->pml_next);
+ }
+}
diff --git a/lib/libc/rpc/pmap_rmt.c b/lib/libc/rpc/pmap_rmt.c
new file mode 100644
index 0000000..07a81e2
--- /dev/null
+++ b/lib/libc/rpc/pmap_rmt.c
@@ -0,0 +1,415 @@
+/*
+ * 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 = "from: @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: pmap_rmt.c,v 1.9 1996/12/30 14:53:20 peter Exp $";
+#endif
+
+/*
+ * pmap_rmt.c
+ * Client interface to pmap rpc service.
+ * remote call and broadcast service
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_rmt.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#define MAX_BROADCAST_SIZE 1400
+
+static 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 socket = -1;
+ register CLIENT *client;
+ struct rmtcallargs a;
+ struct rmtcallres r;
+ enum clnt_stat stat;
+
+ addr->sin_port = htons(PMAPPORT);
+ client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket);
+ if (client != (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, PMAPPROC_CALLIT, xdr_rmtcall_args, &a,
+ xdr_rmtcallres, &r, tout);
+ CLNT_DESTROY(client);
+ } else {
+ stat = RPC_FAILED;
+ }
+ if (socket != -1)
+ (void)close(socket);
+ addr->sin_port = 0;
+ return (stat);
+}
+
+
+/*
+ * XDR remote call arguments
+ * written for XDR_ENCODE direction only
+ */
+bool_t
+xdr_rmtcall_args(xdrs, cap)
+ register XDR *xdrs;
+ register struct rmtcallargs *cap;
+{
+ u_int lenposition, argposition, position;
+
+ 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)
+ register XDR *xdrs;
+ register struct rmtcallres *crp;
+{
+ caddr_t port_ptr;
+
+ port_ptr = (caddr_t)crp->port_ptr;
+ if (xdr_reference(xdrs, &port_ptr, sizeof (u_long),
+ xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) {
+ crp->port_ptr = (u_long *)port_ptr;
+ return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
+ }
+ return (FALSE);
+}
+
+
+/*
+ * The following is kludged-up support for simple rpc broadcasts.
+ * Someday a large, complicated system will replace these trivial
+ * routines which only support udp/ip .
+ */
+
+static int
+getbroadcastnets(addrs, sock, buf)
+ struct in_addr *addrs;
+ int sock; /* any valid socket will do */
+ char *buf; /* why allocxate more when we can use existing... */
+{
+ struct ifconf ifc;
+ struct ifreq ifreq, *ifr;
+ struct sockaddr_in *sin;
+ struct in_addr addr;
+ char *cp, *cplim;
+ int n, i = 0;
+
+ ifc.ifc_len = UDPMSGSIZE;
+ ifc.ifc_buf = buf;
+ if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+ perror("broadcast: ioctl (get interface configuration)");
+ return (0);
+ }
+#define max(a, b) (a > b ? a : b)
+#define size(p) max((p).sa_len, sizeof(p))
+ cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
+ for (cp = buf; cp < cplim;
+ cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
+ ifr = (struct ifreq *)cp;
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ continue;
+ ifreq = *ifr;
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+ perror("broadcast: ioctl (get interface flags)");
+ continue;
+ }
+ if ((ifreq.ifr_flags & IFF_BROADCAST) &&
+ (ifreq.ifr_flags & IFF_UP)) {
+ sin = (struct sockaddr_in *)&ifr->ifr_addr;
+#ifdef SIOCGIFBRDADDR /* 4.3BSD */
+ if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+ addr =
+ inet_makeaddr(inet_netof(sin->sin_addr),
+ INADDR_ANY);
+ } else {
+ addr = ((struct sockaddr_in*)
+ &ifreq.ifr_addr)->sin_addr;
+ }
+#else /* 4.2 BSD */
+ addr = inet_makeaddr(inet_netof(sin->sin_addr),
+ INADDR_ANY);
+#endif
+ for (n=i-1; n>=0; n--) {
+ if (addr.s_addr == addrs[n].s_addr)
+ break;
+ }
+ if (n<0) {
+ addrs[i++] = addr;
+ }
+ }
+ }
+ return (i);
+}
+
+typedef bool_t (*resultproc_t)();
+
+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 */
+ 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 */
+{
+ enum clnt_stat stat;
+ AUTH *unix_auth = authunix_create_default();
+ XDR xdr_stream;
+ register XDR *xdrs = &xdr_stream;
+ int outlen, inlen, fromlen, nets;
+ register int sock;
+ int on = 1;
+ fd_set *fds, readfds;
+ register int i;
+ bool_t done = FALSE;
+ register u_long xid;
+ u_long port;
+ struct in_addr addrs[20];
+ struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
+ struct rmtcallargs a;
+ struct rmtcallres r;
+ struct rpc_msg msg;
+ struct timeval t, tv;
+ char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
+ static u_int32_t disrupt;
+
+ if (disrupt == 0)
+ disrupt = (u_int32_t)(long)resultsp;
+
+ /*
+ * initialization: create a socket, a broadcast address, and
+ * preserialize the arguments into a send buffer.
+ */
+ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ perror("Cannot create socket for broadcast rpc");
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+#ifdef SO_BROADCAST
+ if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
+ perror("Cannot set socket option SO_BROADCAST");
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+#endif /* def SO_BROADCAST */
+ if (sock + 1 > FD_SETSIZE) {
+ int bytes = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+ if (fds == NULL) {
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+ memset(fds, 0, bytes);
+ } else {
+ fds = &readfds;
+ FD_ZERO(fds);
+ }
+
+ nets = getbroadcastnets(addrs, sock, inbuf);
+ memset(&baddr, 0, sizeof (baddr));
+ baddr.sin_len = sizeof(struct sockaddr_in);
+ baddr.sin_family = AF_INET;
+ baddr.sin_port = htons(PMAPPORT);
+ baddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ (void)gettimeofday(&t, (struct timezone *)0);
+ msg.rm_xid = xid = (++disrupt) ^ getpid() ^ t.tv_sec ^ t.tv_usec;
+ t.tv_usec = 0;
+ msg.rm_direction = CALL;
+ msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ msg.rm_call.cb_prog = PMAPPROG;
+ msg.rm_call.cb_vers = PMAPVERS;
+ msg.rm_call.cb_proc = PMAPPROC_CALLIT;
+ msg.rm_call.cb_cred = unix_auth->ah_cred;
+ msg.rm_call.cb_verf = unix_auth->ah_verf;
+ a.prog = prog;
+ a.vers = vers;
+ a.proc = proc;
+ a.xdr_args = xargs;
+ a.args_ptr = argsp;
+ r.port_ptr = &port;
+ r.xdr_results = xresults;
+ r.results_ptr = resultsp;
+ xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
+ if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
+ stat = RPC_CANTENCODEARGS;
+ goto done_broad;
+ }
+ outlen = (int)xdr_getpos(xdrs);
+ xdr_destroy(xdrs);
+ /*
+ * Basic loop: broadcast a packet and wait a while for response(s).
+ * The response timeout grows larger per iteration.
+ *
+ * XXX This will loop about 5 times the stop. If there are
+ * lots of signals being received by the process it will quit
+ * send them all in one quick burst, not paying attention to
+ * the intended function of sending them slowly over half a
+ * minute or so
+ */
+ for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
+ for (i = 0; i < nets; i++) {
+ baddr.sin_addr = addrs[i];
+ if (sendto(sock, outbuf, outlen, 0,
+ (struct sockaddr *)&baddr,
+ sizeof (struct sockaddr)) != outlen) {
+ perror("Cannot send broadcast packet");
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+ }
+ if (eachresult == NULL) {
+ stat = RPC_SUCCESS;
+ goto done_broad;
+ }
+ recv_again:
+ msg.acpted_rply.ar_verf = _null_auth;
+ msg.acpted_rply.ar_results.where = (caddr_t)&r;
+ msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
+ /* XXX we know the other bits are still clear */
+ FD_SET(sock, fds);
+ tv = t; /* for select() that copies back */
+ switch (select(sock + 1, fds, NULL, NULL, &tv)) {
+
+ case 0: /* timed out */
+ stat = RPC_TIMEDOUT;
+ continue;
+
+ case -1: /* some kind of error */
+ if (errno == EINTR)
+ goto recv_again;
+ perror("Broadcast select problem");
+ stat = RPC_CANTRECV;
+ goto done_broad;
+
+ } /* end of select results switch */
+ try_again:
+ fromlen = sizeof(struct sockaddr);
+ inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0,
+ (struct sockaddr *)&raddr, &fromlen);
+ if (inlen < 0) {
+ if (errno == EINTR)
+ goto try_again;
+ perror("Cannot receive reply to broadcast");
+ stat = RPC_CANTRECV;
+ goto done_broad;
+ }
+ if (inlen < sizeof(u_int32_t))
+ goto recv_again;
+ /*
+ * see if reply transaction id matches sent id.
+ * If so, decode the results.
+ */
+ xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
+ if (xdr_replymsg(xdrs, &msg)) {
+ if ((msg.rm_xid == xid) &&
+ (msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+ (msg.acpted_rply.ar_stat == SUCCESS)) {
+ raddr.sin_port = htons((u_short)port);
+ done = (*eachresult)(resultsp, &raddr);
+ }
+ /* otherwise, we just ignore the errors ... */
+ }
+ xdrs->x_op = XDR_FREE;
+ msg.acpted_rply.ar_results.proc = 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;
+ }
+ }
+done_broad:
+ if (fds != &readfds)
+ free(fds);
+ if (sock >= 0)
+ (void)close(sock);
+ AUTH_DESTROY(unix_auth);
+ return (stat);
+}
+
diff --git a/lib/libc/rpc/publickey.3 b/lib/libc/rpc/publickey.3
new file mode 100644
index 0000000..7063e8a
--- /dev/null
+++ b/lib/libc/rpc/publickey.3
@@ -0,0 +1,44 @@
+.\" @(#)publickey.3r 2.1 88/08/07 4.0 RPCSRC
+.TH PUBLICKEY 3R "6 October 1987"
+.SH NAME
+publickey, getpublickey, getsecretkey \- get public or secret key
+.SH SYNOPSIS
+.nf
+.B #include <rpc/rpc.h>
+.B #include <rpc/key_prot.h>
+.LP
+.B getpublickey(netname, publickey)
+.B char netname[\s-1MAXNETNAMELEN\s0+1];
+.B char publickey[\s-1HEXKEYBYTES\s0+1];
+.LP
+.B getsecretkey(netname, secretkey, passwd)
+.B char netname[\s-1MAXNETNAMELEN\s0+1];
+.B char secretkey[\s-1HEXKEYBYTES\s0+1];
+.B char *passwd;
+.fi
+.SH DESCRIPTION
+.IX "getpublickey function" "" "\fLgetpublickey()\fP function"
+.IX "getsecretkey function" "" "\fLgetsecretkey()\fP function"
+These routines are used to get public and secret keys from the
+.SM YP
+database.
+.B getsecretkey(\|)
+has an extra argument,
+.IR 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
+.SM NULL\s0-terminated,
+hexadecimal strings. If the password supplied to
+.B getsecretkey(\|)
+fails to decrypt the secret key, the routine will return 1 but the
+.I secretkey
+argument will be a
+.SM NULL
+string (``'').
+.SH "SEE ALSO"
+.BR publickey (5)
+.LP
+.I \s-1RPC\s0 Programmer's Manual
+in
+.TX NETP
diff --git a/lib/libc/rpc/publickey.5 b/lib/libc/rpc/publickey.5
new file mode 100644
index 0000000..de3c1e9
--- /dev/null
+++ b/lib/libc/rpc/publickey.5
@@ -0,0 +1,37 @@
+.\" @(#)publickey.5 2.1 88/08/07 4.0 RPCSRC; from 1.6 88/02/29 SMI;
+.TH PUBLICKEY 5 "19 October 1987"
+.SH NAME
+publickey \- public key database
+.SH SYNOPSIS
+.B /etc/publickey
+.SH DESCRIPTION
+.LP
+.B /etc/publickey
+is the public key database used for secure
+networking. 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).
+.LP
+This file is altered either by the user through the
+.BR chkey (1)
+command or by the system administrator through the
+.BR newkey (8)
+command.
+The file
+.B /etc/publickey
+should only contain data on the Yellow
+Pages master machine, where it
+is converted into the
+.SM YP
+database
+.BR publickey.byname .
+.SH SEE ALSO
+.BR chkey (1),
+.BR publickey (3R),
+.BR newkey (8),
+.BR ypupdated (8C)
diff --git a/lib/libc/rpc/rpc.3 b/lib/libc/rpc/rpc.3
new file mode 100644
index 0000000..dd55c22
--- /dev/null
+++ b/lib/libc/rpc/rpc.3
@@ -0,0 +1,1737 @@
+.\" @(#)rpc.3n 2.4 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI
+.TH RPC 3 "16 February 1988"
+.SH NAME
+rpc \- library routines for remote procedure calls
+.SH SYNOPSIS AND DESCRIPTION
+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.
+.LP
+Routines that are used for Secure RPC (DES authentication) are described in
+.BR rpc_secure (3).
+Secure RPC can be used only if DES encryption is available.
+.LP
+.ft B
+.nf
+.sp .5
+#include <rpc/rpc.h>
+.fi
+.ft R
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+auth_destroy(auth)
+\s-1AUTH\s0 *auth;
+.fi
+.ft R
+.IP
+A macro that destroys the authentication information associated with
+.IR auth .
+Destruction usually involves deallocation of private data
+structures. The use of
+.I auth
+is undefined after calling
+.BR auth_destroy(\|) .
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authnone_create(\|)
+.fi
+.ft R
+.IP
+Create and returns an
+.SM RPC
+authentication handle that passes nonusable authentication
+information with each remote procedure call. This is the
+default authentication used by
+.SM RPC.
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authunix_create(host, uid, gid, len, aup_gids)
+char *host;
+int uid, gid, len, *aup.gids;
+.fi
+.ft R
+.IP
+Create and return an
+.SM RPC
+authentication handle that contains
+.UX
+authentication information.
+The parameter
+.I host
+is the name of the machine on which the information was
+created;
+.I uid
+is the user's user
+.SM ID ;
+.I gid
+is the user's current group
+.SM ID ;
+.I len
+and
+.I aup_gids
+refer to a counted array of groups to which the user belongs.
+It is easy to impersonate a user.
+.br
+.if t .ne 5
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authunix_create_default(\|)
+.fi
+.ft R
+.IP
+Calls
+.B authunix_create(\|)
+with the appropriate parameters.
+.br
+.if t .ne 13
+.LP
+.ft B
+.nf
+.sp .5
+callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
+char *host;
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+.fi
+.ft R
+.IP
+Call the remote procedure associated with
+.IR prognum ,
+.IR versnum ,
+and
+.I procnum
+on the machine,
+.IR host .
+The parameter
+.I in
+is the address of the procedure's argument(s), and
+.I out
+is the address of where to place the result(s);
+.I inproc
+is used to encode the procedure's parameters, and
+.I outproc
+is used to decode the procedure's results.
+This routine returns zero if it succeeds, or the value of
+.B "enum clnt_stat"
+cast to an integer if it fails.
+The routine
+.B clnt_perrno(\|)
+is handy for translating failure statuses into messages.
+.IP
+Warning: calling remote procedures with this routine
+uses
+.SM UDP/IP
+as a transport; see
+.B clntudp_create(\|)
+for restrictions.
+You do not have control of timeouts or authentication using
+this routine.
+.br
+.if t .ne 16
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+clnt_broadcast(prognum, versnum, procnum, inproc, in, outproc, out, eachresult)
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+resultproc_t eachresult;
+.fi
+.ft R
+.IP
+Like
+.BR callrpc(\|) ,
+except the call message is broadcast to all locally
+connected broadcast nets. Each time it receives a
+response, this routine calls
+.BR eachresult(\|) ,
+whose form is:
+.IP
+.RS 1i
+.ft B
+.nf
+eachresult(out, addr)
+char *out;
+struct sockaddr_in *addr;
+.ft R
+.fi
+.RE
+.IP
+where
+.I out
+is the same as
+.I out
+passed to
+.BR clnt_broadcast(\|) ,
+except that the remote procedure's output is decoded there;
+.I addr
+points to the address of the machine that sent the results.
+If
+.B eachresult(\|)
+returns zero,
+.B clnt_broadcast(\|)
+waits for more replies; otherwise it returns with appropriate
+status.
+.IP
+Warning: broadcast sockets are limited in size to the
+maximum transfer unit of the data link. For ethernet,
+this value is 1500 bytes.
+.br
+.if t .ne 13
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+clnt_call(clnt, procnum, inproc, in, outproc, out, tout)
+\s-1CLIENT\s0 *clnt;
+u_long
+procnum;
+xdrproc_t inproc, outproc;
+char *in, *out;
+struct timeval tout;
+.fi
+.ft R
+.IP
+A macro that calls the remote procedure
+.I procnum
+associated with the client handle,
+.IR clnt ,
+which is obtained with an
+.SM RPC
+client creation routine such as
+.BR clnt_create(\|) .
+The parameter
+.I in
+is the address of the procedure's argument(s), and
+.I out
+is the address of where to place the result(s);
+.I inproc
+is used to encode the procedure's parameters, and
+.I outproc
+is used to decode the procedure's results;
+.I tout
+is the time allowed for results to come back.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+clnt_destroy(clnt)
+\s-1CLIENT\s0 *clnt;
+.fi
+.ft R
+.IP
+A macro that destroys the client's
+.SM RPC
+handle. Destruction usually involves deallocation
+of private data structures, including
+.I clnt
+itself. Use of
+.I clnt
+is undefined after calling
+.BR clnt_destroy(\|) .
+If the
+.SM RPC
+library opened the associated socket, it will close it also.
+Otherwise, the socket remains open.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clnt_create(host, prog, vers, proto)
+char *host;
+u_long prog, vers;
+char *proto;
+.fi
+.ft R
+.IP
+Generic client creation routine.
+.I host
+identifies the name of the remote host where the server
+is located.
+.I proto
+indicates which kind of transport protocol to use. The
+currently supported values for this field are \(lqudp\(rq
+and \(lqtcp\(rq.
+Default timeouts are set, but can be modified using
+.BR clnt_control(\|) .
+.IP
+Warning: Using
+.SM UDP
+has its shortcomings. Since
+.SM UDP\s0-based
+.SM 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.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+bool_t
+clnt_control(cl, req, info)
+\s-1CLIENT\s0 *cl;
+char *info;
+.fi
+.ft R
+.IP
+A macro used to change or retrieve various information
+about a client object.
+.I req
+indicates the type of operation, and
+.I info
+is a pointer to the information. For both
+.SM UDP
+and
+.SM TCP\s0,
+the supported values of
+.I req
+and their argument types and what they do are:
+.IP
+.nf
+.ta +2.0i +2.0i +2.0i
+.SM CLSET_TIMEOUT\s0 struct timeval set total timeout
+.SM CLGET_TIMEOUT\s0 struct timeval get total timeout
+.fi
+.IP
+Note: if you set the timeout using
+.BR clnt_control(\|) ,
+the timeout parameter passed to
+.B clnt_call(\|)
+will be ignored in all future calls.
+.IP
+.nf
+.SM CLGET_SERVER_ADDR\s0 struct sockaddr_in get server's address
+.fi
+.br
+.IP
+The following operations are valid for
+.SM UDP
+only:
+.IP
+.nf
+.ta +2.0i ; +2.0i ; +2.0i
+.SM CLSET_RETRY_TIMEOUT\s0 struct timeval set the retry timeout
+.SM CLGET_RETRY_TIMEOUT\s0 struct timeval get the retry timeout
+.fi
+.br
+.IP
+The retry timeout is the time that
+.SM "UDP RPC"
+waits for the server to reply before
+retransmitting the request.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+clnt_freeres(clnt, outproc, out)
+\s-1CLIENT\s0 *clnt;
+xdrproc_t outproc;
+char *out;
+.fi
+.ft R
+.IP
+A macro that frees any data allocated by the
+.SM RPC/XDR
+system when it decoded the results of an
+.SM RPC
+call. The
+parameter
+.I out
+is the address of the results, and
+.I outproc
+is the
+.SM XDR
+routine describing the results.
+This routine returns one if the results were successfully
+freed,
+and zero otherwise.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_geterr(clnt, errp)
+\s-1CLIENT\s0 *clnt;
+struct rpc_err *errp;
+.fi
+.ft R
+.IP
+A macro that copies the error structure out of the client
+handle
+to the structure at address
+.IR errp .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_pcreateerror(s)
+char *s;
+.fi
+.ft R
+.IP
+Print a message to standard error indicating
+why a client
+.SM RPC
+handle could not be created.
+The message is prepended with string
+.I s
+and a colon.
+Used when a
+.BR clnt_create(\|) ,
+.BR clntraw_create(\|) ,
+.BR clnttcp_create(\|) ,
+or
+.B clntudp_create(\|)
+call fails.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_perrno(stat)
+enum clnt_stat stat;
+.fi
+.ft R
+.IP
+Print a message to standard error corresponding
+to the condition indicated by
+.IR stat .
+Used after
+.BR callrpc(\|) .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+clnt_perror(clnt, s)
+\s-1CLIENT\s0 *clnt;
+char *s;
+.fi
+.ft R
+.IP
+Print a message to standard error indicating why an
+.SM RPC
+call failed;
+.I clnt
+is the handle used to do the call.
+The message is prepended with string
+.I s
+and a colon.
+Used after
+.BR clnt_call(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_spcreateerror
+char *s;
+.fi
+.ft R
+.IP
+Like
+.BR clnt_pcreateerror(\|) ,
+except that it returns a string
+instead of printing to the standard error.
+.IP
+Bugs: returns pointer to static data that is overwritten
+on each call.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_sperrno(stat)
+enum clnt_stat stat;
+.fi
+.ft R
+.IP
+Take the same arguments as
+.BR clnt_perrno(\|) ,
+but instead of sending a message to the standard error
+indicating why an
+.SM RPC
+call failed, return a pointer to a string which contains
+the message. The string ends with a
+.SM NEWLINE\s0.
+.IP
+.B clnt_sperrno(\|)
+is used instead of
+.B 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
+.BR printf ,
+or if a message format different than that supported by
+.B clnt_perrno(\|)
+is to be used.
+Note: unlike
+.B clnt_sperror(\|)
+and
+.BR clnt_spcreaterror(\|) ,
+.B clnt_sperrno(\|)
+returns pointer to static data, but the
+result will not get overwritten on each call.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_sperror(rpch, s)
+\s-1CLIENT\s0 *rpch;
+char *s;
+.fi
+.ft R
+.IP
+Like
+.BR clnt_perror(\|) ,
+except that (like
+.BR clnt_sperrno(\|) )
+it returns a string instead of printing to standard error.
+.IP
+Bugs: returns pointer to static data that is overwritten
+on each call.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntraw_create(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+This routine creates a toy
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum .
+The transport used to pass messages to the service is
+actually a buffer within the process's address space, so the
+corresponding
+.SM RPC
+server should live in the same address space; see
+.BR svcraw_create(\|) .
+This allows simulation of
+.SM RPC
+and acquisition of
+.SM RPC
+overheads, such as round trip times, without any
+kernel interference. This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clnttcp_create(addr, prognum, versnum, sockp, sendsz, recvsz)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+int *sockp;
+u_int sendsz, recvsz;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum ;
+the client uses
+.SM TCP/IP
+as a transport. The remote program is located at Internet
+address
+.IR *addr .
+If
+.\"The following in-line font conversion is necessary for the hyphen indicator
+\fB\%addr\->sin_port\fR
+is zero, then it is set to the actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.IR sockp .
+Since
+.SM TCP\s0-based
+.SM RPC
+uses buffered
+.SM I/O ,
+the user may specify the size of the send and receive buffers
+with the parameters
+.I sendsz
+and
+.IR recvsz ;
+values of zero choose suitable defaults.
+This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntudp_create(addr, prognum, versnum, wait, sockp)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+struct timeval wait;
+int *sockp;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum ;
+the client uses
+.SM UDP/IP
+as a transport. The remote program is located at Internet
+address
+.IR addr .
+If
+\fB\%addr\->sin_port\fR
+is zero, then it is set to actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.IR sockp .
+The
+.SM UDP
+transport resends the call message in intervals of
+.B 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
+.BR clnt_call(\|) .
+.IP
+Warning: since
+.SM UDP\s0-based
+.SM 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.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntudp_bufcreate(addr, prognum, versnum, wait, sockp, sendsize, recosize)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+struct timeval wait;
+int *sockp;
+unsigned int sendsize;
+unsigned int recosize;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+on
+.IR versnum ;
+the client uses
+.SM UDP/IP
+as a transport. The remote program is located at Internet
+address
+.IR addr .
+If
+\fB\%addr\->sin_port\fR
+is zero, then it is set to actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.BR sockp .
+The
+.SM UDP
+transport resends the call message in intervals of
+.B 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
+.BR clnt_call(\|) .
+.IP
+This allows the user to specify the maximum packet size for sending and receiving
+.SM UDP\s0-based
+.SM RPC
+messages.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+int
+get_myaddress(addr)
+struct sockaddr_in *addr;
+.fi
+.ft R
+.IP
+Stuff the machine's
+.SM IP
+address into
+.IR *addr ,
+without consulting the library routines that deal with
+.BR /etc/hosts .
+The port number is always set to
+.BR htons(\s-1PMAPPORT\s0) .
+Returns zero on success, non-zero on failure.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+struct pmaplist *
+pmap_getmaps(addr)
+struct sockaddr_in *addr;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which returns a list of the current
+.SM RPC
+program-to-port mappings
+on the host located at
+.SM IP
+address
+.IR *addr .
+This routine can return
+.SM NULL .
+The command
+.RB ` "rpcinfo \-p" '
+uses this routine.
+.br
+.if t .ne 12
+.LP
+.ft B
+.nf
+.sp .5
+u_short
+pmap_getport(addr, prognum, versnum, protocol)
+struct sockaddr_in *addr;
+u_long prognum, versnum, protocol;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which returns the port number
+on which waits a service that supports program number
+.IR prognum ,
+version
+.IR versnum ,
+and speaks the transport protocol associated with
+.IR protocol .
+The value of
+.I protocol
+is most likely
+.B
+.SM IPPROTO_UDP
+or
+.BR \s-1IPPROTO_TCP\s0 .
+A return value of zero means that the mapping does not exist
+or that
+the
+.SM RPC
+system failed to contact the remote
+.B portmap
+service. In the latter case, the global variable
+.B rpc_createerr(\|)
+contains the
+.SM RPC
+status.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+pmap_rmtcall(addr, prognum, versnum, procnum, inproc, in, outproc, out, tout, portp)
+struct sockaddr_in *addr;
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+struct timeval tout;
+u_long *portp;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which instructs
+.B portmap
+on the host at
+.SM IP
+address
+.I *addr
+to make an
+.SM RPC
+call on your behalf to a procedure on that host.
+The parameter
+.I *portp
+will be modified to the program's port number if the
+procedure
+succeeds. The definitions of other parameters are discussed
+in
+.B callrpc(\|)
+and
+.BR clnt_call(\|) .
+This procedure should be used for a \(lqping\(rq and nothing
+else.
+See also
+.BR clnt_broadcast(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+pmap_set(prognum, versnum, protocol, port)
+u_long prognum, versnum, protocol;
+u_short port;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which establishes a mapping between the triple
+.RI [ prognum , versnum , protocol\fR]
+and
+.I port
+on the machine's
+.B portmap
+service. The value of
+.I protocol
+is most likely
+.B
+.SM IPPROTO_UDP
+or
+.BR \s-1IPPROTO_TCP\s0 .
+This routine returns one if it succeeds, zero otherwise.
+Automatically done by
+.BR svc_register(\|) .
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+pmap_unset(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which destroys all mapping between the triple
+.RI [ prognum , versnum , *\fR]
+and
+.B ports
+on the machine's
+.B portmap
+service. This routine returns one if it succeeds, zero
+otherwise.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+registerrpc(prognum, versnum, procnum, procname, inproc, outproc)
+u_long prognum, versnum, procnum;
+char *(*procname) (\|) ;
+xdrproc_t inproc, outproc;
+.fi
+.ft R
+.IP
+Register procedure
+.I procname
+with the
+.SM RPC
+service package. If a request arrives for program
+.IR prognum ,
+version
+.IR versnum ,
+and procedure
+.IR procnum ,
+.I procname
+is called with a pointer to its parameter(s);
+.I progname
+should return a pointer to its static result(s);
+.I inproc
+is used to decode the parameters while
+.I outproc
+is used to encode the results.
+This routine returns zero if the registration succeeded, \-1
+otherwise.
+.IP
+Warning: remote procedures registered in this form
+are accessed using the
+.SM UDP/IP
+transport; see
+.B svcudp_create(\|)
+for restrictions.
+.br
+.if t .ne 5
+.LP
+.ft B
+.nf
+.sp .5
+struct rpc_createerr rpc_createerr;
+.fi
+.ft R
+.IP
+A global variable whose value is set by any
+.SM RPC
+client creation routine
+that does not succeed. Use the routine
+.B clnt_pcreateerror(\|)
+to print the reason why.
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+svc_destroy(xprt)
+\s-1SVCXPRT\s0 *
+xprt;
+.fi
+.ft R
+.IP
+A macro that destroys the
+.SM RPC
+service transport handle,
+.IR xprt .
+Destruction usually involves deallocation
+of private data structures, including
+.I xprt
+itself. Use of
+.I xprt
+is undefined after calling this routine.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+fd_set svc_fdset;
+.fi
+.ft R
+.IP
+A global variable reflecting the
+.SM RPC
+service side's
+read file descriptor bit mask; it is suitable as a template parameter
+to the
+.B select
+system call. This is only of interest
+if a service implementor does not call
+.BR svc_run(\|) ,
+but rather does his own asynchronous event processing.
+This variable is read-only (do not pass its address to
+.BR select !),
+yet it may change after calls to
+.B svc_getreqset(\|)
+or any creation routines.
+.br
+As well, note that if the process has descriptor limits
+which are extended beyond
+.BR FD_SETSIZE ,
+this variable will only be usable for the first
+.BR FD_SETSIZE
+descriptors.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+int svc_fds;
+.fi
+.ft R
+.IP
+Similar to
+.BR svc_fedset(\|) ,
+but limited to 32 descriptors. This
+interface is obsoleted by
+.BR svc_fdset(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_freeargs(xprt, inproc, in)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t inproc;
+char *in;
+.fi
+.ft R
+.IP
+A macro that frees any data allocated by the
+.SM RPC/XDR
+system when it decoded the arguments to a service procedure
+using
+.BR svc_getargs(\|) .
+This routine returns 1 if the results were successfully
+freed,
+and zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+svc_getargs(xprt, inproc, in)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t inproc;
+char *in;
+.fi
+.ft R
+.IP
+A macro that decodes the arguments of an
+.SM RPC
+request
+associated with the
+.SM RPC
+service transport handle,
+.IR xprt .
+The parameter
+.I in
+is the address where the arguments will be placed;
+.I inproc
+is the
+.SM XDR
+routine used to decode the arguments.
+This routine returns one if decoding succeeds, and zero
+otherwise.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+struct sockaddr_in *
+svc_getcaller(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+The approved way of getting the network address of the caller
+of a procedure associated with the
+.SM RPC
+service transport handle,
+.IR xprt .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_getreqset(rdfds)
+fd_set *rdfds;
+.fi
+.ft R
+.IP
+This routine is only of interest if a service implementor
+does not call
+.BR svc_run(\|) ,
+but instead implements custom asynchronous event processing.
+It is called when the
+.B select
+system call has determined that an
+.SM RPC
+request has arrived on some
+.SM RPC
+.B socket(s) ;
+.I rdfds
+is the resultant read file descriptor bit mask.
+The routine returns when all sockets associated with the
+value of
+.I rdfds
+have been serviced.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+svc_getreq(rdfds)
+int rdfds;
+.fi
+.ft R
+.IP
+Similar to
+.BR svc_getreqset(\|) ,
+but limited to 32 descriptors. This interface is obsoleted by
+.BR svc_getreqset(\|) .
+.br
+.if t .ne 17
+.LP
+.ft B
+.nf
+.sp .5
+svc_register(xprt, prognum, versnum, dispatch, protocol)
+\s-1SVCXPRT\s0 *xprt;
+u_long prognum, versnum;
+void (*dispatch) (\|);
+u_long protocol;
+.fi
+.ft R
+.IP
+Associates
+.I prognum
+and
+.I versnum
+with the service dispatch procedure,
+.IR dispatch .
+If
+.I protocol
+is zero, the service is not registered with the
+.B portmap
+service. If
+.I protocol
+is non-zero, then a mapping of the triple
+.RI [ prognum , versnum , protocol\fR]
+to
+\fB\%xprt\->xp_port\fR
+is established with the local
+.B portmap
+service (generally
+.I protocol
+is zero,
+.B
+.SM IPPROTO_UDP
+or
+.B
+.SM IPPROTO_TCP
+).
+The procedure
+.I dispatch
+has the following form:
+.RS 1i
+.ft B
+.nf
+dispatch(request, xprt)
+struct svc_req *request;
+\s-1SVCXPRT\s0 *xprt;
+.ft R
+.fi
+.RE
+.IP
+The
+.B svc_register(\|)
+routine returns one if it succeeds, and zero otherwise.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+svc_run(\|)
+.fi
+.ft R
+.IP
+This routine never returns. It waits for
+.SM RPC
+requests to arrive, and calls the appropriate service
+procedure using
+.B svc_getreq(\|)
+when one arrives. This procedure is usually waiting for a
+.B select(\|)
+system call to return.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_sendreply(xprt, outproc, out)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t outproc;
+char *out;
+.fi
+.ft R
+.IP
+Called by an
+.SM RPC
+service's dispatch routine to send the results of a
+remote procedure call. The parameter
+.I xprt
+is the request's associated transport handle;
+.I outproc
+is the
+.SM XDR
+routine which is used to encode the results; and
+.I out
+is the address of the results.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svc_unregister(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+Remove all mapping of the double
+.RI [ prognum , versnum ]
+to dispatch routines, and of the triple
+.RI [ prognum , versnum , *\fR]
+to port number.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_auth(xprt, why)
+\s-1SVCXPRT\s0 *xprt;
+enum auth_stat why;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to an authentication error.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_decode(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that cannot successfully
+decode its parameters. See also
+.BR svc_getargs(\|) .
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_noproc(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that does not implement
+the procedure number that the caller requests.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_noprog(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called when the desired program is not registered with the
+.SM RPC
+package. Service implementors usually do not need this routine.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_progvers(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called when the desired version of a program is not registered
+with the
+.SM RPC
+package. Service implementors usually do not need this routine.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_systemerr(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+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.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_weakauth(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to insufficient
+authentication parameters. The routine calls
+.BR "svcerr_auth(xprt, \s-1AUTH_TOOWEAK\s0)" .
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcraw_create(\|)
+.fi
+.ft R
+.IP
+This routine creates a toy
+.SM RPC
+service transport, to which it returns a pointer. The
+transport
+is really a buffer within the process's address space,
+so the corresponding
+.SM RPC
+client should live in the same
+address space;
+see
+.BR clntraw_create(\|) .
+This routine allows simulation of
+.SM RPC
+and acquisition of
+.SM RPC
+overheads (such as round trip times), without any kernel
+interference.
+This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svctcp_create(sock, send_buf_size, recv_buf_size)
+int sock;
+u_int send_buf_size, recv_buf_size;
+.fi
+.ft R
+.IP
+This routine creates a
+.SM TCP/IP\s0-based
+.SM RPC
+service transport, to which it returns a pointer.
+The transport is associated with the socket
+.IR sock ,
+which may be
+.BR \s-1RPC_ANYSOCK\s0 ,
+in which case a new socket is created.
+If the socket is not bound to a local
+.SM TCP
+port, then this routine binds it to an arbitrary port. Upon
+completion,
+\fB\%xprt\->xp_sock\fR
+is the transport's socket descriptor, and
+\fB\%xprt\->xp_port\fR
+is the transport's port number.
+This routine returns
+.SM NULL
+if it fails. Since
+.SM TCP\s0-based
+.SM RPC
+uses buffered
+.SM I/O ,
+users may specify the size of buffers; values of zero
+choose suitable defaults.
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcfd_create(fd, sendsize, recvsize)
+int fd;
+u_int sendsize;
+u_int recvsize;
+.fi
+.ft R
+.IP
+Create a service on top of any open descriptor. Typically,
+this
+descriptor is a connected socket for a stream protocol such
+as
+.SM TCP\s0.
+.I sendsize
+and
+.I recvsize
+indicate sizes for the send and receive buffers. If they are
+zero, a reasonable default is chosen.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcudp_bufcreate(sock, sendsize, recosize)
+int sock;
+.fi
+.ft R
+.IP
+This routine creates a
+.SM UDP/IP\s0-based
+.SM RPC
+service transport, to which it returns a pointer.
+The transport is associated with the socket
+.IR sock ,
+which may be
+.B \s-1RPC_ANYSOCK\s0 ,
+in which case a new socket is created.
+If the socket is not bound to a local
+.SM UDP
+port, then this routine binds it to an arbitrary port. Upon
+completion,
+\fB\%xprt\->xp_sock\fR
+is the transport's socket descriptor, and
+\fB\%xprt\->xp_port\fR
+is the transport's port number.
+This routine returns
+.SM NULL
+if it fails.
+.IP
+This allows the user to specify the maximum packet size for sending and
+receiving
+.SM UDP\s0-based
+.SM RPC messages.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_accepted_reply(xdrs, ar)
+\s-1XDR\s0 *xdrs;
+struct accepted_reply *ar;
+.fi
+.ft R
+.IP
+Used for encoding
+.SM RPC
+reply messages. This routine is useful for users who
+wish to generate
+\s-1RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_authunix_parms(xdrs, aupp)
+\s-1XDR\s0 *xdrs;
+struct authunix_parms *aupp;
+.fi
+.ft R
+.IP
+Used for describing
+.SM UNIX
+credentials. This routine is useful for users
+who wish to generate these credentials without using the
+.SM RPC
+authentication package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdr_callhdr(xdrs, chdr)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *chdr;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+call header messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_callmsg(xdrs, cmsg)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *cmsg;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+call messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_opaque_auth(xdrs, ap)
+\s-1XDR\s0 *xdrs;
+struct opaque_auth *ap;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+authentication information messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_pmap(xdrs, regs)
+\s-1XDR\s0 *xdrs;
+struct pmap *regs;
+.fi
+.ft R
+.IP
+Used for describing parameters to various
+.B portmap
+procedures, externally.
+This routine is useful for users who wish to generate
+these parameters without using the
+.B pmap
+interface.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_pmaplist(xdrs, rp)
+\s-1XDR\s0 *xdrs;
+struct pmaplist **rp;
+.fi
+.ft R
+.IP
+Used for describing a list of port mappings, externally.
+This routine is useful for users who wish to generate
+these parameters without using the
+.B pmap
+interface.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_rejected_reply(xdrs, rr)
+\s-1XDR\s0 *xdrs;
+struct rejected_reply *rr;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+reply messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_replymsg(xdrs, rmsg)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *rmsg;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+reply messages.
+This routine is useful for users who wish to generate
+.SM RPC
+style messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+xprt_register(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+After
+.SM RPC
+service transport handles are created,
+they should register themselves with the
+.SM RPC
+service package.
+This routine modifies the global variable
+.BR svc_fds(\|) .
+Service implementors usually do not need this routine.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+xprt_unregister(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Before an
+.SM RPC
+service transport handle is destroyed,
+it should unregister itself with the
+.SM RPC
+service package.
+This routine modifies the global variable
+.BR svc_fds(\|) .
+Service implementors usually do not need this routine.
+.SH SEE ALSO
+.BR rpc_secure (3),
+.BR xdr (3)
+.br
+The following manuals:
+.RS
+.ft I
+Remote Procedure Calls: Protocol Specification
+.br
+Remote Procedure Call Programming Guide
+.br
+rpcgen Programming Guide
+.br
+.ft R
+.RE
+.IR "\s-1RPC\s0: Remote Procedure Call Protocol Specification" ,
+.SM RFC1050, Sun Microsystems, Inc.,
+.SM USC-ISI\s0.
+
diff --git a/lib/libc/rpc/rpc.5 b/lib/libc/rpc/rpc.5
new file mode 100644
index 0000000..d464395
--- /dev/null
+++ b/lib/libc/rpc/rpc.5
@@ -0,0 +1,34 @@
+.\" @(#)rpc.5 2.2 88/08/03 4.0 RPCSRC; from 1.4 87/11/27 SMI;
+.Dd September 26, 1985
+.Dt RPC 5
+.Sh NAME
+.Nm rpc
+.Nd rpc program number data base
+.Sh SYNOPSIS
+/etc/rpc
+.Sh DESCRIPTION
+The
+.Pa /etc/rpc
+file contains user readable names that
+can be used in place of rpc program numbers.
+Each line has the following information:
+.Pp
+.Bl -bullet -compact
+.It
+name of server for the rpc program
+.It
+rpc program number
+.It
+aliases
+.El
+.Pp
+Items are separated by any number of blanks and/or
+tab characters.
+A ``#'' 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 -compact -width /etc/rpc
+.Pa /etc/rpc
+.El
+.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..af8e573
--- /dev/null
+++ b/lib/libc/rpc/rpc_callmsg.c
@@ -0,0 +1,193 @@
+/*
+ * 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 = "from: @(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: rpc_callmsg.c,v 1.5 1996/12/30 14:55:38 peter Exp $";
+#endif
+
+/*
+ * rpc_callmsg.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/rpc.h>
+
+/*
+ * XDR a call message
+ */
+bool_t
+xdr_callmsg(xdrs, cmsg)
+ register XDR *xdrs;
+ register struct rpc_msg *cmsg;
+{
+ register int32_t *buf;
+ register struct opaque_auth *oa;
+
+ 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_LONG(buf, cmsg->rm_xid);
+ IXDR_PUT_ENUM(buf, cmsg->rm_direction);
+ if (cmsg->rm_direction != CALL) {
+ return (FALSE);
+ }
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_rpcvers);
+ if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+ return (FALSE);
+ }
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_prog);
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_vers);
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_proc);
+ oa = &cmsg->rm_call.cb_cred;
+ IXDR_PUT_ENUM(buf, oa->oa_flavor);
+ IXDR_PUT_LONG(buf, oa->oa_length);
+ if (oa->oa_length) {
+ memcpy((caddr_t)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_LONG(buf, oa->oa_length);
+ if (oa->oa_length) {
+ memcpy((caddr_t)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_LONG(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_LONG(buf);
+ if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+ return (FALSE);
+ }
+ cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf);
+ cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf);
+ cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf);
+ oa = &cmsg->rm_call.cb_cred;
+ oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+ oa->oa_length = IXDR_GET_LONG(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);
+ }
+ 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 {
+ memcpy(oa->oa_base, (caddr_t)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 = IXDR_GET_LONG(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);
+ }
+ 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 {
+ memcpy(oa->oa_base, (caddr_t)buf,
+ oa->oa_length);
+ /* no real need...
+ buf += RNDUP(oa->oa_length) /
+ sizeof (int32_t);
+ */
+ }
+ }
+ return (TRUE);
+ }
+ }
+ if (
+ xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *)&(cmsg->rm_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_commondata.c b/lib/libc/rpc/rpc_commondata.c
new file mode 100644
index 0000000..9640782
--- /dev/null
+++ b/lib/libc/rpc/rpc_commondata.c
@@ -0,0 +1,43 @@
+/*
+ * 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 = "from: @(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: rpc_commondata.c,v 1.3 1996/12/30 14:57:33 peter Exp $";
+#endif
+
+#include <rpc/rpc.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;
+struct rpc_createerr rpc_createerr;
diff --git a/lib/libc/rpc/rpc_dtablesize.c b/lib/libc/rpc/rpc_dtablesize.c
new file mode 100644
index 0000000..c2703fa
--- /dev/null
+++ b/lib/libc/rpc/rpc_dtablesize.c
@@ -0,0 +1,61 @@
+/*
+ * 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 = "from: @(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";*/
+/*static char *sccsid = "from: @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: rpc_dtablesize.c,v 1.6 1996/12/30 18:41:20 peter Exp $";
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+
+/*
+ * 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_prot.c b/lib/libc/rpc/rpc_prot.c
new file mode 100644
index 0000000..8debaf1
--- /dev/null
+++ b/lib/libc/rpc/rpc_prot.c
@@ -0,0 +1,297 @@
+/*
+ * 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 = "from: @(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC";*/
+static char *rcsid = "$Id: rpc_prot.c,v 1.4 1996/12/30 15:00:53 peter Exp $";
+#endif
+
+/*
+ * 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 <sys/param.h>
+
+#include <rpc/rpc.h>
+
+/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
+
+struct opaque_auth _null_auth;
+
+/*
+ * XDR an opaque authentication struct
+ * (see auth.h)
+ */
+bool_t
+xdr_opaque_auth(xdrs, ap)
+ register XDR *xdrs;
+ register struct opaque_auth *ap;
+{
+
+ 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)
+ register XDR *xdrs;
+ register des_block *blkp;
+{
+ return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block)));
+}
+
+/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
+
+/*
+ * XDR the MSG_ACCEPTED part of a reply message union
+ */
+bool_t
+xdr_accepted_reply(xdrs, ar)
+ register XDR *xdrs;
+ register struct accepted_reply *ar;
+{
+
+ /* personalized union, rather than calling xdr_union */
+ if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
+ return (FALSE);
+ if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_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)));
+ default:
+ 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)
+ register XDR *xdrs;
+ register struct rejected_reply *rr;
+{
+
+ /* personalized union, rather than calling xdr_union */
+ if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_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:
+ return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
+ }
+ return (FALSE);
+}
+
+static struct xdr_discrim reply_dscrm[3] = {
+ { (int)MSG_ACCEPTED, xdr_accepted_reply },
+ { (int)MSG_DENIED, xdr_rejected_reply },
+ { __dontcare__, NULL_xdrproc_t } };
+
+/*
+ * XDR a reply message
+ */
+bool_t
+xdr_replymsg(xdrs, rmsg)
+ register XDR *xdrs;
+ register struct rpc_msg *rmsg;
+{
+ if (
+ xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
+ (rmsg->rm_direction == REPLY) )
+ return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
+ (caddr_t)&(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)
+ register XDR *xdrs;
+ register struct rpc_msg *cmsg;
+{
+
+ 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 *)&(cmsg->rm_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)
+ register enum accept_stat acpt_stat;
+ register struct rpc_err *error;
+{
+
+ 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;
+ }
+ /* something's wrong, but we don't know what ... */
+ error->re_status = RPC_FAILED;
+ error->re_lb.s1 = (long)MSG_ACCEPTED;
+ error->re_lb.s2 = (long)acpt_stat;
+}
+
+static void
+rejected(rjct_stat, error)
+ register enum reject_stat rjct_stat;
+ register struct rpc_err *error;
+{
+
+ switch (rjct_stat) {
+
+ case RPC_VERSMISMATCH:
+ error->re_status = RPC_VERSMISMATCH;
+ return;
+
+ case AUTH_ERROR:
+ error->re_status = RPC_AUTHERROR;
+ return;
+ default:
+ break;
+ }
+ /* something's wrong, but we don't know what ... */
+ error->re_status = RPC_FAILED;
+ error->re_lb.s1 = (long)MSG_DENIED;
+ error->re_lb.s2 = (long)rjct_stat;
+}
+
+/*
+ * given a reply message, fills in the error
+ */
+void
+_seterr_reply(msg, error)
+ register struct rpc_msg *msg;
+ register struct rpc_err *error;
+{
+
+ /* 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 = (long)(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;
+ default:
+ break;
+ }
+}
diff --git a/lib/libc/rpc/rpc_secure.3 b/lib/libc/rpc/rpc_secure.3
new file mode 100644
index 0000000..6e9a2ee
--- /dev/null
+++ b/lib/libc/rpc/rpc_secure.3
@@ -0,0 +1,330 @@
+.\" @(#)rpc_secure.3n 2.1 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI
+.TH RPC 3N "16 February 1988"
+.SH NAME
+rpc_secure \- library routines for secure remote procedure calls
+.SH SYNOPSIS AND DESCRIPTION
+These routines are part of the RPC library. They implement DES
+Authentication. See
+.BR rpc (3N)
+for further details about RPC.
+.LP
+.ft B
+.nf
+.sp .5
+#include <rpc/rpc.h>
+.fi
+.ft R
+.br
+.if t .ne 22
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authdes_create(name, window, syncaddr, ckey)
+char *name;
+unsigned window;
+struct sockaddr_in *addr;
+des_block *ckey;
+.fi
+.ft R
+.IP
+.B authdes_create(\|)
+is the first of two routines which interface to the
+.SM RPC
+secure authentication system, known as
+.SM DES
+authentication.
+The second is
+.BR authdes_getucred(\|) ,
+below. Note: the keyserver daemon
+.BR keyserv (8C)
+must be running for the
+.SM DES
+authentication system to work.
+.IP
+.BR authdes_create(\|) ,
+used on the client side, returns an authentication handle that
+will enable the use of the secure authentication system.
+The first parameter
+.I name
+is the network name, or
+.IR netname ,
+of the owner of the server process. This field usually
+represents a
+.I hostname
+derived from the utility routine
+.BR host2netname ,
+but could also represent a user name using
+.BR 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
+parameter
+.I syncaddr
+is optional. If it is
+.SM NULL\s0,
+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 parameter is usually the
+address of the
+.SM RPC
+server itself. The final parameter
+.I ckey
+is also optional. If it is
+.SM NULL\s0,
+then the authentication system will
+generate a random
+.SM DES
+key to be used for the encryption of credentials.
+If it is supplied, however, then it will be used instead.
+.br
+.if t .ne 13
+.LP
+.ft B
+.nf
+.sp .5
+authdes_getucred(adc, uid, gid, grouplen, groups)
+struct authdes_cred *adc;
+short *uid;
+short *gid;
+short *grouplen;
+int *groups;
+.fi
+.ft R
+.IP
+.BR authdes_getucred(\|) ,
+the second of the two
+.SM DES
+authentication routines,
+is used on the server side for converting a
+.SM DES
+credential, which is
+operating system independent, into a
+.UX
+credential. This routine differs from utility routine
+.B netname2user
+in that
+.B 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.
+.br
+.ft .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+host2netname(name, host, domain)
+char *name;
+char *host;
+char *domain;
+.fi
+.ft R
+.IP
+Convert from a domain-specific hostname to an
+operating-system independent netname. Return
+.SM TRUE
+if it succeeds and
+.SM FALSE
+if it fails. Inverse of
+.BR netname2host(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+key_decryptsession(remotename, deskey)
+char *remotename;
+des_block *deskey;
+.fi
+.ft R
+.IP
+.B key_decryptsession(\|)
+is an interface to the keyserver daemon, which is associated
+with
+.SM RPC\s0's
+secure authentication system (\s-1DES\s0
+authentication).
+User programs rarely need to call it, or its associated routines
+.BR key_encryptsession(\|) ,
+.B key_gendes(\|)
+and
+.BR key_setsecret(\|) .
+System commands such as
+.B login
+and the
+.SM RPC
+library are the main clients of these four routines.
+.IP
+.B key_decryptsession(\|)
+takes a server netname and a des key, and decrypts the key by
+using the the public key of the the server and the secret key
+associated with the effective uid of the calling process. It
+is the inverse of
+.BR key_encryptsession(\|) .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+key_encryptsession(remotename, deskey)
+char *remotename;
+des_block *deskey;
+.fi
+.ft R
+.IP
+.B key_encryptsession(\|)
+is a keyserver interface routine. It
+takes a server netname and a des key, and encrypts
+it using the public key of the the server and the secret key
+associated with the effective uid of the calling process. It
+is the inverse of
+.BR key_decryptsession(\|) .
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+key_gendes(deskey)
+des_block *deskey;
+.fi
+.ft R
+.IP
+.B key_gendes(\|)
+is a keyserver interface routine. It
+is used to ask the keyserver for a secure conversation key.
+Choosing one at \(lqrandom\(rq is usually not good enough,
+because
+the common ways of choosing random numbers, such as using the
+current time, are very easy to guess.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+key_setsecret(key)
+char *key;
+.fi
+.ft R
+.IP
+.B key_setsecret(\|)
+is a keyserver interface routine. It is used to set the key for
+the effective
+.I uid
+of the calling process.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+getnetname(name)
+char name[\s-1MAXNETNAMELEN\s0];
+.fi
+.ft R
+.IP
+.B getnetname(\|)
+installs the unique, operating-system independent netname of
+the
+caller in the fixed-length array
+.IR name .
+Returns
+.SM TRUE
+if it succeeds and
+.SM FALSE
+if it fails.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+netname2host(name, host, hostlen)
+char *name;
+char *host;
+int hostlen;
+.fi
+.ft R
+.IP
+Convert from an operating-system independent netname to a
+domain-specific hostname. Returns
+.SM TRUE
+if it succeeds and
+.SM FALSE
+if it fails. Inverse of
+.BR host2netname(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+netname2user(name, uidp, gidp, gidlenp, gidlist)
+char *name;
+int *uidp;
+int *gidp;
+int *gidlenp;
+int *gidlist;
+.fi
+.ft R
+.IP
+Convert from an operating-system independent netname to a
+domain-specific user
+.SM ID.
+Returns
+.SM TRUE
+if it succeeds and
+.SM FALSE
+if it fails. Inverse of
+.BR user2netname(\|) .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+user2netname(name, uid, domain)
+char *name;
+int uid;
+char *domain;
+.fi
+.ft R
+.IP
+Convert from a domain-specific username to an operating-system
+independent netname. Returns
+.SM TRUE
+if it succeeds and
+.SM FALSE
+if it fails. Inverse of
+.BR netname2user(\|) .
+.br
+.SH SEE ALSO
+.BR xdr (3N),
+.BR keyserv (8C),
+.BR rpc (3N)
+.br
+The following manuals:
+.RS
+.ft I
+Remote Procedure Calls: Protocol Specification
+.br
+Remote Procedure Call Programming Guide
+.br
+rpcgen Programming Guide
+.br
+.ft R
+.RE
+.IR "\s-1RPC\s0: Remote Procedure Call Protocol Specification" ,
+.SM RFC1050, Sun Microsystems, Inc.,
+.SM USC-ISI\s0.
+
diff --git a/lib/libc/rpc/rpcdname.c b/lib/libc/rpc/rpcdname.c
new file mode 100644
index 0000000..f28b4fd
--- /dev/null
+++ b/lib/libc/rpc/rpcdname.c
@@ -0,0 +1,77 @@
+/*
+ * 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(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpcdname.c 1.7 91/03/11 Copyr 1989 Sun Micro";
+#endif
+
+/*
+ * rpcdname.c
+ * Gets the default domain name
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.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/rstat.1 b/lib/libc/rpc/rstat.1
new file mode 100644
index 0000000..03c3a06
--- /dev/null
+++ b/lib/libc/rpc/rstat.1
@@ -0,0 +1,57 @@
+.\" @(#)rstat.1 2.1 88/08/03 4.0 RPCSRC
+.TH RSTAT 1 "3 August 1988"
+.SH NAME
+rstat \- remote status display
+.SH SYNOPSIS
+.B rstat
+.B host
+.SH DESCRIPTION
+.LP
+.B rstat
+displays a summary of the current system status of a particular
+.BR host .
+The output shows the current time of day, how long the system has
+been up,
+and the load averages.
+The load average numbers give the number of jobs in the run queue
+averaged over 1, 5 and 15 minutes.
+.PP
+The
+.B rstat_svc(8)
+daemon must be running on the remote host for this command to
+work.
+.B rstat
+uses an RPC protocol defined in /usr/include/rpcsvc/rstat.x.
+.SH EXAMPLE
+.RS
+.ft B
+.nf
+example% rstat otherhost
+7:36am up 6 days, 16:45, load average: 0.20, 0.23, 0.18
+example%
+.ft R
+.fi
+.RE
+.SH DIAGNOSTICS
+.LP
+rstat: RPC: Program not registered
+.IP
+The
+.B rstat_svc
+daemon has not been started on the remote host.
+.LP
+rstat: RPC: Timed out
+.IP
+A communication error occurred. Either the network is
+excessively congested, or the
+.B rstat_svc
+daemon has terminated on the remote host.
+.LP
+rstat: RPC: Port mapper failure - RPC: Timed out
+.IP
+The remote host is not running the portmapper (see
+.BR portmap(8) ),
+and cannot accommodate any RPC-based services. The host may be down.
+.SH "SEE ALSO"
+.BR portmap (8),
+.BR rstat_svc (8)
diff --git a/lib/libc/rpc/rstat_svc.8 b/lib/libc/rpc/rstat_svc.8
new file mode 100644
index 0000000..b7b4386
--- /dev/null
+++ b/lib/libc/rpc/rstat_svc.8
@@ -0,0 +1,21 @@
+.\" @(#)rstat_svc.8c 2.2 88/08/03 4.0 RPCSRC; from 1.10 87/09/09 SMI
+.TH RSTAT_SVC 8 "24 November 1987"
+.SH NAME
+rstat_svc \- kernel statistics server
+.SH SYNOPSIS
+.B /etc/rstat_svc
+.SH DESCRIPTION
+.LP
+.B rstat_svc
+is a server which returns performance statistics
+obtained from the kernel.
+These statistics are graphically displayed by the Sun Microsystems program,
+.BR perfmeter (1).
+The
+.B rstat_svc
+daemon is normally invoked at boot time through /etc/rc.local.
+.PP
+.B rstat_svc
+uses an RPC protocol defined in /usr/include/rpcsvc/rstat.x.
+.\" .SH "SEE ALSO"
+.\" .BR rstat (1),
diff --git a/lib/libc/rpc/rtime.3 b/lib/libc/rpc/rtime.3
new file mode 100644
index 0000000..af0c1ca
--- /dev/null
+++ b/lib/libc/rpc/rtime.3
@@ -0,0 +1,43 @@
+.\" @(#)rtime.3n 2.1 88/08/08 4.0 RPCSRC; from 1.5 88/02/08 SMI
+.TH RTIME 3 "22 November 1987"
+.SH NAME
+rtime \- get remote time
+.SH SYNOPSIS
+.nf
+.B #include <sys/types.h>
+.B #include <sys/time.h>
+.B #include <netinet/in.h>
+.LP
+.B int rtime(addrp, timep, timeout)
+.B struct sockaddr_in \(**addrp;
+.B struct timeval \(**timep;
+.B struct timeval \(**timeout;
+.fi
+.SH DESCRIPTION
+.B rtime(\|)
+consults the Internet Time Server at the address pointed to by
+.I addrp
+and returns the remote time in the
+.B timeval
+struct pointed to by
+.IR timep .
+Normally, the
+.SM UDP
+protocol is used when consulting the Time Server. The
+.I timeout
+parameter specifies how long the
+routine should wait before giving
+up when waiting for a reply. If
+.I timeout
+is specified as
+.SM NULL\s0,
+however, the routine will instead use
+.SM TCP
+and block until a reply is received from the time server.
+.LP
+The routine returns 0 if it is successful. Otherwise,
+it returns \-1 and
+.B errno
+is set to reflect the cause of the error.
+.SH "SEE ALSO"
+.BR timed (8c)
diff --git a/lib/libc/rpc/rtime.c b/lib/libc/rpc/rtime.c
new file mode 100644
index 0000000..fb2b402
--- /dev/null
+++ b/lib/libc/rpc/rtime.c
@@ -0,0 +1,157 @@
+/*
+ * 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 <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>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/* from: static char sccsid[] = "@(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI"; */
+static const char rcsid[] = "$Id$";
+#endif
+
+extern int _rpc_dtablesize __P(( void ));
+
+#define NYEARS (unsigned long)(1970 - 1900)
+#define TOFFSET (unsigned long)(60*60*24*(365*NYEARS + (NYEARS/4)))
+
+static void do_close __P(( 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;
+ int 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..ab0e8c1
--- /dev/null
+++ b/lib/libc/rpc/svc.c
@@ -0,0 +1,494 @@
+/*
+ * 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 = "from: @(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc.c 2.4 88/08/11 4.0 RPCSRC";*/
+static char *rcsid = "$Id: svc.c,v 1.7 1996/12/30 15:07:33 peter Exp $";
+#endif
+
+/*
+ * 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 <string.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+
+static SVCXPRT **xports;
+static int xportssize;
+
+#define NULL_SVC ((struct svc_callout *)0)
+#define RQCRED_SIZE 400 /* this size is excessive */
+
+#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;
+ u_long sc_prog;
+ u_long sc_vers;
+ void (*sc_dispatch)();
+} *svc_head;
+
+static struct svc_callout *svc_find();
+
+int __svc_fdsetsize;
+fd_set *__svc_fdset;
+
+/* *************** SVCXPRT related stuff **************** */
+
+/*
+ * Activate a transport handle.
+ */
+void
+xprt_register(xprt)
+ SVCXPRT *xprt;
+{
+ register int sock = xprt->xp_sock;
+
+ if (sock + 1 > __svc_fdsetsize) {
+ int bytes = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
+ fd_set *fds;
+
+ fds = (fd_set *)malloc(bytes);
+ memset(fds, 0, bytes);
+ if (__svc_fdset) {
+ memcpy(fds, __svc_fdset, howmany(__svc_fdsetsize,
+ NFDBITS) * sizeof(fd_mask));
+ free(__svc_fdset);
+ }
+ __svc_fdset = fds;
+ __svc_fdsetsize = howmany(sock+1, NFDBITS);
+ }
+
+ if (sock < FD_SETSIZE)
+ FD_SET(sock, &svc_fdset);
+ FD_SET(sock, __svc_fdset);
+
+ if (xports == NULL || sock + 1 > xportssize) {
+ SVCXPRT **xp;
+ int size = FD_SETSIZE;
+
+ if (sock + 1 > size)
+ size = sock + 1;
+ xp = (SVCXPRT **)mem_alloc(size * sizeof(SVCXPRT *));
+ memset(xp, 0, size * sizeof(SVCXPRT *));
+ if (xports) {
+ memcpy(xp, xports, xportssize * sizeof(SVCXPRT *));
+ free(xports);
+ }
+ xportssize = size;
+ xports = xp;
+ }
+ xports[sock] = xprt;
+ svc_maxfd = max(svc_maxfd, sock);
+}
+
+/*
+ * De-activate a transport handle.
+ */
+void
+xprt_unregister(xprt)
+ SVCXPRT *xprt;
+{
+ register int sock = xprt->xp_sock;
+
+ if (xports[sock] == xprt) {
+ xports[sock] = (SVCXPRT *)0;
+ if (sock < FD_SETSIZE)
+ FD_CLR(sock, &svc_fdset);
+ FD_CLR(sock, __svc_fdset);
+ if (sock == svc_maxfd) {
+ for (svc_maxfd--; svc_maxfd >= 0; svc_maxfd--)
+ if (xports[svc_maxfd])
+ break;
+ }
+ /*
+ * XXX could use svc_maxfd as a hint to
+ * decrease the size of __svc_fdset
+ */
+ }
+}
+
+
+/* ********************** CALLOUT list related stuff ************* */
+
+/*
+ * 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)();
+ int protocol;
+{
+ struct svc_callout *prev;
+ register struct svc_callout *s;
+
+ if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
+ if (s->sc_dispatch == dispatch)
+ goto pmap_it; /* he is registering another xptr */
+ return (FALSE);
+ }
+ s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
+ if (s == (struct svc_callout *)0) {
+ return (FALSE);
+ }
+ s->sc_prog = prog;
+ s->sc_vers = 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;
+ register struct svc_callout *s;
+
+ if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
+ return;
+ if (prev == NULL_SVC) {
+ svc_head = s->sc_next;
+ } else {
+ prev->sc_next = s->sc_next;
+ }
+ s->sc_next = NULL_SVC;
+ mem_free((char *) s, (u_int) sizeof(struct svc_callout));
+ /* now unregister the information with the local binder service */
+ (void)pmap_unset(prog, vers);
+}
+
+/*
+ * Search the callout list for a program number, return the callout
+ * struct.
+ */
+static struct svc_callout *
+svc_find(prog, vers, prev)
+ u_long prog;
+ u_long vers;
+ struct svc_callout **prev;
+{
+ register struct svc_callout *s, *p;
+
+ p = NULL_SVC;
+ for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
+ if ((s->sc_prog == prog) && (s->sc_vers == vers))
+ goto done;
+ p = s;
+ }
+done:
+ *prev = p;
+ return (s);
+}
+
+/* ******************* REPLY GENERATION ROUTINES ************ */
+
+/*
+ * Send a reply to an rpc request
+ */
+bool_t
+svc_sendreply(xprt, xdr_results, xdr_location)
+ register SVCXPRT *xprt;
+ xdrproc_t xdr_results;
+ caddr_t xdr_location;
+{
+ struct rpc_msg rply;
+
+ 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)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ 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)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ 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)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ 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);
+}
+
+/*
+ * Authentication error reply
+ */
+void
+svcerr_auth(xprt, why)
+ SVCXPRT *xprt;
+ enum auth_stat why;
+{
+ struct rpc_msg rply;
+
+ 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;
+{
+
+ svcerr_auth(xprt, AUTH_TOOWEAK);
+}
+
+/*
+ * Program unavailable error reply
+ */
+void
+svcerr_noprog(xprt)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ 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)
+ register SVCXPRT *xprt;
+ u_long low_vers;
+ u_long high_vers;
+{
+ struct rpc_msg rply;
+
+ 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 = low_vers;
+ rply.acpted_rply.ar_vers.high = high_vers;
+ SVC_REPLY(xprt, &rply);
+}
+
+/* ******************* 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;
+{
+ svc_getreqset2(readfds, FD_SETSIZE);
+}
+
+void
+svc_getreqset2(readfds, width)
+ fd_set *readfds;
+ int width;
+{
+ enum xprt_stat stat;
+ struct rpc_msg msg;
+ int prog_found;
+ u_long low_vers;
+ u_long high_vers;
+ struct svc_req r;
+ register SVCXPRT *xprt;
+ register int bit;
+ register int sock;
+ register fd_mask mask, *maskp;
+ 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]);
+
+
+ maskp = readfds->fds_bits;
+ for (sock = 0; sock < width; sock += NFDBITS) {
+ for (mask = *maskp++; (bit = ffs(mask)); mask ^= (1 << (bit - 1))) {
+ /* sock has input waiting */
+ xprt = xports[sock + bit - 1];
+ if (xprt == NULL)
+ /* But do we control sock? */
+ continue;
+ /* now receive msgs from xprtprt (support batch calls) */
+ do {
+ if (SVC_RECV(xprt, &msg)) {
+
+ /* now find the exported program and call it */
+ register 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) {
+ svcerr_auth(xprt, why);
+ goto call_done;
+ }
+ /* now match message with a registered service*/
+ prog_found = FALSE;
+ low_vers = (u_long) - 1;
+ high_vers = 0;
+ for (s = svc_head; s != NULL_SVC; 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 ... */
+ }
+ call_done:
+ if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
+ SVC_DESTROY(xprt);
+ break;
+ }
+ } while (stat == XPRT_MOREREQS);
+ }
+ }
+}
diff --git a/lib/libc/rpc/svc_auth.c b/lib/libc/rpc/svc_auth.c
new file mode 100644
index 0000000..0063e75
--- /dev/null
+++ b/lib/libc/rpc/svc_auth.c
@@ -0,0 +1,211 @@
+/*
+ * 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_auth.c 1.16 94/04/24 SMI"
+
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_auth.c 1.26 89/02/07 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_auth.c, Server-side rpc authenticator interface.
+ *
+ */
+
+#ifdef KERNEL
+#include <sys/param.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+#include <rpc/rpc_msg.h>
+#include <rpc/svc.h>
+#include <rpc/svc_auth.h>
+#else
+#include <stdlib.h>
+#include <rpc/rpc.h>
+#endif
+#include <sys/types.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)
+ * register struct svc_req *rqst;
+ * register struct rpc_msg *msg;
+ *
+ */
+
+enum auth_stat _svcauth_null(); /* no authentication */
+enum auth_stat _svcauth_unix(); /* (system) unix style (uid, gids) */
+enum auth_stat _svcauth_short(); /* short hand unix style */
+enum auth_stat _svcauth_des(); /* des style */
+
+/* declarations to allow servers to specify new authentication flavors */
+struct authsvc {
+ int flavor;
+ enum auth_stat (*handler)();
+ struct authsvc *next;
+};
+static struct authsvc *Auths = NULL;
+
+/*
+ * 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)
+ register struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ register int cred_flavor;
+ register struct authsvc *asp;
+
+ rqst->rq_cred = msg->rm_call.cb_cred;
+ 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:
+ return(_svcauth_null(rqst, msg));
+ case AUTH_UNIX:
+ return(_svcauth_unix(rqst, msg));
+ case AUTH_SHORT:
+ return(_svcauth_short(rqst, msg));
+ /*
+ * We leave AUTH_DES turned off by default because svcauth_des()
+ * needs getpublickey(), which is in librpcsvc, not libc. If we
+ * included AUTH_DES as a built-in flavor, programs that don't
+ * have -lrpcsvc in their Makefiles wouldn't link correctly, even
+ * though they don't use AUTH_DES. And I'm too lazy to go through
+ * the tree looking for all of them.
+ */
+#ifdef DES_BUILTIN
+ case AUTH_DES:
+ return(_svcauth_des(rqst, msg));
+#endif
+ }
+
+ /* flavor doesn't match any of the builtin types, so try new ones */
+ for (asp = Auths; asp; asp = asp->next) {
+ if (asp->flavor == cred_flavor) {
+ enum auth_stat as;
+
+ as = (*asp->handler)(rqst, msg);
+ return (as);
+ }
+ }
+
+ return (AUTH_REJECTEDCRED);
+}
+
+/*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)
+ register int cred_flavor;
+ enum auth_stat (*handler)();
+{
+ register struct authsvc *asp;
+
+ switch (cred_flavor) {
+ case AUTH_NULL:
+ case AUTH_UNIX:
+ case AUTH_SHORT:
+#ifdef DES_BUILTIN
+ case AUTH_DES:
+#endif
+ /* already registered */
+ return (1);
+
+ default:
+ for (asp = Auths; asp; asp = asp->next) {
+ if (asp->flavor == cred_flavor) {
+ /* already registered */
+ return (1);
+ }
+ }
+
+ /* this is a new one, so go ahead and register it */
+ asp = (struct authsvc *)mem_alloc(sizeof (*asp));
+ if (asp == NULL) {
+ return (-1);
+ }
+ asp->flavor = cred_flavor;
+ asp->handler = handler;
+ asp->next = Auths;
+ Auths = asp;
+ 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..889182e
--- /dev/null
+++ b/lib/libc/rpc/svc_auth_des.c
@@ -0,0 +1,531 @@
+
+/*
+ * 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 <string.h>
+#include <stdlib.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>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/* from: static char sccsid[] = "@(#)svcauth_des.c 2.3 89/07/11 4.0 RPCSRC; from 1.15 88/02/08 SMI"; */
+static const char rcsid[] = "$Id$";
+#endif
+
+#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)
+ register struct svc_req *rqst;
+ register struct rpc_msg *msg;
+{
+
+ register long *ixdr;
+ des_block cryptbuf[2];
+ register struct authdes_cred *cred;
+ struct authdes_verf verf;
+ int status;
+ register 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 >= 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()
+{
+ register 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)
+ register short sid;
+{
+ register int i;
+ register short curr;
+ register 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)
+ register des_block *key;
+ char *name;
+ struct timeval *timestamp;
+{
+ register struct cache_entry *cp;
+ register int i;
+ register 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 {
+ short uid; /* cached uid */
+ short gid; /* cached gid */
+ short grouplen; /* length of cached groups */
+ short groups[NGROUPS]; /* 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;
+ register gid_t *groups;
+{
+ unsigned sid;
+ register 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..959cb73
--- /dev/null
+++ b/lib/libc/rpc/svc_auth_unix.c
@@ -0,0 +1,148 @@
+/*
+ * 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 = "from: @(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_auth_unix.c 2.3 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: svc_auth_unix.c,v 1.4 1996/12/30 15:10:14 peter Exp $";
+#endif
+
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include <rpc/rpc.h>
+
+/*
+ * Unix longhand authenticator
+ */
+enum auth_stat
+_svcauth_unix(rqst, msg)
+ register struct svc_req *rqst;
+ register struct rpc_msg *msg;
+{
+ register enum auth_stat stat;
+ XDR xdrs;
+ register struct authunix_parms *aup;
+ register 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;
+ int str_len, gid_len;
+ register int i;
+
+ 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_LONG(buf);
+ str_len = IXDR_GET_U_LONG(buf);
+ if (str_len > MAX_MACHINE_NAME) {
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+ memcpy(aup->aup_machname, (caddr_t)buf, (u_int)str_len);
+ aup->aup_machname[str_len] = 0;
+ str_len = RNDUP(str_len);
+ buf += str_len / sizeof (int32_t);
+ aup->aup_uid = IXDR_GET_LONG(buf);
+ aup->aup_gid = IXDR_GET_LONG(buf);
+ gid_len = IXDR_GET_U_LONG(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] = IXDR_GET_LONG(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 %d str %d auth %d\n",
+ gid_len, 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_raw.c b/lib/libc/rpc/svc_raw.c
new file mode 100644
index 0000000..3a5bcb3
--- /dev/null
+++ b/lib/libc/rpc/svc_raw.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
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_raw.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: svc_raw.c,v 1.3 1995/10/22 14:51:36 phk Exp $";
+#endif
+
+/*
+ * 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 kernal.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <stdlib.h>
+
+/*
+ * This is the "network" that we will be moving data over
+ */
+static struct svcraw_private {
+ char _raw_buf[UDPMSGSIZE];
+ SVCXPRT server;
+ XDR xdr_stream;
+ char verf_body[MAX_AUTH_BYTES];
+} *svcraw_private;
+
+static bool_t svcraw_recv();
+static enum xprt_stat svcraw_stat();
+static bool_t svcraw_getargs();
+static bool_t svcraw_reply();
+static bool_t svcraw_freeargs();
+static void svcraw_destroy();
+
+static struct xp_ops server_ops = {
+ svcraw_recv,
+ svcraw_stat,
+ svcraw_getargs,
+ svcraw_reply,
+ svcraw_freeargs,
+ svcraw_destroy
+};
+
+SVCXPRT *
+svcraw_create()
+{
+ register struct svcraw_private *srp = svcraw_private;
+
+ if (srp == 0) {
+ srp = (struct svcraw_private *)calloc(1, sizeof (*srp));
+ if (srp == 0)
+ return (0);
+ }
+ srp->server.xp_sock = 0;
+ srp->server.xp_port = 0;
+ srp->server.xp_ops = &server_ops;
+ srp->server.xp_verf.oa_base = srp->verf_body;
+ xdrmem_create(&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+ return (&srp->server);
+}
+
+static enum xprt_stat
+svcraw_stat()
+{
+
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svcraw_recv(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svcraw_private *srp = svcraw_private;
+ register XDR *xdrs;
+
+ if (srp == 0)
+ return (0);
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_DECODE;
+ XDR_SETPOS(xdrs, 0);
+ if (! xdr_callmsg(xdrs, msg))
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+svcraw_reply(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svcraw_private *srp = svcraw_private;
+ register XDR *xdrs;
+
+ if (srp == 0)
+ return (FALSE);
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ if (! xdr_replymsg(xdrs, msg))
+ return (FALSE);
+ (void)XDR_GETPOS(xdrs); /* called just for overhead */
+ return (TRUE);
+}
+
+static bool_t
+svcraw_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register struct svcraw_private *srp = svcraw_private;
+
+ if (srp == 0)
+ return (FALSE);
+ return ((*xdr_args)(&srp->xdr_stream, args_ptr));
+}
+
+static bool_t
+svcraw_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register struct svcraw_private *srp = svcraw_private;
+ register XDR *xdrs;
+
+ if (srp == 0)
+ return (FALSE);
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static void
+svcraw_destroy()
+{
+}
diff --git a/lib/libc/rpc/svc_run.c b/lib/libc/rpc/svc_run.c
new file mode 100644
index 0000000..0692c25
--- /dev/null
+++ b/lib/libc/rpc/svc_run.c
@@ -0,0 +1,87 @@
+/*
+ * 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 = "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";*/
+static char *rcsid = "$Id: svc_run.c,v 1.7 1997/02/22 15:01:32 peter Exp $";
+#endif
+
+/*
+ * This is the rpc server side idle loop
+ * Wait for input, call server program.
+ */
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern int __svc_fdsetsize;
+extern fd_set *__svc_fdset;
+
+void
+svc_run()
+{
+ fd_set *fds;
+
+ for (;;) {
+ if (__svc_fdset) {
+ int bytes = howmany(__svc_fdsetsize, NFDBITS) *
+ sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+ memcpy(fds, __svc_fdset, bytes);
+ } else
+ fds = NULL;
+ switch (select(svc_maxfd + 1, fds, NULL, NULL,
+ (struct timeval *)0)) {
+ case -1:
+ if (errno == EINTR) {
+ if (fds)
+ free(fds);
+ continue;
+ }
+ perror("svc_run: - select failed");
+ if (fds)
+ free(fds);
+ return;
+ case 0:
+ if (fds)
+ free(fds);
+ continue;
+ default:
+ /* if fds == NULL, select() can't return a result */
+ svc_getreqset2(fds, svc_maxfd + 1);
+ free(fds);
+ }
+ }
+}
diff --git a/lib/libc/rpc/svc_simple.c b/lib/libc/rpc/svc_simple.c
new file mode 100644
index 0000000..0324675
--- /dev/null
+++ b/lib/libc/rpc/svc_simple.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.
+ *
+ * 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 = "from: @(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_simple.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: svc_simple.c,v 1.5 1996/12/30 15:16:22 peter Exp $";
+#endif
+
+/*
+ * svc_simple.c
+ * Simplified front end to rpc.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+static struct proglst {
+ char *(*p_progname)();
+ int p_prognum;
+ int p_procnum;
+ xdrproc_t p_inproc, p_outproc;
+ struct proglst *p_nxt;
+} *proglst;
+static void universal();
+static SVCXPRT *transp;
+struct proglst *pl;
+
+int
+registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
+ int prognum, versnum, procnum;
+ char *(*progname)();
+ xdrproc_t inproc, outproc;
+{
+
+ if (procnum == NULLPROC) {
+ (void) fprintf(stderr,
+ "can't reassign procedure number %ld\n", NULLPROC);
+ return (-1);
+ }
+ if (transp == 0) {
+ transp = svcudp_create(RPC_ANYSOCK);
+ if (transp == NULL) {
+ (void) fprintf(stderr, "couldn't create an rpc server\n");
+ return (-1);
+ }
+ }
+ (void) pmap_unset((u_long)prognum, (u_long)versnum);
+ if (!svc_register(transp, (u_long)prognum, (u_long)versnum,
+ universal, IPPROTO_UDP)) {
+ (void) fprintf(stderr, "couldn't register prog %d vers %d\n",
+ prognum, versnum);
+ return (-1);
+ }
+ pl = (struct proglst *)malloc(sizeof(struct proglst));
+ if (pl == NULL) {
+ (void) fprintf(stderr, "registerrpc: out of memory\n");
+ return (-1);
+ }
+ pl->p_progname = progname;
+ pl->p_prognum = prognum;
+ pl->p_procnum = procnum;
+ pl->p_inproc = inproc;
+ pl->p_outproc = outproc;
+ pl->p_nxt = proglst;
+ proglst = pl;
+ return (0);
+}
+
+static void
+universal(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ int prog, proc;
+ char *outdata;
+ char xdrbuf[UDPMSGSIZE];
+ struct proglst *pl;
+
+ /*
+ * enforce "procnum 0 is echo" convention
+ */
+ if (rqstp->rq_proc == NULLPROC) {
+ if (svc_sendreply(transp, xdr_void, NULL) == FALSE) {
+ (void) fprintf(stderr, "xxx\n");
+ exit(1);
+ }
+ return;
+ }
+ prog = rqstp->rq_prog;
+ proc = rqstp->rq_proc;
+ for (pl = proglst; pl != NULL; pl = pl->p_nxt)
+ if (pl->p_prognum == prog && pl->p_procnum == proc) {
+ /* decode arguments into a CLEAN buffer */
+ memset(xdrbuf, 0, sizeof(xdrbuf)); /* required ! */
+ if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) {
+ svcerr_decode(transp);
+ return;
+ }
+ outdata = (*(pl->p_progname))(xdrbuf);
+ if (outdata == NULL && pl->p_outproc != xdr_void)
+ /* there was an error */
+ return;
+ if (!svc_sendreply(transp, pl->p_outproc, outdata)) {
+ (void) fprintf(stderr,
+ "trouble replying to prog %d\n",
+ pl->p_prognum);
+ exit(1);
+ }
+ /* free the decoded arguments */
+ (void)svc_freeargs(transp, pl->p_inproc, xdrbuf);
+ return;
+ }
+ (void) fprintf(stderr, "never registered prog %d\n", prog);
+ exit(1);
+}
+
diff --git a/lib/libc/rpc/svc_tcp.c b/lib/libc/rpc/svc_tcp.c
new file mode 100644
index 0000000..1387ee1
--- /dev/null
+++ b/lib/libc/rpc/svc_tcp.c
@@ -0,0 +1,448 @@
+/*
+ * 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 = "from: @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: svc_tcp.c,v 1.8 1996/12/30 15:19:08 peter Exp $";
+#endif
+
+/*
+ * svc_tcp.c, Server side for TCP/IP based RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Actually implements two flavors of transporter -
+ * a tcp rendezvouser (a listner and connection establisher)
+ * and a record/tcp stream.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+/*
+ * Ops vector for TCP/IP based rpc service handle
+ */
+static bool_t svctcp_recv();
+static enum xprt_stat svctcp_stat();
+static bool_t svctcp_getargs();
+static bool_t svctcp_reply();
+static bool_t svctcp_freeargs();
+static void svctcp_destroy();
+
+static struct xp_ops svctcp_op = {
+ svctcp_recv,
+ svctcp_stat,
+ svctcp_getargs,
+ svctcp_reply,
+ svctcp_freeargs,
+ svctcp_destroy
+};
+
+/*
+ * Ops vector for TCP/IP rendezvous handler
+ */
+static bool_t rendezvous_request();
+static enum xprt_stat rendezvous_stat();
+
+static struct xp_ops svctcp_rendezvous_op = {
+ rendezvous_request,
+ rendezvous_stat,
+ (bool_t (*)())abort,
+ (bool_t (*)())abort,
+ (bool_t (*)())abort,
+ svctcp_destroy
+};
+
+static int readtcp(), writetcp();
+static SVCXPRT *makefd_xprt();
+
+struct tcp_rendezvous { /* kept in xprt->xp_p1 */
+ u_int sendsize;
+ u_int recvsize;
+};
+
+struct tcp_conn { /* kept in xprt->xp_p1 */
+ enum xprt_stat strm_stat;
+ u_long x_id;
+ XDR xdrs;
+ char verf_body[MAX_AUTH_BYTES];
+};
+
+/*
+ * Usage:
+ * xprt = svctcp_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.
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svctcp_create
+ * binds it to an arbitrary port. The routine then starts a tcp
+ * listener on the socket's associated port. In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ *
+ * Since tcp 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 *
+svctcp_create(sock, sendsize, recvsize)
+ register int sock;
+ u_int sendsize;
+ u_int recvsize;
+{
+ bool_t madesock = FALSE;
+ register SVCXPRT *xprt;
+ register struct tcp_rendezvous *r;
+ struct sockaddr_in addr;
+ int len = sizeof(struct sockaddr_in);
+
+ if (sock == RPC_ANYSOCK) {
+ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ perror("svctcp_.c - udp socket creation problem");
+ return ((SVCXPRT *)NULL);
+ }
+ madesock = TRUE;
+ }
+ memset(&addr, 0, sizeof (addr));
+ addr.sin_len = sizeof(struct sockaddr_in);
+ addr.sin_family = AF_INET;
+ if (bindresvport(sock, &addr)) {
+ addr.sin_port = 0;
+ (void)bind(sock, (struct sockaddr *)&addr, len);
+ }
+ if ((getsockname(sock, (struct sockaddr *)&addr, &len) != 0) ||
+ (listen(sock, 2) != 0)) {
+ perror("svctcp_.c - cannot getsockname or listen");
+ if (madesock)
+ (void)close(sock);
+ return ((SVCXPRT *)NULL);
+ }
+ r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r));
+ if (r == NULL) {
+ (void) fprintf(stderr, "svctcp_create: out of memory\n");
+ return (NULL);
+ }
+ r->sendsize = sendsize;
+ r->recvsize = recvsize;
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == NULL) {
+ (void) fprintf(stderr, "svctcp_create: out of memory\n");
+ return (NULL);
+ }
+ xprt->xp_p2 = NULL;
+ xprt->xp_p1 = (caddr_t)r;
+ xprt->xp_verf = _null_auth;
+ xprt->xp_ops = &svctcp_rendezvous_op;
+ xprt->xp_port = ntohs(addr.sin_port);
+ xprt->xp_sock = sock;
+ xprt_register(xprt);
+ return (xprt);
+}
+
+/*
+ * Like svtcp_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+SVCXPRT *
+svcfd_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+
+ return (makefd_xprt(fd, sendsize, recvsize));
+}
+
+static SVCXPRT *
+makefd_xprt(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ register SVCXPRT *xprt;
+ register struct tcp_conn *cd;
+
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == (SVCXPRT *)NULL) {
+ (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
+ goto done;
+ }
+ cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn));
+ if (cd == (struct tcp_conn *)NULL) {
+ (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
+ mem_free((char *) xprt, sizeof(SVCXPRT));
+ xprt = (SVCXPRT *)NULL;
+ goto done;
+ }
+ cd->strm_stat = XPRT_IDLE;
+ xdrrec_create(&(cd->xdrs), sendsize, recvsize,
+ (caddr_t)xprt, readtcp, writetcp);
+ xprt->xp_p2 = NULL;
+ xprt->xp_p1 = (caddr_t)cd;
+ xprt->xp_verf.oa_base = cd->verf_body;
+ xprt->xp_addrlen = 0;
+ xprt->xp_ops = &svctcp_op; /* truely deals with calls */
+ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
+ xprt->xp_sock = fd;
+ xprt_register(xprt);
+ done:
+ return (xprt);
+}
+
+static bool_t
+rendezvous_request(xprt)
+ register SVCXPRT *xprt;
+{
+ int sock;
+ struct tcp_rendezvous *r;
+ struct sockaddr_in addr;
+ int len;
+
+ r = (struct tcp_rendezvous *)xprt->xp_p1;
+ again:
+ len = sizeof(struct sockaddr_in);
+ if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
+ &len)) < 0) {
+ if (errno == EINTR)
+ goto again;
+ return (FALSE);
+ }
+ /*
+ * XXX careful for ftp bounce attacks. If discovered, close the
+ * socket and look for another connection.
+ */
+ if (addr.sin_port == htons(20)) {
+ close(sock);
+ goto again;
+ }
+ /*
+ * make a new transporter (re-uses xprt)
+ */
+ xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
+ xprt->xp_raddr = addr;
+ xprt->xp_addrlen = len;
+ return (FALSE); /* there is never an rpc msg to be processed */
+}
+
+static enum xprt_stat
+rendezvous_stat()
+{
+
+ return (XPRT_IDLE);
+}
+
+static void
+svctcp_destroy(xprt)
+ register SVCXPRT *xprt;
+{
+ register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1;
+
+ xprt_unregister(xprt);
+ (void)close(xprt->xp_sock);
+ if (xprt->xp_port != 0) {
+ /* a rendezvouser socket */
+ xprt->xp_port = 0;
+ } else {
+ /* an actual connection socket */
+ XDR_DESTROY(&(cd->xdrs));
+ }
+ mem_free((caddr_t)cd, sizeof(struct tcp_conn));
+ mem_free((caddr_t)xprt, sizeof(SVCXPRT));
+}
+
+/*
+ * All read operations timeout after 35 seconds.
+ * A timeout is fatal for the connection.
+ */
+static struct timeval wait_per_try = { 35, 0 };
+
+/*
+ * reads data from the tcp conection.
+ * any error is fatal and the connection is closed.
+ * (And a read of zero bytes is a half closed stream => error.)
+ */
+static int
+readtcp(xprt, buf, len)
+ register SVCXPRT *xprt;
+ caddr_t buf;
+ register int len;
+{
+ register int sock = xprt->xp_sock;
+ struct timeval start, delta, tv;
+ struct timeval tmp1, tmp2;
+ fd_set *fds, readfds;
+
+ if (sock + 1 > FD_SETSIZE) {
+ int bytes = howmany(sock+1, NFDBITS) * sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+
+ if (fds == NULL)
+ goto fatal_err;
+ memset(fds, 0, bytes);
+ } else {
+ fds = &readfds;
+ FD_ZERO(fds);
+ }
+
+ delta = wait_per_try;
+ gettimeofday(&start, NULL);
+ do {
+ /* XXX we know the other bits are still clear */
+ FD_SET(sock, fds);
+ tv = delta; /* in case select() implements writeback */
+ switch (select(sock + 1, fds, NULL, NULL, &tv)) {
+ case -1:
+ if (errno != EINTR)
+ goto fatal_err;
+ gettimeofday(&tmp1, NULL);
+ timersub(&tmp1, &start, &tmp2);
+ timersub(&delta, &tmp2, &tmp1);
+ if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
+ goto fatal_err;
+ delta = tmp1;
+ continue;
+ case 0:
+ goto fatal_err;
+ }
+ } while (!FD_ISSET(sock, fds));
+ if ((len = read(sock, buf, len)) > 0) {
+ if (fds != &readfds)
+ free(fds);
+ return (len);
+ }
+fatal_err:
+ ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
+ if (fds != &readfds)
+ free(fds);
+ return (-1);
+}
+
+/*
+ * writes data to the tcp connection.
+ * Any error is fatal and the connection is closed.
+ */
+static int
+writetcp(xprt, buf, len)
+ register SVCXPRT *xprt;
+ caddr_t buf;
+ int len;
+{
+ register int i, cnt;
+
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = write(xprt->xp_sock, buf, cnt)) < 0) {
+ ((struct tcp_conn *)(xprt->xp_p1))->strm_stat =
+ XPRT_DIED;
+ return (-1);
+ }
+ }
+ return (len);
+}
+
+static enum xprt_stat
+svctcp_stat(xprt)
+ SVCXPRT *xprt;
+{
+ register struct tcp_conn *cd =
+ (struct tcp_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
+svctcp_recv(xprt, msg)
+ SVCXPRT *xprt;
+ register struct rpc_msg *msg;
+{
+ register struct tcp_conn *cd =
+ (struct tcp_conn *)(xprt->xp_p1);
+ register XDR *xdrs = &(cd->xdrs);
+
+ xdrs->x_op = XDR_DECODE;
+ (void)xdrrec_skiprecord(xdrs);
+ if (xdr_callmsg(xdrs, msg)) {
+ cd->x_id = msg->rm_xid;
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+static bool_t
+svctcp_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+
+ return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), args_ptr));
+}
+
+static bool_t
+svctcp_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register XDR *xdrs =
+ &(((struct tcp_conn *)(xprt->xp_p1))->xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static bool_t
+svctcp_reply(xprt, msg)
+ SVCXPRT *xprt;
+ register struct rpc_msg *msg;
+{
+ register struct tcp_conn *cd =
+ (struct tcp_conn *)(xprt->xp_p1);
+ register XDR *xdrs = &(cd->xdrs);
+ register bool_t stat;
+
+ xdrs->x_op = XDR_ENCODE;
+ msg->rm_xid = cd->x_id;
+ stat = xdr_replymsg(xdrs, msg);
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ return (stat);
+}
diff --git a/lib/libc/rpc/svc_udp.c b/lib/libc/rpc/svc_udp.c
new file mode 100644
index 0000000..6622de2
--- /dev/null
+++ b/lib/libc/rpc/svc_udp.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
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: svc_udp.c,v 1.7 1996/12/30 15:21:19 peter Exp $";
+#endif
+
+/*
+ * svc_udp.c,
+ * Server side for UDP/IP based RPC. (Does some caching in the hopes of
+ * achieving execute-at-most-once semantics.)
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#define rpc_buffer(xprt) ((xprt)->xp_p1)
+#define MAX(a, b) ((a > b) ? a : b)
+
+static bool_t svcudp_recv();
+static bool_t svcudp_reply();
+static enum xprt_stat svcudp_stat();
+static bool_t svcudp_getargs();
+static bool_t svcudp_freeargs();
+static void svcudp_destroy();
+static void cache_set __P((SVCXPRT *, u_long));
+static int cache_get __P((SVCXPRT *, struct rpc_msg *, char **, u_long *));
+
+static struct xp_ops svcudp_op = {
+ svcudp_recv,
+ svcudp_stat,
+ svcudp_getargs,
+ svcudp_reply,
+ svcudp_freeargs,
+ svcudp_destroy
+};
+
+/*
+ * kept in xprt->xp_p2
+ */
+struct svcudp_data {
+ u_int su_iosz; /* byte size of send.recv buffer */
+ u_long su_xid; /* transaction id */
+ XDR su_xdrs; /* XDR handle */
+ char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
+ char * su_cache; /* cached data, NULL if no cache */
+};
+#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2))
+
+/*
+ * Usage:
+ * xprt = svcudp_create(sock);
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svcudp_create
+ * binds it to an arbitrary port. In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ * Once *xprt is initialized, it is registered as a transporter;
+ * see (svc.h, xprt_register).
+ * The routines returns NULL if a problem occurred.
+ */
+SVCXPRT *
+svcudp_bufcreate(sock, sendsz, recvsz)
+ register int sock;
+ u_int sendsz, recvsz;
+{
+ bool_t madesock = FALSE;
+ register SVCXPRT *xprt;
+ register struct svcudp_data *su;
+ struct sockaddr_in addr;
+ int len = sizeof(struct sockaddr_in);
+
+ if (sock == RPC_ANYSOCK) {
+ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ perror("svcudp_create: socket creation problem");
+ return ((SVCXPRT *)NULL);
+ }
+ madesock = TRUE;
+ }
+ memset((char *)&addr, 0, sizeof (addr));
+ addr.sin_len = sizeof(struct sockaddr_in);
+ addr.sin_family = AF_INET;
+ if (bindresvport(sock, &addr)) {
+ addr.sin_port = 0;
+ (void)bind(sock, (struct sockaddr *)&addr, len);
+ }
+ if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) {
+ perror("svcudp_create - cannot getsockname");
+ if (madesock)
+ (void)close(sock);
+ return ((SVCXPRT *)NULL);
+ }
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == NULL) {
+ (void)fprintf(stderr, "svcudp_create: out of memory\n");
+ return (NULL);
+ }
+ su = (struct svcudp_data *)mem_alloc(sizeof(*su));
+ if (su == NULL) {
+ (void)fprintf(stderr, "svcudp_create: out of memory\n");
+ return (NULL);
+ }
+ su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4;
+ if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL) {
+ (void)fprintf(stderr, "svcudp_create: out of memory\n");
+ return (NULL);
+ }
+ xdrmem_create(
+ &(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE);
+ su->su_cache = NULL;
+ xprt->xp_p2 = (caddr_t)su;
+ xprt->xp_verf.oa_base = su->su_verfbody;
+ xprt->xp_ops = &svcudp_op;
+ xprt->xp_port = ntohs(addr.sin_port);
+ xprt->xp_sock = sock;
+ xprt_register(xprt);
+ return (xprt);
+}
+
+SVCXPRT *
+svcudp_create(sock)
+ int sock;
+{
+
+ return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE));
+}
+
+static enum xprt_stat
+svcudp_stat(xprt)
+ SVCXPRT *xprt;
+{
+
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svcudp_recv(xprt, msg)
+ register SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svcudp_data *su = su_data(xprt);
+ register XDR *xdrs = &(su->su_xdrs);
+ register int rlen;
+ char *reply;
+ u_long replylen;
+
+ again:
+ xprt->xp_addrlen = sizeof(struct sockaddr_in);
+ rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz,
+ 0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen));
+ if (rlen == -1 && errno == EINTR)
+ goto again;
+ if (rlen == -1 || rlen < 4*sizeof(u_int32_t))
+ return (FALSE);
+ 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_sock, reply, (int) replylen, 0,
+ (struct sockaddr *) &xprt->xp_raddr, xprt->xp_addrlen);
+ return (TRUE);
+ }
+ }
+ return (TRUE);
+}
+
+static bool_t
+svcudp_reply(xprt, msg)
+ register SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svcudp_data *su = su_data(xprt);
+ register XDR *xdrs = &(su->su_xdrs);
+ register int slen;
+ register bool_t stat = FALSE;
+
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ msg->rm_xid = su->su_xid;
+ if (xdr_replymsg(xdrs, msg)) {
+ slen = (int)XDR_GETPOS(xdrs);
+ if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0,
+ (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen)
+ == slen) {
+ stat = TRUE;
+ if (su->su_cache && slen >= 0) {
+ cache_set(xprt, (u_long) slen);
+ }
+ }
+ }
+ return (stat);
+}
+
+static bool_t
+svcudp_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+
+ return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr));
+}
+
+static bool_t
+svcudp_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register XDR *xdrs = &(su_data(xprt)->su_xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static void
+svcudp_destroy(xprt)
+ register SVCXPRT *xprt;
+{
+ register struct svcudp_data *su = su_data(xprt);
+
+ xprt_unregister(xprt);
+ (void)close(xprt->xp_sock);
+ XDR_DESTROY(&(su->su_xdrs));
+ mem_free(rpc_buffer(xprt), su->su_iosz);
+ mem_free((caddr_t)su, sizeof(struct svcudp_data));
+ mem_free((caddr_t)xprt, sizeof(SVCXPRT));
+}
+
+
+/***********this could be a separate file*********************/
+
+/*
+ * Fifo cache for udp server
+ * Copies pointers to reply buffers into fifo cache
+ * Buffers are sent again if retransmissions are detected.
+ */
+
+#define SPARSENESS 4 /* 75% sparse */
+
+#define CACHE_PERROR(msg) \
+ (void) fprintf(stderr,"%s\n", msg)
+
+#define ALLOC(type, size) \
+ (type *) mem_alloc((unsigned) (sizeof(type) * (size)))
+
+#define BZERO(addr, type, size) \
+ memset((char *) addr, 0, sizeof(type) * (int) (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_long cache_xid;
+ u_long cache_proc;
+ u_long cache_vers;
+ u_long cache_prog;
+ struct sockaddr_in cache_addr;
+ /*
+ * The cached reply and length
+ */
+ char * cache_reply;
+ u_long cache_replylen;
+ /*
+ * Next node on the list, if there is a collision
+ */
+ cache_ptr cache_next;
+};
+
+
+
+/*
+ * The entire cache
+ */
+struct udp_cache {
+ u_long 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_long uc_nextvictim; /* points to next victim in fifo list */
+ u_long uc_prog; /* saved program number */
+ u_long uc_vers; /* saved version number */
+ u_long uc_proc; /* saved procedure number */
+ struct sockaddr_in uc_addr; /* saved caller's address */
+};
+
+
+/*
+ * the hashing function
+ */
+#define CACHE_LOC(transp, xid) \
+ (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size))
+
+
+/*
+ * Enable use of the cache.
+ * Note: there is no disable.
+ */
+int svcudp_enablecache(transp, size)
+ SVCXPRT *transp;
+ u_long size;
+{
+ struct svcudp_data *su = su_data(transp);
+ struct udp_cache *uc;
+
+ if (su->su_cache != NULL) {
+ CACHE_PERROR("enablecache: cache already enabled");
+ return(0);
+ }
+ uc = ALLOC(struct udp_cache, 1);
+ if (uc == NULL) {
+ CACHE_PERROR("enablecache: could not allocate cache");
+ return(0);
+ }
+ uc->uc_size = size;
+ uc->uc_nextvictim = 0;
+ uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
+ if (uc->uc_entries == NULL) {
+ CACHE_PERROR("enablecache: could not allocate cache data");
+ return(0);
+ }
+ BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
+ uc->uc_fifo = ALLOC(cache_ptr, size);
+ if (uc->uc_fifo == NULL) {
+ CACHE_PERROR("enablecache: could not allocate cache fifo");
+ return(0);
+ }
+ BZERO(uc->uc_fifo, cache_ptr, size);
+ su->su_cache = (char *) uc;
+ return(1);
+}
+
+
+/*
+ * Set an entry in the cache
+ */
+static void
+cache_set(xprt, replylen)
+ SVCXPRT *xprt;
+ u_long replylen;
+{
+ register cache_ptr victim;
+ register cache_ptr *vicp;
+ register struct svcudp_data *su = su_data(xprt);
+ struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+ u_int loc;
+ char *newbuf;
+
+ /*
+ * 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) {
+ CACHE_PERROR("cache_set: victim not found");
+ return;
+ }
+ *vicp = victim->cache_next; /* remote from cache */
+ newbuf = victim->cache_reply;
+ } else {
+ victim = ALLOC(struct cache_node, 1);
+ if (victim == NULL) {
+ CACHE_PERROR("cache_set: victim alloc failed");
+ return;
+ }
+ newbuf = mem_alloc(su->su_iosz);
+ if (newbuf == NULL) {
+ CACHE_PERROR("cache_set: could not allocate new rpc_buffer");
+ return;
+ }
+ }
+
+ /*
+ * Store it away
+ */
+ 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 = uc->uc_addr;
+ 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;
+}
+
+/*
+ * Try to get an entry from the cache
+ * return 1 if found, 0 if not found
+ */
+static int
+cache_get(xprt, msg, replyp, replylenp)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+ char **replyp;
+ u_long *replylenp;
+{
+ u_int loc;
+ register cache_ptr ent;
+ register struct svcudp_data *su = su_data(xprt);
+ register struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+
+# define EQADDR(a1, a2) (memcmp(&a1, &a2, sizeof(a1)) == 0)
+
+ 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 == uc->uc_proc &&
+ ent->cache_vers == uc->uc_vers &&
+ ent->cache_prog == uc->uc_prog &&
+ EQADDR(ent->cache_addr, uc->uc_addr)) {
+ *replyp = ent->cache_reply;
+ *replylenp = ent->cache_replylen;
+ 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;
+ uc->uc_addr = xprt->xp_raddr;
+ return(0);
+}
+
diff --git a/lib/libc/rpc/svc_unix.c b/lib/libc/rpc/svc_unix.c
new file mode 100644
index 0000000..04e3223
--- /dev/null
+++ b/lib/libc/rpc/svc_unix.c
@@ -0,0 +1,511 @@
+/*
+ * 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 = "from: @(#)svc_unix.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: svc_unix.c,v 1.8 1996/12/30 15:19:08 peter Exp $";
+#endif
+
+/*
+ * svc_unix.c, Server side for TCP/IP based RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Actually implements two flavors of transporter -
+ * a unix rendezvouser (a listner and connection establisher)
+ * and a record/unix stream.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/uio.h>
+#include <errno.h>
+
+/*
+ * Ops vector for AF_UNIX based rpc service handle
+ */
+static bool_t svcunix_recv();
+static enum xprt_stat svcunix_stat();
+static bool_t svcunix_getargs();
+static bool_t svcunix_reply();
+static bool_t svcunix_freeargs();
+static void svcunix_destroy();
+
+static struct xp_ops svcunix_op = {
+ svcunix_recv,
+ svcunix_stat,
+ svcunix_getargs,
+ svcunix_reply,
+ svcunix_freeargs,
+ svcunix_destroy
+};
+
+/*
+ * Ops vector for TCP/IP rendezvous handler
+ */
+static bool_t rendezvous_request();
+static enum xprt_stat rendezvous_stat();
+
+static struct xp_ops svcunix_rendezvous_op = {
+ rendezvous_request,
+ rendezvous_stat,
+ (bool_t (*)())abort,
+ (bool_t (*)())abort,
+ (bool_t (*)())abort,
+ svcunix_destroy
+};
+
+static int readunix(), writeunix();
+static SVCXPRT *makefd_xprt();
+
+struct unix_rendezvous { /* kept in xprt->xp_p1 */
+ u_int sendsize;
+ u_int recvsize;
+};
+
+struct unix_conn { /* kept in xprt->xp_p1 */
+ enum xprt_stat strm_stat;
+ u_long x_id;
+ XDR xdrs;
+ char verf_body[MAX_AUTH_BYTES];
+};
+
+
+struct cmessage {
+ struct cmsghdr cmsg;
+ struct cmsgcred cmcred;
+};
+
+static struct cmessage cm;
+
+static int __msgread(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+
+ 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 = sizeof(struct cmessage);
+ 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;
+
+ 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 = sizeof(struct cmessage);
+
+ 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 = sizeof(struct cmessage);
+ msg.msg_flags = 0;
+
+ return(sendmsg(sock, &msg, 0));
+}
+
+/*
+ * Usage:
+ * xprt = svcunix_create(sock, send_buf_size, recv_buf_size);
+ *
+ * Creates, registers, and returns a (rpc) unix 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.
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svcunix_create
+ * binds it to an arbitrary port. The routine then starts a unix
+ * listener on the socket's associated port. In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ *
+ * Since unix 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 *
+svcunix_create(sock, sendsize, recvsize, path)
+ register int sock;
+ u_int sendsize;
+ u_int recvsize;
+ char *path;
+{
+ bool_t madesock = FALSE;
+ register SVCXPRT *xprt;
+ register struct unix_rendezvous *r;
+ struct sockaddr_un addr;
+ int len = sizeof(struct sockaddr_un);
+
+ if (sock == RPC_ANYSOCK) {
+ if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ perror("svc_unix.c - AF_UNIX socket creation problem");
+ return ((SVCXPRT *)NULL);
+ }
+ madesock = TRUE;
+ }
+ memset(&addr, 0, sizeof (addr));
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, path);
+ len = strlen(addr.sun_path) + sizeof(addr.sun_family) +
+ sizeof(addr.sun_len) + 1;
+ addr.sun_len = len;
+
+ bind(sock, (struct sockaddr *)&addr, len);
+
+ if ((getsockname(sock, (struct sockaddr *)&addr, &len) != 0) ||
+ (listen(sock, 2) != 0)) {
+ perror("svc_unix.c - cannot getsockname or listen");
+ if (madesock)
+ (void)close(sock);
+ return ((SVCXPRT *)NULL);
+ }
+ r = (struct unix_rendezvous *)mem_alloc(sizeof(*r));
+ if (r == NULL) {
+ (void) fprintf(stderr, "svcunix_create: out of memory\n");
+ return (NULL);
+ }
+ r->sendsize = sendsize;
+ r->recvsize = recvsize;
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == NULL) {
+ (void) fprintf(stderr, "svcunix_create: out of memory\n");
+ return (NULL);
+ }
+ xprt->xp_p2 = NULL;
+ xprt->xp_p1 = (caddr_t)r;
+ xprt->xp_verf = _null_auth;
+ xprt->xp_ops = &svcunix_rendezvous_op;
+ xprt->xp_port = -1 /*ntohs(addr.sin_port)*/;
+ xprt->xp_sock = sock;
+ xprt_register(xprt);
+ return (xprt);
+}
+
+/*
+ * Like svunix_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+SVCXPRT *
+svcunixfd_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+
+ return (makefd_xprt(fd, sendsize, recvsize));
+}
+
+static SVCXPRT *
+makefd_xprt(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ register SVCXPRT *xprt;
+ register struct unix_conn *cd;
+
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == (SVCXPRT *)NULL) {
+ (void) fprintf(stderr, "svc_unix: makefd_xprt: out of memory\n");
+ goto done;
+ }
+ cd = (struct unix_conn *)mem_alloc(sizeof(struct unix_conn));
+ if (cd == (struct unix_conn *)NULL) {
+ (void) fprintf(stderr, "svc_unix: makefd_xprt: out of memory\n");
+ mem_free((char *) xprt, sizeof(SVCXPRT));
+ xprt = (SVCXPRT *)NULL;
+ goto done;
+ }
+ cd->strm_stat = XPRT_IDLE;
+ xdrrec_create(&(cd->xdrs), sendsize, recvsize,
+ (caddr_t)xprt, readunix, writeunix);
+ xprt->xp_p2 = NULL;
+ xprt->xp_p1 = (caddr_t)cd;
+ xprt->xp_verf.oa_base = cd->verf_body;
+ xprt->xp_addrlen = 0;
+ xprt->xp_ops = &svcunix_op; /* truely deals with calls */
+ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
+ xprt->xp_sock = fd;
+ xprt_register(xprt);
+ done:
+ return (xprt);
+}
+
+static bool_t
+rendezvous_request(xprt)
+ register SVCXPRT *xprt;
+{
+ int sock;
+ struct unix_rendezvous *r;
+ struct sockaddr_un addr;
+ struct sockaddr_in in_addr;
+ int len;
+
+ r = (struct unix_rendezvous *)xprt->xp_p1;
+ again:
+ len = sizeof(struct sockaddr_in);
+ if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
+ &len)) < 0) {
+ if (errno == EINTR)
+ goto again;
+ return (FALSE);
+ }
+
+ /*
+ * make a new transporter (re-uses xprt)
+ */
+ bzero((char *)&in_addr, sizeof(in_addr));
+ in_addr.sin_family = AF_UNIX;
+ xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
+ xprt->xp_raddr = in_addr;
+ xprt->xp_addrlen = len;
+ return (FALSE); /* there is never an rpc msg to be processed */
+}
+
+static enum xprt_stat
+rendezvous_stat()
+{
+
+ return (XPRT_IDLE);
+}
+
+static void
+svcunix_destroy(xprt)
+ register SVCXPRT *xprt;
+{
+ register struct unix_conn *cd = (struct unix_conn *)xprt->xp_p1;
+
+ xprt_unregister(xprt);
+ (void)close(xprt->xp_sock);
+ if (xprt->xp_port != 0) {
+ /* a rendezvouser socket */
+ xprt->xp_port = 0;
+ } else {
+ /* an actual connection socket */
+ XDR_DESTROY(&(cd->xdrs));
+ }
+ mem_free((caddr_t)cd, sizeof(struct unix_conn));
+ mem_free((caddr_t)xprt, sizeof(SVCXPRT));
+}
+
+/*
+ * All read operations timeout after 35 seconds.
+ * A timeout is fatal for the connection.
+ */
+static struct timeval wait_per_try = { 35, 0 };
+
+/*
+ * reads data from the unix conection.
+ * any error is fatal and the connection is closed.
+ * (And a read of zero bytes is a half closed stream => error.)
+ */
+static int
+readunix(xprt, buf, len)
+ register SVCXPRT *xprt;
+ caddr_t buf;
+ register int len;
+{
+ register int sock = xprt->xp_sock;
+ struct timeval start, delta, tv;
+ struct timeval tmp1, tmp2;
+ fd_set *fds, readfds;
+
+ if (sock + 1 > FD_SETSIZE) {
+ int bytes = howmany(sock+1, NFDBITS) * sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+
+ if (fds == NULL)
+ goto fatal_err;
+ memset(fds, 0, bytes);
+ } else {
+ fds = &readfds;
+ FD_ZERO(fds);
+ }
+
+ delta = wait_per_try;
+ gettimeofday(&start, NULL);
+ do {
+ /* XXX we know the other bits are still clear */
+ FD_SET(sock, fds);
+ tv = delta; /* in case select() implements writeback */
+ switch (select(sock + 1, fds, NULL, NULL, &tv)) {
+ case -1:
+ if (errno != EINTR)
+ goto fatal_err;
+ gettimeofday(&tmp1, NULL);
+ timersub(&tmp1, &start, &tmp2);
+ timersub(&delta, &tmp2, &tmp1);
+ if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
+ goto fatal_err;
+ delta = tmp1;
+ continue;
+ case 0:
+ goto fatal_err;
+ }
+ } while (!FD_ISSET(sock, fds));
+ if ((len = __msgread(sock, buf, len)) > 0) {
+ if (fds != &readfds)
+ free(fds);
+ return (len);
+ }
+fatal_err:
+ ((struct unix_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
+ if (fds != &readfds)
+ free(fds);
+ return (-1);
+}
+
+/*
+ * writes data to the unix connection.
+ * Any error is fatal and the connection is closed.
+ */
+static int
+writeunix(xprt, buf, len)
+ register SVCXPRT *xprt;
+ caddr_t buf;
+ int len;
+{
+ register int i, cnt;
+
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = __msgwrite(xprt->xp_sock, buf, cnt)) < 0) {
+ ((struct unix_conn *)(xprt->xp_p1))->strm_stat =
+ XPRT_DIED;
+ return (-1);
+ }
+ }
+ return (len);
+}
+
+static enum xprt_stat
+svcunix_stat(xprt)
+ SVCXPRT *xprt;
+{
+ register struct unix_conn *cd =
+ (struct unix_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
+svcunix_recv(xprt, msg)
+ SVCXPRT *xprt;
+ register struct rpc_msg *msg;
+{
+ register struct unix_conn *cd =
+ (struct unix_conn *)(xprt->xp_p1);
+ register XDR *xdrs = &(cd->xdrs);
+
+ xdrs->x_op = XDR_DECODE;
+ (void)xdrrec_skiprecord(xdrs);
+ if (xdr_callmsg(xdrs, msg)) {
+ cd->x_id = msg->rm_xid;
+ /* set up verifiers */
+ msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
+ msg->rm_call.cb_verf.oa_base = (caddr_t)&cm;
+ msg->rm_call.cb_verf.oa_length = sizeof(cm);
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+static bool_t
+svcunix_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+
+ return ((*xdr_args)(&(((struct unix_conn *)(xprt->xp_p1))->xdrs), args_ptr));
+}
+
+static bool_t
+svcunix_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register XDR *xdrs =
+ &(((struct unix_conn *)(xprt->xp_p1))->xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static bool_t
+svcunix_reply(xprt, msg)
+ SVCXPRT *xprt;
+ register struct rpc_msg *msg;
+{
+ register struct unix_conn *cd =
+ (struct unix_conn *)(xprt->xp_p1);
+ register XDR *xdrs = &(cd->xdrs);
+ register bool_t stat;
+
+ xdrs->x_op = XDR_ENCODE;
+ msg->rm_xid = cd->x_id;
+ stat = xdr_replymsg(xdrs, msg);
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ return (stat);
+}
diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc
index 47ea776..b86404a 100644
--- a/lib/libc/stdio/Makefile.inc
+++ b/lib/libc/stdio/Makefile.inc
@@ -1,22 +1,27 @@
# @(#)Makefile.inc 8.3 (Berkeley) 4/17/94
+# $Id: Makefile.inc,v 1.8 1997/02/22 15:01:45 peter Exp $
# stdio sources
-.PATH: ${.CURDIR}/stdio
+.PATH: ${.CURDIR}/../libc/stdio
-SRCS+= clrerr.c fclose.c fdopen.c feof.c ferror.c fflush.c fgetc.c \
- fgetln.c fgetpos.c fgets.c fileno.c findfp.c flags.c fopen.c \
+SRCS+= asprintf.c clrerr.c fclose.c fdopen.c feof.c ferror.c fflush.c \
+ fgetc.c fgetln.c fgetpos.c fgets.c fileno.c findfp.c flags.c fopen.c \
fprintf.c fpurge.c fputc.c fputs.c fread.c freopen.c fscanf.c \
fseek.c fsetpos.c ftell.c funopen.c fvwrite.c fwalk.c fwrite.c \
getc.c getchar.c gets.c getw.c makebuf.c mktemp.c perror.c \
printf.c putc.c putchar.c puts.c putw.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 tempnam.c tmpfile.c tmpnam.c ungetc.c vfprintf.c \
- vfscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c vsscanf.c \
- wbuf.c wsetup.c
+ sscanf.c stdio.c tempnam.c tmpfile.c tmpnam.c ungetc.c vasprintf.c \
+ vfprintf.c vfscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c \
+ vsscanf.c wbuf.c wsetup.c
-MAN3+= fclose.0 ferror.0 fflush.0 fgetln.0 fgets.0 fopen.0 fputs.0 \
- fread.0 fseek.0 funopen.0 getc.0 mktemp.0 printf.0 putc.0 remove.0 \
- scanf.0 setbuf.0 stdio.0 tmpnam.0 ungetc.0
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN3+= stdio/fclose.3 stdio/ferror.3 stdio/fflush.3 stdio/fgetln.3 \
+ stdio/fgets.3 stdio/fopen.3 stdio/fputs.3 stdio/fread.3 stdio/fseek.3 \
+ stdio/funopen.3 stdio/getc.3 stdio/mktemp.3 stdio/printf.3 \
+ stdio/putc.3 stdio/remove.3 stdio/scanf.3 stdio/setbuf.3 \
+ stdio/stdio.3 stdio/tmpnam.3 stdio/ungetc.3
MLINKS+=ferror.3 clearerr.3 ferror.3 feof.3 ferror.3 fileno.3
MLINKS+=fflush.3 fpurge.3
@@ -30,9 +35,10 @@ MLINKS+=getc.3 fgetc.3 getc.3 getchar.3 getc.3 getw.3
MLINKS+=mktemp.3 mkstemp.3
MLINKS+=printf.3 fprintf.3 printf.3 snprintf.3 printf.3 sprintf.3 \
printf.3 vfprintf.3 printf.3 vprintf.3 printf.3 vsnprintf.3 \
- printf.3 vsprintf.3
+ printf.3 vsprintf.3 printf.3 asprintf.3 printf.3 vasprintf.3
MLINKS+=putc.3 fputc.3 putc.3 putchar.3 putc.3 putw.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
+.endif
diff --git a/lib/libc/stdio/asprintf.c b/lib/libc/stdio/asprintf.c
new file mode 100644
index 0000000..9b4d05b
--- /dev/null
+++ b/lib/libc/stdio/asprintf.c
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1996 Peter Wemm <peter@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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
+
+#include <stdio.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#if __STDC__
+int
+asprintf(char **str, char const *fmt, ...)
+#else
+int
+asprintf(str, fmt, va_alist)
+ char **str;
+ char *fmt;
+ va_dcl
+#endif
+{
+ int ret;
+ va_list ap;
+
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ ret = vasprintf(str, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
diff --git a/lib/libc/stdio/clrerr.c b/lib/libc/stdio/clrerr.c
index de4526e..a230119 100644
--- a/lib/libc/stdio/clrerr.c
+++ b/lib/libc/stdio/clrerr.c
@@ -35,15 +35,29 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)clrerr.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#undef clearerr
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
void
clearerr(fp)
FILE *fp;
{
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
__sclearerr(fp);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
}
diff --git a/lib/libc/stdio/fclose.c b/lib/libc/stdio/fclose.c
index 8315c3c..1104bd0 100644
--- a/lib/libc/stdio/fclose.c
+++ b/lib/libc/stdio/fclose.c
@@ -35,14 +35,23 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fclose.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "local.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
+int
fclose(fp)
register FILE *fp;
{
@@ -52,6 +61,9 @@ fclose(fp)
errno = EBADF;
return (EOF);
}
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
r = fp->_flags & __SWR ? __sflush(fp) : 0;
if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
r = EOF;
@@ -61,7 +73,11 @@ fclose(fp)
FREEUB(fp);
if (HASLB(fp))
FREELB(fp);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
fp->_flags = 0; /* Release this FILE for reuse. */
+ fp->_file = -1;
fp->_r = fp->_w = 0; /* Mess up if reaccessed. */
return (r);
}
diff --git a/lib/libc/stdio/feof.c b/lib/libc/stdio/feof.c
index 7f58057..e42df61 100644
--- a/lib/libc/stdio/feof.c
+++ b/lib/libc/stdio/feof.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)feof.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -45,6 +49,7 @@ static char sccsid[] = "@(#)feof.c 8.1 (Berkeley) 6/4/93";
*/
#undef feof
+int
feof(fp)
FILE *fp;
{
diff --git a/lib/libc/stdio/ferror.c b/lib/libc/stdio/ferror.c
index 27ca107..8a68500 100644
--- a/lib/libc/stdio/ferror.c
+++ b/lib/libc/stdio/ferror.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)ferror.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -45,6 +49,7 @@ static char sccsid[] = "@(#)ferror.c 8.1 (Berkeley) 6/4/93";
*/
#undef ferror
+int
ferror(fp)
FILE *fp;
{
diff --git a/lib/libc/stdio/fflush.3 b/lib/libc/stdio/fflush.3
index ce3f1b7..abc8c67 100644
--- a/lib/libc/stdio/fflush.3
+++ b/lib/libc/stdio/fflush.3
@@ -99,8 +99,8 @@ for any of the errors specified for the routine
.Xr write 2 .
.Sh SEE ALSO
.Xr write 2 ,
-.Xr fopen 3 ,
.Xr fclose 3 ,
+.Xr fopen 3 ,
.Xr setbuf 3
.Sh STANDARDS
The
diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c
index 4a5cf0f..aed57ec 100644
--- a/lib/libc/stdio/fflush.c
+++ b/lib/libc/stdio/fflush.c
@@ -35,27 +35,46 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fflush.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <errno.h>
#include <stdio.h>
#include "local.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/* Flush a single file, or (if fp is NULL) all files. */
+int
fflush(fp)
register FILE *fp;
{
+ int retval;
if (fp == NULL)
return (_fwalk(__sflush));
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
if ((fp->_flags & (__SWR | __SRW)) == 0) {
errno = EBADF;
- return (EOF);
+ retval = EOF;
+ } else {
+ retval = __sflush(fp);
}
- return (__sflush(fp));
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
+ return (retval);
}
+int
__sflush(fp)
register FILE *fp;
{
diff --git a/lib/libc/stdio/fgetc.c b/lib/libc/stdio/fgetc.c
index 800846c..f93a004 100644
--- a/lib/libc/stdio/fgetc.c
+++ b/lib/libc/stdio/fgetc.c
@@ -35,13 +35,30 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fgetc.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
+int
fgetc(fp)
FILE *fp;
{
- return (__sgetc(fp));
+ int retval;
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
+ retval = __sgetc(fp);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
+ return (retval);
}
diff --git a/lib/libc/stdio/fgetln.3 b/lib/libc/stdio/fgetln.3
index 60089ea..e6c395d 100644
--- a/lib/libc/stdio/fgetln.3
+++ b/lib/libc/stdio/fgetln.3
@@ -120,4 +120,5 @@ or
.Sh HISTORY
The
.Fn fgetln
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/stdio/fgetln.c b/lib/libc/stdio/fgetln.c
index ec81a2d..7c5742b 100644
--- a/lib/libc/stdio/fgetln.c
+++ b/lib/libc/stdio/fgetln.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -50,6 +54,7 @@ static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94";
* so we add 1 here.
#endif
*/
+int
__slbexpand(fp, newsize)
FILE *fp;
size_t newsize;
@@ -91,7 +96,7 @@ fgetln(fp, lenp)
}
/* look for a newline in the input */
- if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) {
+ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) != NULL) {
register char *ret;
/*
@@ -133,7 +138,7 @@ fgetln(fp, lenp)
off = len;
if (__srefill(fp))
break; /* EOF or error: return partial line */
- if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL)
+ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) == NULL)
continue;
/* got it: finish up the line (like code above) */
diff --git a/lib/libc/stdio/fgetpos.c b/lib/libc/stdio/fgetpos.c
index 1f4ec1d..ab8a9e5 100644
--- a/lib/libc/stdio/fgetpos.c
+++ b/lib/libc/stdio/fgetpos.c
@@ -35,14 +35,31 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fgetpos.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
+int
fgetpos(fp, pos)
FILE *fp;
fpos_t *pos;
{
- return((*pos = ftell(fp)) == (fpos_t)-1);
+ int retval;
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
+ retval = (*pos = ftell(fp)) == (fpos_t)-1;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
+ return(retval);
}
diff --git a/lib/libc/stdio/fgets.3 b/lib/libc/stdio/fgets.3
index 231e8f2..22ce5e6 100644
--- a/lib/libc/stdio/fgets.3
+++ b/lib/libc/stdio/fgets.3
@@ -45,7 +45,7 @@
.Sh SYNOPSIS
.Fd #include <stdio.h>
.Ft char *
-.Fn fgets "char *str" "size_t size" "FILE *stream"
+.Fn fgets "char *str" "int size" "FILE *stream"
.Ft char *
.Fn gets "char *str"
.Sh DESCRIPTION
@@ -53,7 +53,7 @@ The
.Fn fgets
function
reads at most one less than the number of characters specified by
-.Xr size
+.Fa size
from the given
.Fa stream
and stores them in the string
@@ -61,7 +61,7 @@ and stores them in the string
Reading stops when a newline character is found,
at end-of-file or error.
The newline, if any, is retained.
-In any case a
+If any characters are read and there is no error, a
.Ql \e0
character is appended to end the string.
.Pp
@@ -71,7 +71,7 @@ function
is equivalent to
.Fn fgets
with an infinite
-.Xr size
+.Fa size
and a
.Fa stream
of
@@ -87,14 +87,19 @@ and
.Fn gets
return
a pointer to the string.
-If end-of-file or an error occurs before any characters are read,
+If end-of-file occurs before any characters are read,
they return
-.Dv NULL.
+.Dv NULL
+and the buffer contents is unchanged.
+If an error occurs,
+they return
+.Dv NULL
+and the buffer contents is indeterminate.
The
.Fn fgets
and
-functions
.Fn gets
+functions
do not distinguish between end-of-file and error, and callers must use
.Xr feof 3
and
@@ -128,7 +133,7 @@ for any of the errors specified for the routine
.Sh SEE ALSO
.Xr feof 3 ,
.Xr ferror 3 ,
-.Xr fgetline 3
+.Xr fgetln 3
.Sh STANDARDS
The functions
.Fn fgets
diff --git a/lib/libc/stdio/fgets.c b/lib/libc/stdio/fgets.c
index 09f6877..434fc07 100644
--- a/lib/libc/stdio/fgets.c
+++ b/lib/libc/stdio/fgets.c
@@ -35,11 +35,20 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fgets.c 8.2 (Berkeley) 12/22/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <string.h>
+#include "local.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/*
* Read at most n-1 characters from the given file.
@@ -49,16 +58,19 @@ static char sccsid[] = "@(#)fgets.c 8.2 (Berkeley) 12/22/93";
char *
fgets(buf, n, fp)
char *buf;
- register size_t n;
+ register int n;
register FILE *fp;
{
register size_t len;
register char *s;
register unsigned char *p, *t;
- if (n == 0) /* sanity check */
+ if (n <= 0) /* sanity check */
return (NULL);
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
s = buf;
n--; /* leave space for NUL */
while (n != 0) {
@@ -68,8 +80,12 @@ fgets(buf, n, fp)
if ((len = fp->_r) <= 0) {
if (__srefill(fp)) {
/* EOF/error: stop with partial or no line */
- if (s == buf)
+ if (s == buf) {
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (NULL);
+ }
break;
}
len = fp->_r;
@@ -91,6 +107,9 @@ fgets(buf, n, fp)
fp->_p = t;
(void)memcpy((void *)s, (void *)p, len);
s[len] = 0;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (buf);
}
fp->_r -= len;
@@ -100,5 +119,8 @@ fgets(buf, n, fp)
n -= len;
}
*s = 0;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (buf);
}
diff --git a/lib/libc/stdio/fileno.c b/lib/libc/stdio/fileno.c
index 91e82e8..6ceac0c 100644
--- a/lib/libc/stdio/fileno.c
+++ b/lib/libc/stdio/fileno.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fileno.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -45,6 +49,7 @@ static char sccsid[] = "@(#)fileno.c 8.1 (Berkeley) 6/4/93";
*/
#undef fileno
+int
fileno(fp)
FILE *fp;
{
diff --git a/lib/libc/stdio/findfp.c b/lib/libc/stdio/findfp.c
index 64548db..8a6cddd 100644
--- a/lib/libc/stdio/findfp.c
+++ b/lib/libc/stdio/findfp.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)findfp.c 8.2 (Berkeley) 1/4/94";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
@@ -66,6 +70,8 @@ FILE __sF[3] = {
};
struct glue __sglue = { &uglue, 3, __sF };
+static struct glue * moreglue __P((int));
+
static struct glue *
moreglue(n)
register int n;
@@ -127,6 +133,10 @@ found:
* 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 stupid.");
+
+void
f_prealloc()
{
register struct glue *g;
diff --git a/lib/libc/stdio/flags.c b/lib/libc/stdio/flags.c
index ee1a76c..4ef0db1 100644
--- a/lib/libc/stdio/flags.c
+++ b/lib/libc/stdio/flags.c
@@ -35,21 +35,27 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)flags.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#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)
- register char *mode;
+ register const char *mode;
int *optr;
{
register int ret, m, o;
diff --git a/lib/libc/stdio/fopen.3 b/lib/libc/stdio/fopen.3
index 23d790c..f954d6c 100644
--- a/lib/libc/stdio/fopen.3
+++ b/lib/libc/stdio/fopen.3
@@ -46,11 +46,11 @@
.Sh SYNOPSIS
.Fd #include <stdio.h>
.Ft FILE *
-.Fn fopen "char *path" "char *mode"
+.Fn fopen "const char *path" "const char *mode"
.Ft FILE *
-.Fn fdopen "int fildes" "char *mode"
+.Fn fdopen "int fildes" "const char *mode"
.Ft FILE *
-.Fn freopen "char *path" "char *mode" "FILE *stream"
+.Fn freopen "const char *path" "const char *mode" "FILE *stream"
.Sh DESCRIPTION
The
.Fn fopen
@@ -73,7 +73,7 @@ The stream is positioned at the beginning of the file.
.It Dq Li w
Truncate file to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
-.No It Dq Li w+
+.It Dq Li w+
Open for reading and writing.
The file is created if it does not exist, otherwise it is truncated.
The stream is positioned at the beginning of the file.
@@ -142,7 +142,7 @@ The original stream (if it exists) is closed.
The
.Fa mode
argument is used just as in the
-.Xr fopen
+.Fn fopen
function.
The primary use of the
.Fn freopen
diff --git a/lib/libc/stdio/fprintf.c b/lib/libc/stdio/fprintf.c
index 479ee24..383f1e1 100644
--- a/lib/libc/stdio/fprintf.c
+++ b/lib/libc/stdio/fprintf.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fprintf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -45,6 +49,7 @@ static char sccsid[] = "@(#)fprintf.c 8.1 (Berkeley) 6/4/93";
#include <varargs.h>
#endif
+int
#if __STDC__
fprintf(FILE *fp, const char *fmt, ...)
#else
diff --git a/lib/libc/stdio/fpurge.c b/lib/libc/stdio/fpurge.c
index 3bee513..d1d9e87 100644
--- a/lib/libc/stdio/fpurge.c
+++ b/lib/libc/stdio/fpurge.c
@@ -35,13 +35,21 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fpurge.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "local.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/*
* fpurge: like fflush, but without writing anything: leave the
@@ -51,15 +59,23 @@ int
fpurge(fp)
register FILE *fp;
{
+ int retval;
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
if (!fp->_flags) {
errno = EBADF;
- return(EOF);
+ 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;
}
-
- if (HASUB(fp))
- FREEUB(fp);
- fp->_p = fp->_bf._base;
- fp->_r = 0;
- fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
- return (0);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
+ return (retval);
}
diff --git a/lib/libc/stdio/fputc.c b/lib/libc/stdio/fputc.c
index c86f711..89b138d 100644
--- a/lib/libc/stdio/fputc.c
+++ b/lib/libc/stdio/fputc.c
@@ -35,14 +35,31 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fputc.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
+int
fputc(c, fp)
int c;
register FILE *fp;
{
- return (putc(c, fp));
+ int retval;
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
+ retval = putc(c, fp);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
+ return (retval);
}
diff --git a/lib/libc/stdio/fputs.3 b/lib/libc/stdio/fputs.3
index 5578ec2..0961366 100644
--- a/lib/libc/stdio/fputs.3
+++ b/lib/libc/stdio/fputs.3
@@ -95,8 +95,8 @@ may also fail and set
for any of the errors specified for the routines
.Xr write 2 .
.Sh SEE ALSO
-.Xr putc 3 ,
.Xr ferror 3 ,
+.Xr putc 3 ,
.Xr stdio 3
.Sh STANDARDS
The functions
diff --git a/lib/libc/stdio/fputs.c b/lib/libc/stdio/fputs.c
index 9f9be2e..537c348 100644
--- a/lib/libc/stdio/fputs.c
+++ b/lib/libc/stdio/fputs.c
@@ -35,20 +35,30 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fputs.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <string.h>
#include "fvwrite.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/*
* Write the given string to the given file.
*/
+int
fputs(s, fp)
const char *s;
FILE *fp;
{
+ int retval;
struct __suio uio;
struct __siov iov;
@@ -56,5 +66,12 @@ fputs(s, fp)
iov.iov_len = uio.uio_resid = strlen(s);
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
- return (__sfvwrite(fp, &uio));
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
+ retval = __sfvwrite(fp, &uio);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
+ return (retval);
}
diff --git a/lib/libc/stdio/fread.3 b/lib/libc/stdio/fread.3
index 8dd65af..c3e591a 100644
--- a/lib/libc/stdio/fread.3
+++ b/lib/libc/stdio/fread.3
@@ -44,9 +44,9 @@
.Nd binary stream input/output
.Sh SYNOPSIS
.Fd #include <stdio.h>
-.Ft int
+.Ft size_t
.Fn fread "void *ptr" "size_t size" "size_t nmemb" "FILE *stream"
-.Ft int
+.Ft size_t
.Fn fwrite "const void *ptr" "size_t size" "size_t nmemb" "FILE *stream"
.Sh DESCRIPTION
The function
@@ -54,7 +54,7 @@ The function
reads
.Fa nmemb
objects, each
-.Xr size
+.Fa size
bytes long, from the stream pointed to by
.Fa stream ,
storing them at the location given by
diff --git a/lib/libc/stdio/fread.c b/lib/libc/stdio/fread.c
index 22436ec..4f67fbf 100644
--- a/lib/libc/stdio/fread.c
+++ b/lib/libc/stdio/fread.c
@@ -35,11 +35,20 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fread.c 8.2 (Berkeley) 12/11/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <string.h>
+#include "local.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
size_t
fread(buf, size, count, fp)
@@ -59,6 +68,9 @@ fread(buf, size, count, fp)
*/
if ((resid = count * size) == 0)
return (0);
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
if (fp->_r < 0)
fp->_r = 0;
total = resid;
@@ -77,5 +89,8 @@ fread(buf, size, count, fp)
(void)memcpy((void *)p, (void *)fp->_p, resid);
fp->_r -= resid;
fp->_p += resid;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (count);
}
diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c
index 88dd03c..7a8a3ef 100644
--- a/lib/libc/stdio/freopen.c
+++ b/lib/libc/stdio/freopen.c
@@ -47,8 +47,8 @@ static char sccsid[] = "@(#)freopen.c 8.1 (Berkeley) 6/4/93";
#include <stdlib.h>
#include "local.h"
-/*
- * Re-direct an existing, open (probably) file to some other file.
+/*
+ * 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.
*/
diff --git a/lib/libc/stdio/fscanf.c b/lib/libc/stdio/fscanf.c
index f0e726a..8513f80 100644
--- a/lib/libc/stdio/fscanf.c
+++ b/lib/libc/stdio/fscanf.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fscanf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -44,14 +48,20 @@ static char sccsid[] = "@(#)fscanf.c 8.1 (Berkeley) 6/4/93";
#else
#include <varargs.h>
#endif
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
#if __STDC__
+int
fscanf(FILE *fp, char const *fmt, ...) {
int ret;
va_list ap;
va_start(ap, fmt);
#else
+int
fscanf(fp, fmt, va_alist)
FILE *fp;
char *fmt;
@@ -62,7 +72,13 @@ fscanf(fp, fmt, va_alist)
va_start(ap);
#endif
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
ret = __svfscanf(fp, fmt, ap);
va_end(ap);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (ret);
}
diff --git a/lib/libc/stdio/fseek.3 b/lib/libc/stdio/fseek.3
index 4d22276..5dd79e9 100644
--- a/lib/libc/stdio/fseek.3
+++ b/lib/libc/stdio/fseek.3
@@ -56,7 +56,7 @@
.Ft int
.Fn fgetpos "FILE *stream" "fpos_t *pos"
.Ft int
-.Fn fsetpos "FILE *stream" "fpos_t *pos"
+.Fn fsetpos "FILE *stream" "const fpos_t *pos"
.Sh DESCRIPTION
The
.Fn fseek
diff --git a/lib/libc/stdio/fseek.c b/lib/libc/stdio/fseek.c
index 6b0cc8b..c6707df 100644
--- a/lib/libc/stdio/fseek.c
+++ b/lib/libc/stdio/fseek.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fseek.c 8.3 (Berkeley) 1/2/94";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -45,6 +49,10 @@ static char sccsid[] = "@(#)fseek.c 8.3 (Berkeley) 1/2/94";
#include <stdlib.h>
#include <errno.h>
#include "local.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
#define POS_ERR (-(fpos_t)1)
@@ -68,6 +76,9 @@ fseek(fp, offset, whence)
if (!__sdidinit)
__sinit();
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
/*
* Have to be able to seek.
*/
@@ -92,8 +103,12 @@ fseek(fp, offset, whence)
curoff = fp->_offset;
else {
curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR);
- if (curoff == -1L)
+ if (curoff == -1) {
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (EOF);
+ }
}
if (fp->_flags & __SRD) {
curoff -= fp->_r;
@@ -115,6 +130,9 @@ fseek(fp, offset, whence)
default:
errno = EINVAL;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (EOF);
}
@@ -198,6 +216,9 @@ fseek(fp, offset, whence)
if (HASUB(fp))
FREEUB(fp);
fp->_flags &= ~__SEOF;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (0);
}
@@ -213,6 +234,7 @@ fseek(fp, offset, whence)
if ((*seekfn)(fp->_cookie, curoff, SEEK_SET) == POS_ERR)
goto dumb;
fp->_r = 0;
+ fp->_p = fp->_bf._base;
if (HASUB(fp))
FREEUB(fp);
fp->_flags &= ~__SEOF;
@@ -223,6 +245,9 @@ fseek(fp, offset, whence)
fp->_p += n;
fp->_r -= n;
}
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (0);
/*
@@ -232,6 +257,9 @@ fseek(fp, offset, whence)
dumb:
if (__sflush(fp) ||
(*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) {
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (EOF);
}
/* success: clear EOF indicator and discard ungetc() data */
@@ -241,5 +269,8 @@ dumb:
fp->_r = 0;
/* fp->_w = 0; */ /* unnecessary (I think...) */
fp->_flags &= ~__SEOF;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (0);
}
diff --git a/lib/libc/stdio/fsetpos.c b/lib/libc/stdio/fsetpos.c
index 4dace2d..d521a20 100644
--- a/lib/libc/stdio/fsetpos.c
+++ b/lib/libc/stdio/fsetpos.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fsetpos.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -43,6 +47,7 @@ static char sccsid[] = "@(#)fsetpos.c 8.1 (Berkeley) 6/4/93";
/*
* fsetpos: like fseek.
*/
+int
fsetpos(iop, pos)
FILE *iop;
const fpos_t *pos;
diff --git a/lib/libc/stdio/ftell.c b/lib/libc/stdio/ftell.c
index e7a5923..9b85ee0 100644
--- a/lib/libc/stdio/ftell.c
+++ b/lib/libc/stdio/ftell.c
@@ -35,12 +35,20 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)ftell.c 8.2 (Berkeley) 5/4/95";
+#endif
+static const char rcsid[] =
+ "$Id: ftell.c,v 1.7 1997/02/22 15:02:07 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <errno.h>
#include "local.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/*
* ftell: return current offset.
@@ -56,6 +64,9 @@ ftell(fp)
return (-1L);
}
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp, __FILE__, __LINE__);
+#endif
/*
* Find offset of underlying I/O object, then
* adjust for buffered bytes.
@@ -64,8 +75,12 @@ ftell(fp)
pos = fp->_offset;
else {
pos = (*fp->_seek)(fp->_cookie, (fpos_t)0, SEEK_CUR);
- if (pos == -1L)
+ if (pos == -1) {
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (pos);
+ }
}
if (fp->_flags & __SRD) {
/*
@@ -84,5 +99,8 @@ ftell(fp)
*/
pos += fp->_p - fp->_bf._base;
}
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (pos);
}
diff --git a/lib/libc/stdio/funopen.3 b/lib/libc/stdio/funopen.3
index 8ed9b30..90e98d4 100644
--- a/lib/libc/stdio/funopen.3
+++ b/lib/libc/stdio/funopen.3
@@ -44,11 +44,11 @@
.Sh SYNOPSIS
.Fd #include <stdio.h>
.Ft FILE *
-.Fn funopen "void *cookie" "int (*readfn)(void *, char *, int)" "int (writefn*)(void *, const char *, int)" "fpos_t (seekfn*)(void *, fpos_t, int)" "int (closefn*)(void *)"
+.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 *, char *, int)"
+.Fn fwopen "void *cookie" "int (*writefn)(void *, const char *, int)"
.Sh DESCRIPTION
The
.Fn funopen
@@ -159,7 +159,8 @@ specified for the routine
.Sh HISTORY
The
.Fn funopen
-functions first appeared in 4.4BSD.
+functions first appeared in
+.Bx 4.4 .
.Sh BUGS
The
.Fn funopen
diff --git a/lib/libc/stdio/fvwrite.c b/lib/libc/stdio/fvwrite.c
index 3ab6279..28db2ba 100644
--- a/lib/libc/stdio/fvwrite.c
+++ b/lib/libc/stdio/fvwrite.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fvwrite.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -49,6 +53,7 @@ static char sccsid[] = "@(#)fvwrite.c 8.1 (Berkeley) 6/4/93";
* 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)
register FILE *fp;
register struct __suio *uio;
diff --git a/lib/libc/stdio/fwalk.c b/lib/libc/stdio/fwalk.c
index 7771c41..8f91b46 100644
--- a/lib/libc/stdio/fwalk.c
+++ b/lib/libc/stdio/fwalk.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fwalk.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <errno.h>
@@ -43,8 +47,9 @@ static char sccsid[] = "@(#)fwalk.c 8.1 (Berkeley) 6/4/93";
#include "local.h"
#include "glue.h"
+int
_fwalk(function)
- register int (*function)();
+ register int (*function)(FILE *);
{
register FILE *fp;
register int n, ret;
diff --git a/lib/libc/stdio/fwrite.c b/lib/libc/stdio/fwrite.c
index dbc2e97..ba8540d 100644
--- a/lib/libc/stdio/fwrite.c
+++ b/lib/libc/stdio/fwrite.c
@@ -35,12 +35,20 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)fwrite.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include "local.h"
#include "fvwrite.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/*
* Write `count' objects (each size `size') from memory to the given file.
@@ -61,12 +69,18 @@ fwrite(buf, size, count, fp)
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
/*
* 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)
- return (count);
- return ((n - uio.uio_resid) / size);
+ if (__sfvwrite(fp, &uio) != 0)
+ count = (n - uio.uio_resid) / size;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
+ return (count);
}
diff --git a/lib/libc/stdio/getc.3 b/lib/libc/stdio/getc.3
index de93a19..0c63fbe 100644
--- a/lib/libc/stdio/getc.3
+++ b/lib/libc/stdio/getc.3
@@ -61,7 +61,7 @@ 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 .
+.Xr ungetc 3 .
.Pp
The
.Fn getc
@@ -103,11 +103,11 @@ 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 .
+.Xr clearerr 3 .
.Sh SEE ALSO
.Xr ferror 3 ,
-.Xr fread 3 ,
.Xr fopen 3 ,
+.Xr fread 3 ,
.Xr putc 3 ,
.Xr ungetc 3
.Sh STANDARDS
@@ -123,9 +123,9 @@ conform to
Since
.Dv EOF
is a valid integer value,
-.Xr feof
+.Xr feof 3
and
-.Xr ferror
+.Xr ferror 3
must be used to check for failure after calling
.Fn getw .
The size and byte order of an
diff --git a/lib/libc/stdio/getc.c b/lib/libc/stdio/getc.c
index 1e900cd..ced796b 100644
--- a/lib/libc/stdio/getc.c
+++ b/lib/libc/stdio/getc.c
@@ -35,18 +35,35 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)getc.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/*
* A subroutine version of the macro getc.
*/
#undef getc
+int
getc(fp)
register FILE *fp;
{
- return (__sgetc(fp));
+ int retval;
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
+ retval = __sgetc(fp);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
+ return (retval);
}
diff --git a/lib/libc/stdio/getchar.c b/lib/libc/stdio/getchar.c
index 20e52b7..0bcbd3a 100644
--- a/lib/libc/stdio/getchar.c
+++ b/lib/libc/stdio/getchar.c
@@ -35,17 +35,34 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)getchar.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
/*
* A subroutine version of the macro getchar.
*/
#include <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
#undef getchar
+int
getchar()
{
- return (getc(stdin));
+ int retval;
+#ifdef _THREAD_SAFE
+ _thread_flockfile(stdin,__FILE__,__LINE__);
+#endif
+ retval = getc(stdin);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(stdin);
+#endif
+ return (retval);
}
diff --git a/lib/libc/stdio/gets.c b/lib/libc/stdio/gets.c
index 0517930..0c821ea 100644
--- a/lib/libc/stdio/gets.c
+++ b/lib/libc/stdio/gets.c
@@ -35,11 +35,18 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)gets.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <unistd.h>
#include <stdio.h>
+#include <sys/cdefs.h>
+
+__warn_references(gets, "warning: this program uses gets(), which is unsafe.");
char *
gets(buf)
@@ -49,7 +56,7 @@ gets(buf)
register char *s;
static int warned;
static char w[] =
- "warning: this program uses gets(), which is unsafe.\r\n";
+ "warning: this program uses gets(), which is unsafe.\n";
if (!warned) {
(void) write(STDERR_FILENO, w, sizeof(w) - 1);
diff --git a/lib/libc/stdio/getw.c b/lib/libc/stdio/getw.c
index 5220290..c72756d 100644
--- a/lib/libc/stdio/getw.c
+++ b/lib/libc/stdio/getw.c
@@ -35,11 +35,16 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)getw.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
+int
getw(fp)
FILE *fp;
{
diff --git a/lib/libc/stdio/mktemp.3 b/lib/libc/stdio/mktemp.3
index 361bebf..28a662d 100644
--- a/lib/libc/stdio/mktemp.3
+++ b/lib/libc/stdio/mktemp.3
@@ -124,6 +124,28 @@ may also set
to any value specified by the
.Xr open 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
+or
+.Fn mkstemp .
+This is common with programs that were developed before
+.St -ansiC
+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.
+If the program in question makes heavy use of that type
+of function call, you do have the option of compiling the program
+so that it will store string constants in a writable segment of memory.
+See
+.Xr gcc 1
+for more information.
.Sh SEE ALSO
.Xr chmod 2 ,
.Xr getpid 2 ,
diff --git a/lib/libc/stdio/mktemp.c b/lib/libc/stdio/mktemp.c
index 6cedd6a..19125e6 100644
--- a/lib/libc/stdio/mktemp.c
+++ b/lib/libc/stdio/mktemp.c
@@ -32,7 +32,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id: mktemp.c,v 1.6 1997/02/22 15:02:16 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -41,9 +45,11 @@ static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
+#include <unistd.h>
-static int _gettemp();
+static int _gettemp(char *, int *);
+int
mkstemp(path)
char *path;
{
@@ -59,15 +65,14 @@ mktemp(path)
return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
}
-static
+static int
_gettemp(path, doopen)
char *path;
register int *doopen;
{
- extern int errno;
register char *start, *trv;
struct stat sbuf;
- u_int pid;
+ pid_t pid;
pid = getpid();
for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
@@ -104,7 +109,7 @@ _gettemp(path, doopen)
if (errno != EEXIST)
return(0);
}
- else if (stat(path, &sbuf))
+ else if (lstat(path, &sbuf))
return(errno == ENOENT ? 1 : 0);
/* tricky little algorithm for backward compatibility */
diff --git a/lib/libc/stdio/perror.c b/lib/libc/stdio/perror.c
index 57a73fc..91a7dee 100644
--- a/lib/libc/stdio/perror.c
+++ b/lib/libc/stdio/perror.c
@@ -50,7 +50,7 @@ perror(s)
struct iovec iov[4];
v = iov;
- if (s && *s) {
+ if (s != NULL) {
v->iov_base = (char *)s;
v->iov_len = strlen(s);
v++;
diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3
index 70f8b99..6d5ad8a 100644
--- a/lib/libc/stdio/printf.3
+++ b/lib/libc/stdio/printf.3
@@ -43,10 +43,12 @@
.Nm fprintf ,
.Nm sprintf ,
.Nm snprintf ,
+.Nm asprintf ,
.Nm vprintf ,
.Nm vfprintf,
.Nm vsprintf ,
-.Nm vsnprintf
+.Nm vsnprintf ,
+.Nm vasprintf
.Nd formatted output conversion
.Sh SYNOPSIS
.Fd #include <stdio.h>
@@ -58,19 +60,19 @@
.Fn sprintf "char *str" "const char *format" ...
.Ft int
.Fn snprintf "char *str" "size_t size" "const char *format" ...
-.\" .Ft int
-.\" .Fn smprintf "const char *format" ...
+.Ft int
+.Fn asprintf "char **ret" "const char *format" ...
.Fd #include <stdarg.h>
.Ft int
.Fn vprintf "const char *format" "va_list ap"
.Ft int
.Fn vfprintf "FILE *stream" "const char *format" "va_list ap"
.Ft int
-.Fn vsprintf "char *str" "char *format" "va_list ap"
+.Fn vsprintf "char *str" "const char *format" "va_list ap"
.Ft int
.Fn vsnprintf "char *str" "size_t size" "const char *format" "va_list ap"
-.\" .Ft int
-.\" .Fn vsmprintf "const char *format" "va_list ap"
+.Ft int
+.Fn vasprintf "char **ret" "const char *format" "va_list ap"
.Sh DESCRIPTION
The
.Fn printf
@@ -94,45 +96,47 @@ write output to the given output
and
.Fn vsnprintf
write to the character string
-.Fa str .
-.\" .IR str ;
-.\" and
-.\" .I smprintf
-.\" and
-.\" .I vsmprintf
-.\" dynamically allocate a new string with
-.\" .IR malloc .
+.Fa str ;
+and
+.Fn asprintf
+and
+.Fn vasprintf
+dynamically allocate a new string with
+.Xr malloc 3
+/
+.Xr realloc 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.
-.\" Except for
-.\" .I smprintf
-.\" and
-.\" .IR vsmprintf ,
-.\" all of these functions return
+.Pp
These functions return
the number of characters printed
(not including the trailing
.Ql \e0
used to end output to strings).
-.\" .I Smprintf
-.\" and
-.\" .I vsmprintf
-.\" return a pointer to a string of an appropriate length;
-.\" this pointer should be passed to
-.\" .I free
-.\" to release the associated storage
-.\" when it is no longer needed.
-.\" If sufficient space is not avaliable,
-.\" .I smprintf
-.\" and
-.\" .I vsmprintf
-.\" will return
-.\" .SM
-.\" .BR
+.Pp
+.Fn Asprintf
+and
+.Fn vasprintf
+return a pointer to a buffer sufficiently large to hold the
+string in the
+.Fa ret
+argument;
+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 NULL pointer.
+.Pp
.Fn Snprintf
and
.Fn vsnprintf
@@ -147,6 +151,7 @@ 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.
+.Pp
.Fn Sprintf
and
.Fn vsprintf
@@ -171,6 +176,16 @@ After the
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 -hyphen
.It
@@ -228,7 +243,7 @@ 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
-.Pf ( Mc d ,
+.Pf ( Cm d ,
.Cm i ,
.Cm o ,
.Cm u ,
@@ -389,6 +404,8 @@ A character that specifies the type of conversion to be applied.
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
@@ -397,6 +414,8 @@ 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 (nn$)
+and non-positional arguments, the results are undefined.
.Pp
The conversion specifiers and their meanings are:
.Bl -tag -width "diouxX"
@@ -422,7 +441,7 @@ are used for
conversions; the letters
.Cm ABCDEF
are used for
-.m X
+.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
@@ -600,6 +619,15 @@ The functions
and
.Fn vsnprintf
are new to this release.
+.Pp
+The functions
+.Fn asprintf
+and
+.Fn vasprintf
+first appeared in the GNU C library. This implementation is thought
+to be compatable but is not derived from the GNU code. This implementation
+was written by Peter Wemm <peter@FreeBSD.org> and first appeared in
+.Fx 2.2 .
.Sh BUGS
The conversion formats
.Cm \&%D ,
@@ -631,7 +659,7 @@ and
.Fn vsprintf
assume an infinitely long string,
callers must be careful not to overflow the actual space;
-this is often impossible to assure.
+this is often hard to assure.
For safety, programmers should use the
.Fn snprintf
interface instead.
diff --git a/lib/libc/stdio/printf.c b/lib/libc/stdio/printf.c
index eb6ae83..9711549 100644
--- a/lib/libc/stdio/printf.c
+++ b/lib/libc/stdio/printf.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -45,6 +49,7 @@ static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 6/4/93";
#include <varargs.h>
#endif
+int
#if __STDC__
printf(char const *fmt, ...)
#else
diff --git a/lib/libc/stdio/putc.c b/lib/libc/stdio/putc.c
index c18353b..a1b0814 100644
--- a/lib/libc/stdio/putc.c
+++ b/lib/libc/stdio/putc.c
@@ -35,19 +35,36 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)putc.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/*
* A subroutine version of the macro putc.
*/
#undef putc
+int
putc(c, fp)
int c;
register FILE *fp;
{
- return (__sputc(c, fp));
+ int retval;
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
+ retval = __sputc(c, fp);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
+ return (retval);
}
diff --git a/lib/libc/stdio/putchar.c b/lib/libc/stdio/putchar.c
index 036b897..99439ac 100644
--- a/lib/libc/stdio/putchar.c
+++ b/lib/libc/stdio/putchar.c
@@ -35,20 +35,37 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)putchar.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
#undef putchar
/*
* A subroutine version of the macro putchar
*/
+int
putchar(c)
int c;
{
+ int retval;
register FILE *so = stdout;
- return (__sputc(c, so));
+#ifdef _THREAD_SAFE
+ _thread_flockfile(so,__FILE__,__LINE__);
+#endif
+ retval = __sputc(c, so);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(so);
+#endif
+ return (retval);
}
diff --git a/lib/libc/stdio/puts.c b/lib/libc/stdio/puts.c
index 96a8184..91a20de 100644
--- a/lib/libc/stdio/puts.c
+++ b/lib/libc/stdio/puts.c
@@ -35,19 +35,29 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)puts.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <string.h>
#include "fvwrite.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/*
* 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];
@@ -59,5 +69,12 @@ puts(s)
uio.uio_resid = c + 1;
uio.uio_iov = &iov[0];
uio.uio_iovcnt = 2;
- return (__sfvwrite(stdout, &uio) ? EOF : '\n');
+#ifdef _THREAD_SAFE
+ _thread_flockfile(stdout,__FILE__,__LINE__);
+#endif
+ retval = __sfvwrite(stdout, &uio) ? EOF : '\n';
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(stdout);
+#endif
+ return (retval);
}
diff --git a/lib/libc/stdio/putw.c b/lib/libc/stdio/putw.c
index 4ba8982..946a311 100644
--- a/lib/libc/stdio/putw.c
+++ b/lib/libc/stdio/putw.c
@@ -35,16 +35,26 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)putw.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include "fvwrite.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
+int
putw(w, fp)
int w;
FILE *fp;
{
+ int retval;
struct __suio uio;
struct __siov iov;
@@ -52,5 +62,12 @@ putw(w, fp)
iov.iov_len = uio.uio_resid = sizeof(w);
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
- return (__sfvwrite(fp, &uio));
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
+ retval = __sfvwrite(fp, &uio);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
+ return (retval);
}
diff --git a/lib/libc/stdio/refill.c b/lib/libc/stdio/refill.c
index 35af0c0..f0583f7 100644
--- a/lib/libc/stdio/refill.c
+++ b/lib/libc/stdio/refill.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)refill.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <errno.h>
@@ -43,12 +47,14 @@ static char sccsid[] = "@(#)refill.c 8.1 (Berkeley) 6/4/93";
#include <stdlib.h>
#include "local.h"
-static
+static int lflush __P((FILE *));
+
+static int
lflush(fp)
FILE *fp;
{
- if ((fp->_flags & (__SLBF|__SWR)) == __SLBF|__SWR)
+ if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
return (__sflush(fp));
return (0);
}
@@ -57,6 +63,7 @@ lflush(fp)
* Refill a stdio buffer.
* Return EOF on eof or error, 0 otherwise.
*/
+int
__srefill(fp)
register FILE *fp;
{
diff --git a/lib/libc/stdio/remove.c b/lib/libc/stdio/remove.c
index 216535a..6a25563 100644
--- a/lib/libc/stdio/remove.c
+++ b/lib/libc/stdio/remove.c
@@ -35,12 +35,17 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)remove.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <unistd.h>
#include <stdio.h>
+int
remove(file)
const char *file;
{
diff --git a/lib/libc/stdio/rewind.c b/lib/libc/stdio/rewind.c
index 4f8391b..f6609d6 100644
--- a/lib/libc/stdio/rewind.c
+++ b/lib/libc/stdio/rewind.c
@@ -35,17 +35,31 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)rewind.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <errno.h>
#include <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
void
rewind(fp)
register FILE *fp;
{
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
(void) fseek(fp, 0L, SEEK_SET);
clearerr(fp);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
errno = 0; /* not required, but seems reasonable */
}
diff --git a/lib/libc/stdio/rget.c b/lib/libc/stdio/rget.c
index 3299fb5..45d817d 100644
--- a/lib/libc/stdio/rget.c
+++ b/lib/libc/stdio/rget.c
@@ -35,17 +35,25 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)rget.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
+#include "local.h"
+
+int
+__srefill(FILE *);
/*
* Handle getc() when the buffer ran out:
* Refill, then return the first character
* in the newly-filled buffer.
*/
-__srget(fp)
+int __srget(fp)
register FILE *fp;
{
if (__srefill(fp) == 0) {
diff --git a/lib/libc/stdio/scanf.3 b/lib/libc/stdio/scanf.3
index 377a602..a9bbc41 100644
--- a/lib/libc/stdio/scanf.3
+++ b/lib/libc/stdio/scanf.3
@@ -171,6 +171,15 @@ and the next pointer is a pointer to
(This type is not implemented; the
.Cm L
flag is currently ignored.)
+.It Cm q
+Indicates either that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Em long long int
+(rather than
+.Em int ) ,
.El
.Pp
In addition to these flags,
@@ -200,7 +209,7 @@ the next pointer must be a pointer to
.Em int .
.It Cm D
Equivalent to
-.Xr ld ;
+.Cm ld ;
this exists only for backwards compatibility.
.It Cm i
Matches an optionally signed integer;
@@ -221,7 +230,7 @@ the next pointer must be a pointer to
.Em unsigned int .
.It Cm O
Equivalent to
-.Xr lo ;
+.Cm lo ;
this exists for backwards compatibility.
.It Cm u
Matches an optionally signed decimal integer;
@@ -391,11 +400,11 @@ 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 strtol 3 ,
-.Xr strtoul 3 ,
-.Xr strtod 3 ,
.Xr getc 3 ,
-.Xr printf 3
+.Xr printf 3 ,
+.Xr strtod 3 ,
+.Xr strtol 3 ,
+.Xr strtoul 3
.Sh STANDARDS
The functions
.Fn fscanf ,
diff --git a/lib/libc/stdio/scanf.c b/lib/libc/stdio/scanf.c
index d36b13a..7a8bd65 100644
--- a/lib/libc/stdio/scanf.c
+++ b/lib/libc/stdio/scanf.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)scanf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -44,10 +48,16 @@ static char sccsid[] = "@(#)scanf.c 8.1 (Berkeley) 6/4/93";
#else
#include <varargs.h>
#endif
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
#if __STDC__
+int
scanf(char const *fmt, ...)
#else
+int
scanf(fmt, va_alist)
char *fmt;
va_dcl
@@ -61,7 +71,13 @@ scanf(fmt, va_alist)
#else
va_start(ap);
#endif
+#ifdef _THREAD_SAFE
+ _thread_flockfile(stdin,__FILE__,__LINE__);
+#endif
ret = __svfscanf(stdin, fmt, ap);
va_end(ap);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(stdin);
+#endif
return (ret);
}
diff --git a/lib/libc/stdio/setbuf.3 b/lib/libc/stdio/setbuf.3
index 30e9db7..ec5bbd8 100644
--- a/lib/libc/stdio/setbuf.3
+++ b/lib/libc/stdio/setbuf.3
@@ -49,7 +49,7 @@
.Ft void
.Fn setbuf "FILE *stream" "char *buf"
.Ft void
-.Fn setbuffer "FILE *stream" "char *buf" "size_t size"
+.Fn setbuffer "FILE *stream" "char *buf" "int size"
.Ft int
.Fn setlinebuf "FILE *stream"
.Ft int
@@ -170,12 +170,12 @@ function returns what the equivalent
.Fn setvbuf
would have returned.
.Sh SEE ALSO
-.Xr fopen 3 ,
.Xr fclose 3 ,
+.Xr fopen 3 ,
.Xr fread 3 ,
.Xr malloc 3 ,
-.Xr puts 3 ,
-.Xr printf 3
+.Xr printf 3 ,
+.Xr puts 3
.Sh STANDARDS
The
.Fn setbuf
diff --git a/lib/libc/stdio/setbuffer.c b/lib/libc/stdio/setbuffer.c
index a6d06dd..d272177 100644
--- a/lib/libc/stdio/setbuffer.c
+++ b/lib/libc/stdio/setbuffer.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)setbuffer.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -47,7 +51,7 @@ setbuffer(fp, buf, size)
int size;
{
- (void)setvbuf(fp, buf, buf ? _IOFBF : _IONBF, size);
+ (void)setvbuf(fp, buf, buf ? _IOFBF : _IONBF, (size_t)size);
}
/*
diff --git a/lib/libc/stdio/setvbuf.c b/lib/libc/stdio/setvbuf.c
index 867f9b4..9cc6bb6 100644
--- a/lib/libc/stdio/setvbuf.c
+++ b/lib/libc/stdio/setvbuf.c
@@ -35,17 +35,26 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)setvbuf.c 8.2 (Berkeley) 11/16/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <stdlib.h>
#include "local.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/*
* Set one of the three kinds of buffering, optionally including
* a buffer.
*/
+int
setvbuf(fp, buf, mode, size)
register FILE *fp;
char *buf;
@@ -65,6 +74,9 @@ setvbuf(fp, buf, mode, size)
if ((mode != _IOFBF && mode != _IOLBF) || (int)size < 0)
return (EOF);
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
/*
* Write current buffer, if any. Discard unread input (including
* ungetc data), cancel line buffering, and free old buffer if
@@ -116,6 +128,9 @@ nbf:
fp->_w = 0;
fp->_bf._base = fp->_p = fp->_nbuf;
fp->_bf._size = 1;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (ret);
}
flags |= __SMBF;
@@ -156,5 +171,8 @@ nbf:
}
__cleanup = _cleanup;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (ret);
}
diff --git a/lib/libc/stdio/snprintf.c b/lib/libc/stdio/snprintf.c
index 3c3cf7d..0e3c456 100644
--- a/lib/libc/stdio/snprintf.c
+++ b/lib/libc/stdio/snprintf.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)snprintf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -46,8 +50,10 @@ static char sccsid[] = "@(#)snprintf.c 8.1 (Berkeley) 6/4/93";
#endif
#if __STDC__
+int
snprintf(char *str, size_t n, char const *fmt, ...)
#else
+int
snprintf(str, n, fmt, va_alist)
char *str;
size_t n;
@@ -66,6 +72,7 @@ snprintf(str, n, fmt, va_alist)
#else
va_start(ap);
#endif
+ f._file = -1;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = n - 1;
diff --git a/lib/libc/stdio/sprintf.c b/lib/libc/stdio/sprintf.c
index 254064f..fb0514d 100644
--- a/lib/libc/stdio/sprintf.c
+++ b/lib/libc/stdio/sprintf.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)sprintf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -47,6 +51,7 @@ static char sccsid[] = "@(#)sprintf.c 8.1 (Berkeley) 6/4/93";
#include <limits.h>
#include "local.h"
+int
#if __STDC__
sprintf(char *str, char const *fmt, ...)
#else
@@ -60,6 +65,7 @@ sprintf(str, fmt, va_alist)
va_list ap;
FILE f;
+ f._file = -1;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = INT_MAX;
diff --git a/lib/libc/stdio/sscanf.c b/lib/libc/stdio/sscanf.c
index bb72744..d114ae3 100644
--- a/lib/libc/stdio/sscanf.c
+++ b/lib/libc/stdio/sscanf.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)sscanf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -47,6 +51,8 @@ static char sccsid[] = "@(#)sscanf.c 8.1 (Berkeley) 6/4/93";
#endif
#include "local.h"
+static int eofread __P((void *, char *, int));
+
/* ARGSUSED */
static int
eofread(cookie, buf, len)
@@ -59,8 +65,10 @@ eofread(cookie, buf, len)
}
#if __STDC__
+int
sscanf(const char *str, char const *fmt, ...)
#else
+int
sscanf(str, fmt, va_alist)
char *str;
char *fmt;
@@ -71,6 +79,7 @@ sscanf(str, fmt, va_alist)
va_list ap;
FILE f;
+ f._file = -1;
f._flags = __SRD;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._r = strlen(str);
diff --git a/lib/libc/stdio/stdio.3 b/lib/libc/stdio/stdio.3
index 572df8c..81a6970 100644
--- a/lib/libc/stdio/stdio.3
+++ b/lib/libc/stdio/stdio.3
@@ -48,7 +48,7 @@ The standard
library provides a simple and efficient buffered stream
.Tn I/O
interface.
-Input and ouput is mapped into logical data streams
+Input and output is mapped into logical data streams
and the physical
.Tn I/O
characteristics are concealed. The functions and macros are listed
@@ -63,13 +63,13 @@ 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 appended mode. If append mode
+zero), unless the file is opened with append mode. If append mode
is used, the position indicator will be placed 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 ouput takes place as if all characters were
+function; all output takes place as if all characters were
read by successive calls to the
.Xr fputc 3
function.
@@ -77,7 +77,7 @@ function.
A file is disassociated from a stream by
.Em closing
the file.
-Ouput streams are flushed (any unwritten buffer contents are transferred
+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
@@ -111,7 +111,7 @@ opened explicitly:
(for reading conventional input),
.It
.Em standard output
-(for writing conventional input), and
+(for writing conventional output), and
.It
.Em standard error
(for writing diagnostic output).
@@ -151,7 +151,7 @@ function.
The
.Nm stdio
library is a part of the library
-.Xr libc
+.Nm libc
and routines are automatically loaded as needed by the compilers
.Xr cc 1
and
@@ -169,7 +169,7 @@ without first removing their current definitions with
.Dv BUFSIZ ,
.Dv EOF ,
.Dv FILENAME_MAX ,
-.DV FOPEN_MAX ,
+.Dv FOPEN_MAX ,
.Dv L_cuserid ,
.Dv L_ctermid ,
.Dv L_tmpnam,
@@ -192,28 +192,28 @@ without first removing their current definitions with
.Dv stdin ,
.Dv stdout .
Function versions of the macro functions
-.Xr feof ,
-.Xr ferror ,
-.Xr clearerr ,
-.Xr fileno ,
-.Xr getc ,
-.Xr getchar ,
-.Xr putc ,
+.Fn feof ,
+.Fn ferror ,
+.Fn clearerr ,
+.Fn fileno ,
+.Fn getc ,
+.Fn getchar ,
+.Fn putc ,
and
-.Xr putchar
+.Fn putchar
exist and will be used if the macros
definitions are explicitly removed.
.Sh SEE ALSO
-.Xr open 2 ,
.Xr close 2 ,
+.Xr open 2 ,
.Xr read 2 ,
.Xr write 2
.Sh BUGS
The standard buffered functions do not interact well with certain other
library and system functions, especially
-.Xr vfork
+.Xr vfork 2
and
-.Xr abort .
+.Xr abort 3 .
.Sh STANDARDS
The
.Nm stdio
@@ -229,7 +229,7 @@ feof check and reset stream status
ferror check and reset stream status
fflush flush a stream
fgetc get next character or word from input stream
-fgetline get a line from a stream
+fgetln get a line from a stream
fgetpos reposition a stream
fgets get a line from a stream
fileno check and reset stream status
diff --git a/lib/libc/stdio/stdio.c b/lib/libc/stdio/stdio.c
index 7899387..852e971 100644
--- a/lib/libc/stdio/stdio.c
+++ b/lib/libc/stdio/stdio.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)stdio.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <fcntl.h>
@@ -47,6 +51,7 @@ static char sccsid[] = "@(#)stdio.c 8.1 (Berkeley) 6/4/93";
* Small standard I/O/seek/close functions.
* These maintain the `known seek offset' for seek optimisation.
*/
+int
__sread(cookie, buf, n)
void *cookie;
char *buf;
@@ -54,8 +59,8 @@ __sread(cookie, buf, n)
{
register FILE *fp = cookie;
register int ret;
-
- ret = read(fp->_file, buf, n);
+
+ ret = read(fp->_file, buf, (size_t)n);
/* if the read succeeded, update the current offset */
if (ret >= 0)
fp->_offset += ret;
@@ -64,6 +69,7 @@ __sread(cookie, buf, n)
return (ret);
}
+int
__swrite(cookie, buf, n)
void *cookie;
char const *buf;
@@ -74,7 +80,7 @@ __swrite(cookie, buf, n)
if (fp->_flags & __SAPP)
(void) lseek(fp->_file, (off_t)0, SEEK_END);
fp->_flags &= ~__SOFF; /* in case FAPPEND mode is set */
- return (write(fp->_file, buf, n));
+ return (write(fp->_file, buf, (size_t)n));
}
fpos_t
@@ -85,9 +91,9 @@ __sseek(cookie, offset, whence)
{
register FILE *fp = cookie;
register off_t ret;
-
+
ret = lseek(fp->_file, (off_t)offset, whence);
- if (ret == -1L)
+ if (ret == -1)
fp->_flags &= ~__SOFF;
else {
fp->_flags |= __SOFF;
@@ -96,6 +102,7 @@ __sseek(cookie, offset, whence)
return (ret);
}
+int
__sclose(cookie)
void *cookie;
{
diff --git a/lib/libc/stdio/tempnam.c b/lib/libc/stdio/tempnam.c
index 6644ae5..243fa39 100644
--- a/lib/libc/stdio/tempnam.c
+++ b/lib/libc/stdio/tempnam.c
@@ -32,13 +32,18 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)tempnam.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <paths.h>
@@ -55,28 +60,28 @@ tempnam(dir, pfx)
if (!pfx)
pfx = "tmp.";
- if (f = getenv("TMPDIR")) {
+ if ((f = getenv("TMPDIR"))) {
(void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXX", f,
*(f + strlen(f) - 1) == '/'? "": "/", pfx);
- if (f = mktemp(name))
+ if ((f = mktemp(name)))
return(f);
}
- if (f = (char *)dir) {
+ if ((f = (char *)dir)) {
(void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXX", f,
*(f + strlen(f) - 1) == '/'? "": "/", pfx);
- if (f = mktemp(name))
+ if ((f = mktemp(name)))
return(f);
}
f = P_tmpdir;
(void)snprintf(name, MAXPATHLEN, "%s%sXXXXXX", f, pfx);
- if (f = mktemp(name))
+ if ((f = mktemp(name)))
return(f);
f = _PATH_TMP;
(void)snprintf(name, MAXPATHLEN, "%s%sXXXXXX", f, pfx);
- if (f = mktemp(name))
+ if ((f = mktemp(name)))
return(f);
sverrno = errno;
diff --git a/lib/libc/stdio/tmpnam.3 b/lib/libc/stdio/tmpnam.3
index 3b053ee..d7e0326 100644
--- a/lib/libc/stdio/tmpnam.3
+++ b/lib/libc/stdio/tmpnam.3
@@ -201,7 +201,7 @@ Second, most historic implementations provide only a limited number
of possible temporary file names (usually 26) before file names will
start being recycled.
Third, the System V implementations of these functions (and of
-.Xr mktemp )
+.Xr mktemp 3 )
use the
.Xr access 2
function to determine whether or not the temporary file may be created.
diff --git a/lib/libc/stdio/ungetc.3 b/lib/libc/stdio/ungetc.3
index e88b64f..e5c68d0 100644
--- a/lib/libc/stdio/ungetc.3
+++ b/lib/libc/stdio/ungetc.3
@@ -85,8 +85,8 @@ character equals
.Dv EOF ,
the operation will fail and the stream will remain unchanged.
.Sh SEE ALSO
-.Xr getc 3 ,
.Xr fseek 3 ,
+.Xr getc 3 ,
.Xr setvbuf 3
.Sh STANDARDS
The
diff --git a/lib/libc/stdio/ungetc.c b/lib/libc/stdio/ungetc.c
index deaed75..c0355b7 100644
--- a/lib/libc/stdio/ungetc.c
+++ b/lib/libc/stdio/ungetc.c
@@ -35,13 +35,23 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)ungetc.c 8.2 (Berkeley) 11/3/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "local.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
+
+static int __submore __P((FILE *));
/*
* Expand the ungetc buffer `in place'. That is, adjust fp->_p when
@@ -49,7 +59,7 @@ static char sccsid[] = "@(#)ungetc.c 8.2 (Berkeley) 11/3/93";
* and move the bytes in the buffer around as necessary so that they
* are all at the end (stack-style).
*/
-static
+static int
__submore(fp)
register FILE *fp;
{
@@ -71,7 +81,7 @@ __submore(fp)
return (0);
}
i = fp->_ub._size;
- p = realloc(fp->_ub._base, i << 1);
+ 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 */
@@ -82,6 +92,7 @@ __submore(fp)
return (0);
}
+int
ungetc(c, fp)
int c;
register FILE *fp;
@@ -90,16 +101,27 @@ ungetc(c, fp)
return (EOF);
if (!__sdidinit)
__sinit();
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
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)
+ if ((fp->_flags & __SRW) == 0) {
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (EOF);
+ }
if (fp->_flags & __SWR) {
- if (__sflush(fp))
+ if (__sflush(fp)) {
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (EOF);
+ }
fp->_flags &= ~__SWR;
fp->_w = 0;
fp->_lbfsize = 0;
@@ -113,10 +135,17 @@ ungetc(c, fp)
* This may require expanding the current ungetc buffer.
*/
if (HASUB(fp)) {
- if (fp->_r >= fp->_ub._size && __submore(fp))
+ if (fp->_r >= fp->_ub._size && __submore(fp)) {
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (EOF);
+ }
*--fp->_p = c;
fp->_r++;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (c);
}
fp->_flags &= ~__SEOF;
@@ -130,6 +159,9 @@ ungetc(c, fp)
fp->_p[-1] == c) {
fp->_p--;
fp->_r++;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (c);
}
@@ -144,5 +176,8 @@ ungetc(c, fp)
fp->_ubuf[sizeof(fp->_ubuf) - 1] = c;
fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1];
fp->_r = 1;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (c);
}
diff --git a/lib/libc/stdio/vasprintf.c b/lib/libc/stdio/vasprintf.c
new file mode 100644
index 0000000..8030e11
--- /dev/null
+++ b/lib/libc/stdio/vasprintf.c
@@ -0,0 +1,119 @@
+/*-
+ * Copyright (c) 1996 Peter Wemm <peter@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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#define CHUNK_SPARE 128 /* how much spare to allocate to avoid realloc calls */
+
+struct bufcookie {
+ char *base; /* start of buffer */
+ size_t size;
+ size_t left;
+};
+
+static int writehook __P((void *cookie, const char *, int));
+
+static int
+writehook(cookie, buf, len)
+ void *cookie;
+ const char *buf;
+ int len;
+{
+ struct bufcookie *h = (struct bufcookie *)cookie;
+ char *newbuf;
+
+ if (len == 0)
+ return 0;
+
+ if (len > h->left) {
+ /* grow malloc region */
+ /*
+ * XXX this is linearly expanded, which is slow for obscenely
+ * large strings.
+ */
+ h->left = h->left + len + CHUNK_SPARE;
+ h->size = h->size + len + CHUNK_SPARE;
+ newbuf = realloc(h->base, h->size);
+ if (newbuf == NULL) {
+ free(h->base);
+ h->base = NULL;
+ return (-1);
+ } else
+ h->base = newbuf;
+ }
+ /* "write" it */
+ (void)memcpy(h->base + h->size - h->left, buf, (size_t)len);
+ h->left -= len;
+ return (len);
+}
+
+
+int
+vasprintf(str, fmt, ap)
+ char **str;
+ const char *fmt;
+ va_list ap;
+{
+ int ret;
+ FILE *f;
+ struct bufcookie h;
+
+ h.base = malloc(CHUNK_SPARE);
+ if (h.base == NULL)
+ return (-1);
+ h.size = CHUNK_SPARE;
+ h.left = CHUNK_SPARE;
+
+ f = funopen(&h, NULL, writehook, NULL, NULL);
+ if (f == NULL) {
+ free(h.base);
+ return (-1);
+ }
+ ret = vfprintf(f, fmt, ap);
+ fclose(f);
+ if (ret < 0) {
+ free(h.base);
+ return (-1);
+ }
+ if (h.base == NULL) /* failed to realloc in writehook */
+ return (-1);
+
+ h.base[h.size - h.left] = '\0';
+ *str = realloc(h.base, (size_t)(h.size - h.left + 1));
+ if (*str == NULL) /* failed to realloc it to actual size */
+ *str = h.base; /* return oversize buffer */
+ return (ret);
+}
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
index 3610e10..61dba47 100644
--- a/lib/libc/stdio/vfprintf.c
+++ b/lib/libc/stdio/vfprintf.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
/*
@@ -59,10 +63,21 @@ static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
#include "local.h"
#include "fvwrite.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/* Define FLOATING_POINT to get floating point. */
#define FLOATING_POINT
+static int __sprint __P((FILE *, struct __suio *));
+static int __sbprintf __P((FILE *, const char *, va_list));
+static char * __ultoa __P((u_long, char *, int, int, char *));
+static char * __uqtoa __P((u_quad_t, char *, int, int, char *));
+static void __find_arguments __P((const char *, va_list, void ***));
+static void __grow_type_table __P((int, unsigned char **, int *));
+
/*
* Flush out all the vectors defined by the given uio,
* then reset it so that it can be reused.
@@ -261,6 +276,7 @@ static int exponent __P((char *, int, int));
#endif /* FLOATING_POINT */
+#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
/*
* Flags used during conversion.
@@ -282,7 +298,7 @@ vfprintf(fp, fmt0, ap)
{
register char *fmt; /* format string */
register int ch; /* character from fmt */
- register int n; /* handy integer (short term usage) */
+ register int n, n2; /* handy integer (short term usage) */
register char *cp; /* handy char pointer (short term usage) */
register struct __siov *iovp;/* for PRINT macro */
register int flags; /* flags as above */
@@ -302,8 +318,7 @@ vfprintf(fp, fmt0, ap)
u_quad_t uqval; /* %q integers */
int base; /* base for [diouxX] conversion */
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
- int fieldsz; /* field size expanded by sign, etc */
- int realsz; /* field size expanded by dprec */
+ int realsz; /* field size expanded by dprec, sign, etc */
int size; /* size of converted field or string */
char *xdigs; /* digits for [xX] conversion */
#define NIOV 8
@@ -311,6 +326,10 @@ vfprintf(fp, fmt0, ap)
struct __siov iov[NIOV];/* ... and individual io vectors */
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
char ox[2]; /* space for 0x hex-prefix */
+ void **argtable; /* args, built due to positional arg */
+ void *statargtable [STATIC_ARG_TBL_SIZE];
+ int nextarg; /* 1-based argument index */
+ va_list orgap; /* original argument pointer */
/*
* Choose PADSIZE to trade efficiency vs. size. If larger printf
@@ -353,29 +372,78 @@ vfprintf(fp, fmt0, ap)
iovp = iov; \
}
+ /*
+ * 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 ? va_arg(ap, long) : \
- flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
- (long)va_arg(ap, int))
+ (flags&LONGINT ? GETARG(long) : \
+ flags&SHORTINT ? (long)(short)GETARG(int) : \
+ (long)GETARG(int))
#define UARG() \
- (flags&LONGINT ? va_arg(ap, u_long) : \
- flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
- (u_long)va_arg(ap, u_int))
+ (flags&LONGINT ? GETARG(u_long) : \
+ flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
+ (u_long)GETARG(u_int))
+
+ /*
+ * 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; \
+ __find_arguments (fmt0, orgap, &argtable); \
+ } \
+ nextarg = n2; \
+ val = GETARG (int); \
+ nextarg = hold; \
+ fmt = ++cp; \
+ } else { \
+ val = GETARG (int); \
+ }
+
+#ifdef _THREAD_SAFE
+ _thread_flockfile(fp,__FILE__,__LINE__);
+#endif
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
- if (cantwrite(fp))
+ if (cantwrite(fp)) {
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (EOF);
+ }
/* optimise fprintf(stderr) (and other unbuffered Unix files) */
if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
- fp->_file >= 0)
+ fp->_file >= 0) {
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
return (__sbprintf(fp, fmt0, ap));
+ }
fmt = (char *)fmt0;
+ argtable = NULL;
+ nextarg = 1;
+ orgap = ap;
uio.uio_iov = iovp = iov;
uio.uio_resid = 0;
uio.uio_iovcnt = 0;
@@ -422,7 +490,8 @@ reswitch: switch (ch) {
* -- ANSI X3J11
* They don't exclude field widths read from args.
*/
- if ((width = va_arg(ap, int)) >= 0)
+ GETASTER (width);
+ if (width >= 0)
goto rflag;
width = -width;
/* FALLTHROUGH */
@@ -434,7 +503,7 @@ reswitch: switch (ch) {
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
- n = va_arg(ap, int);
+ GETASTER (n);
prec = n < 0 ? -1 : n;
goto rflag;
}
@@ -460,6 +529,15 @@ reswitch: switch (ch) {
n = 10 * n + to_digit(ch);
ch = *fmt++;
} while (is_digit(ch));
+ if (ch == '$') {
+ nextarg = n;
+ if (argtable == NULL) {
+ argtable = statargtable;
+ __find_arguments (fmt0, orgap,
+ &argtable);
+ }
+ goto rflag;
+ }
width = n;
goto reswitch;
#ifdef FLOATING_POINT
@@ -477,7 +555,7 @@ reswitch: switch (ch) {
flags |= QUADINT;
goto rflag;
case 'c':
- *(cp = buf) = va_arg(ap, int);
+ *(cp = buf) = GETARG(int);
size = 1;
sign = '\0';
break;
@@ -487,7 +565,7 @@ reswitch: switch (ch) {
case 'd':
case 'i':
if (flags & QUADINT) {
- uqval = va_arg(ap, quad_t);
+ uqval = GETARG(quad_t);
if ((quad_t)uqval < 0) {
uqval = -uqval;
sign = '-';
@@ -502,20 +580,20 @@ reswitch: switch (ch) {
base = 10;
goto number;
#ifdef FLOATING_POINT
- case 'e': /* anomalous precision */
+ case 'e':
case 'E':
- prec = (prec == -1) ?
- DEFPREC + 1 : prec + 1;
- /* FALLTHROUGH */
+ case 'f':
goto fp_begin;
- case 'f': /* always print trailing zeroes */
- if (prec != 0)
- flags |= ALT;
case 'g':
case 'G':
- if (prec == -1)
+ if (prec == 0)
+ prec = 1;
+fp_begin: if (prec == -1)
prec = DEFPREC;
-fp_begin: _double = va_arg(ap, double);
+ if (flags & LONGDBL)
+ _double = (double)GETARG(long double);
+ else
+ _double = GETARG(double);
/* do this before tricky precision changes */
if (isinf(_double)) {
if (_double < 0)
@@ -537,7 +615,7 @@ fp_begin: _double = va_arg(ap, double);
ch = (ch == 'g') ? 'e' : 'E';
else
ch = 'g';
- }
+ }
if (ch <= 'e') { /* 'e' or 'E' fmt */
--expt;
expsize = exponent(expstr, expt, ch);
@@ -565,20 +643,20 @@ fp_begin: _double = va_arg(ap, double);
#endif /* FLOATING_POINT */
case 'n':
if (flags & QUADINT)
- *va_arg(ap, quad_t *) = ret;
+ *GETARG(quad_t *) = ret;
else if (flags & LONGINT)
- *va_arg(ap, long *) = ret;
+ *GETARG(long *) = ret;
else if (flags & SHORTINT)
- *va_arg(ap, short *) = ret;
+ *GETARG(short *) = ret;
else
- *va_arg(ap, int *) = ret;
+ *GETARG(int *) = ret;
continue; /* no output */
case 'O':
flags |= LONGINT;
/*FALLTHROUGH*/
case 'o':
if (flags & QUADINT)
- uqval = va_arg(ap, u_quad_t);
+ uqval = GETARG(u_quad_t);
else
ulval = UARG();
base = 8;
@@ -591,14 +669,14 @@ fp_begin: _double = va_arg(ap, double);
* defined manner.''
* -- ANSI X3J11
*/
- ulval = (u_long)va_arg(ap, void *);
+ ulval = (u_long)GETARG(void *);
base = 16;
xdigs = "0123456789abcdef";
flags = (flags & ~QUADINT) | HEXPREFIX;
ch = 'x';
goto nosign;
case 's':
- if ((cp = va_arg(ap, char *)) == NULL)
+ if ((cp = GETARG(char *)) == NULL)
cp = "(null)";
if (prec >= 0) {
/*
@@ -606,7 +684,7 @@ fp_begin: _double = va_arg(ap, double);
* NUL in the first `prec' characters, and
* strlen() will go further.
*/
- char *p = memchr(cp, 0, prec);
+ char *p = memchr(cp, 0, (size_t)prec);
if (p != NULL) {
size = p - cp;
@@ -623,7 +701,7 @@ fp_begin: _double = va_arg(ap, double);
/*FALLTHROUGH*/
case 'u':
if (flags & QUADINT)
- uqval = va_arg(ap, u_quad_t);
+ uqval = GETARG(u_quad_t);
else
ulval = UARG();
base = 10;
@@ -634,7 +712,7 @@ fp_begin: _double = va_arg(ap, double);
case 'x':
xdigs = "0123456789abcdef";
hex: if (flags & QUADINT)
- uqval = va_arg(ap, u_quad_t);
+ uqval = GETARG(u_quad_t);
else
ulval = UARG();
base = 16;
@@ -693,14 +771,13 @@ number: if ((dprec = prec) >= 0)
* floating precision; finally, if LADJUST, pad with blanks.
*
* Compute actual size, so we know how much to pad.
- * fieldsz excludes decimal prec; realsz includes it.
+ * size excludes decimal prec; realsz includes it.
*/
- fieldsz = size;
+ realsz = dprec > size ? dprec : size;
if (sign)
- fieldsz++;
+ realsz++;
else if (flags & HEXPREFIX)
- fieldsz += 2;
- realsz = dprec > fieldsz ? dprec : fieldsz;
+ realsz += 2;
/* right-adjusting blank padding */
if ((flags & (LADJUST|ZEROPAD)) == 0)
@@ -720,7 +797,7 @@ number: if ((dprec = prec) >= 0)
PAD(width - realsz, zeroes);
/* leading zeroes from decimal precision */
- PAD(dprec - fieldsz, zeroes);
+ PAD(dprec - size, zeroes);
/* the string or number proper */
#ifdef FLOATING_POINT
@@ -729,8 +806,8 @@ number: if ((dprec = prec) >= 0)
} else { /* glue together f_p fragments */
if (ch >= 'f') { /* 'f' or 'g' */
if (_double == 0) {
- /* kludge for __dtoa irregularity */
- if (prec == 0 ||
+ /* kludge for __dtoa irregularity */
+ if (expt >= ndig &&
(flags & ALT) == 0) {
PRINT("0", 1);
} else {
@@ -757,7 +834,7 @@ number: if ((dprec = prec) >= 0)
ox[0] = *cp++;
ox[1] = '.';
PRINT(ox, 2);
- if (_double || flags & ALT == 0) {
+ if (_double) {
PRINT(cp, ndig-1);
} else /* 0.[0..] */
/* __dtoa irregularity */
@@ -782,10 +859,338 @@ number: if ((dprec = prec) >= 0)
done:
FLUSH();
error:
- return (__sferror(fp) ? EOF : ret);
+ if (__sferror(fp))
+ ret = EOF;
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(fp);
+#endif
+ if ((argtable != NULL) && (argtable != statargtable))
+ free (argtable);
+ return (ret);
/* NOTREACHED */
}
+/*
+ * Type ids for argument type table.
+ */
+#define T_UNUSED 0
+#define T_SHORT 1
+#define T_U_SHORT 2
+#define TP_SHORT 3
+#define T_INT 4
+#define T_U_INT 5
+#define TP_INT 6
+#define T_LONG 7
+#define T_U_LONG 8
+#define TP_LONG 9
+#define T_QUAD 10
+#define T_U_QUAD 11
+#define TP_QUAD 12
+#define T_DOUBLE 13
+#define T_LONG_DOUBLE 14
+#define TP_CHAR 15
+#define TP_VOID 16
+
+/*
+ * 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 on if it overflows.
+ */
+static void
+__find_arguments (fmt0, ap, argtable)
+ const char *fmt0;
+ va_list ap;
+ void ***argtable;
+{
+ register char *fmt; /* format string */
+ register int ch; /* character from fmt */
+ register int n, n2; /* handy integer (short term usage) */
+ register char *cp; /* handy char pointer (short term usage) */
+ register int flags; /* flags as above */
+ int width; /* width from format (%8d), or 0 */
+ unsigned char *typetable; /* table of types */
+ unsigned char stattypetable [STATIC_ARG_TBL_SIZE];
+ int tablesize; /* current size of type table */
+ int tablemax; /* largest used index in table */
+ int nextarg; /* 1-based argument index */
+
+ /*
+ * Add an argument type to the table, expanding if necessary.
+ */
+#define ADDTYPE(type) \
+ ((nextarg >= tablesize) ? \
+ __grow_type_table(nextarg, &typetable, &tablesize) : 0, \
+ typetable[nextarg++] = type, \
+ (nextarg > tablemax) ? tablemax = nextarg : 0)
+
+#define ADDSARG() \
+ ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
+ ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT)))
+
+#define ADDUARG() \
+ ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
+ ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT)))
+
+ /*
+ * Add * arguments to the type array.
+ */
+#define ADDASTER() \
+ n2 = 0; \
+ cp = fmt; \
+ while (is_digit(*cp)) { \
+ n2 = 10 * n2 + to_digit(*cp); \
+ cp++; \
+ } \
+ if (*cp == '$') { \
+ int hold = nextarg; \
+ nextarg = n2; \
+ ADDTYPE (T_INT); \
+ nextarg = hold; \
+ fmt = ++cp; \
+ } else { \
+ ADDTYPE (T_INT); \
+ }
+ fmt = (char *)fmt0;
+ typetable = stattypetable;
+ tablesize = STATIC_ARG_TBL_SIZE;
+ tablemax = 0;
+ nextarg = 1;
+ memset (typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+ /* void */;
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ width = 0;
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ case '#':
+ goto rflag;
+ case '*':
+ ADDASTER ();
+ goto rflag;
+ case '-':
+ case '+':
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ ADDASTER ();
+ 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 == '$') {
+ nextarg = n;
+ goto rflag;
+ }
+ width = n;
+ goto reswitch;
+#ifdef FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ flags |= SHORTINT;
+ goto rflag;
+ case 'l':
+ flags |= LONGINT;
+ goto rflag;
+ case 'q':
+ flags |= QUADINT;
+ goto rflag;
+ case 'c':
+ ADDTYPE(T_INT);
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+ if (flags & QUADINT) {
+ ADDTYPE(T_QUAD);
+ } else {
+ ADDSARG();
+ }
+ break;
+#ifdef FLOATING_POINT
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ if (flags & LONGDBL)
+ ADDTYPE(T_LONG_DOUBLE);
+ else
+ ADDTYPE(T_DOUBLE);
+ break;
+#endif /* FLOATING_POINT */
+ case 'n':
+ if (flags & QUADINT)
+ ADDTYPE(TP_QUAD);
+ else if (flags & LONGINT)
+ ADDTYPE(TP_LONG);
+ else if (flags & SHORTINT)
+ ADDTYPE(TP_SHORT);
+ else
+ ADDTYPE(TP_INT);
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+ if (flags & QUADINT)
+ ADDTYPE(T_U_QUAD);
+ else
+ ADDUARG();
+ break;
+ case 'p':
+ ADDTYPE(TP_VOID);
+ break;
+ case 's':
+ ADDTYPE(TP_CHAR);
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+ if (flags & QUADINT)
+ ADDTYPE(T_U_QUAD);
+ else
+ ADDUARG();
+ break;
+ case 'X':
+ case 'x':
+ if (flags & QUADINT)
+ ADDTYPE(T_U_QUAD);
+ else
+ ADDUARG();
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ break;
+ }
+ }
+done:
+ /*
+ * Build the argument table.
+ */
+ if (tablemax >= STATIC_ARG_TBL_SIZE) {
+ *argtable = (void **)
+ malloc (sizeof (void *) * (tablemax + 1));
+ }
+
+ (*argtable) [0] = NULL;
+ for (n = 1; n <= tablemax; n++) {
+ (*argtable) [n] = ap;
+ switch (typetable [n]) {
+ case T_UNUSED:
+ (void) va_arg (ap, int);
+ break;
+ case T_SHORT:
+ (void) va_arg (ap, int);
+ break;
+ case T_U_SHORT:
+ (void) va_arg (ap, int);
+ break;
+ case TP_SHORT:
+ (void) va_arg (ap, short *);
+ break;
+ case T_INT:
+ (void) va_arg (ap, int);
+ break;
+ case T_U_INT:
+ (void) va_arg (ap, unsigned int);
+ break;
+ case TP_INT:
+ (void) va_arg (ap, int *);
+ break;
+ case T_LONG:
+ (void) va_arg (ap, long);
+ break;
+ case T_U_LONG:
+ (void) va_arg (ap, unsigned long);
+ break;
+ case TP_LONG:
+ (void) va_arg (ap, long *);
+ break;
+ case T_QUAD:
+ (void) va_arg (ap, quad_t);
+ break;
+ case T_U_QUAD:
+ (void) va_arg (ap, u_quad_t);
+ break;
+ case TP_QUAD:
+ (void) va_arg (ap, quad_t *);
+ break;
+ case T_DOUBLE:
+ (void) va_arg (ap, double);
+ break;
+ case T_LONG_DOUBLE:
+ (void) va_arg (ap, long double);
+ break;
+ case TP_CHAR:
+ (void) va_arg (ap, char *);
+ break;
+ case TP_VOID:
+ (void) va_arg (ap, void *);
+ break;
+ }
+ }
+
+ if ((typetable != NULL) && (typetable != stattypetable))
+ free (typetable);
+}
+
+/*
+ * Increase the size of the type table.
+ */
+static void
+__grow_type_table (nextarg, typetable, tablesize)
+ int nextarg;
+ unsigned char **typetable;
+ int *tablesize;
+{
+ unsigned char *oldtable = *typetable;
+ int newsize = *tablesize * 2;
+
+ if (*tablesize == STATIC_ARG_TBL_SIZE) {
+ *typetable = (unsigned char *)
+ malloc (sizeof (unsigned char) * newsize);
+ bcopy (oldtable, *typetable, *tablesize);
+ } else {
+ *typetable = (unsigned char *)
+ realloc (typetable, sizeof (unsigned char) * newsize);
+
+ }
+ memset (&typetable [*tablesize], T_UNUSED, (newsize - *tablesize));
+
+ *tablesize = newsize;
+}
+
+
#ifdef FLOATING_POINT
extern char *__dtoa __P((double, int, int, int *, int *, char **));
@@ -800,9 +1205,16 @@ cvt(value, ndigits, flags, sign, decpt, ch, length)
char *digits, *bp, *rve;
if (ch == 'f')
- mode = 3;
+ mode = 3; /* ndigits after the decimal point */
else {
- mode = 2;
+ /*
+ * To obtain ndigits after the decimal point for the 'e'
+ * and 'E' formats, round to ndigits + 1 significant
+ * figures.
+ */
+ if (ch == 'e' || ch == 'E')
+ ndigits++;
+ mode = 2; /* ndigits significant digits */
}
if (value < 0) {
value = -value;
@@ -810,7 +1222,8 @@ cvt(value, ndigits, flags, sign, decpt, ch, length)
} else
*sign = '\000';
digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
- if (flags & ALT) { /* Print trailing zeros */
+ if ((ch != 'g' && ch != 'G') || flags & ALT) {
+ /* print trailing zeros */
bp = digits + ndigits;
if (ch == 'f') {
if (*digits == '0' && value)
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
index 22ed5a0..0df3720 100644
--- a/lib/libc/stdio/vfscanf.c
+++ b/lib/libc/stdio/vfscanf.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id: vfscanf.c,v 1.10 1997/04/04 19:07:02 ache Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -46,6 +50,9 @@ static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
#else
#include <varargs.h>
#endif
+#include <string.h>
+
+#include "collate.h"
#include "local.h"
#define FLOATING_POINT
@@ -62,6 +69,7 @@ static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
#define SUPPRESS 0x08 /* suppress assignment */
#define POINTER 0x10 /* weird %p pointer (`fake hex') */
#define NOSKIP 0x20 /* do not skip blanks */
+#define QUAD 0x400
/*
* The following are used in numeric conversions only:
@@ -83,17 +91,18 @@ static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
#define CT_CHAR 0 /* %c conversion */
#define CT_CCL 1 /* %[...] conversion */
#define CT_STRING 2 /* %s conversion */
-#define CT_INT 3 /* integer, i.e., strtol or strtoul */
+#define CT_INT 3 /* integer, i.e., strtoq or strtouq */
#define CT_FLOAT 4 /* floating, i.e., strtod */
#define u_char unsigned char
#define u_long unsigned long
-static u_char *__sccl();
+static u_char *__sccl(char *, u_char *);
/*
* vfscanf
*/
+int
__svfscanf(fp, fmt0, ap)
register FILE *fp;
char const *fmt0;
@@ -107,9 +116,10 @@ __svfscanf(fp, fmt0, ap)
register int flags; /* flags as defined above */
register char *p0; /* saves original value of p when necessary */
int nassigned; /* number of fields assigned */
+ int nconversions; /* number of conversions */
int nread; /* number of characters consumed from fp */
- int base; /* base argument to strtol/strtoul */
- u_long (*ccfn)(); /* conversion function (strtol/strtoul) */
+ int base; /* base argument to strtoq/strtouq */
+ u_quad_t(*ccfn)(); /* conversion function (strtoq/strtouq) */
char ccltab[256]; /* character class table for %[...] */
char buf[BUF]; /* buffer for numeric conversions */
@@ -118,6 +128,7 @@ __svfscanf(fp, fmt0, ap)
{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
nassigned = 0;
+ nconversions = 0;
nread = 0;
base = 0; /* XXX just to keep gcc happy */
ccfn = NULL; /* XXX just to keep gcc happy */
@@ -128,7 +139,7 @@ __svfscanf(fp, fmt0, ap)
if (isspace(c)) {
for (;;) {
if (fp->_r <= 0 && __srefill(fp))
- return (nassigned);
+ goto input_failure;
if (!isspace(*fp->_p))
break;
nread++, fp->_r--, fp->_p++;
@@ -161,6 +172,9 @@ literal:
case 'l':
flags |= LONG;
goto again;
+ case 'q':
+ flags |= QUAD;
+ goto again;
case 'L':
flags |= LONGDBL;
goto again;
@@ -185,13 +199,13 @@ literal:
/* FALLTHROUGH */
case 'd':
c = CT_INT;
- ccfn = (u_long (*)())strtol;
+ ccfn = (u_quad_t (*)())strtoq;
base = 10;
break;
case 'i':
c = CT_INT;
- ccfn = (u_long (*)())strtol;
+ ccfn = (u_quad_t (*)())strtoq;
base = 0;
break;
@@ -200,13 +214,13 @@ literal:
/* FALLTHROUGH */
case 'o':
c = CT_INT;
- ccfn = strtoul;
+ ccfn = strtouq;
base = 8;
break;
case 'u':
c = CT_INT;
- ccfn = strtoul;
+ ccfn = strtouq;
base = 10;
break;
@@ -216,7 +230,7 @@ literal:
case 'x':
flags |= PFXOK; /* enable 0x prefixing */
c = CT_INT;
- ccfn = strtoul;
+ ccfn = strtouq;
base = 16;
break;
@@ -248,17 +262,20 @@ literal:
case 'p': /* pointer format is like hex */
flags |= POINTER | PFXOK;
c = CT_INT;
- ccfn = strtoul;
+ ccfn = strtouq;
base = 16;
break;
case 'n':
+ nconversions++;
if (flags & SUPPRESS) /* ??? */
continue;
if (flags & SHORT)
*va_arg(ap, short *) = nread;
else if (flags & LONG)
*va_arg(ap, long *) = nread;
+ else if (flags & QUAD)
+ *va_arg(ap, quad_t *) = nread;
else
*va_arg(ap, int *) = nread;
continue;
@@ -273,7 +290,7 @@ literal:
if (isupper(c))
flags |= LONG;
c = CT_INT;
- ccfn = (u_long (*)())strtol;
+ ccfn = (u_quad_t (*)())strtoq;
base = 10;
break;
}
@@ -341,12 +358,13 @@ literal:
nread += r;
nassigned++;
}
+ nconversions++;
break;
case CT_CCL:
/* scan a (nonempty) character class (sets NOSKIP) */
if (width == 0)
- width = ~0; /* `infinity' */
+ width = (size_t)~0; /* `infinity' */
/* take only those things in the class */
if (flags & SUPPRESS) {
n = 0;
@@ -382,12 +400,13 @@ literal:
nassigned++;
}
nread += n;
+ nconversions++;
break;
case CT_STRING:
/* like CCL, but zero-length string OK, & no NOSKIP */
if (width == 0)
- width = ~0;
+ width = (size_t)~0;
if (flags & SUPPRESS) {
n = 0;
while (!isspace(*fp->_p)) {
@@ -412,10 +431,11 @@ literal:
nread += p - p0;
nassigned++;
}
+ nconversions++;
continue;
case CT_INT:
- /* scan an integer as if by strtol/strtoul */
+ /* scan an integer as if by strtoq/strtouq */
#ifdef hardway
if (width == 0 || width > sizeof(buf) - 1)
width = sizeof(buf) - 1;
@@ -533,21 +553,25 @@ literal:
(void) ungetc(c, fp);
}
if ((flags & SUPPRESS) == 0) {
- u_long res;
+ u_quad_t res;
*p = 0;
res = (*ccfn)(buf, (char **)NULL, base);
if (flags & POINTER)
- *va_arg(ap, void **) = (void *)res;
+ *va_arg(ap, void **) =
+ (void *)(u_long)res;
else if (flags & SHORT)
*va_arg(ap, short *) = res;
else if (flags & LONG)
*va_arg(ap, long *) = res;
+ else if (flags & QUAD)
+ *va_arg(ap, quad_t *) = res;
else
*va_arg(ap, int *) = res;
nassigned++;
}
nread += p - buf;
+ nconversions++;
break;
#ifdef FLOATING_POINT
@@ -639,12 +663,13 @@ literal:
nassigned++;
}
nread += p - buf;
+ nconversions++;
break;
#endif /* FLOATING_POINT */
}
}
input_failure:
- return (nassigned ? nassigned : -1);
+ return (nconversions != 0 ? nassigned : EOF);
match_failure:
return (nassigned);
}
@@ -660,7 +685,7 @@ __sccl(tab, fmt)
register char *tab;
register u_char *fmt;
{
- register int c, n, v;
+ register int c, n, v, i;
/* first `clear' the whole table */
c = *fmt++; /* first char hat => negated scanset */
@@ -669,9 +694,10 @@ __sccl(tab, fmt)
c = *fmt++; /* get new first char */
} else
v = 0; /* default => reject */
- /* should probably use memset here */
- for (n = 0; n < 256; n++)
- tab[n] = v;
+
+ /* XXX: Will not work if sizeof(tab*) > sizeof(char) */
+ (void) memset(tab, v, 256);
+
if (c == 0)
return (fmt - 1);/* format ended before closing ] */
@@ -712,15 +738,29 @@ doswitch:
* we just stored in the table (c).
*/
n = *fmt;
- if (n == ']' || n < c) {
+ if (n == ']'
+ || (__collate_load_error ? n < c :
+ __collate_range_cmp (n, c) < 0
+ )
+ ) {
c = '-';
break; /* resume the for(;;) */
}
fmt++;
- do { /* fill in the range */
- tab[++c] = v;
- } while (c < n);
+ /* fill in the range */
+ if (__collate_load_error) {
+ do {
+ tab[++c] = v;
+ } while (c < n);
+ } else {
+ for (i = 0; i < 256; i ++)
+ if ( __collate_range_cmp (c, i) < 0
+ && __collate_range_cmp (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'.
diff --git a/lib/libc/stdio/vprintf.c b/lib/libc/stdio/vprintf.c
index f8184bb..8d449d6 100644
--- a/lib/libc/stdio/vprintf.c
+++ b/lib/libc/stdio/vprintf.c
@@ -35,11 +35,16 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)vprintf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
+int
vprintf(fmt, ap)
char const *fmt;
_BSD_VA_LIST_ ap;
diff --git a/lib/libc/stdio/vscanf.c b/lib/libc/stdio/vscanf.c
index 5d12865..9381710 100644
--- a/lib/libc/stdio/vscanf.c
+++ b/lib/libc/stdio/vscanf.c
@@ -35,15 +35,32 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)vscanf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
+int
vscanf(fmt, ap)
const char *fmt;
_BSD_VA_LIST_ ap;
{
+ int retval;
- return (__svfscanf(stdin, fmt, ap));
+#ifdef _THREAD_SAFE
+ _thread_flockfile(stdin,__FILE__,__LINE__);
+#endif
+ retval = __svfscanf(stdin, fmt, ap);
+#ifdef _THREAD_SAFE
+ _thread_funlockfile(stdin);
+#endif
+ return (retval);
}
diff --git a/lib/libc/stdio/vsnprintf.c b/lib/libc/stdio/vsnprintf.c
index ccc8af6..8837c2e 100644
--- a/lib/libc/stdio/vsnprintf.c
+++ b/lib/libc/stdio/vsnprintf.c
@@ -35,11 +35,16 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)vsnprintf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
+int
vsnprintf(str, n, fmt, ap)
char *str;
size_t n;
@@ -51,6 +56,7 @@ vsnprintf(str, n, fmt, ap)
if ((int)n < 1)
return (EOF);
+ f._file = -1;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = n - 1;
diff --git a/lib/libc/stdio/vsprintf.c b/lib/libc/stdio/vsprintf.c
index c6e192a..911d97f 100644
--- a/lib/libc/stdio/vsprintf.c
+++ b/lib/libc/stdio/vsprintf.c
@@ -35,12 +35,17 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)vsprintf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <limits.h>
+int
vsprintf(str, fmt, ap)
char *str;
const char *fmt;
@@ -49,6 +54,7 @@ vsprintf(str, fmt, ap)
int ret;
FILE f;
+ f._file = -1;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = INT_MAX;
diff --git a/lib/libc/stdio/vsscanf.c b/lib/libc/stdio/vsscanf.c
index 540f290..4cfa662 100644
--- a/lib/libc/stdio/vsscanf.c
+++ b/lib/libc/stdio/vsscanf.c
@@ -35,12 +35,19 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)vsscanf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <string.h>
+static int
+eofread __P((void *, char *, int));
+
/* ARGSUSED */
static int
eofread(cookie, buf, len)
@@ -52,14 +59,15 @@ eofread(cookie, buf, len)
return (0);
}
+int
vsscanf(str, fmt, ap)
const char *str;
const char *fmt;
_BSD_VA_LIST_ ap;
{
- int ret;
FILE f;
+ f._file = -1;
f._flags = __SRD;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._r = strlen(str);
diff --git a/lib/libc/stdio/wbuf.c b/lib/libc/stdio/wbuf.c
index 36d7c8d..b85ac51 100644
--- a/lib/libc/stdio/wbuf.c
+++ b/lib/libc/stdio/wbuf.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)wbuf.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -46,6 +50,7 @@ static char sccsid[] = "@(#)wbuf.c 8.1 (Berkeley) 6/4/93";
* the given file. Flush the buffer out if it is or becomes full,
* or if c=='\n' and the file is line buffered.
*/
+int
__swbuf(c, fp)
register int c;
register FILE *fp;
diff --git a/lib/libc/stdio/wsetup.c b/lib/libc/stdio/wsetup.c
index 1215edc..74f0f77 100644
--- a/lib/libc/stdio/wsetup.c
+++ b/lib/libc/stdio/wsetup.c
@@ -35,7 +35,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)wsetup.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -47,6 +51,7 @@ static char sccsid[] = "@(#)wsetup.c 8.1 (Berkeley) 6/4/93";
* because either _flags does not include __SWR, or _buf is NULL.
* _wsetup returns 0 if OK to write, nonzero otherwise.
*/
+int
__swsetup(fp)
register FILE *fp;
{
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc
index 9982037..58842bf 100644
--- a/lib/libc/stdlib/Makefile.inc
+++ b/lib/libc/stdlib/Makefile.inc
@@ -1,25 +1,35 @@
-# @(#)Makefile.inc 8.3 (Berkeley) 2/4/95
+# from @(#)Makefile.inc 8.3 (Berkeley) 2/4/95
+# $Id: Makefile.inc,v 1.9 1997/06/22 17:54:24 phk Exp $
# machine-independent stdlib sources
-.PATH: ${.CURDIR}/${MACHINE}/stdlib ${.CURDIR}/stdlib
+.PATH: ${.CURDIR}/../libc/${MACHINE}/stdlib ${.CURDIR}/../libc/stdlib
SRCS+= abort.c atexit.c atof.c atoi.c atol.c bsearch.c calloc.c div.c \
- exit.c getenv.c getopt.c getsubopt.c heapsort.c labs.c ldiv.c \
- malloc.c merge.c putenv.c qsort.c radixsort.c rand.c random.c \
- setenv.c strtod.c strtol.c strtoq.c strtoul.c \
+ exit.c getenv.c getopt.c getsubopt.c strhash.c heapsort.c labs.c \
+ ldiv.c malloc.c merge.c putenv.c qsort.c radixsort.c rand.c random.c \
+ realpath.c setenv.c strtod.c strtol.c strtoq.c strtoul.c \
strtouq.c system.c
# machine-dependent stdlib sources
-.include "${.CURDIR}/${MACHINE}/stdlib/Makefile.inc"
+.include "${.CURDIR}/../libc/${MACHINE}/stdlib/Makefile.inc"
-MAN3+= abort.0 abs.0 alloca.0 atexit.0 atof.0 atoi.0 atol.0 bsearch.0 \
- calloc.0 div.0 exit.0 free.0 getenv.0 getopt.0 getsubopt.0 labs.0 \
- ldiv.0 malloc.0 memory.0 qsort.0 radixsort.0 rand.0 random.0 \
- realloc.0 strtol.0 strtoul.0 system.0
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN3+= stdlib/abort.3 stdlib/abs.3 stdlib/alloca.3 stdlib/atexit.3 \
+ stdlib/atof.3 stdlib/atoi.3 stdlib/atol.3 stdlib/bsearch.3 \
+ stdlib/div.3 stdlib/exit.3 \
+ stdlib/getenv.3 stdlib/getopt.3 stdlib/getsubopt.3 stdlib/labs.3 \
+ stdlib/ldiv.3 stdlib/malloc.3 stdlib/memory.3 stdlib/qsort.3 \
+ stdlib/radixsort.3 stdlib/rand.3 stdlib/random.3 \
+ stdlib/realpath.3 stdlib/strtod.3 stdlib/strtol.3 stdlib/strtoul.3 \
+ stdlib/system.3
MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
MLINKS+=rand.3 srand.3
-MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3
+MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 \
+ random.3 srandomdev.3
MLINKS+=strtol.3 strtoq.3
MLINKS+=strtoul.3 strtouq.3
+MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
+.endif
diff --git a/lib/libc/stdlib/abort.3 b/lib/libc/stdlib/abort.3
index 83b4e04..17717e9 100644
--- a/lib/libc/stdlib/abort.3
+++ b/lib/libc/stdlib/abort.3
@@ -53,18 +53,18 @@ signal
.Dv SIGABRT
is being caught and the signal handler does not return.
.Pp
-No open streams are closed or flushed.
+Any open streams are flushed and closed.
.Sh RETURN VALUES
The
-.Nm abort
+.Fn abort
function
never returns.
.Sh SEE ALSO
.Xr sigaction 2 ,
-.Xr exit 2
+.Xr exit 3
.Sh STANDARDS
The
.Fn abort
function
conforms to
-.St -ansiC .
+.St -p1003.1-90 .
diff --git a/lib/libc/stdlib/abort.c b/lib/libc/stdlib/abort.c
index e56e7e9..4fd34dc 100644
--- a/lib/libc/stdlib/abort.c
+++ b/lib/libc/stdlib/abort.c
@@ -35,31 +35,52 @@
static char sccsid[] = "@(#)abort.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
-#include <sys/signal.h>
+#include <signal.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
+
+void (*__cleanup)();
void
abort()
{
sigset_t mask;
+ /*
+ * POSIX requires we flush stdio buffers on abort
+ */
+ if (__cleanup)
+ (*__cleanup)();
+
sigfillset(&mask);
/*
* don't block SIGABRT to give any handler a chance; we ignore
* any errors -- X311J doesn't allow abort to return anyway.
*/
sigdelset(&mask, SIGABRT);
+#ifdef _THREAD_SAFE
+ (void) _thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
+#else
(void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
+#endif
(void)kill(getpid(), SIGABRT);
/*
* if SIGABRT ignored, or caught and the handler returns, do
* it again, only harder.
*/
+#ifdef _THREAD_SAFE
+ (void) _thread_sys_signal(SIGABRT, SIG_DFL);
+ (void) _thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
+#else
(void)signal(SIGABRT, SIG_DFL);
(void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
+#endif
(void)kill(getpid(), SIGABRT);
exit(1);
}
diff --git a/lib/libc/stdlib/abs.3 b/lib/libc/stdlib/abs.3
index e12f798..501263e 100644
--- a/lib/libc/stdlib/abs.3
+++ b/lib/libc/stdlib/abs.3
@@ -34,6 +34,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)abs.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt ABS 3
@@ -59,10 +60,10 @@ function
returns
the absolute value.
.Sh SEE ALSO
+.Xr cabs 3 ,
.Xr floor 3 ,
-.Xr labs 3
-.Xr cabs 3
-.Xr hypot 3
+.Xr hypot 3 ,
+.Xr labs 3 ,
.Xr math 3
.Sh STANDARDS
The
diff --git a/lib/libc/stdlib/alloca.3 b/lib/libc/stdlib/alloca.3
index ad5aaf69..498348c 100644
--- a/lib/libc/stdlib/alloca.3
+++ b/lib/libc/stdlib/alloca.3
@@ -59,10 +59,10 @@ If the allocation failed, a
pointer is returned.
.Sh SEE ALSO
.Xr brk 2 ,
-.Xr pagesize 2
.Xr calloc 3 ,
+.Xr getpagesize 3 ,
.Xr malloc 3 ,
-.Xr realloc 3 ,
+.Xr realloc 3
.Sh BUGS
The
.Fn alloca
diff --git a/lib/libc/stdlib/atexit.c b/lib/libc/stdlib/atexit.c
index bbf374e..a65dae5 100644
--- a/lib/libc/stdlib/atexit.c
+++ b/lib/libc/stdlib/atexit.c
@@ -40,6 +40,7 @@ static char sccsid[] = "@(#)atexit.c 8.2 (Berkeley) 7/3/94";
#include <stddef.h>
#include <stdlib.h>
+#include <unistd.h>
#include "atexit.h"
struct atexit *__atexit; /* points to head of LIFO stack */
@@ -57,7 +58,7 @@ atexit(fn)
if ((p = __atexit) == NULL)
__atexit = p = &__atexit0;
else if (p->ind >= ATEXIT_SIZE) {
- if ((p = malloc(sizeof(*p))) == NULL)
+ if ((p = (struct atexit *)sbrk(sizeof(*p))) == (struct atexit *)-1)
return (-1);
p->ind = 0;
p->next = __atexit;
diff --git a/lib/libc/stdlib/atoi.c b/lib/libc/stdlib/atoi.c
index a13c0e2..48e508a 100644
--- a/lib/libc/stdlib/atoi.c
+++ b/lib/libc/stdlib/atoi.c
@@ -38,6 +38,7 @@ static char sccsid[] = "@(#)atoi.c 8.1 (Berkeley) 6/4/93";
#include <stdlib.h>
#include <stddef.h>
+int
atoi(str)
const char *str;
{
diff --git a/lib/libc/stdlib/bsearch.3 b/lib/libc/stdlib/bsearch.3
index e4cf49f..a4e076e 100644
--- a/lib/libc/stdlib/bsearch.3
+++ b/lib/libc/stdlib/bsearch.3
@@ -81,7 +81,7 @@ 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 qsort 3
.\" .Xr tsearch 3
.Sh STANDARDS
The
diff --git a/lib/libc/stdlib/calloc.c b/lib/libc/stdlib/calloc.c
index d7c8e07..7a83603 100644
--- a/lib/libc/stdlib/calloc.c
+++ b/lib/libc/stdlib/calloc.c
@@ -46,7 +46,7 @@ calloc(num, size)
register void *p;
size *= num;
- if (p = malloc(size))
+ if ( (p = malloc(size)) )
bzero(p, size);
return(p);
}
diff --git a/lib/libc/stdlib/exit.3 b/lib/libc/stdlib/exit.3
index 43ee3c0..de91276 100644
--- a/lib/libc/stdlib/exit.3
+++ b/lib/libc/stdlib/exit.3
@@ -65,6 +65,11 @@ Unlink all files created with the
.Xr tmpfile 3
function.
.El
+.Pp
+Passing arbitrary values back to the environment as
+.Ar status
+is considered bad style. Instead, use the values as described in
+.Xr sysexits 3 .
.Sh RETURN VALUES
The
.Fn exit
@@ -74,6 +79,7 @@ never returns.
.Xr _exit 2 ,
.Xr atexit 3 ,
.Xr intro 3 ,
+.Xr sysexits 3 ,
.Xr tmpfile 3
.Sh STANDARDS
The
diff --git a/lib/libc/stdlib/getenv.c b/lib/libc/stdlib/getenv.c
index 7407e0b..a6bbd35 100644
--- a/lib/libc/stdlib/getenv.c
+++ b/lib/libc/stdlib/getenv.c
@@ -39,20 +39,7 @@ static char sccsid[] = "@(#)getenv.c 8.1 (Berkeley) 6/4/93";
#include <stddef.h>
#include <string.h>
-char *__findenv __P((const char *, int *));
-
-/*
- * getenv --
- * Returns ptr to value associated with name, if any, else NULL.
- */
-char *
-getenv(name)
- const char *name;
-{
- int offset;
-
- return (__findenv(name, &offset));
-}
+inline char *__findenv __P((const char *, int *));
/*
* __findenv --
@@ -63,25 +50,42 @@ getenv(name)
*
* This routine *should* be a static; don't use it.
*/
-char *
+inline char *
__findenv(name, offset)
register const char *name;
int *offset;
{
extern char **environ;
- register int len;
+ register int len, i;
register const char *np;
- register char **p, *c;
+ register char **p, *cp;
if (name == NULL || environ == NULL)
return (NULL);
for (np = name; *np && *np != '='; ++np)
continue;
len = np - name;
- for (p = environ; (c = *p) != NULL; ++p)
- if (strncmp(c, name, len) == 0 && c[len] == '=') {
+ for (p = environ; (cp = *p) != NULL; ++p) {
+ for (np = name, i = len; i && *cp; i--)
+ if (*cp++ != *np++)
+ break;
+ if (i == 0 && *cp++ == '=') {
*offset = p - environ;
- return (c + len + 1);
+ return (cp);
}
+ }
return (NULL);
}
+
+/*
+ * getenv --
+ * Returns ptr to value associated with name, if any, else NULL.
+ */
+char *
+getenv(name)
+ const char *name;
+{
+ int offset;
+
+ return (__findenv(name, &offset));
+}
diff --git a/lib/libc/stdlib/getopt.3 b/lib/libc/stdlib/getopt.3
index 39cc5de..ad4a4dc 100644
--- a/lib/libc/stdlib/getopt.3
+++ b/lib/libc/stdlib/getopt.3
@@ -121,9 +121,11 @@ The
.Fn getopt
function
returns \-1
-when the argument list is exhausted, or a non-recognized
+when the argument list is exhausted, or
+.Ql ?
+if a non-recognized
option is encountered.
-The interpretation of options in the argument list may be cancelled
+The interpretation of options in the argument list may be canceled
by the option
.Ql --
(double dash) which causes
@@ -139,10 +141,10 @@ If the
function encounters a character not found in the string
.Va optarg
or detects
-a missing option argument it writes an error message and returns
-.Ql ?
-to the
-.Em stderr .
+a missing option argument it writes an error message to the
+.Em stderr
+and returns
+.Ql ? .
Setting
.Va opterr
to a zero will disable these error messages.
@@ -213,7 +215,7 @@ from
.Pp
A single dash
.Dq Li -
-may be specified as an character in
+may be specified as a character in
.Fa optstring ,
however it should
.Em never
diff --git a/lib/libc/stdlib/getsubopt.3 b/lib/libc/stdlib/getsubopt.3
index e1040d7..3f6f547 100644
--- a/lib/libc/stdlib/getsubopt.3
+++ b/lib/libc/stdlib/getsubopt.3
@@ -142,4 +142,5 @@ while ((ch = getopt(argc, argv, "ab:")) != \-1) {
.Sh HISTORY
The
.Fn getsubopt
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/stdlib/getsubopt.c b/lib/libc/stdlib/getsubopt.c
index d0ebde2..bc055b8 100644
--- a/lib/libc/stdlib/getsubopt.c
+++ b/lib/libc/stdlib/getsubopt.c
@@ -46,6 +46,7 @@ static char sccsid[] = "@(#)getsubopt.c 8.1 (Berkeley) 6/4/93";
*/
char *suboptarg;
+int
getsubopt(optionp, tokens, valuep)
register char **optionp, **valuep;
register char * const *tokens;
@@ -80,7 +81,7 @@ getsubopt(optionp, tokens, valuep)
*p = '\0';
for (*valuep = ++p;
*p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
- if (*p)
+ if (*p)
*p++ = '\0';
} else
*p++ = '\0';
diff --git a/lib/libc/stdlib/heapsort.c b/lib/libc/stdlib/heapsort.c
index d800064..9649553 100644
--- a/lib/libc/stdlib/heapsort.c
+++ b/lib/libc/stdlib/heapsort.c
@@ -38,10 +38,9 @@
static char sccsid[] = "@(#)heapsort.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
-#include <sys/types.h>
#include <errno.h>
-#include <stdlib.h>
#include <stddef.h>
+#include <stdlib.h>
/*
* Swap two areas of size number of bytes. Although qsort(3) permits random
diff --git a/lib/libc/stdlib/labs.3 b/lib/libc/stdlib/labs.3
index ef9ba80..2dba8cc 100644
--- a/lib/libc/stdlib/labs.3
+++ b/lib/libc/stdlib/labs.3
@@ -53,8 +53,8 @@ returns the absolute value of the long integer
.Ar j .
.Sh SEE ALSO
.Xr abs 3 ,
-.Xr floor 3 ,
.Xr cabs 3 ,
+.Xr floor 3 ,
.Xr math 3
.Sh STANDARDS
The
diff --git a/lib/libc/stdlib/ldiv.3 b/lib/libc/stdlib/ldiv.3
index a68952f..2b61499 100644
--- a/lib/libc/stdlib/ldiv.3
+++ b/lib/libc/stdlib/ldiv.3
@@ -44,7 +44,7 @@
.Sh SYNOPSIS
.Fd #include <stdlib.h>
.Ft ldiv_t
-.Fn ldiv "int num" "int denom"
+.Fn ldiv "long num" "long denom"
.Sh DESCRIPTION
The
.Fn ldiv
diff --git a/lib/libc/stdlib/malloc.3 b/lib/libc/stdlib/malloc.3
index 98ebadc..ef77e80 100644
--- a/lib/libc/stdlib/malloc.3
+++ b/lib/libc/stdlib/malloc.3
@@ -34,57 +34,390 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)malloc.3 8.1 (Berkeley) 6/4/93
+.\" $Id: malloc.3,v 1.12 1997/06/22 17:54:27 phk Exp $
.\"
-.Dd June 4, 1993
+.Dd August 27, 1996
.Dt MALLOC 3
-.Os BSD 4
+.Os FreeBSD 2
.Sh NAME
-.Nm malloc ,
-.Nd general memory allocation function
+.Nm malloc, calloc, realloc, free
+.Nd general purpose memory allocation functions
.Sh SYNOPSIS
.Fd #include <stdlib.h>
.Ft void *
.Fn malloc "size_t size"
+.Ft void *
+.Fn calloc "size_t number" "size_t size"
+.Ft void *
+.Fn realloc "void *ptr" "size_t size"
+.Ft void
+.Fn free "void *ptr"
+.Ft char *
+.Va malloc_options;
.Sh DESCRIPTION
The
.Fn malloc
-function allocates uninitialized space for an object whose
-size is specified by
-.Fa size .
+function allocates
+.Fa size
+bytes of memory.
+The allocated space is suitably aligned (after possible pointer coercion)
+for storage of any type of object.
+If the space is at least
+.Em pagesize
+bytes in length (see
+.Xr getpagesize (3)),
+the returned memory will be page boundary aligned as well.
+If
+.Fn malloc
+fails, a NULL pointer is returned.
+.Pp
+The
+.Fn calloc
+function allocates space for
+.Fa number
+objects,
+each
+.Fa size
+bytes in length.
+The result is identical to calling
+.Fn malloc
+with an argument of
+.Dq "number * size" ,
+with the exception that the allocated memory is initialized to nul bytes.
+.Pp
The
+.Fn realloc
+function changes the size of the previously allocated memory referenced by
+.Fa ptr
+to
+.Fa size
+bytes.
+The contents of the memory are unchanged up to the lesser of the new and
+old sizes.
+If the new size is larger,
+the value of the newly allocated portion of the memory is undefined.
+If the requested memory cannot be allocated, NULL is returned and
+the memory referenced by
+.Fa ptr
+is valid and unchanged.
+If
+.Fa ptr
+is NULL, the
+.Fn realloc
+function behaves identically to
.Fn malloc
-function maintains multiple lists of free blocks according to size, allocating
-space from the appropriate list.
+for the specified size.
.Pp
-The allocated space is
-suitably aligned (after possible pointer
-coercion) for storage of any type of object. If the space is of
-.Em pagesize
-or larger, the memory returned will be page-aligned.
+The
+.Fn free
+function causes the allocated memory referenced by
+.Fa ptr
+to be made available for future allocations.
+If
+.Fa ptr
+is NULL, no action occurs.
+.Sh TUNING
+Once, when the first call is made to one of these memory allocation
+routines, various flags will be set or reset, which affect the
+workings of this allocation implementation.
+.Pp
+The ``name'' of the file referenced by the symbolic link named
+.Pa /etc/malloc.conf ,
+the value of the environment variable
+.Ev MALLOC_OPTIONS ,
+and the string pointed to by the global variable
+.Va malloc_options
+will be interpreted, in that order, character by character as flags.
+.Pp
+Most flags are single letters,
+where uppercase indicates that the behavior is set, or on,
+and lowercase means that the behavior is not set, or off.
+.Bl -tag -width indent
+.It A
+All warnings (except for the warning about unknown
+flags being set), and failure to allocate memory become fatal.
+The process will call
+.Fn abort 3
+in these cases.
+.It J
+Each byte of new memory allocated by
+.Fn malloc
+or
+.Fn realloc
+as well as all memory returned by
+.Fn free
+or
+.Fn realloc
+will be initialized to 0xd0.
+This options also sets the
+.Dq R
+option.
+This is intended for debugging and will impact performance negatively.
+.It H
+Pass a hint to the kernel about pages unused by the allocation functions.
+This may help performance if the system is paging excessively.
+.It R
+Cause the
+.Fn realloc
+function to always reallocate memory even if the initial allocation was
+sufficiently large.
+This can substantially aid in compacting memory.
+.It U
+Generate
+.Dq utrace
+entries for
+.Xr ktrace 1 ,
+for all operations.
+Consult the source for details on this option.
+.It V
+Attempting to allocate zero bytes will return a NULL pointer instead of
+a valid pointer.
+(The default behavior is to make a minimal allocation and return a
+pointer to it.)
+This option is provided for System V compatibility.
+This option is incompatible with the
+.Dq X
+option.
+.It X
+Rather than return failure for any allocation function,
+display a diagnostic message on stderr and cause the program to drop
+core (using
+.Fn abort 3 ).
+This option should be set at compile time by including the following in
+the source code:
+.Bd -literal -offset indent
+extern char *malloc_options;
+malloc_options = "X";
+.Ed
+.It Z
+This option implicitly sets the
+.Dq J
+and
+.Dq R
+options, and then zeros out the bytes that were requested.
+This is intended for debugging and will impact performance negatively.
+.It <
+Reduce the size of the cache by a factor of two.
+The default cache size is 16 pages.
+This option can be specified multiple times.
+.It >
+Double the size of the cache by a factor of two.
+The default cache size is 16 pages.
+This option can be specified multiple times.
+.El
+.Pp
+The
+.Dq J
+and
+.Dq Z
+options are intended for testing and debugging.
+An application which changes its behavior when these options are used
+is flawed.
+.Sh EXAMPLES
+To set a systemwide reduction of cache size, and to dump core whenever
+a problem occurs:
+.Pp
+.Bd -literal -offset indent
+ln -s 'A<' /etc/malloc.conf
+.Ed
+.Pp
+To specify in the source that a program does no return value checking
+on calls to these functions:
+.Bd -literal -offset indent
+extern char *malloc_options;
+malloc_options = "X";
+.Ed
+.Sh ENVIRONMENT
+The following environment variables affect the execution of the allocation
+functions:
+.Bl -tag -width MMM
+.It Ev MALLOC_OPTIONS
+If the environmental variable
+.Ev MALLOC_OPTIONS
+is set, the characters it contains will be interpreted as flags to the
+allocation functions.
.Sh RETURN VALUES
The
.Fn malloc
-function returns
-a pointer to the allocated space if successful; otherwise
-a null pointer is returned.
+and
+.Fn calloc
+functions return a pointer to the allocated memory if successful; otherwise
+a NULL pointer is returned.
+.Pp
+The
+.Fn realloc
+function returns a pointer, possibly identical to
+.Fa ptr ,
+to the allocated memory
+if successful; otherwise a NULL pointer is returned, in which case the
+memory referenced by
+.Fa ptr
+is still available and intact.
+.Pp
+The
+.Fn free
+function returns no value.
+.Sh "DEBUGGING MALLOC PROBLEMS"
+.Pp
+The major difference between this implementation and other allocation
+implementations is that the free pages are not accessed unless allocated,
+and are aggressively returned to the kernel for reuse.
+.Bd -filled -offset indent
+Most allocation implementations will store a data structure containing a
+linked list in the free chunks of memory,
+used to tie all the free memory together.
+That can be suboptimal,
+as every time the free-list is traversed,
+the otherwise unused, and likely paged out,
+pages are faulted into primary memory.
+On systems which are paging,
+this can result in a factor of five increase in the number of page-faults
+done by a process.
+.Ed
+.Pp
+A side effect of this architecture is that many minor transgressions on
+the interface which would traditionally not be detected are in fact
+detected. As a result, programs that have been running happily for
+years may suddenly start to complain loudly, when linked with this
+allocation implementation.
+.Pp
+The first and most important thing to do is to set the
+.Dq A
+option.
+This option forces a coredump (if possible) at the first sign of trouble,
+rather than the normal policy of trying to continue if at all possible.
+.Pp
+It is probably also a good idea to recompile the program with suitable
+options and symbols for debugger support.
+.Pp
+If the program starts to give unusual results, coredump or generally behave
+differently without emitting any of the messages listed in the next
+section, it is likely because it depends on the storage being filled with
+nul bytes. Try running it with
+.Dq Z
+option set;
+if that improves the situation, this diagnosis has been confirmed.
+If the program still misbehaves,
+the likely problem is accessing memory outside the allocated area,
+more likely after than before the allocated area.
+.Pp
+Alternatively, if the symptoms are not easy to reproduce, setting the
+.Dq J
+option may help provoke the problem.
+.Pp
+In truly difficult cases, the
+.Dq U
+option, if supported by the kernel, can provide a detailed trace of
+all calls made to these functions.
+.Pp
+Unfortunately this implementation does not provide much detail about
+the problems it detects, the performance impact for storing such information
+would be prohibitive.
+There are a number of allocation implementations available on the 'Net
+which focus on detecting and pinpointing problems by trading performance
+for extra sanity checks and detailed diagnostics.
+.Sh "DIAGNOSTIC MESSAGES
+If
+.Fn malloc ,
+.Fn calloc ,
+.Fn realloc
+or
+.Fn free
+detect an error or warning condition,
+a message will be printed to file descriptor STDERR_FILENO.
+Errors will result in the process dumping core.
+If the
+.Dq A
+option is set, all warnings are treated as errors.
+.Pp
+The following is a brief description of possible error messages and
+their meanings:
+.Pp
+.Bl -tag -width indent
+.It "(ES): mumble mumble mumble
+The allocation functions were compiled with
+.Dq EXTRA_SANITY
+defined, and an error was found during the additional error checking.
+Consult the source code for further information.
+.It "allocation failed
+If the
+.Dq A
+option is specified it is a fatal error for an allocation function to fail.
+.It "mmap(2) failed, check limits
+This most likely means that the system is dangerously overloaded or that
+the process' limits are incorrectly specified.
+.It "freelist is destroyed
+The internal free-list has been corrupted.
+.El
+.Pp
+.Bl -tag -width indent
+The following is a brief description of possible warning messages and
+their meanings:
+.Pp
+.It "chunk/page is already free
+The process attempted to
+.Fn free
+memory which had already been freed.
+.It "junk pointer ...
+A pointer specified to one of the allocation functions points outside the
+bounds of the memory of which they are aware.
+.It "malloc() has never been called
+No memory has been allocated,
+yet something is being freed or
+realloc'ed.
+.It "modified (chunk-/page-) pointer
+The pointer passed to
+.Fn free
+or
+.Fn realloc
+has been modified.
+.It "pointer to wrong page
+The pointer that
+.Fn malloc
+or
+.Fn calloc
+is trying to free does not reference a possible page.
+.It "recursive call
+A process has attempted to call an allocation function recursively.
+This is not permitted. In particular, signal handlers should not
+attempt to allocate memory.
+.It "out of memory
+The
+.Dq X
+option was specified and an allocation of memory failed.
+.It "unknown char in MALLOC_OPTIONS
+An unknown option was specified.
+Even with the
+.Dq A
+option set, this warning is still only a warning.
.Sh SEE ALSO
.Xr brk 2 ,
-.Xr pagesize 2 ,
-.Xr free 3 ,
-.Xr calloc 3 ,
.Xr alloca 3 ,
-.Xr realloc 3 ,
+.Xr getpagesize 3 ,
.Xr memory 3
+.Pa /usr/share/doc/papers/malloc.ascii.gz
.Sh STANDARDS
The
-.Fn malloc
-function conforms to
+.Fn malloc ,
+.Fn calloc ,
+.Fn realloc
+and
+.Fn free
+functions conform to
.St -ansiC .
.Sh BUGS
-The current implementation of
-.Xr malloc
-does not always fail gracefully when system
-memory limits are approached.
-It may fail to allocate memory when larger free blocks could be broken
-up, or when limits are exceeded because the size is rounded up.
-It is optimized for sizes that are powers of two.
+The messages printed in case of problems provide no detail about the
+actual values.
+.Pp
+It can be argued that returning a null pointer when asked to
+allocate zero bytes is a silly response to a silly question.
+.Pp
+This implementation was authored by Poul-Henning Kamp.
+Please report any problems to him at
+.Li <phk@FreeBSD.org> .
+.Sh HISTORY
+The present allocation implementation started out as a filesystem for a
+drum attached to a 20bit binary challenged computer which was built
+with discrete germanium transistors. It has since graduated to
+handle primary storage rather than secondary.
+It first appeared in its new shape and ability in FreeBSD release 2.2.
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index ea8f092..88bd04b 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -1,420 +1,1126 @@
/*
- * Copyright (c) 1983, 1993
- * The Regents of the University of California. All rights reserved.
+ * ----------------------------------------------------------------------------
+ * "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
+ * ----------------------------------------------------------------------------
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must 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.
+ * $Id: malloc.c,v 1.27 1997/07/01 18:39:38 phk Exp $
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)malloc.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
+/*
+ * Defining EXTRA_SANITY will enable extra checks which are related
+ * to internal conditions and consistency in malloc.c. This has a
+ * noticeable runtime performance hit, and generally will not do you
+ * any good unless you fiddle with the internals of malloc or want
+ * to catch random pointer corruption as early as possible.
+ */
+#ifndef MALLOC_EXTRA_SANITY
+#undef MALLOC_EXTRA_SANITY
+#endif
+
+/*
+ * What to use for Junk. This is the byte value we use to fill with
+ * when the 'J' option is enabled.
+ */
+#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
/*
- * malloc.c (Caltech) 2/21/82
- * Chris Kingsley, kingsley@cit-20.
+ * The basic parameters you can tweak.
+ *
+ * malloc_pageshift pagesize = 1 << malloc_pageshift
+ * It's probably best if this is the native
+ * page size, but it doesn't have to be.
+ *
+ * malloc_minsize minimum size of an allocation in bytes.
+ * If this is too small it's too much work
+ * to manage them. This is also the smallest
+ * unit of alignment used for the storage
+ * returned by malloc/realloc.
*
- * This is a very fast storage allocator. It allocates blocks of a small
- * number of different sizes, and keeps free lists of each size. Blocks that
- * don't exactly fit are passed up to the next larger size. In this
- * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long.
- * This is designed for use in a virtual memory environment.
*/
+#if defined(__FreeBSD__)
+# if defined(__i386__)
+# define malloc_pageshift 12U
+# define malloc_minsize 16U
+# endif
+# define HAS_UTRACE
+# if defined(_THREAD_SAFE)
+# include <pthread.h>
+# include "pthread_private.h"
+# define THREAD_LOCK() pthread_mutex_lock(&malloc_lock)
+# define THREAD_UNLOCK() pthread_mutex_unlock(&malloc_lock)
+ static struct pthread_mutex _malloc_lock = PTHREAD_MUTEX_INITIALIZER;
+ static pthread_mutex_t malloc_lock = &_malloc_lock;
+# endif
+#endif /* __FreeBSD__ */
+
+#if defined(__sparc__) && defined(sun)
+# define malloc_pageshirt 12U
+# define malloc_minsize 16U
+# define MAP_ANON (0)
+ static int fdzero;
+# define MMAP_FD fdzero
+# define INIT_MMAP() \
+ { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
+ wrterror("open of /dev/zero"); }
+# define MADV_FREE MADV_DONTNEED
+#endif /* __sparc__ */
+
+/* Insert your combination here... */
+#if defined(__FOOCPU__) && defined(__BAROS__)
+# define malloc_pageshift 12U
+# define malloc_minsize 16U
+#endif /* __FOOCPU__ && __BAROS__ */
+
+
+/*
+ * No user serviceable parts behind this point.
+ */
#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#define NULL 0
+/*
+ * This structure describes a page worth of chunks.
+ */
-static void morecore();
-static int findbucket();
+struct pginfo {
+ struct pginfo *next; /* next on the free list */
+ void *page; /* Pointer to the page */
+ u_short size; /* size of this page's chunks */
+ u_short shift; /* How far to shift for this size chunks */
+ u_short free; /* How many free chunks */
+ u_short total; /* How many chunk */
+ u_int bits[1]; /* Which chunks are free */
+};
/*
- * The overhead on a block is at least 4 bytes. When free, this space
- * contains a pointer to the next free block, and the bottom two bits must
- * be zero. When in use, the first byte is set to MAGIC, and the second
- * byte is the size index. The remaining bytes are for alignment.
- * If range checking is enabled then a second word holds the size of the
- * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
- * The order of elements is critical: ov_magic must overlay the low order
- * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
+ * This structure describes a number of free pages.
*/
-union overhead {
- union overhead *ov_next; /* when free */
- struct {
- u_char ovu_magic; /* magic number */
- u_char ovu_index; /* bucket # */
-#ifdef RCHECK
- u_short ovu_rmagic; /* range magic number */
- u_int ovu_size; /* actual block size */
-#endif
- } ovu;
-#define ov_magic ovu.ovu_magic
-#define ov_index ovu.ovu_index
-#define ov_rmagic ovu.ovu_rmagic
-#define ov_size ovu.ovu_size
+
+struct pgfree {
+ struct pgfree *next; /* next run of free pages */
+ struct pgfree *prev; /* prev run of free pages */
+ void *page; /* pointer to free pages */
+ void *end; /* pointer to end of free pages */
+ size_t size; /* number of bytes free */
};
-#define MAGIC 0xef /* magic # on accounting info */
-#define RMAGIC 0x5555 /* magic # on range info */
+/*
+ * How many bits per u_int in the bitmap.
+ * Change only if not 8 bits/byte
+ */
+#define MALLOC_BITS (8*sizeof(u_int))
+
+/*
+ * Magic values to put in the page_directory
+ */
+#define MALLOC_NOT_MINE ((struct pginfo*) 0)
+#define MALLOC_FREE ((struct pginfo*) 1)
+#define MALLOC_FIRST ((struct pginfo*) 2)
+#define MALLOC_FOLLOW ((struct pginfo*) 3)
+#define MALLOC_MAGIC ((struct pginfo*) 4)
+
+#ifndef malloc_pageshift
+#define malloc_pageshift 12U
+#endif
+
+#ifndef malloc_minsize
+#define malloc_minsize 16U
+#endif
+
+#if !defined(malloc_pagesize)
+#define malloc_pagesize (1U<<malloc_pageshift)
+#endif
+
+#if ((1<<malloc_pageshift) != malloc_pagesize)
+#error "(1<<malloc_pageshift) != malloc_pagesize"
+#endif
+
+#ifndef malloc_maxsize
+#define malloc_maxsize ((malloc_pagesize)>>1)
+#endif
+
+/* A mask for the offset inside a page. */
+#define malloc_pagemask ((malloc_pagesize)-1)
+
+#define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask)))
+#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo)
-#ifdef RCHECK
-#define RSLOP sizeof (u_short)
-#else
-#define RSLOP 0
+#ifndef THREAD_LOCK
+#define THREAD_LOCK()
#endif
+#ifndef THREAD_UNLOCK
+#define THREAD_UNLOCK()
+#endif
+
+#ifndef MMAP_FD
+#define MMAP_FD (-1)
+#endif
+
+#ifndef INIT_MMAP
+#define INIT_MMAP()
+#endif
+
+/* Set when initialization has been done */
+static unsigned malloc_started;
+
+/* Recusion flag for public interface. */
+static int malloc_active;
+
+/* Number of free pages we cache */
+static unsigned malloc_cache = 16;
+
+/* The offset from pagenumber to index into the page directory */
+static u_long malloc_origo;
+
+/* The last index in the page directory we care about */
+static u_long last_index;
+
+/* Pointer to page directory. Allocated "as if with" malloc */
+static struct pginfo **page_dir;
+
+/* How many slots in the page directory */
+static unsigned malloc_ninfo;
+
+/* Free pages line up here */
+static struct pgfree free_list;
+
+/* Abort(), user doesn't handle problems. */
+static int malloc_abort;
+
+/* Are we trying to die ? */
+static int suicide;
+
+/* always realloc ? */
+static int malloc_realloc;
+
+/* pass the kernel a hint on free pages ? */
+static int malloc_hint;
+
+/* xmalloc behaviour ? */
+static int malloc_xmalloc;
+
+/* sysv behaviour for malloc(0) ? */
+static int malloc_sysv;
+
+/* zero fill ? */
+static int malloc_zero;
+
+/* junk fill ? */
+static int malloc_junk;
+
+#ifdef HAS_UTRACE
+
+/* utrace ? */
+static int malloc_utrace;
+
+struct ut { void *p; size_t s; void *r; };
+
+void utrace __P((struct ut *, int));
+
+#define UTRACE(a, b, c) \
+ if (malloc_utrace) \
+ {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
+#else /* !HAS_UTRACE */
+#define UTRACE(a,b,c)
+#endif /* HAS_UTRACE */
+
+/* my last break. */
+static void *malloc_brk;
+
+/* one location cache for free-list holders */
+static struct pgfree *px;
+
+/* compile-time options */
+char *malloc_options;
+
+/* Name of the current public function */
+static char *malloc_func;
+
+/* Macro for mmap */
+#define MMAP(size) \
+ mmap((caddr_t)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
+ MMAP_FD, 0);
+
/*
- * nextf[i] is the pointer to the next free block of size 2^(i+3). The
- * smallest allocatable block is 8 bytes. The overhead information
- * precedes the data area returned to the user.
+ * Necessary function declarations
*/
-#define NBUCKETS 30
-static union overhead *nextf[NBUCKETS];
-extern char *sbrk();
+static int extend_pgdir(u_long index);
+static void *imalloc(size_t size);
+static void ifree(void *ptr);
+static void *irealloc(void *ptr, size_t size);
+
+extern char *__progname;
+
+static void
+wrterror(char *p)
+{
+ char *q = " error: ";
+ write(STDERR_FILENO, __progname, strlen(__progname));
+ write(STDERR_FILENO, malloc_func, strlen(malloc_func));
+ write(STDERR_FILENO, q, strlen(q));
+ write(STDERR_FILENO, p, strlen(p));
+ suicide = 1;
+ abort();
+}
+
+static void
+wrtwarning(char *p)
+{
+ char *q = " warning: ";
+ if (malloc_abort)
+ wrterror(p);
+ write(STDERR_FILENO, __progname, strlen(__progname));
+ write(STDERR_FILENO, malloc_func, strlen(malloc_func));
+ write(STDERR_FILENO, q, strlen(q));
+ write(STDERR_FILENO, p, strlen(p));
+}
-static int pagesz; /* page size */
-static int pagebucket; /* page size bucket */
-#ifdef MSTATS
/*
- * nmalloc[i] is the difference between the number of mallocs and frees
- * for a given block size.
+ * Allocate a number of pages from the OS
*/
-static u_int nmalloc[NBUCKETS];
-#include <stdio.h>
-#endif
+static caddr_t
+map_pages(int pages)
+{
+ caddr_t result, tail;
-#if defined(DEBUG) || defined(RCHECK)
-#define ASSERT(p) if (!(p)) botch("p")
-#include <stdio.h>
-static
-botch(s)
- char *s;
+ result = (caddr_t)pageround((u_long)sbrk(0));
+ tail = result + (pages << malloc_pageshift);
+
+ if (brk(tail)) {
+#ifdef EXTRA_SANITY
+ wrterror("(ES): map_pages fails\n");
+#endif /* EXTRA_SANITY */
+ return 0;
+ }
+
+ last_index = ptr2index(tail) - 1;
+ malloc_brk = tail;
+
+ if ((last_index+1) >= malloc_ninfo && !extend_pgdir(last_index))
+ return 0;;
+
+ return result;
+}
+
+/*
+ * Extend page directory
+ */
+static int
+extend_pgdir(u_long index)
{
- fprintf(stderr, "\r\nassertion botched: %s\r\n", s);
- (void) fflush(stderr); /* just in case user buffered it */
- abort();
+ struct pginfo **new, **old;
+ int i, oldlen;
+
+ /* Make it this many pages */
+ i = index * sizeof *page_dir;
+ i /= malloc_pagesize;
+ i += 2;
+
+ /* remember the old mapping size */
+ oldlen = malloc_ninfo * sizeof *page_dir;
+
+ /*
+ * NOTE: we allocate new pages and copy the directory rather than tempt
+ * fate by trying to "grow" the region.. There is nothing to prevent
+ * us from accidently re-mapping space that's been allocated by our caller
+ * via dlopen() or other mmap().
+ *
+ * The copy problem is not too bad, as there is 4K of page index per
+ * 4MB of malloc arena.
+ *
+ * We can totally avoid the copy if we open a file descriptor to associate
+ * the anon mappings with. Then, when we remap the pages at the new
+ * address, the old pages will be "magically" remapped.. But this means
+ * keeping open a "secret" file descriptor.....
+ */
+
+ /* Get new pages */
+ new = (struct pginfo**) MMAP(i * malloc_pagesize);
+ if (new == (struct pginfo **)-1)
+ return 0;
+
+ /* Copy the old stuff */
+ memcpy(new, page_dir,
+ malloc_ninfo * sizeof *page_dir);
+
+ /* register the new size */
+ malloc_ninfo = i * malloc_pagesize / sizeof *page_dir;
+
+ /* swap the pointers */
+ old = page_dir;
+ page_dir = new;
+
+ /* Now free the old stuff */
+ munmap((caddr_t)old, oldlen);
+ return 1;
}
-#else
-#define ASSERT(p)
-#endif
-void *
-malloc(nbytes)
- size_t nbytes;
+/*
+ * Initialize the world
+ */
+static void
+malloc_init ()
{
- register union overhead *op;
- register int bucket, n;
- register unsigned amt;
+ char *p, b[64];
+ int i, j;
- /*
- * First time malloc is called, setup page size and
- * align break pointer so all data will be page aligned.
- */
- if (pagesz == 0) {
- pagesz = n = getpagesize();
- op = (union overhead *)sbrk(0);
- n = n - sizeof (*op) - ((int)op & (n - 1));
- if (n < 0)
- n += pagesz;
- if (n) {
- if (sbrk(n) == (char *)-1)
- return (NULL);
- }
- bucket = 0;
- amt = 8;
- while (pagesz > amt) {
- amt <<= 1;
- bucket++;
- }
- pagebucket = bucket;
+ INIT_MMAP();
+
+#ifdef EXTRA_SANITY
+ malloc_junk = 1;
+#endif /* EXTRA_SANITY */
+
+ for (i = 0; i < 3; i++) {
+ if (i == 0) {
+ j = readlink("/etc/malloc.conf", b, sizeof b - 1);
+ if (j <= 0)
+ continue;
+ b[j] = '\0';
+ p = b;
+ } else if (i == 1) {
+ p = getenv("MALLOC_OPTIONS");
+ } else {
+ p = malloc_options;
}
- /*
- * Convert amount of memory requested into closest block size
- * stored in hash buckets which satisfies request.
- * Account for space used per block for accounting.
- */
- if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) {
-#ifndef RCHECK
- amt = 8; /* size of first bucket */
- bucket = 0;
-#else
- amt = 16; /* size of first bucket */
- bucket = 1;
+ for (; p && *p; p++) {
+ switch (*p) {
+ case '>': malloc_cache <<= 1; break;
+ case '<': malloc_cache >>= 1; break;
+ case 'a': malloc_abort = 0; break;
+ case 'A': malloc_abort = 1; break;
+ case 'h': malloc_hint = 0; break;
+ case 'H': malloc_hint = 1; break;
+ case 'r': malloc_realloc = 0; break;
+ case 'R': malloc_realloc = 1; break;
+ case 'j': malloc_junk = 0; break;
+ case 'J': malloc_junk = 1; break;
+#ifdef HAS_UTRACE
+ case 'u': malloc_utrace = 0; break;
+ case 'U': malloc_utrace = 1; break;
#endif
- n = -(sizeof (*op) + RSLOP);
- } else {
- amt = pagesz;
- bucket = pagebucket;
+ case 'v': malloc_sysv = 0; break;
+ case 'V': malloc_sysv = 1; break;
+ case 'x': malloc_xmalloc = 0; break;
+ case 'X': malloc_xmalloc = 1; break;
+ case 'z': malloc_zero = 0; break;
+ case 'Z': malloc_zero = 1; break;
+ default:
+ j = malloc_abort;
+ malloc_abort = 0;
+ wrtwarning("unknown char in MALLOC_OPTIONS\n");
+ malloc_abort = j;
+ break;
+ }
}
- while (nbytes > amt + n) {
- amt <<= 1;
- if (amt == 0)
- return (NULL);
- bucket++;
+ }
+
+ UTRACE(0, 0, 0);
+
+ /*
+ * We want junk in the entire allocation, and zero only in the part
+ * the user asked for.
+ */
+ if (malloc_zero)
+ malloc_junk=1;
+
+ /*
+ * If we run with junk (or implicitly from above: zero), we want to
+ * force realloc() to get new storage, so we can DTRT with it.
+ */
+ if (malloc_junk)
+ malloc_realloc=1;
+
+ /* Allocate one page for the page directory */
+ page_dir = (struct pginfo **) MMAP(malloc_pagesize);
+
+ if (page_dir == (struct pginfo **) -1)
+ wrterror("mmap(2) failed, check limits.\n");
+
+ /*
+ * We need a maximum of malloc_pageshift buckets, steal these from the
+ * front of the page_directory;
+ */
+ malloc_origo = ((u_long)pageround((u_long)sbrk(0))) >> malloc_pageshift;
+ malloc_origo -= malloc_pageshift;
+
+ malloc_ninfo = malloc_pagesize / sizeof *page_dir;
+
+ /* Recalculate the cache size in bytes, and make sure it's nonzero */
+
+ if (!malloc_cache)
+ malloc_cache++;
+
+ malloc_cache <<= malloc_pageshift;
+
+ /*
+ * This is a nice hack from Kaleb Keithly (kaleb@x.org).
+ * We can sbrk(2) further back when we keep this on a low address.
+ */
+ px = (struct pgfree *) imalloc (sizeof *px);
+
+ /* Been here, done that */
+ malloc_started++;
+}
+
+/*
+ * Allocate a number of complete pages
+ */
+static void *
+malloc_pages(size_t size)
+{
+ void *p, *delay_free = 0;
+ int i;
+ struct pgfree *pf;
+ u_long index;
+
+ size = pageround(size);
+
+ p = 0;
+
+ /* Look for free pages before asking for more */
+ for(pf = free_list.next; pf; pf = pf->next) {
+
+#ifdef EXTRA_SANITY
+ if (pf->size & malloc_pagemask)
+ wrterror("(ES): junk length entry on free_list\n");
+ if (!pf->size)
+ wrterror("(ES): zero length entry on free_list\n");
+ if (pf->page == pf->end)
+ wrterror("(ES): zero entry on free_list\n");
+ if (pf->page > pf->end)
+ wrterror("(ES): sick entry on free_list\n");
+ if ((void*)pf->page >= (void*)sbrk(0))
+ wrterror("(ES): entry on free_list past brk\n");
+ if (page_dir[ptr2index(pf->page)] != MALLOC_FREE)
+ wrterror("(ES): non-free first page on free-list\n");
+ if (page_dir[ptr2index(pf->end)-1] != MALLOC_FREE)
+ wrterror("(ES): non-free last page on free-list\n");
+#endif /* EXTRA_SANITY */
+
+ if (pf->size < size)
+ continue;
+
+ if (pf->size == size) {
+ p = pf->page;
+ if (pf->next)
+ pf->next->prev = pf->prev;
+ pf->prev->next = pf->next;
+ delay_free = pf;
+ break;
+ }
+
+ p = pf->page;
+ pf->page = (char *)pf->page + size;
+ pf->size -= size;
+ break;
+ }
+
+#ifdef EXTRA_SANITY
+ if (p && page_dir[ptr2index(p)] != MALLOC_FREE)
+ wrterror("(ES): allocated non-free page on free-list\n");
+#endif /* EXTRA_SANITY */
+
+ size >>= malloc_pageshift;
+
+ /* Map new pages */
+ if (!p)
+ p = map_pages(size);
+
+ if (p) {
+
+ index = ptr2index(p);
+ page_dir[index] = MALLOC_FIRST;
+ for (i=1;i<size;i++)
+ page_dir[index+i] = MALLOC_FOLLOW;
+
+ if (malloc_junk)
+ memset(p, SOME_JUNK, size << malloc_pageshift);
+ }
+
+ if (delay_free) {
+ if (!px)
+ px = delay_free;
+ else
+ ifree(delay_free);
+ }
+
+ return p;
+}
+
+/*
+ * Allocate a page of fragments
+ */
+
+static __inline__ int
+malloc_make_chunks(int bits)
+{
+ struct pginfo *bp;
+ void *pp;
+ int i, k, l;
+
+ /* Allocate a new bucket */
+ pp = malloc_pages(malloc_pagesize);
+ if (!pp)
+ return 0;
+
+ /* Find length of admin structure */
+ l = sizeof *bp - sizeof(u_long);
+ l += sizeof(u_long) *
+ (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);
+
+ /* Don't waste more than two chunks on this */
+ if ((1<<(bits)) <= l+l) {
+ bp = (struct pginfo *)pp;
+ } else {
+ bp = (struct pginfo *)imalloc(l);
+ if (!bp) {
+ ifree(pp);
+ return 0;
}
- /*
- * If nothing in hash bucket right now,
- * request more memory from the system.
- */
- if ((op = nextf[bucket]) == NULL) {
- morecore(bucket);
- if ((op = nextf[bucket]) == NULL)
- return (NULL);
+ }
+
+ bp->size = (1<<bits);
+ bp->shift = bits;
+ bp->total = bp->free = malloc_pagesize >> bits;
+ bp->page = pp;
+
+ /* set all valid bits in the bitmap */
+ k = bp->total;
+ i = 0;
+
+ /* Do a bunch at a time */
+ for(;k-i >= MALLOC_BITS; i += MALLOC_BITS)
+ bp->bits[i / MALLOC_BITS] = ~0;
+
+ for(; i < k; i++)
+ bp->bits[i/MALLOC_BITS] |= 1<<(i%MALLOC_BITS);
+
+ if (bp == bp->page) {
+ /* Mark the ones we stole for ourselves */
+ for(i=0;l > 0;i++) {
+ bp->bits[i/MALLOC_BITS] &= ~(1<<(i%MALLOC_BITS));
+ bp->free--;
+ bp->total--;
+ l -= (1 << bits);
}
- /* remove from linked list */
- nextf[bucket] = op->ov_next;
- op->ov_magic = MAGIC;
- op->ov_index = bucket;
-#ifdef MSTATS
- nmalloc[bucket]++;
-#endif
-#ifdef RCHECK
- /*
- * Record allocated size of block and
- * bound space with magic numbers.
- */
- op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
- op->ov_rmagic = RMAGIC;
- *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
-#endif
- return ((char *)(op + 1));
+ }
+
+ /* MALLOC_LOCK */
+
+ page_dir[ptr2index(pp)] = bp;
+
+ bp->next = page_dir[bits];
+ page_dir[bits] = bp;
+
+ /* MALLOC_UNLOCK */
+
+ return 1;
}
/*
- * Allocate more memory to the indicated bucket.
+ * Allocate a fragment
*/
-static void
-morecore(bucket)
- int bucket;
+static void *
+malloc_bytes(size_t size)
{
- register union overhead *op;
- register int sz; /* size of desired block */
- int amt; /* amount to allocate */
- int nblks; /* how many blocks we get */
+ int i,j;
+ u_int u;
+ struct pginfo *bp;
+ int k;
+ u_int *lp;
- /*
- * sbrk_size <= 0 only for big, FLUFFY, requests (about
- * 2^30 bytes on a VAX, I think) or for a negative arg.
- */
- sz = 1 << (bucket + 3);
-#ifdef DEBUG
- ASSERT(sz > 0);
-#else
- if (sz <= 0)
- return;
-#endif
- if (sz < pagesz) {
- amt = pagesz;
- nblks = amt / sz;
- } else {
- amt = sz + pagesz;
- nblks = 1;
- }
- op = (union overhead *)sbrk(amt);
- /* no more room! */
- if ((int)op == -1)
- return;
- /*
- * Add new memory allocated to that on
- * free list for this hash bucket.
- */
- nextf[bucket] = op;
- while (--nblks > 0) {
- op->ov_next = (union overhead *)((caddr_t)op + sz);
- op = (union overhead *)((caddr_t)op + sz);
- }
+ /* Don't bother with anything less than this */
+ if (size < malloc_minsize)
+ size = malloc_minsize;
+
+ /* Find the right bucket */
+ j = 1;
+ i = size-1;
+ while (i >>= 1)
+ j++;
+
+ /* If it's empty, make a page more of that size chunks */
+ if (!page_dir[j] && !malloc_make_chunks(j))
+ return 0;
+
+ bp = page_dir[j];
+
+ /* Find first word of bitmap which isn't empty */
+ for (lp = bp->bits; !*lp; lp++)
+ ;
+
+ /* Find that bit, and tweak it */
+ u = 1;
+ k = 0;
+ while (!(*lp & u)) {
+ u += u;
+ k++;
+ }
+ *lp ^= u;
+
+ /* If there are no more free, remove from free-list */
+ if (!--bp->free) {
+ page_dir[j] = bp->next;
+ bp->next = 0;
+ }
+
+ /* Adjust to the real offset of that chunk */
+ k += (lp-bp->bits)*MALLOC_BITS;
+ k <<= bp->shift;
+
+ if (malloc_junk)
+ memset((u_char*)bp->page + k, SOME_JUNK, bp->size);
+
+ return (u_char *)bp->page + k;
}
-void
-free(cp)
- void *cp;
-{
- register int size;
- register union overhead *op;
-
- if (cp == NULL)
- return;
- op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
-#ifdef DEBUG
- ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */
-#else
- if (op->ov_magic != MAGIC)
- return; /* sanity */
-#endif
-#ifdef RCHECK
- ASSERT(op->ov_rmagic == RMAGIC);
- ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC);
-#endif
- size = op->ov_index;
- ASSERT(size < NBUCKETS);
- op->ov_next = nextf[size]; /* also clobbers ov_magic */
- nextf[size] = op;
-#ifdef MSTATS
- nmalloc[size]--;
-#endif
+/*
+ * Allocate a piece of memory
+ */
+static void *
+imalloc(size_t size)
+{
+ void *result;
+
+ if (suicide)
+ abort();
+
+ if ((size + malloc_pagesize) < size) /* Check for overflow */
+ result = 0;
+ else if (size <= malloc_maxsize)
+ result = malloc_bytes(size);
+ else
+ result = malloc_pages(size);
+
+ if (malloc_abort && !result)
+ wrterror("allocation failed.\n");
+
+ if (malloc_zero && result)
+ memset(result, 0, size);
+
+ return result;
}
/*
- * When a program attempts "storage compaction" as mentioned in the
- * old malloc man page, it realloc's an already freed block. Usually
- * this is the last block it freed; occasionally it might be farther
- * back. We have to search all the free lists for the block in order
- * to determine its bucket: 1st we make one pass thru the lists
- * checking only the first block in each; if that fails we search
- * ``__realloc_srchlen'' blocks in each list for a match (the variable
- * is extern so the caller can modify it). If that fails we just copy
- * however many bytes was given to realloc() and hope it's not huge.
+ * Change the size of an allocation.
*/
-int __realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */
+static void *
+irealloc(void *ptr, size_t size)
+{
+ void *p;
+ u_long osize, index;
+ struct pginfo **mp;
+ int i;
-void *
-realloc(cp, nbytes)
- void *cp;
- size_t nbytes;
-{
- register u_int onb;
- register int i;
- union overhead *op;
- char *res;
- int was_alloced = 0;
-
- if (cp == NULL)
- return (malloc(nbytes));
- op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
- if (op->ov_magic == MAGIC) {
- was_alloced++;
- i = op->ov_index;
- } else {
- /*
- * Already free, doing "compaction".
- *
- * Search for the old block of memory on the
- * free list. First, check the most common
- * case (last element free'd), then (this failing)
- * the last ``__realloc_srchlen'' items free'd.
- * If all lookups fail, then assume the size of
- * the memory block being realloc'd is the
- * largest possible (so that all "nbytes" of new
- * memory are copied into). Note that this could cause
- * a memory fault if the old area was tiny, and the moon
- * is gibbous. However, that is very unlikely.
- */
- if ((i = findbucket(op, 1)) < 0 &&
- (i = findbucket(op, __realloc_srchlen)) < 0)
- i = NBUCKETS;
+ if (suicide)
+ abort();
+
+ index = ptr2index(ptr);
+
+ if (index < malloc_pageshift) {
+ wrtwarning("junk pointer, too low to make sense.\n");
+ return 0;
+ }
+
+ if (index > last_index) {
+ wrtwarning("junk pointer, too high to make sense.\n");
+ return 0;
+ }
+
+ mp = &page_dir[index];
+
+ if (*mp == MALLOC_FIRST) { /* Page allocation */
+
+ /* Check the pointer */
+ if ((u_long)ptr & malloc_pagemask) {
+ wrtwarning("modified (page-) pointer.\n");
+ return 0;
}
- onb = 1 << (i + 3);
- if (onb < pagesz)
- onb -= sizeof (*op) + RSLOP;
- else
- onb += pagesz - sizeof (*op) - RSLOP;
- /* avoid the copy if same size block */
- if (was_alloced) {
- if (i) {
- i = 1 << (i + 2);
- if (i < pagesz)
- i -= sizeof (*op) + RSLOP;
- else
- i += pagesz - sizeof (*op) - RSLOP;
- }
- if (nbytes <= onb && nbytes > i) {
-#ifdef RCHECK
- op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
- *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
-#endif
- return(cp);
- } else
- free(cp);
+
+ /* Find the size in bytes */
+ for (osize = malloc_pagesize; *++mp == MALLOC_FOLLOW;)
+ osize += malloc_pagesize;
+
+ if (!malloc_realloc && /* unless we have to, */
+ size <= osize && /* .. or are too small, */
+ size > (osize - malloc_pagesize)) { /* .. or can free a page, */
+ return ptr; /* don't do anything. */
}
- if ((res = malloc(nbytes)) == NULL)
- return (NULL);
- if (cp != res) /* common optimization if "compacting" */
- bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
- return (res);
+
+ } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
+
+ /* Check the pointer for sane values */
+ if (((u_long)ptr & ((*mp)->size-1))) {
+ wrtwarning("modified (chunk-) pointer.\n");
+ return 0;
+ }
+
+ /* Find the chunk index in the page */
+ i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift;
+
+ /* Verify that it isn't a free chunk already */
+ if ((*mp)->bits[i/MALLOC_BITS] & (1<<(i%MALLOC_BITS))) {
+ wrtwarning("chunk is already free.\n");
+ return 0;
+ }
+
+ osize = (*mp)->size;
+
+ if (!malloc_realloc && /* Unless we have to, */
+ size < osize && /* ..or are too small, */
+ (size > osize/2 || /* ..or could use a smaller size, */
+ osize == malloc_minsize)) { /* ..(if there is one) */
+ return ptr; /* ..Don't do anything */
+ }
+
+ } else {
+ wrtwarning("pointer to wrong page.\n");
+ return 0;
+ }
+
+ p = imalloc(size);
+
+ if (p) {
+ /* copy the lesser of the two sizes, and free the old one */
+ if (!size || !osize)
+ ;
+ else if (osize < size)
+ memcpy(p, ptr, osize);
+ else
+ memcpy(p, ptr, size);
+ ifree(ptr);
+ }
+ return p;
}
/*
- * Search ``srchlen'' elements of each free list for a block whose
- * header starts at ``freep''. If srchlen is -1 search the whole list.
- * Return bucket number, or -1 if not found.
+ * Free a sequence of pages
*/
-static
-findbucket(freep, srchlen)
- union overhead *freep;
- int srchlen;
+
+static __inline__ void
+free_pages(void *ptr, int index, struct pginfo *info)
{
- register union overhead *p;
- register int i, j;
-
- for (i = 0; i < NBUCKETS; i++) {
- j = 0;
- for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
- if (p == freep)
- return (i);
- j++;
- }
+ int i;
+ struct pgfree *pf, *pt=0;
+ u_long l;
+ void *tail;
+
+ if (info == MALLOC_FREE) {
+ wrtwarning("page is already free.\n");
+ return;
+ }
+
+ if (info != MALLOC_FIRST) {
+ wrtwarning("pointer to wrong page.\n");
+ return;
+ }
+
+ if ((u_long)ptr & malloc_pagemask) {
+ wrtwarning("modified (page-) pointer.\n");
+ return;
+ }
+
+ /* Count how many pages and mark them free at the same time */
+ page_dir[index] = MALLOC_FREE;
+ for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++)
+ page_dir[index + i] = MALLOC_FREE;
+
+ l = i << malloc_pageshift;
+
+ if (malloc_junk)
+ memset(ptr, SOME_JUNK, l);
+
+ if (malloc_hint)
+ madvise(ptr, l, MADV_FREE);
+
+ tail = (char *)ptr+l;
+
+ /* add to free-list */
+ if (!px)
+ px = imalloc(sizeof *pt); /* This cannot fail... */
+ px->page = ptr;
+ px->end = tail;
+ px->size = l;
+ if (!free_list.next) {
+
+ /* Nothing on free list, put this at head */
+ px->next = free_list.next;
+ px->prev = &free_list;
+ free_list.next = px;
+ pf = px;
+ px = 0;
+
+ } else {
+
+ /* Find the right spot, leave pf pointing to the modified entry. */
+ tail = (char *)ptr+l;
+
+ for(pf = free_list.next; pf->end < ptr && pf->next; pf = pf->next)
+ ; /* Race ahead here */
+
+ if (pf->page > tail) {
+ /* Insert before entry */
+ px->next = pf;
+ px->prev = pf->prev;
+ pf->prev = px;
+ px->prev->next = px;
+ pf = px;
+ px = 0;
+ } else if (pf->end == ptr ) {
+ /* Append to the previous entry */
+ pf->end = (char *)pf->end + l;
+ pf->size += l;
+ if (pf->next && pf->end == pf->next->page ) {
+ /* And collapse the next too. */
+ pt = pf->next;
+ pf->end = pt->end;
+ pf->size += pt->size;
+ pf->next = pt->next;
+ if (pf->next)
+ pf->next->prev = pf;
+ }
+ } else if (pf->page == tail) {
+ /* Prepend to entry */
+ pf->size += l;
+ pf->page = ptr;
+ } else if (!pf->next) {
+ /* Append at tail of chain */
+ px->next = 0;
+ px->prev = pf;
+ pf->next = px;
+ pf = px;
+ px = 0;
+ } else {
+ wrterror("freelist is destroyed.\n");
}
- return (-1);
+ }
+
+ /* Return something to OS ? */
+ if (!pf->next && /* If we're the last one, */
+ pf->size > malloc_cache && /* ..and the cache is full, */
+ pf->end == malloc_brk && /* ..and none behind us, */
+ malloc_brk == sbrk(0)) { /* ..and it's OK to do... */
+
+ /*
+ * Keep the cache intact. Notice that the '>' above guarantees that
+ * the pf will always have at least one page afterwards.
+ */
+ pf->end = (char *)pf->page + malloc_cache;
+ pf->size = malloc_cache;
+
+ brk(pf->end);
+ malloc_brk = pf->end;
+
+ index = ptr2index(pf->end);
+ last_index = index - 1;
+
+ for(i=index;i <= last_index;)
+ page_dir[i++] = MALLOC_NOT_MINE;
+
+ /* XXX: We could realloc/shrink the pagedir here I guess. */
+ }
+ if (pt)
+ ifree(pt);
}
-#ifdef MSTATS
/*
- * mstats - print out statistics about malloc
- *
- * Prints two lines of numbers, one showing the length of the free list
- * for each size category, the second showing the number of mallocs -
- * frees for each size category.
+ * Free a chunk, and possibly the page it's on, if the page becomes empty.
*/
-mstats(s)
- char *s;
+
+static __inline__ void
+free_bytes(void *ptr, int index, struct pginfo *info)
{
- register int i, j;
- register union overhead *p;
- int totfree = 0,
- totused = 0;
-
- fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
- for (i = 0; i < NBUCKETS; i++) {
- for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
- ;
- fprintf(stderr, " %d", j);
- totfree += j * (1 << (i + 3));
- }
- fprintf(stderr, "\nused:\t");
- for (i = 0; i < NBUCKETS; i++) {
- fprintf(stderr, " %d", nmalloc[i]);
- totused += nmalloc[i] * (1 << (i + 3));
- }
- fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
- totused, totfree);
+ int i;
+ struct pginfo **mp;
+ void *vp;
+
+ /* Find the chunk number on the page */
+ i = ((u_long)ptr & malloc_pagemask) >> info->shift;
+
+ if (((u_long)ptr & (info->size-1))) {
+ wrtwarning("modified (chunk-) pointer.\n");
+ return;
+ }
+
+ if (info->bits[i/MALLOC_BITS] & (1<<(i%MALLOC_BITS))) {
+ wrtwarning("chunk is already free.\n");
+ return;
+ }
+
+ if (malloc_junk)
+ memset(ptr, SOME_JUNK, info->size);
+
+ info->bits[i/MALLOC_BITS] |= 1<<(i%MALLOC_BITS);
+ info->free++;
+
+ mp = page_dir + info->shift;
+
+ if (info->free == 1) {
+
+ /* Page became non-full */
+
+ mp = page_dir + info->shift;
+ /* Insert in address order */
+ while (*mp && (*mp)->next && (*mp)->next->page < info->page)
+ mp = &(*mp)->next;
+ info->next = *mp;
+ *mp = info;
+ return;
+ }
+
+ if (info->free != info->total)
+ return;
+
+ /* Find & remove this page in the queue */
+ while (*mp != info) {
+ mp = &((*mp)->next);
+#ifdef EXTRA_SANITY
+ if (!*mp)
+ wrterror("(ES): Not on queue\n");
+#endif /* EXTRA_SANITY */
+ }
+ *mp = info->next;
+
+ /* Free the page & the info structure if need be */
+ page_dir[ptr2index(info->page)] = MALLOC_FIRST;
+ vp = info->page; /* Order is important ! */
+ if(vp != (void*)info)
+ ifree(info);
+ ifree(vp);
}
-#endif
+
+static void
+ifree(void *ptr)
+{
+ struct pginfo *info;
+ int index;
+
+ /* This is legal */
+ if (!ptr)
+ return;
+
+ if (!malloc_started) {
+ wrtwarning("malloc() has never been called.\n");
+ return;
+ }
+
+ /* If we're already sinking, don't make matters any worse. */
+ if (suicide)
+ return;
+
+ index = ptr2index(ptr);
+
+ if (index < malloc_pageshift) {
+ wrtwarning("junk pointer, too low to make sense.\n");
+ return;
+ }
+
+ if (index > last_index) {
+ wrtwarning("junk pointer, too high to make sense.\n");
+ return;
+ }
+
+ info = page_dir[index];
+
+ if (info < MALLOC_MAGIC)
+ free_pages(ptr, index, info);
+ else
+ free_bytes(ptr, index, info);
+ return;
+}
+
+/*
+ * These are the public exported interface routines.
+ */
+
+
+void *
+malloc(size_t size)
+{
+ register void *r;
+
+ malloc_func = " in malloc():";
+ THREAD_LOCK();
+ if (malloc_active++) {
+ wrtwarning("recursive call.\n");
+ malloc_active--;
+ return (0);
+ }
+ if (!malloc_started)
+ malloc_init();
+ if (malloc_sysv && !size)
+ r = 0;
+ else
+ r = imalloc(size);
+ UTRACE(0, size, r);
+ malloc_active--;
+ THREAD_UNLOCK();
+ if (malloc_xmalloc && !r)
+ wrterror("out of memory.\n");
+ return (r);
+}
+
+void
+free(void *ptr)
+{
+ malloc_func = " in free():";
+ THREAD_LOCK();
+ if (malloc_active++) {
+ wrtwarning("recursive call.\n");
+ malloc_active--;
+ return;
+ }
+ ifree(ptr);
+ UTRACE(ptr, 0, 0);
+ malloc_active--;
+ THREAD_UNLOCK();
+ return;
+}
+
+void *
+realloc(void *ptr, size_t size)
+{
+ register void *r;
+
+ malloc_func = " in realloc():";
+ THREAD_LOCK();
+ if (malloc_active++) {
+ wrtwarning("recursive call.\n");
+ malloc_active--;
+ return (0);
+ }
+ if (ptr && !malloc_started) {
+ wrtwarning("malloc() has never been called.\n");
+ ptr = 0;
+ }
+ if (!malloc_started)
+ malloc_init();
+ if (malloc_sysv && !size) {
+ ifree(ptr);
+ r = 0;
+ } else if (!ptr) {
+ r = imalloc(size);
+ } else {
+ r = irealloc(ptr, size);
+ }
+ UTRACE(ptr, size, r);
+ malloc_active--;
+ THREAD_UNLOCK();
+ if (malloc_xmalloc && !r)
+ wrterror("out of memory.\n");
+ return (r);
+}
+
diff --git a/lib/libc/stdlib/memory.3 b/lib/libc/stdlib/memory.3
index 9bc600b..0a1fed4 100644
--- a/lib/libc/stdlib/memory.3
+++ b/lib/libc/stdlib/memory.3
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)memory.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt MEMORY 3
@@ -58,11 +59,11 @@ These functions allocate and free memory for the calling process.
They are described in the
individual manual pages.
.Sh SEE ALSO
+.Xr alloca 3 ,
.Xr calloc 3 ,
.Xr free 3 ,
.Xr malloc 3 ,
-.Xr realloc 3 ,
-.Xr alloca 3 ,
+.Xr realloc 3
.Sh STANDARDS
These functions, with the exception of
.Fn alloca
diff --git a/lib/libc/stdlib/merge.c b/lib/libc/stdlib/merge.c
index 7d00844..a47e300 100644
--- a/lib/libc/stdlib/merge.c
+++ b/lib/libc/stdlib/merge.c
@@ -80,7 +80,7 @@ static void insertionsort __P((u_char *, size_t, size_t, int (*)()));
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
@@ -164,7 +164,7 @@ EXPONENTIAL: for (i = size; ; i <<= 1)
} else if ((*cmp)(q, p) <= sense) {
t = p;
if (i == size)
- big = 0;
+ big = 0;
goto FASTCASE;
} else
b = p;
diff --git a/lib/libc/stdlib/qsort.c b/lib/libc/stdlib/qsort.c
index 1d3aa93..ff3def5 100644
--- a/lib/libc/stdlib/qsort.c
+++ b/lib/libc/stdlib/qsort.c
@@ -32,13 +32,17 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
-#include <sys/types.h>
#include <stdlib.h>
-static inline char *med3 __P((char *, char *, char *, int (*)()));
+typedef int cmp_t __P((const void *, const void *));
+static inline char *med3 __P((char *, char *, char *, cmp_t *));
static inline void swapfunc __P((char *, char *, int, int));
#define min(a, b) (a) < (b) ? a : b
@@ -65,7 +69,7 @@ swapfunc(a, b, n, swaptype)
char *a, *b;
int n, swaptype;
{
- if(swaptype <= 1)
+ if(swaptype <= 1)
swapcode(long, a, b, n)
else
swapcode(char, a, b, n)
@@ -84,7 +88,7 @@ swapfunc(a, b, n, swaptype)
static inline char *
med3(a, b, c, cmp)
char *a, *b, *c;
- int (*cmp)();
+ cmp_t *cmp;
{
return cmp(a, b) < 0 ?
(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
@@ -95,7 +99,7 @@ void
qsort(a, n, es, cmp)
void *a;
size_t n, es;
- int (*cmp)();
+ cmp_t *cmp;
{
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
int d, r, swaptype, swap_cnt;
@@ -103,16 +107,16 @@ qsort(a, n, es, cmp)
loop: SWAPINIT(a, es);
swap_cnt = 0;
if (n < 7) {
- for (pm = a + es; pm < (char *) a + n * es; pm += es)
- for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
- pm = a + (n / 2) * es;
+ pm = (char *)a + (n / 2) * es;
if (n > 7) {
pl = a;
- pn = a + (n - 1) * es;
+ pn = (char *)a + (n - 1) * es;
if (n > 40) {
d = (n / 8) * es;
pl = med3(pl, pl + d, pl + 2 * d, cmp);
@@ -122,9 +126,9 @@ loop: SWAPINIT(a, es);
pm = med3(pl, pm, pn, cmp);
}
swap(a, pm);
- pa = pb = a + es;
+ pa = pb = (char *)a + es;
- pc = pd = a + (n - 1) * es;
+ pc = pd = (char *)a + (n - 1) * es;
for (;;) {
while (pb <= pc && (r = cmp(pb, a)) <= 0) {
if (r == 0) {
@@ -150,21 +154,21 @@ loop: SWAPINIT(a, es);
pc -= es;
}
if (swap_cnt == 0) { /* Switch to insertion sort */
- for (pm = a + es; pm < (char *) a + n * es; pm += es)
- for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
- pn = a + n * es;
+ 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)
qsort(a, r / es, es, cmp);
- if ((r = pd - pc) > es) {
+ if ((r = pd - pc) > es) {
/* Iterate rather than recurse to save stack space */
a = pn - r;
n = r / es;
diff --git a/lib/libc/stdlib/radixsort.3 b/lib/libc/stdlib/radixsort.3
index ce30378..29a1d9d 100644
--- a/lib/libc/stdlib/radixsort.3
+++ b/lib/libc/stdlib/radixsort.3
@@ -41,9 +41,9 @@
.Fd #include <limits.h>
.Fd #include <stdlib.h>
.Ft int
-.Fn radixsort "u_char **base" "int nmemb" "u_char *table" "u_int endbyte"
+.Fn radixsort "const unsigned char **base" "int nmemb" "const unsigned char *table" "unsigned endbyte"
.Ft int
-.Fn sradixsort "u_char **base" "int nmemb" "u_char *table" "u_int endbyte"
+.Fn sradixsort "const unsigned char **base" "int nmemb" "const unsigned char *table" "unsigned endbyte"
.Sh DESCRIPTION
The
.Fn radixsort
@@ -157,4 +157,5 @@ for any of the errors specified for the library routine
.Sh HISTORY
The
.Fn radixsort
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/stdlib/radixsort.c b/lib/libc/stdlib/radixsort.c
index b932bf5..0a583ac 100644
--- a/lib/libc/stdlib/radixsort.c
+++ b/lib/libc/stdlib/radixsort.c
@@ -3,7 +3,7 @@
* 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,
+ * 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
@@ -40,13 +40,13 @@ static char sccsid[] = "@(#)radixsort.c 8.2 (Berkeley) 4/28/95";
/*
* 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".
*/
@@ -294,7 +294,7 @@ r_sort_b(a, ta, n, i, tr, endch)
*--top[tr[(*ak)[i]]] = *ak;
}
}
-
+
static inline void
simplesort(a, n, b, tr, endch) /* insertion sort */
register const u_char **a;
diff --git a/lib/libc/stdlib/random.3 b/lib/libc/stdlib/random.3
index 84680e2..4691498 100644
--- a/lib/libc/stdlib/random.3
+++ b/lib/libc/stdlib/random.3
@@ -37,6 +37,7 @@
.Sh NAME
.Nm random ,
.Nm srandom ,
+.Nm srandomdev ,
.Nm initstate ,
.Nm setstate
.Nd better random number generator; routines for changing generators
@@ -45,9 +46,11 @@
.Ft long
.Fn random void
.Ft void
-.Fn srandom "unsigned seed"
+.Fn srandom "unsigned long seed"
+.Ft void
+.Fn srandomdev void
.Ft char *
-.Fn initstate "unsigned seed" "char *state" "int n"
+.Fn initstate "unsigned long seed" "char *state" "long n"
.Ft char *
.Fn setstate "char *state"
.Sh DESCRIPTION
@@ -64,11 +67,16 @@ The period of this random number generator is very large, approximately
.if n 16*((2**31)\(mi1).
.Pp
The
-.Fn random Ns / Fn srandom
-have (almost) the same calling sequence and initialization properties as
-.Xr rand 3 Ns / Xr srand 3 .
+.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
+.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
@@ -77,15 +85,8 @@ are usable. For example,
will produce a random binary
value.
.Pp
-Unlike
-.Xr srand ,
-.Fn srandom
-does not return the old seed; the reason for this is that the amount of
-state information used is much more than a single word. (Two other
-routines are provided to deal with restarting/changing random
-number generators). Like
+Like
.Xr rand 3 ,
-however,
.Fn random
will by default produce a sequence of numbers that can be duplicated
by calling
@@ -95,6 +96,20 @@ with
as the seed.
.Pp
The
+.Fn srandomdev
+routine initialize a state array using
+.Xr urandom 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
@@ -156,11 +171,19 @@ is called with less than 8 bytes of state information, or if
detects that the state information has been garbled, error
messages are printed on the standard error output.
.Sh SEE ALSO
-.Xr rand 3
+.Xr rand 3 ,
+.Xr srand 3 ,
+.Xr urandom 4
.Sh HISTORY
These
functions appeared in
.Bx 4.2 .
.Sh BUGS
+.Pp
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.
diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c
index 7c76158..4737e40 100644
--- a/lib/libc/stdlib/random.c
+++ b/lib/libc/stdlib/random.c
@@ -29,14 +29,20 @@
* LIABILITY, OR TORT (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: random.c,v 1.9 1997/06/14 00:13:56 ache Exp $
+ *
*/
#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/time.h> /* for srandomdev() */
+#include <fcntl.h> /* for srandomdev() */
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h> /* for srandomdev() */
/*
* random.c:
@@ -61,7 +67,7 @@ static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95";
* 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
@@ -141,7 +147,7 @@ static long 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);
+ * 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
@@ -154,12 +160,23 @@ static long seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
static long 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 */
};
/*
@@ -195,6 +212,38 @@ static long rand_deg = DEG_3;
static long rand_sep = SEP_3;
static long *end_ptr = &randtbl[DEG_3 + 1];
+static inline long good_rand __P((long));
+
+static inline long good_rand (x)
+ register long 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.
+ */
+ register long hi, lo;
+
+ hi = x / 127773;
+ lo = x % 127773;
+ x = 16807 * lo - 2836 * hi;
+ if (x <= 0)
+ x += 0x7fffffff;
+ return (x);
+#endif /* !USE_WEAK_SEEDING */
+}
+
/*
* srandom:
*
@@ -218,7 +267,7 @@ srandom(x)
else {
state[0] = x;
for (i = 1; i < rand_deg; i++)
- state[i] = 1103515245 * state[i - 1] + 12345;
+ state[i] = good_rand(state[i - 1]);
fptr = &state[rand_sep];
rptr = &state[0];
for (i = 0; i < 10 * rand_deg; i++)
@@ -227,6 +276,51 @@ srandom(x)
}
/*
+ * 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 urandom(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/urandom", 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() ^ 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
@@ -234,12 +328,12 @@ srandom(x)
* 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.
*
@@ -378,7 +472,7 @@ random()
if (rand_type == TYPE_0) {
i = state[0];
- state[0] = i = (i * 1103515245 + 12345) & 0x7fffffff;
+ state[0] = i = (good_rand(i)) & 0x7fffffff;
} else {
/*
* Use local variables rather than static variables for speed.
diff --git a/lib/libc/stdlib/realpath.3 b/lib/libc/stdlib/realpath.3
index 83f4a43..1cbbca9 100644
--- a/lib/libc/stdlib/realpath.3
+++ b/lib/libc/stdlib/realpath.3
@@ -34,7 +34,7 @@
.\"
.\" @(#)realpath.3 8.2 (Berkeley) 2/16/94
.\"
-.Dd "February 16, 1994"
+.Dd February 16, 1994
.Dt REALPATH 3
.Os
.Sh NAME
diff --git a/lib/libc/stdlib/realpath.c b/lib/libc/stdlib/realpath.c
index 20efabd..28380d7 100644
--- a/lib/libc/stdlib/realpath.c
+++ b/lib/libc/stdlib/realpath.c
@@ -98,7 +98,7 @@ loop:
p = resolved;
/* Deal with the last component. */
- if (lstat(p, &sb) == 0) {
+ if (*p != '\0' && lstat(p, &sb) == 0) {
if (S_ISLNK(sb.st_mode)) {
n = readlink(p, resolved, MAXPATHLEN);
if (n < 0)
diff --git a/lib/libc/stdlib/setenv.c b/lib/libc/stdlib/setenv.c
index b36d673..d981277 100644
--- a/lib/libc/stdlib/setenv.c
+++ b/lib/libc/stdlib/setenv.c
@@ -39,13 +39,14 @@ static char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93";
#include <stdlib.h>
#include <string.h>
-char *__findenv __P((const char *, int *));
+char *__findenv __P((const char *, int *));
/*
* setenv --
* Set the value of the environmental variable "name" to be
* "value". If rewrite is set, replace any current value.
*/
+int
setenv(name, value, rewrite)
register const char *name;
register const char *value;
@@ -63,7 +64,7 @@ setenv(name, value, rewrite)
if (!rewrite)
return (0);
if (strlen(c) >= l_value) { /* old larger; copy over */
- while (*c++ = *value++);
+ while ( (*c++ = *value++) );
return (0);
}
} else { /* create new slot */
@@ -93,7 +94,7 @@ setenv(name, value, rewrite)
malloc((size_t)((int)(c - name) + l_value + 2))))
return (-1);
for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
- for (*c++ = '='; *c++ = *value++;);
+ for (*c++ = '='; (*c++ = *value++); );
return (0);
}
diff --git a/lib/libc/stdlib/strhash.c b/lib/libc/stdlib/strhash.c
new file mode 100644
index 0000000..8e2230b
--- /dev/null
+++ b/lib/libc/stdlib/strhash.c
@@ -0,0 +1,436 @@
+#ifndef lint
+static char *rcsid = "$Header: /home/ncvs/src/lib/libc/stdlib/strhash.c,v 1.5 1995/10/22 14:53:17 phk Exp $";
+#endif
+
+/*
+ *
+ * Copyright 1990
+ * Terry Jones & Jordan Hubbard
+ *
+ * PCS Computer Systeme, GmbH.
+ * Munich, West Germany
+ *
+ *
+ * All rights reserved.
+ *
+ * This is unsupported software and is subject to change without notice.
+ * the author makes no representations about the suitability of this software
+ * for any purpose. It is supplied "as is" without express or implied
+ * warranty.
+ *
+ * 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 the author not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.
+ *
+ */
+
+/*
+ * This is a fairly simple open addressing hash scheme.
+ * Terry did all the code, I just did the spec.
+ * Thanks again, you crazy Aussie..
+ *
+ */
+
+/*
+ * $Log: strhash.c,v $
+ * Revision 1.5 1995/10/22 14:53:17 phk
+ * Mino cleanup, #includes & unused vars.
+ *
+ * Revision 1.4 1995/05/30 05:41:55 rgrimes
+ * Remove trailing whitespace.
+ *
+ * Revision 1.3 1995/03/28 08:41:02 jkh
+ * Fix a missing _hash() to prevent namespace pollution with the db/hash routines.
+ * Grrr. If the dbhash routines weren't grossly overengineered I wouldn't
+ * even need to do this! :-(
+ *
+ * Also now export the hash_stats routine. Manpage coming RSN - I promise.
+ *
+ * Revision 1.2 1995/03/26 19:32:24 ache
+ * Hash 8bit chars without sign extension
+ *
+ * Revision 1.1 1995/03/26 10:21:55 jkh
+ * Add the strhash family of routines. They provide a number of features
+ * that the db/hash functions don't, and they're much simpler to use for
+ * low-overhead string hashing.
+ *
+ * Revision 1.1 1995/02/25 02:16:34 jkh
+ * Second version of this - now support the essentials of a basic
+ * attributed file system for storing menu information and command
+ * templates. This is not finished yet, but it does compile so I can
+ * commit it to the tree now and continue working on it.
+ *
+ * Revision 2.0 90/03/26 01:44:26 jkh
+ * pre-beta check-in
+ *
+ * Revision 1.8 90/03/09 19:22:35 jkh
+ * Fixed bogus comment.
+ *
+ * Revision 1.7 90/03/09 19:01:08 jkh
+ * Added comments, GPL.
+ *
+ * Revision 1.6 90/03/08 17:55:58 terry
+ * Rearranged hash_purge to be a tiny bit more efficient.
+ * Added verbose option to hash_stats.
+ *
+ * Revision 1.5 90/03/08 17:19:54 terry
+ * Added hash_purge. Added arg to hash_traverse. Changed all
+ * void * to Generic.
+ *
+ * Revision 1.4 90/03/08 12:02:35 terry
+ * Fixed problems with allocation that I screwed up last night.
+ * Changed bucket lists to be singly linked. Thanks to JKH, my hero.
+ *
+ * Revision 1.3 90/03/07 21:33:33 terry
+ * Cleaned up a few decls to keep gcc -Wall quiet.
+ *
+ * Revision 1.2 90/03/07 21:14:53 terry
+ * Comments. Added HASH_STATS define. Removed hash_find()
+ * and new_node().
+ *
+ * Revision 1.1 90/03/07 20:49:45 terry
+ * Initial revision
+ *
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <strhash.h>
+
+#define HASH_NULL (hash_table *)0
+#define NODE_NULL (hash_node *)0
+#define GENERIC_NULL (void *)0
+
+#define HASH_SZ 97
+
+
+static int _hash(int size, char *key);
+static hash_node *list_find(caddr_t key, hash_node *head);
+
+
+/*
+ * hash_create()
+ *
+ * Malloc room for a new hash table and then room for its
+ * bucket pointers. Then set all the buckets to
+ * point to 0. Return the address of the new table.
+ */
+hash_table *
+hash_create(int size)
+{
+ register int i;
+ hash_table *new = (hash_table *)malloc(sizeof(hash_table));
+
+ if (!new || size < 0){
+ return HASH_NULL;
+ }
+
+ if (size == 0){
+ size = HASH_SZ;
+ }
+
+ if (!(new->buckets = (hash_node **)malloc(size * sizeof(hash_node *)))){
+ return HASH_NULL;
+ }
+
+ for (i = 0; i < size; i++){
+ new->buckets[i] = NODE_NULL;
+ }
+ new->size = size;
+
+ return new;
+}
+
+
+/*
+ * list_find()
+ *
+ * Find the key in the linked list pointed to by head.
+ */
+static hash_node *
+list_find(caddr_t key, hash_node *head)
+{
+ while (head){
+ if (!strcmp(head->key, key)){
+ return head;
+ }
+ head = head->next;
+ }
+ return NODE_NULL;
+}
+
+
+/*
+ * _hash()
+ *
+ * Compute the hash value for the given key.
+ */
+static int
+_hash(int size, char *key)
+{
+ unsigned int h = 0x0;
+
+ while (*key){
+ h = (h << 1) ^ (h ^ (unsigned char) *key++);
+ }
+
+ h %= size;
+ return h;
+}
+
+/*
+ * hash_destroy()
+ *
+ * Find the key and (if it's there) remove it entirely.
+ * The function (*nukefunc)() is in charge of disposing
+ * of the storage help by the data associated with the node.
+ */
+void
+hash_destroy(hash_table *table, char *key, void (*nukefunc)())
+{
+ int bucket = _hash(table->size, key);
+ hash_node *found = table->buckets[bucket];
+ hash_node *to_free = NODE_NULL;
+
+ if (!found) {
+ return;
+ }
+
+ if (!strcmp(found->key, key)) {
+ /*
+ * It was the head of the list.
+ */
+ table->buckets[bucket] = found->next;
+ to_free = found;
+ }
+ else {
+ /*
+ * Walk the list, looking one ahead.
+ */
+ while (found->next) {
+ if (!strcmp(found->next->key, key)) {
+ to_free = found->next;
+ found->next = found->next->next;
+ break;
+ }
+ found = found->next;
+ }
+
+ if (!to_free){
+ return;
+ }
+ }
+
+ if (nukefunc)
+ (*nukefunc)(to_free->key, to_free->data);
+ free(to_free);
+ return;
+}
+
+
+/*
+ * hash_search()
+ *
+ * Search the table for the given key. Then:
+ *
+ * 1) If you find it and there is no replacement function, just
+ * return what you found. (This is a simple search).
+ * 2) If you find it and there is a replacement function, run
+ * the function on the data you found, and replace the old
+ * data with whatever is passed in datum. Return 0.
+ * 3) If you don't find it and there is some datum, insert a
+ * new item into the table. Insertions go at the front of
+ * the bucket. Return 0.
+ * 4) Otherwise just return 0.
+ *
+ */
+void *
+hash_search(hash_table *table, caddr_t key, void *datum,
+ void (*replace_func)())
+{
+ int bucket = _hash(table->size, key);
+ hash_node *found = list_find(key, table->buckets[bucket]);
+
+ if (found){
+ if (!replace_func){
+ return found->data;
+ }
+ else{
+ (*replace_func)(found->data);
+ found->data = datum;
+ }
+ }
+ else{
+ if (datum){
+
+ static int assign_key();
+
+ hash_node *new = (hash_node *)malloc(sizeof(hash_node));
+
+ if (!new || !assign_key(key, new)){
+ return GENERIC_NULL;
+ }
+ new->data = datum;
+ new->next = table->buckets[bucket];
+ table->buckets[bucket] = new;
+ return new;
+ }
+ }
+ return GENERIC_NULL;
+}
+
+
+/*
+ * assign_key()
+ *
+ * Set the key value of a node to be 'key'. Get some space from
+ * malloc and copy it in etc. Return 1 if all is well, 0 otherwise.
+ */
+static int
+assign_key(char *key, hash_node *node)
+{
+ if (!node || !key){
+ return 0;
+ }
+
+ if (!(node->key = (char *)malloc(strlen(key) + 1))){
+ return 0;
+ }
+
+ node->key[0] = '\0';
+ strcat(node->key, key);
+ return 1;
+}
+
+/*
+ * hash_traverse()
+ *
+ * Traverse the hash table and run the function func on the
+ * data found at each node and the argument we're passed for it.
+ */
+void
+hash_traverse(hash_table *table, int (*func)(), void *arg)
+{
+ register int i;
+ register int size = table->size;
+
+ if (!func)
+ return;
+
+ for (i = 0; i < size; i++) {
+ hash_node *n = table->buckets[i];
+ while (n) {
+ if ((*func)(n->key, n->data, arg) == 0)
+ return;
+ n = n->next;
+ }
+ }
+ return;
+}
+
+/*
+ * hash_purge()
+ *
+ * Run through the entire hash table. Call purge_func
+ * on the data found at each node, and then free the node.
+ * Set all the bucket pointers to 0.
+ */
+void
+hash_purge(hash_table *table, void (*purge_func)(char *p1, void *p2))
+{
+ register int i;
+ register int size = table->size;
+
+ for (i = 0; i < size; i++) {
+ hash_node *n = table->buckets[i];
+ if (n) {
+ do {
+ hash_node *to_free = n;
+ if (purge_func) {
+ (*purge_func)(n->key, n->data);
+ }
+ n = n->next;
+ free(to_free);
+ } while (n);
+ table->buckets[i] = NODE_NULL;
+ }
+ }
+}
+
+#undef min
+#define min(a, b) (a) < (b) ? (a) : (b)
+
+/*
+ * hash_stats()
+ *
+ * Print statistics about the current table allocation to stdout.
+ */
+void
+hash_stats(hash_table *table, int verbose)
+{
+ register int i;
+ int total_elements = 0;
+ int non_empty_buckets = 0;
+ int max_count = 0;
+ int max_repeats = 0;
+ int *counts;
+ int size = table->size;
+
+ if (!(counts = (int *)malloc(size * sizeof(int)))){
+ fprintf(stderr, "malloc returns 0\n");
+ exit(1);
+ }
+
+ for (i = 0; i < size; i++){
+ int x = 0;
+ hash_node *n = table->buckets[i];
+ counts[i] = 0;
+ while (n){
+ if (!x){
+ x = 1;
+ non_empty_buckets++;
+ if (verbose){
+ printf("bucket %2d: ", i);
+ }
+ }
+ if (verbose){
+ printf(" %s", n->key);
+ }
+ counts[i]++;
+ n = n->next;
+ }
+
+ total_elements += counts[i];
+ if (counts[i] > max_count){
+ max_count = counts[i];
+ max_repeats = 1;
+ }
+ else if (counts[i] == max_count){
+ max_repeats++;
+ }
+
+ if (counts[i] && verbose){
+ printf(" (%d)\n", counts[i]);
+ }
+ }
+
+ printf("\n");
+ printf("%d element%s in storage.\n", total_elements, total_elements == 1 ? "" : "s");
+
+ if (total_elements){
+ printf("%d of %d (%.2f%%) buckets are in use\n", non_empty_buckets, size,
+ (double)100 * (double)non_empty_buckets / (double)(size));
+ printf("the maximum number of elements in a bucket is %d (%d times)\n", max_count, max_repeats);
+ printf("average per bucket is %f\n", (double)total_elements / (double)non_empty_buckets);
+ printf("optimal would be %f\n", (double)total_elements / (double)(min(size, total_elements)));
+ }
+ return;
+}
diff --git a/lib/libc/stdlib/strtod.c b/lib/libc/stdlib/strtod.c
index cd82c73..27fb499 100644
--- a/lib/libc/stdlib/strtod.c
+++ b/lib/libc/stdlib/strtod.c
@@ -146,6 +146,7 @@ static char sccsid[] = "@(#)strtod.c 8.1 (Berkeley) 6/4/93";
#endif
#include "errno.h"
+#include <ctype.h>
#ifdef Bad_float_h
#undef __STDC__
#ifdef IEEE_MC68k
@@ -381,7 +382,7 @@ Balloc
int x;
Bigint *rv;
- if (rv = freelist[k]) {
+ if ( (rv = freelist[k]) ) {
freelist[k] = rv->next;
} else {
x = 1 << k;
@@ -627,7 +628,7 @@ mult
xc0 = c->x;
#ifdef Pack_32
for (; xb < xbe; xb++, xc0++) {
- if (y = *xb & 0xffff) {
+ if ( (y = *xb & 0xffff) ) {
x = xa;
xc = xc0;
carry = 0;
@@ -640,7 +641,7 @@ mult
} while (x < xae);
*xc = carry;
}
- if (y = *xb >> 16) {
+ if ( (y = *xb >> 16) ) {
x = xa;
xc = xc0;
carry = 0;
@@ -689,7 +690,7 @@ pow5mult
int i;
static int p05[3] = { 5, 25, 125 };
- if (i = k & 3)
+ if ( (i = k & 3) )
b = multadd(b, p05[i-1], 0);
if (!(k >>= 2))
@@ -751,7 +752,7 @@ lshift
*x1++ = *x << k | z;
z = *x++ >> k1;
} while (x < xe);
- if (*x1 = z)
+ if ( (*x1 = z) )
++n1;
}
#else
@@ -917,7 +918,7 @@ ulp
} else {
word0(a) = 0;
L -= Exp_shift;
- word1(a) = L >= 31 ? 1 : 1 << 31 - L;
+ word1(a) = L >= 31 ? 1 : 1 << (31 - L);
}
}
#endif
@@ -952,16 +953,16 @@ b2d
*e = 32 - k;
#ifdef Pack_32
if (k < Ebits) {
- d0 = Exp_1 | y >> Ebits - k;
+ d0 = Exp_1 | (y >> (Ebits - k));
w = xa > xa0 ? *--xa : 0;
- d1 = y << (32-Ebits) + k | w >> Ebits - k;
+ d1 = (y << ((32-Ebits) + k)) | (w >> (Ebits - k));
goto ret_d;
}
z = xa > xa0 ? *--xa : 0;
if (k -= Ebits) {
- d0 = Exp_1 | y << k | z >> 32 - k;
+ d0 = Exp_1 | (y << k) | (z >> (32 - k));
y = xa > xa0 ? *--xa : 0;
- d1 = z << k | y >> 32 - k;
+ d1 = (z << k) | (y >> (32 - k));
} else {
d0 = Exp_1 | y;
d1 = z;
@@ -1028,13 +1029,13 @@ d2b
z |= Exp_msk11;
#endif
#else
- if (de = (int)(d0 >> Exp_shift))
+ if ( (de = (int)(d0 >> Exp_shift)) )
z |= Exp_msk1;
#endif
#ifdef Pack_32
- if (y = d1) {
- if (k = lo0bits(&y)) {
- x[0] = y | z << 32 - k;
+ if ( (y = d1) ) {
+ if ( (k = lo0bits(&y)) ) {
+ x[0] = y | (z << (32 - k));
z >>= k;
}
else
@@ -1212,14 +1213,9 @@ strtod
case 0:
s = s00;
goto ret;
- case '\t':
- case '\n':
- case '\v':
- case '\f':
- case '\r':
- case ' ':
- continue;
default:
+ if (isspace((unsigned char)*s))
+ continue;
goto break2;
}
break2:
@@ -1375,9 +1371,9 @@ strtod
/* Get starting approximation = rv * 10**e1 */
if (e1 > 0) {
- if (i = e1 & 15)
+ if ( (i = e1 & 15) )
rv *= tens[i];
- if (e1 &= ~15) {
+ if ( (e1 &= ~15) ) {
if (e1 > DBL_MAX_10_EXP) {
ovfl:
errno = ERANGE;
@@ -1417,9 +1413,9 @@ strtod
}
} else if (e1 < 0) {
e1 = -e1;
- if (i = e1 & 15)
+ if ( (i = e1 & 15) )
rv /= tens[i];
- if (e1 &= ~15) {
+ if ( (e1 &= ~15) ) {
e1 >>= 4;
for (j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
@@ -1950,13 +1946,13 @@ __dtoa
#ifdef Sudden_Underflow
i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
#else
- if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
+ if ( (i = (int)((word0(d) >> Exp_shift1) & (Exp_mask>>Exp_shift1))) ) {
#endif
d2 = d;
word0(d2) &= Frac_mask1;
word0(d2) |= Exp_11;
#ifdef IBM
- if (j = 11 - hi0bits(word0(d2) & Frac_mask))
+ if ( (j = 11 - hi0bits(word0(d2) & Frac_mask)) )
d2 /= 1 << j;
#endif
@@ -1993,8 +1989,8 @@ __dtoa
/* d is denormalized */
i = bbits + be + (Bias + (P-1) - 1);
- x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
- : word1(d) << 32 - i;
+ x = i > 32 ? ((word0(d) << (64 - i)) | (word1(d) >> (i - 32)))
+ : (word1(d) << (32 - i));
d2 = x;
word0(d2) -= 31*Exp_msk1; /* adjust exponent */
i -= (Bias + (P-1) - 1) + 1;
@@ -2091,7 +2087,7 @@ __dtoa
ds *= bigtens[i];
}
d /= ds;
- } else if (j1 = -k) {
+ } else if ( (j1 = -k) ) {
d *= tens[j1 & 0xf];
for (j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) {
@@ -2190,7 +2186,7 @@ __dtoa
*s++ = '0' + (int)L;
if (i == ilim) {
d += d;
- if (d > ds || d == ds && L & 1) {
+ if (d > ds || (d == ds && L & 1)) {
bump_up:
while (*--s == '9')
if (s == s0) {
@@ -2254,7 +2250,7 @@ __dtoa
Bfree(b);
b = b1;
}
- if (j = b5 - m5)
+ if ( (j = b5 - m5) )
b = pow5mult(b, j);
} else
b = pow5mult(b, b5);
@@ -2287,10 +2283,10 @@ __dtoa
* can do shifts and ors to compute the numerator for q.
*/
#ifdef Pack_32
- if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
+ if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) )
i = 32 - i;
#else
- if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
+ if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) )
i = 16 - i;
#endif
if (i > 4) {
@@ -2363,15 +2359,15 @@ __dtoa
goto ret;
}
#endif
- if (j < 0 || j == 0 && !mode
+ if (j < 0 || (j == 0 && !mode
#ifndef ROUND_BIASED
&& !(word1(d) & 1)
#endif
- ) {
+ )) {
if (j1 > 0) {
b = lshift(b, 1);
j1 = cmp(b, S);
- if ((j1 > 0 || j1 == 0 && dig & 1)
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
&& dig++ == '9')
goto round_9_up;
}
@@ -2410,7 +2406,7 @@ __dtoa
b = lshift(b, 1);
j = cmp(b, S);
- if (j > 0 || j == 0 && dig & 1) {
+ if (j > 0 || (j == 0 && dig & 1)) {
roundoff:
while (*--s == '9')
if (s == s0) {
diff --git a/lib/libc/stdlib/strtol.3 b/lib/libc/stdlib/strtol.3
index 4ebf069..3d43fb3 100644
--- a/lib/libc/stdlib/strtol.3
+++ b/lib/libc/stdlib/strtol.3
@@ -45,13 +45,13 @@
.Fd #include <stdlib.h>
.Fd #include <limits.h>
.Ft long
-.Fn strtol "char *nptr" "char **endptr" "int base"
+.Fn strtol "const char *nptr" "char **endptr" "int base"
.Fd #include <sys/types.h>
.Fd #include <stdlib.h>
.Fd #include <limits.h>
.Ft quad_t
-.Fn strtoq "char *nptr" "char **endptr" "int base"
+.Fn strtoq "const char *nptr" "char **endptr" "int base"
.Sh DESCRIPTION
The
.Fn strtol
diff --git a/lib/libc/stdlib/strtol.c b/lib/libc/stdlib/strtol.c
index 1a7f7b3..18e3972 100644
--- a/lib/libc/stdlib/strtol.c
+++ b/lib/libc/stdlib/strtol.c
@@ -55,7 +55,7 @@ strtol(nptr, endptr, base)
{
register const char *s = nptr;
register unsigned long acc;
- register int c;
+ register unsigned char c;
register unsigned long cutoff;
register int neg = 0, any, cutlim;
@@ -102,6 +102,8 @@ strtol(nptr, endptr, base)
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
+ if (!isascii(c))
+ break;
if (isdigit(c))
c -= '0';
else if (isalpha(c))
@@ -110,7 +112,7 @@ strtol(nptr, endptr, base)
break;
if (c >= base)
break;
- if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
diff --git a/lib/libc/stdlib/strtoll.c b/lib/libc/stdlib/strtoll.c
new file mode 100644
index 0000000..2666749
--- /dev/null
+++ b/lib/libc/stdlib/strtoll.c
@@ -0,0 +1,138 @@
+/*-
+ * 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.
+ * 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[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to a quad integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+quad_t
+strtoq(nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register int base;
+{
+ register const char *s;
+ register u_quad_t acc;
+ register unsigned char c;
+ register u_quad_t qbase, cutoff;
+ register int neg, any, cutlim;
+
+ /*
+ * 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 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.
+ */
+ qbase = (unsigned)base;
+ cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX;
+ cutlim = cutoff % qbase;
+ cutoff /= qbase;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (!isascii(c))
+ break;
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= qbase;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? QUAD_MIN : QUAD_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
diff --git a/lib/libc/stdlib/strtoq.c b/lib/libc/stdlib/strtoq.c
index b31cca4..2666749 100644
--- a/lib/libc/stdlib/strtoq.c
+++ b/lib/libc/stdlib/strtoq.c
@@ -56,7 +56,7 @@ strtoq(nptr, endptr, base)
{
register const char *s;
register u_quad_t acc;
- register int c;
+ register unsigned char c;
register u_quad_t qbase, cutoff;
register int neg, any, cutlim;
@@ -109,6 +109,8 @@ strtoq(nptr, endptr, base)
cutlim = cutoff % qbase;
cutoff /= qbase;
for (acc = 0, any = 0;; c = *s++) {
+ if (!isascii(c))
+ break;
if (isdigit(c))
c -= '0';
else if (isalpha(c))
@@ -117,7 +119,7 @@ strtoq(nptr, endptr, base)
break;
if (c >= base)
break;
- if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
diff --git a/lib/libc/stdlib/strtoul.c b/lib/libc/stdlib/strtoul.c
index e60556c0..304150a 100644
--- a/lib/libc/stdlib/strtoul.c
+++ b/lib/libc/stdlib/strtoul.c
@@ -54,7 +54,7 @@ strtoul(nptr, endptr, base)
{
register const char *s = nptr;
register unsigned long acc;
- register int c;
+ register unsigned char c;
register unsigned long cutoff;
register int neg = 0, any, cutlim;
@@ -80,6 +80,8 @@ strtoul(nptr, endptr, base)
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
+ if (!isascii(c))
+ break;
if (isdigit(c))
c -= '0';
else if (isalpha(c))
@@ -88,7 +90,7 @@ strtoul(nptr, endptr, base)
break;
if (c >= base)
break;
- if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
diff --git a/lib/libc/stdlib/strtoull.c b/lib/libc/stdlib/strtoull.c
new file mode 100644
index 0000000..7656a3c
--- /dev/null
+++ b/lib/libc/stdlib/strtoull.c
@@ -0,0 +1,116 @@
+/*-
+ * 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.
+ * 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[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to an unsigned quad integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+u_quad_t
+strtouq(nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register int base;
+{
+ register const char *s = nptr;
+ register u_quad_t acc;
+ register unsigned char c;
+ register u_quad_t qbase, cutoff;
+ register int neg, any, cutlim;
+
+ /*
+ * See strtoq for comments as to the logic used.
+ */
+ 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;
+ qbase = (unsigned)base;
+ cutoff = (u_quad_t)UQUAD_MAX / qbase;
+ cutlim = (u_quad_t)UQUAD_MAX % qbase;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (!isascii(c))
+ break;
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= qbase;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = UQUAD_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
diff --git a/lib/libc/stdlib/strtouq.c b/lib/libc/stdlib/strtouq.c
index cc62a07..7656a3c 100644
--- a/lib/libc/stdlib/strtouq.c
+++ b/lib/libc/stdlib/strtouq.c
@@ -56,7 +56,7 @@ strtouq(nptr, endptr, base)
{
register const char *s = nptr;
register u_quad_t acc;
- register int c;
+ register unsigned char c;
register u_quad_t qbase, cutoff;
register int neg, any, cutlim;
@@ -70,7 +70,7 @@ strtouq(nptr, endptr, base)
if (c == '-') {
neg = 1;
c = *s++;
- } else {
+ } else {
neg = 0;
if (c == '+')
c = *s++;
@@ -87,6 +87,8 @@ strtouq(nptr, endptr, base)
cutoff = (u_quad_t)UQUAD_MAX / qbase;
cutlim = (u_quad_t)UQUAD_MAX % qbase;
for (acc = 0, any = 0;; c = *s++) {
+ if (!isascii(c))
+ break;
if (isdigit(c))
c -= '0';
else if (isalpha(c))
@@ -95,7 +97,7 @@ strtouq(nptr, endptr, base)
break;
if (c >= base)
break;
- if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
diff --git a/lib/libc/stdlib/system.3 b/lib/libc/stdlib/system.3
index d89c79e..9b82e7b 100644
--- a/lib/libc/stdlib/system.3
+++ b/lib/libc/stdlib/system.3
@@ -76,7 +76,7 @@ The
.Fn system
function
returns the exit status of the shell, or \-1 if the
-.Xr wait 3
+.Xr wait 2
for the shell failed.
A return value of 127 means the execution of the shell
failed.
@@ -91,3 +91,6 @@ The
function
conforms to
.St -ansiC .
+and is expected to be
+.St -p1003.2
+compatible.
diff --git a/lib/libc/stdlib/system.c b/lib/libc/stdlib/system.c
index c438f17..00db7d6 100644
--- a/lib/libc/stdlib/system.c
+++ b/lib/libc/stdlib/system.c
@@ -42,35 +42,51 @@ static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/4/93";
#include <stddef.h>
#include <unistd.h>
#include <paths.h>
+#include <errno.h>
-system(command)
+int system(command)
const char *command;
{
- union wait pstat;
pid_t pid;
- int omask;
- sig_t intsave, quitsave;
+ int pstat;
+ struct sigaction ign, intact, quitact;
+ sigset_t newsigblock, oldsigblock;
if (!command) /* just checking... */
return(1);
- omask = sigblock(sigmask(SIGCHLD));
- switch(pid = vfork()) {
+ /*
+ * 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 */
- (void)sigsetmask(omask);
- pstat.w_status = 0;
- pstat.w_retcode = 127;
- return(pstat.w_status);
+ break;
case 0: /* child */
- (void)sigsetmask(omask);
+ /*
+ * 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 */
+ do {
+ pid = waitpid(pid, &pstat, 0);
+ } while (pid == -1 && errno == EINTR);
+ break;
}
- intsave = signal(SIGINT, SIG_IGN);
- quitsave = signal(SIGQUIT, SIG_IGN);
- pid = waitpid(pid, (int *)&pstat, 0);
- (void)sigsetmask(omask);
- (void)signal(SIGINT, intsave);
- (void)signal(SIGQUIT, quitsave);
- return(pid == -1 ? -1 : pstat.w_status);
+ (void)sigaction(SIGINT, &intact, NULL);
+ (void)sigaction(SIGQUIT, &quitact, NULL);
+ (void)sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
+ return(pid == -1 ? -1 : pstat);
}
diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc
new file mode 100644
index 0000000..cdd4b8a
--- /dev/null
+++ b/lib/libc/stdtime/Makefile.inc
@@ -0,0 +1,16 @@
+# Makefile.inc,v 1.2 1994/09/13 21:26:01 wollman Exp
+# $Id$
+
+.PATH: ${.CURDIR}/../libc/stdtime
+
+SRCS+= asctime.c localtime.c strftime.c difftime.c
+
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN5+= stdtime/tzfile.5
+MAN3+= stdtime/ctime.3 stdtime/strftime.3 stdtime/time2posix.3
+
+MLINKS+=ctime.3 asctime.3 ctime.3 difftime.3 ctime.3 gmtime.3 \
+ ctime.3 localtime.3 ctime.3 mktime.3
+MLINKS+=time2posix.3 posix2time.3
+.endif
diff --git a/lib/libc/stdtime/asctime.c b/lib/libc/stdtime/asctime.c
new file mode 100644
index 0000000..a1834b6
--- /dev/null
+++ b/lib/libc/stdtime/asctime.c
@@ -0,0 +1,61 @@
+/*
+** This file is in the public domain, so clarified as of
+** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+#ifndef lint
+#ifndef NOID
+static char elsieid[] = "@(#)asctime.c 7.7";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*LINTLIBRARY*/
+
+#include "private.h"
+#include "tzfile.h"
+
+/*
+** A la X3J11, with core dump avoidance.
+*/
+
+char *
+asctime(timeptr)
+register const struct tm * timeptr;
+{
+ static const char wday_name[][3] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+ };
+ static const char mon_name[][3] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+ /*
+ ** Big enough for something such as
+ ** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
+ ** (two three-character abbreviations, five strings denoting integers,
+ ** three explicit spaces, two explicit colons, a newline,
+ ** and a trailing ASCII nul).
+ */
+ static char result[3 * 2 + 5 * INT_STRLEN_MAXIMUM(int) +
+ 3 + 2 + 1 + 1];
+ register const char * wn;
+ register const char * mn;
+
+ if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
+ wn = "???";
+ else wn = wday_name[timeptr->tm_wday];
+ if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
+ mn = "???";
+ else mn = mon_name[timeptr->tm_mon];
+ /*
+ ** The X3J11-suggested format is
+ ** "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n"
+ ** Since the .2 in 02.2d is ignored, we drop it.
+ */
+ (void) sprintf(result, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
+ wn, mn,
+ timeptr->tm_mday, timeptr->tm_hour,
+ timeptr->tm_min, timeptr->tm_sec,
+ TM_YEAR_BASE + timeptr->tm_year);
+ return result;
+}
diff --git a/lib/libc/stdtime/ctime.3 b/lib/libc/stdtime/ctime.3
new file mode 100644
index 0000000..eccb664
--- /dev/null
+++ b/lib/libc/stdtime/ctime.3
@@ -0,0 +1,257 @@
+.\" 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.
+.\" 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.
+.\"
+.\" @(#)ctime.3 8.1 (Berkeley) 6/4/93
+.\"
+.Dd June 4, 1993
+.Dt CTIME 3
+.Os BSD 4.3
+.Sh NAME
+.Nm asctime ,
+.Nm ctime ,
+.Nm difftime ,
+.Nm gmtime ,
+.Nm localtime ,
+.Nm mktime
+.Nd transform binary date and time value to
+.Tn ASCII
+.Sh SYNOPSIS
+.Fd #include <time.h>
+.Vt extern char *tzname[2];
+.Ft char *
+.Fn ctime "const time_t *clock"
+.Ft double
+.Fn difftime "time_t time1" "time_t time0"
+.Ft char *
+.Fn asctime "const struct tm *tm"
+.Ft struct tm *
+.Fn localtime "const time_t *clock"
+.Ft struct tm *
+.Fn gmtime "const time_t *clock"
+.Ft time_t
+.Fn mktime "struct tm *tm"
+.Sh DESCRIPTION
+The functions
+.Fn ctime ,
+.Fn gmtime
+and
+.Fn localtime
+all take as an argument a time value representing the time in seconds since
+the Epoch (00:00:00
+.Tn UTC ,
+January 1, 1970; see
+.Xr time 3 ) .
+.Pp
+The function
+.Fn localtime
+converts the time value pointed at by
+.Fa clock ,
+and returns a pointer to a
+.Dq Fa struct tm
+(described below) which contains
+the broken-out time information for the value after adjusting for the current
+time zone (and any other factors such as Daylight Saving Time).
+Time zone adjustments are performed as specified by the
+.Ev TZ
+environmental variable (see
+.Xr tzset 3 ) .
+The function
+.Fn localtime
+uses
+.Xr tzset 3
+to initialize time conversion information if
+.Xr tzset 3
+has not already been called by the process.
+.Pp
+After filling in the tm structure,
+.Fn localtime
+sets the
+.Fa tm_isdst Ns 'th
+element of
+.Fa tzname
+to a pointer to an
+.Tn ASCII
+string that's the time zone abbreviation to be
+used with
+.Fn localtime Ns 's
+return value.
+.Pp
+The function
+.Fn gmtime
+similarly converts the time value, but without any time zone adjustment,
+and returns a pointer to a tm structure (described below).
+.Pp
+The
+.Fn ctime
+function
+adjusts the time value for the current time zone in the same manner as
+.Fn localtime ,
+and returns a pointer to a 26-character string of the form:
+.Bd -literal -offset indent
+Thu Nov 24 18:22:48 1986\en\e0
+.Ed
+.Pp
+All the fields have constant width.
+.Pp
+The
+.Fn asctime
+function
+converts the broken down time in the structure
+.Fa tm
+pointed at by
+.Fa *tm
+to the form
+shown in the example above.
+.Pp
+The function
+.Fn mktime
+converts the broken-down time, expressed as local time, in the structure
+pointed to by tm into a time value with the same encoding as that of the
+values returned by the
+.Xr time 3
+function, that is, seconds from the Epoch,
+.Tn UTC .
+.Pp
+The original values of the
+.Fa tm_wday
+and
+.Fa tm_yday
+components of the structure are ignored, and the original values of the
+other components are not restricted to their normal ranges.
+(A positive or zero value for
+.Fa tm_isdst
+causes
+.Fn mktime
+to presume initially that summer time (for example, Daylight Saving Time)
+is or is not in effect for the specified time, respectively.
+A negative value for
+.Fa tm_isdst
+causes the
+.Fn mktime
+function to attempt to divine whether summer time is in effect for the
+specified time.)
+.Pp
+On successful completion, the values of the
+.Fa tm_wday
+and
+.Fa tm_yday
+components of the structure are set appropriately, and the other components
+are set to represent the specified calendar time, but with their values
+forced to their normal ranges; the final value of
+.Fa tm_mday
+is not set until
+.Fa tm_mon
+and
+.Fa tm_year
+are determined.
+.Fn Mktime
+returns the specified calendar time; if the calendar time cannot be
+represented, it returns \-1;
+.Pp
+The
+.Fn difftime
+function
+returns the difference between two calendar times,
+.Pf ( Fa time1
+-
+.Fa time0 ) ,
+expressed in seconds.
+.Pp
+External declarations as well as the tm structure definition are in the
+.Aq Pa time.h
+include file.
+The tm structure includes at least the following fields:
+.Bd -literal -offset indent
+int tm_sec; /\(** seconds (0 - 60) \(**/
+int tm_min; /\(** minutes (0 - 59) \(**/
+int tm_hour; /\(** hours (0 - 23) \(**/
+int tm_mday; /\(** day of month (1 - 31) \(**/
+int tm_mon; /\(** month of year (0 - 11) \(**/
+int tm_year; /\(** year \- 1900 \(**/
+int tm_wday; /\(** day of week (Sunday = 0) \(**/
+int tm_yday; /\(** day of year (0 - 365) \(**/
+int tm_isdst; /\(** is summer time in effect? \(**/
+char \(**tm_zone; /\(** abbreviation of timezone name \(**/
+long tm_gmtoff; /\(** offset from UTC in seconds \(**/
+.Ed
+.Pp
+The
+field
+.Fa tm_isdst
+is non-zero if summer time is in effect.
+.Pp
+The field
+.Fa tm_gmtoff
+is the offset (in seconds) of the time represented from
+.Tn UTC ,
+with positive
+values indicating east of the Prime Meridian.
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr gettimeofday 2 ,
+.Xr getenv 3 ,
+.Xr time 3 ,
+.Xr tzset 3 ,
+.Xr tzfile 5
+.Sh HISTORY
+This manual page is derived from
+the time package contributed to Berkeley by
+Arthur Olsen and which appeared in
+.Bx 4.3 .
+.Sh BUGS
+Except for
+.Fn difftime
+and
+.Fn mktime ,
+these functions leaves their result in an internal static object and return
+a pointer to that object. Subsequent calls to these
+function will modify the same object.
+.Pp
+The
+.Fa tm_zone
+field of a returned tm structure points to a static array of characters,
+which will also be overwritten by any subsequent calls (as well as by
+subsequent calls to
+.Xr tzset 3
+and
+.Xr tzsetwall 3 ) .
+.Pp
+Use of the external variable
+.Fa tzname
+is discouraged; the
+.Fa tm_zone
+entry in the tm structure is preferred.
+.Pp
+Avoid using out-of-range values with
+.Fn mktime
+when setting up lunch with promptness sticklers in Riyadh.
diff --git a/lib/libc/stdtime/difftime.c b/lib/libc/stdtime/difftime.c
new file mode 100644
index 0000000..f178524
--- /dev/null
+++ b/lib/libc/stdtime/difftime.c
@@ -0,0 +1,77 @@
+/*
+** This file is in the public domain, so clarified as of
+** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+#ifndef lint
+#ifndef NOID
+static char elsieid[] = "@(#)difftime.c 7.7";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*LINTLIBRARY*/
+
+#include "private.h"
+
+/*
+** Algorithm courtesy Paul Eggert (eggert@twinsun.com).
+*/
+
+#ifdef HAVE_LONG_DOUBLE
+#define long_double long double
+#endif /* defined HAVE_LONG_DOUBLE */
+#ifndef HAVE_LONG_DOUBLE
+#define long_double double
+#endif /* !defined HAVE_LONG_DOUBLE */
+
+double
+difftime(time1, time0)
+const time_t time1;
+const time_t time0;
+{
+ time_t delta;
+ time_t hibit;
+
+ if (sizeof(time_t) < sizeof(double))
+ return (double) time1 - (double) time0;
+ if (sizeof(time_t) < sizeof(long_double))
+ return (long_double) time1 - (long_double) time0;
+ if (time1 < time0)
+ return -difftime(time0, time1);
+ /*
+ ** As much as possible, avoid loss of precision
+ ** by computing the difference before converting to double.
+ */
+ delta = time1 - time0;
+ if (delta >= 0)
+ return delta;
+ /*
+ ** Repair delta overflow.
+ */
+ hibit = (~ (time_t) 0) << (TYPE_BIT(time_t) - 1);
+ /*
+ ** The following expression rounds twice, which means
+ ** the result may not be the closest to the true answer.
+ ** For example, suppose time_t is 64-bit signed int,
+ ** long_double is IEEE 754 double with default rounding,
+ ** time1 = 9223372036854775807 and time0 = -1536.
+ ** Then the true difference is 9223372036854777343,
+ ** which rounds to 9223372036854777856
+ ** with a total error of 513.
+ ** But delta overflows to -9223372036854774273,
+ ** which rounds to -9223372036854774784, and correcting
+ ** this by subtracting 2 * (long_double) hibit
+ ** (i.e. by adding 2**64 = 18446744073709551616)
+ ** yields 9223372036854776832, which
+ ** rounds to 9223372036854775808
+ ** with a total error of 1535 instead.
+ ** This problem occurs only with very large differences.
+ ** It's too painful to fix this portably.
+ ** We are not alone in this problem;
+ ** some C compilers round twice when converting
+ ** large unsigned types to small floating types,
+ ** so if time_t is unsigned the "return delta" above
+ ** has the same double-rounding problem with those compilers.
+ */
+ return delta - 2 * (long_double) hibit;
+}
diff --git a/lib/libc/stdtime/localtime.c b/lib/libc/stdtime/localtime.c
new file mode 100644
index 0000000..3438cc6
--- /dev/null
+++ b/lib/libc/stdtime/localtime.c
@@ -0,0 +1,1754 @@
+/*
+** This file is in the public domain, so clarified as of
+** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+#ifndef lint
+#ifndef NOID
+static char elsieid[] = "@(#)localtime.c 7.57";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*
+** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
+** POSIX-style TZ environment variable handling from Guy Harris
+** (guy@auspex.com).
+*/
+
+/*LINTLIBRARY*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "private.h"
+#include "tzfile.h"
+#include "fcntl.h"
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
+
+/*
+** SunOS 4.1.1 headers lack O_BINARY.
+*/
+
+#ifdef O_BINARY
+#define OPEN_MODE (O_RDONLY | O_BINARY)
+#endif /* defined O_BINARY */
+#ifndef O_BINARY
+#define OPEN_MODE O_RDONLY
+#endif /* !defined O_BINARY */
+
+#ifndef WILDABBR
+/*
+** Someone might make incorrect use of a time zone abbreviation:
+** 1. They might reference tzname[0] before calling tzset (explicitly
+** or implicitly).
+** 2. They might reference tzname[1] before calling tzset (explicitly
+** or implicitly).
+** 3. They might reference tzname[1] after setting to a time zone
+** in which Daylight Saving Time is never observed.
+** 4. They might reference tzname[0] after setting to a time zone
+** in which Standard Time is never observed.
+** 5. They might reference tm.TM_ZONE after calling offtime.
+** What's best to do in the above cases is open to debate;
+** for now, we just set things up so that in any of the five cases
+** WILDABBR is used. Another possibility: initialize tzname[0] to the
+** string "tzname[0] used before set", and similarly for the other cases.
+** And another: initialize tzname[0] to "ERA", with an explanation in the
+** manual page of what this "time zone abbreviation" means (doing this so
+** that tzname[0] has the "normal" length of three characters).
+*/
+#define WILDABBR " "
+#endif /* !defined WILDABBR */
+
+static char wildabbr[] = "WILDABBR";
+
+static const char gmt[] = "GMT";
+
+struct ttinfo { /* time type information */
+ long tt_gmtoff; /* GMT offset in seconds */
+ int tt_isdst; /* used to set tm_isdst */
+ int tt_abbrind; /* abbreviation list index */
+ int tt_ttisstd; /* TRUE if transition is std time */
+ int tt_ttisgmt; /* TRUE if transition is GMT */
+};
+
+struct lsinfo { /* leap second information */
+ time_t ls_trans; /* transition time */
+ long ls_corr; /* correction to apply */
+};
+
+#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
+
+#ifdef TZNAME_MAX
+#define MY_TZNAME_MAX TZNAME_MAX
+#endif /* defined TZNAME_MAX */
+#ifndef TZNAME_MAX
+#define MY_TZNAME_MAX 255
+#endif /* !defined TZNAME_MAX */
+
+struct state {
+ int leapcnt;
+ int timecnt;
+ int typecnt;
+ int charcnt;
+ time_t ats[TZ_MAX_TIMES];
+ unsigned char types[TZ_MAX_TIMES];
+ struct ttinfo ttis[TZ_MAX_TYPES];
+ char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
+ (2 * (MY_TZNAME_MAX + 1)))];
+ struct lsinfo lsis[TZ_MAX_LEAPS];
+};
+
+struct rule {
+ int r_type; /* type of rule--see below */
+ int r_day; /* day number of rule */
+ int r_week; /* week number of rule */
+ int r_mon; /* month number of rule */
+ long r_time; /* transition time of rule */
+};
+
+#define JULIAN_DAY 0 /* Jn - Julian day */
+#define DAY_OF_YEAR 1 /* n - day of year */
+#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
+
+/*
+** Prototypes for static functions.
+*/
+
+static long detzcode P((const char * codep));
+static const char * getzname P((const char * strp));
+static const char * getnum P((const char * strp, int * nump, int min,
+ int max));
+static const char * getsecs P((const char * strp, long * secsp));
+static const char * getoffset P((const char * strp, long * offsetp));
+static const char * getrule P((const char * strp, struct rule * rulep));
+static void gmtload P((struct state * sp));
+static void gmtsub P((const time_t * timep, long offset,
+ struct tm * tmp));
+static void localsub P((const time_t * timep, long offset,
+ struct tm * tmp));
+static int increment_overflow P((int * number, int delta));
+static int normalize_overflow P((int * tensptr, int * unitsptr,
+ int base));
+static void settzname P((void));
+static time_t time1 P((struct tm * tmp,
+ void(*funcp) P((const time_t *,
+ long, struct tm *)),
+ long offset));
+static time_t time2 P((struct tm *tmp,
+ void(*funcp) P((const time_t *,
+ long, struct tm*)),
+ long offset, int * okayp));
+static void timesub P((const time_t * timep, long offset,
+ const struct state * sp, struct tm * tmp));
+static int tmcomp P((const struct tm * atmp,
+ const struct tm * btmp));
+static time_t transtime P((time_t janfirst, int year,
+ const struct rule * rulep, long offset));
+static int tzload P((const char * name, struct state * sp));
+static int tzparse P((const char * name, struct state * sp,
+ int lastditch));
+
+#ifdef ALL_STATE
+static struct state * lclptr;
+static struct state * gmtptr;
+#endif /* defined ALL_STATE */
+
+#ifndef ALL_STATE
+static struct state lclmem;
+static struct state gmtmem;
+#define lclptr (&lclmem)
+#define gmtptr (&gmtmem)
+#endif /* State Farm */
+
+#ifndef TZ_STRLEN_MAX
+#define TZ_STRLEN_MAX 255
+#endif /* !defined TZ_STRLEN_MAX */
+
+static char lcl_TZname[TZ_STRLEN_MAX + 1];
+static int lcl_is_set;
+static int gmt_is_set;
+#ifdef _THREAD_SAFE
+static struct pthread_mutex _lcl_mutexd = PTHREAD_MUTEX_INITIALIZER;
+static struct pthread_mutex _gmt_mutexd = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t lcl_mutex = &_lcl_mutexd;
+static pthread_mutex_t gmt_mutex = &_gmt_mutexd;
+#endif
+
+char * tzname[2] = {
+ wildabbr,
+ wildabbr
+};
+
+/*
+** Section 4.12.3 of X3.159-1989 requires that
+** Except for the strftime function, these functions [asctime,
+** ctime, gmtime, localtime] return values in one of two static
+** objects: a broken-down time structure and an array of char.
+** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
+*/
+
+static struct tm tm;
+
+#ifdef USG_COMPAT
+time_t timezone = 0;
+int daylight = 0;
+#endif /* defined USG_COMPAT */
+
+#ifdef ALTZONE
+time_t altzone = 0;
+#endif /* defined ALTZONE */
+
+static long
+detzcode(codep)
+const char * const codep;
+{
+ register long result;
+ register int i;
+
+ result = (codep[0] & 0x80) ? ~0L : 0L;
+ for (i = 0; i < 4; ++i)
+ result = (result << 8) | (codep[i] & 0xff);
+ return result;
+}
+
+static void
+settzname P((void))
+{
+ register struct state * const sp = lclptr;
+ register int i;
+
+ tzname[0] = wildabbr;
+ tzname[1] = wildabbr;
+#ifdef USG_COMPAT
+ daylight = 0;
+ timezone = 0;
+#endif /* defined USG_COMPAT */
+#ifdef ALTZONE
+ altzone = 0;
+#endif /* defined ALTZONE */
+#ifdef ALL_STATE
+ if (sp == NULL) {
+ tzname[0] = tzname[1] = gmt;
+ return;
+ }
+#endif /* defined ALL_STATE */
+ for (i = 0; i < sp->typecnt; ++i) {
+ register const struct ttinfo * const ttisp = &sp->ttis[i];
+
+ tzname[ttisp->tt_isdst] =
+ &sp->chars[ttisp->tt_abbrind];
+#ifdef USG_COMPAT
+ if (ttisp->tt_isdst)
+ daylight = 1;
+ if (i == 0 || !ttisp->tt_isdst)
+ timezone = -(ttisp->tt_gmtoff);
+#endif /* defined USG_COMPAT */
+#ifdef ALTZONE
+ if (i == 0 || ttisp->tt_isdst)
+ altzone = -(ttisp->tt_gmtoff);
+#endif /* defined ALTZONE */
+ }
+ /*
+ ** And to get the latest zone names into tzname. . .
+ */
+ for (i = 0; i < sp->timecnt; ++i) {
+ register const struct ttinfo * const ttisp =
+ &sp->ttis[
+ sp->types[i]];
+
+ tzname[ttisp->tt_isdst] =
+ &sp->chars[ttisp->tt_abbrind];
+ }
+}
+
+static int
+tzload(name, sp)
+register const char * name;
+register struct state * const sp;
+{
+ register const char * p;
+ register int i;
+ register int fid;
+
+ if (name == NULL && (name = TZDEFAULT) == NULL)
+ return -1;
+ {
+ register int doaccess;
+ struct stat stab;
+ /*
+ ** Section 4.9.1 of the C standard says that
+ ** "FILENAME_MAX expands to an integral constant expression
+ ** that is the size needed for an array of char large enough
+ ** to hold the longest file name string that the implementation
+ ** guarantees can be opened."
+ */
+ char fullname[FILENAME_MAX + 1];
+
+ if (name[0] == ':')
+ ++name;
+ doaccess = name[0] == '/';
+ if (!doaccess) {
+ if ((p = TZDIR) == NULL)
+ return -1;
+ if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
+ return -1;
+ (void) strcpy(fullname, p);
+ (void) strcat(fullname, "/");
+ (void) strcat(fullname, name);
+ /*
+ ** Set doaccess if '.' (as in "../") shows up in name.
+ */
+ if (strchr(name, '.') != NULL)
+ doaccess = TRUE;
+ name = fullname;
+ }
+ if (doaccess && access(name, R_OK) != 0)
+ return -1;
+ if ((fid = open(name, OPEN_MODE)) == -1)
+ return -1;
+ if ((fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode))
+ return -1;
+ }
+ {
+ struct tzhead * tzhp;
+ char buf[sizeof *sp + sizeof *tzhp];
+ int ttisstdcnt;
+ int ttisgmtcnt;
+
+ i = read(fid, buf, sizeof buf);
+ if (close(fid) != 0)
+ return -1;
+ p = buf;
+ p += sizeof tzhp->tzh_reserved;
+ ttisstdcnt = (int) detzcode(p);
+ p += 4;
+ ttisgmtcnt = (int) detzcode(p);
+ p += 4;
+ sp->leapcnt = (int) detzcode(p);
+ p += 4;
+ sp->timecnt = (int) detzcode(p);
+ p += 4;
+ sp->typecnt = (int) detzcode(p);
+ p += 4;
+ sp->charcnt = (int) detzcode(p);
+ p += 4;
+ if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
+ sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
+ sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
+ sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
+ (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
+ (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
+ return -1;
+ if (i - (p - buf) < sp->timecnt * 4 + /* ats */
+ sp->timecnt + /* types */
+ sp->typecnt * (4 + 2) + /* ttinfos */
+ sp->charcnt + /* chars */
+ sp->leapcnt * (4 + 4) + /* lsinfos */
+ ttisstdcnt + /* ttisstds */
+ ttisgmtcnt) /* ttisgmts */
+ return -1;
+ for (i = 0; i < sp->timecnt; ++i) {
+ sp->ats[i] = detzcode(p);
+ p += 4;
+ }
+ for (i = 0; i < sp->timecnt; ++i) {
+ sp->types[i] = (unsigned char) *p++;
+ if (sp->types[i] >= sp->typecnt)
+ return -1;
+ }
+ for (i = 0; i < sp->typecnt; ++i) {
+ register struct ttinfo * ttisp;
+
+ ttisp = &sp->ttis[i];
+ ttisp->tt_gmtoff = detzcode(p);
+ p += 4;
+ ttisp->tt_isdst = (unsigned char) *p++;
+ if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
+ return -1;
+ ttisp->tt_abbrind = (unsigned char) *p++;
+ if (ttisp->tt_abbrind < 0 ||
+ ttisp->tt_abbrind > sp->charcnt)
+ return -1;
+ }
+ for (i = 0; i < sp->charcnt; ++i)
+ sp->chars[i] = *p++;
+ sp->chars[i] = '\0'; /* ensure '\0' at end */
+ for (i = 0; i < sp->leapcnt; ++i) {
+ register struct lsinfo * lsisp;
+
+ lsisp = &sp->lsis[i];
+ lsisp->ls_trans = detzcode(p);
+ p += 4;
+ lsisp->ls_corr = detzcode(p);
+ p += 4;
+ }
+ for (i = 0; i < sp->typecnt; ++i) {
+ register struct ttinfo * ttisp;
+
+ ttisp = &sp->ttis[i];
+ if (ttisstdcnt == 0)
+ ttisp->tt_ttisstd = FALSE;
+ else {
+ ttisp->tt_ttisstd = *p++;
+ if (ttisp->tt_ttisstd != TRUE &&
+ ttisp->tt_ttisstd != FALSE)
+ return -1;
+ }
+ }
+ for (i = 0; i < sp->typecnt; ++i) {
+ register struct ttinfo * ttisp;
+
+ ttisp = &sp->ttis[i];
+ if (ttisgmtcnt == 0)
+ ttisp->tt_ttisgmt = FALSE;
+ else {
+ ttisp->tt_ttisgmt = *p++;
+ if (ttisp->tt_ttisgmt != TRUE &&
+ ttisp->tt_ttisgmt != FALSE)
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static const int mon_lengths[2][MONSPERYEAR] = {
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+static const int year_lengths[2] = {
+ DAYSPERNYEAR, DAYSPERLYEAR
+};
+
+/*
+** Given a pointer into a time zone string, scan until a character that is not
+** a valid character in a zone name is found. Return a pointer to that
+** character.
+*/
+
+static const char *
+getzname(strp)
+register const char * strp;
+{
+ register char c;
+
+ while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
+ c != '+')
+ ++strp;
+ return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract a number from that string.
+** Check that the number is within a specified range; if it is not, return
+** NULL.
+** Otherwise, return a pointer to the first character not part of the number.
+*/
+
+static const char *
+getnum(strp, nump, min, max)
+register const char * strp;
+int * const nump;
+const int min;
+const int max;
+{
+ register char c;
+ register int num;
+
+ if (strp == NULL || !is_digit(c = *strp))
+ return NULL;
+ num = 0;
+ do {
+ num = num * 10 + (c - '0');
+ if (num > max)
+ return NULL; /* illegal value */
+ c = *++strp;
+ } while (is_digit(c));
+ if (num < min)
+ return NULL; /* illegal value */
+ *nump = num;
+ return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract a number of seconds,
+** in hh[:mm[:ss]] form, from the string.
+** If any error occurs, return NULL.
+** Otherwise, return a pointer to the first character not part of the number
+** of seconds.
+*/
+
+static const char *
+getsecs(strp, secsp)
+register const char * strp;
+long * const secsp;
+{
+ int num;
+
+ /*
+ ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
+ ** "M10.4.6/26", which does not conform to Posix,
+ ** but which specifies the equivalent of
+ ** ``02:00 on the first Sunday on or after 23 Oct''.
+ */
+ strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
+ if (strp == NULL)
+ return NULL;
+ *secsp = num * (long) SECSPERHOUR;
+ if (*strp == ':') {
+ ++strp;
+ strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
+ if (strp == NULL)
+ return NULL;
+ *secsp += num * SECSPERMIN;
+ if (*strp == ':') {
+ ++strp;
+ /* `SECSPERMIN' allows for leap seconds. */
+ strp = getnum(strp, &num, 0, SECSPERMIN);
+ if (strp == NULL)
+ return NULL;
+ *secsp += num;
+ }
+ }
+ return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract an offset, in
+** [+-]hh[:mm[:ss]] form, from the string.
+** If any error occurs, return NULL.
+** Otherwise, return a pointer to the first character not part of the time.
+*/
+
+static const char *
+getoffset(strp, offsetp)
+register const char * strp;
+long * const offsetp;
+{
+ register int neg = 0;
+
+ if (*strp == '-') {
+ neg = 1;
+ ++strp;
+ } else if (*strp == '+')
+ ++strp;
+ strp = getsecs(strp, offsetp);
+ if (strp == NULL)
+ return NULL; /* illegal time */
+ if (neg)
+ *offsetp = -*offsetp;
+ return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract a rule in the form
+** date[/time]. See POSIX section 8 for the format of "date" and "time".
+** If a valid rule is not found, return NULL.
+** Otherwise, return a pointer to the first character not part of the rule.
+*/
+
+static const char *
+getrule(strp, rulep)
+const char * strp;
+register struct rule * const rulep;
+{
+ if (*strp == 'J') {
+ /*
+ ** Julian day.
+ */
+ rulep->r_type = JULIAN_DAY;
+ ++strp;
+ strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
+ } else if (*strp == 'M') {
+ /*
+ ** Month, week, day.
+ */
+ rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
+ ++strp;
+ strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
+ if (strp == NULL)
+ return NULL;
+ if (*strp++ != '.')
+ return NULL;
+ strp = getnum(strp, &rulep->r_week, 1, 5);
+ if (strp == NULL)
+ return NULL;
+ if (*strp++ != '.')
+ return NULL;
+ strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
+ } else if (is_digit(*strp)) {
+ /*
+ ** Day of year.
+ */
+ rulep->r_type = DAY_OF_YEAR;
+ strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
+ } else return NULL; /* invalid format */
+ if (strp == NULL)
+ return NULL;
+ if (*strp == '/') {
+ /*
+ ** Time specified.
+ */
+ ++strp;
+ strp = getsecs(strp, &rulep->r_time);
+ } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
+ return strp;
+}
+
+/*
+** Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the
+** year, a rule, and the offset from GMT at the time that rule takes effect,
+** calculate the Epoch-relative time that rule takes effect.
+*/
+
+static time_t
+transtime(janfirst, year, rulep, offset)
+const time_t janfirst;
+const int year;
+register const struct rule * const rulep;
+const long offset;
+{
+ register int leapyear;
+ register time_t value;
+ register int i;
+ int d, m1, yy0, yy1, yy2, dow;
+
+ INITIALIZE(value);
+ leapyear = isleap(year);
+ switch (rulep->r_type) {
+
+ case JULIAN_DAY:
+ /*
+ ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
+ ** years.
+ ** In non-leap years, or if the day number is 59 or less, just
+ ** add SECSPERDAY times the day number-1 to the time of
+ ** January 1, midnight, to get the day.
+ */
+ value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
+ if (leapyear && rulep->r_day >= 60)
+ value += SECSPERDAY;
+ break;
+
+ case DAY_OF_YEAR:
+ /*
+ ** n - day of year.
+ ** Just add SECSPERDAY times the day number to the time of
+ ** January 1, midnight, to get the day.
+ */
+ value = janfirst + rulep->r_day * SECSPERDAY;
+ break;
+
+ case MONTH_NTH_DAY_OF_WEEK:
+ /*
+ ** Mm.n.d - nth "dth day" of month m.
+ */
+ value = janfirst;
+ for (i = 0; i < rulep->r_mon - 1; ++i)
+ value += mon_lengths[leapyear][i] * SECSPERDAY;
+
+ /*
+ ** Use Zeller's Congruence to get day-of-week of first day of
+ ** month.
+ */
+ m1 = (rulep->r_mon + 9) % 12 + 1;
+ yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
+ yy1 = yy0 / 100;
+ yy2 = yy0 % 100;
+ dow = ((26 * m1 - 2) / 10 +
+ 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
+ if (dow < 0)
+ dow += DAYSPERWEEK;
+
+ /*
+ ** "dow" is the day-of-week of the first day of the month. Get
+ ** the day-of-month (zero-origin) of the first "dow" day of the
+ ** month.
+ */
+ d = rulep->r_day - dow;
+ if (d < 0)
+ d += DAYSPERWEEK;
+ for (i = 1; i < rulep->r_week; ++i) {
+ if (d + DAYSPERWEEK >=
+ mon_lengths[leapyear][rulep->r_mon - 1])
+ break;
+ d += DAYSPERWEEK;
+ }
+
+ /*
+ ** "d" is the day-of-month (zero-origin) of the day we want.
+ */
+ value += d * SECSPERDAY;
+ break;
+ }
+
+ /*
+ ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in
+ ** question. To get the Epoch-relative time of the specified local
+ ** time on that day, add the transition time and the current offset
+ ** from GMT.
+ */
+ return value + rulep->r_time + offset;
+}
+
+/*
+** Given a POSIX section 8-style TZ string, fill in the rule tables as
+** appropriate.
+*/
+
+static int
+tzparse(name, sp, lastditch)
+const char * name;
+register struct state * const sp;
+const int lastditch;
+{
+ const char * stdname;
+ const char * dstname;
+ size_t stdlen;
+ size_t dstlen;
+ long stdoffset;
+ long dstoffset;
+ register time_t * atp;
+ register unsigned char * typep;
+ register char * cp;
+ register int load_result;
+
+ INITIALIZE(dstname);
+ stdname = name;
+ if (lastditch) {
+ stdlen = strlen(name); /* length of standard zone name */
+ name += stdlen;
+ if (stdlen >= sizeof sp->chars)
+ stdlen = (sizeof sp->chars) - 1;
+ stdoffset = 0;
+ } else {
+ name = getzname(name);
+ stdlen = name - stdname;
+ if (stdlen < 3)
+ return -1;
+ if (*name == '\0')
+ return -1; /* was "stdoffset = 0;" */
+ else {
+ name = getoffset(name, &stdoffset);
+ if (name == NULL)
+ return -1;
+ }
+ }
+ load_result = tzload(TZDEFRULES, sp);
+ if (load_result != 0)
+ sp->leapcnt = 0; /* so, we're off a little */
+ if (*name != '\0') {
+ dstname = name;
+ name = getzname(name);
+ dstlen = name - dstname; /* length of DST zone name */
+ if (dstlen < 3)
+ return -1;
+ if (*name != '\0' && *name != ',' && *name != ';') {
+ name = getoffset(name, &dstoffset);
+ if (name == NULL)
+ return -1;
+ } else dstoffset = stdoffset - SECSPERHOUR;
+ if (*name == ',' || *name == ';') {
+ struct rule start;
+ struct rule end;
+ register int year;
+ register time_t janfirst;
+ time_t starttime;
+ time_t endtime;
+
+ ++name;
+ if ((name = getrule(name, &start)) == NULL)
+ return -1;
+ if (*name++ != ',')
+ return -1;
+ if ((name = getrule(name, &end)) == NULL)
+ return -1;
+ if (*name != '\0')
+ return -1;
+ sp->typecnt = 2; /* standard time and DST */
+ /*
+ ** Two transitions per year, from EPOCH_YEAR to 2037.
+ */
+ sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
+ if (sp->timecnt > TZ_MAX_TIMES)
+ return -1;
+ sp->ttis[0].tt_gmtoff = -dstoffset;
+ sp->ttis[0].tt_isdst = 1;
+ sp->ttis[0].tt_abbrind = stdlen + 1;
+ sp->ttis[1].tt_gmtoff = -stdoffset;
+ sp->ttis[1].tt_isdst = 0;
+ sp->ttis[1].tt_abbrind = 0;
+ atp = sp->ats;
+ typep = sp->types;
+ janfirst = 0;
+ for (year = EPOCH_YEAR; year <= 2037; ++year) {
+ starttime = transtime(janfirst, year, &start,
+ stdoffset);
+ endtime = transtime(janfirst, year, &end,
+ dstoffset);
+ if (starttime > endtime) {
+ *atp++ = endtime;
+ *typep++ = 1; /* DST ends */
+ *atp++ = starttime;
+ *typep++ = 0; /* DST begins */
+ } else {
+ *atp++ = starttime;
+ *typep++ = 0; /* DST begins */
+ *atp++ = endtime;
+ *typep++ = 1; /* DST ends */
+ }
+ janfirst += year_lengths[isleap(year)] *
+ SECSPERDAY;
+ }
+ } else {
+ register long theirstdoffset;
+ register long theirdstoffset;
+ register long theiroffset;
+ register int isdst;
+ register int i;
+ register int j;
+
+ if (*name != '\0')
+ return -1;
+ if (load_result != 0)
+ return -1;
+ /*
+ ** Initial values of theirstdoffset and theirdstoffset.
+ */
+ theirstdoffset = 0;
+ for (i = 0; i < sp->timecnt; ++i) {
+ j = sp->types[i];
+ if (!sp->ttis[j].tt_isdst) {
+ theirstdoffset =
+ -sp->ttis[j].tt_gmtoff;
+ break;
+ }
+ }
+ theirdstoffset = 0;
+ for (i = 0; i < sp->timecnt; ++i) {
+ j = sp->types[i];
+ if (sp->ttis[j].tt_isdst) {
+ theirdstoffset =
+ -sp->ttis[j].tt_gmtoff;
+ break;
+ }
+ }
+ /*
+ ** Initially we're assumed to be in standard time.
+ */
+ isdst = FALSE;
+ theiroffset = theirstdoffset;
+ /*
+ ** Now juggle transition times and types
+ ** tracking offsets as you do.
+ */
+ for (i = 0; i < sp->timecnt; ++i) {
+ j = sp->types[i];
+ sp->types[i] = sp->ttis[j].tt_isdst;
+ if (sp->ttis[j].tt_ttisgmt) {
+ /* No adjustment to transition time */
+ } else {
+ /*
+ ** If summer time is in effect, and the
+ ** transition time was not specified as
+ ** standard time, add the summer time
+ ** offset to the transition time;
+ ** otherwise, add the standard time
+ ** offset to the transition time.
+ */
+ /*
+ ** Transitions from DST to DDST
+ ** will effectively disappear since
+ ** POSIX provides for only one DST
+ ** offset.
+ */
+ if (isdst && !sp->ttis[j].tt_ttisstd) {
+ sp->ats[i] += dstoffset -
+ theirdstoffset;
+ } else {
+ sp->ats[i] += stdoffset -
+ theirstdoffset;
+ }
+ }
+ theiroffset = -sp->ttis[j].tt_gmtoff;
+ if (sp->ttis[j].tt_isdst)
+ theirdstoffset = theiroffset;
+ else theirstdoffset = theiroffset;
+ }
+ /*
+ ** Finally, fill in ttis.
+ ** ttisstd and ttisgmt need not be handled.
+ */
+ sp->ttis[0].tt_gmtoff = -stdoffset;
+ sp->ttis[0].tt_isdst = FALSE;
+ sp->ttis[0].tt_abbrind = 0;
+ sp->ttis[1].tt_gmtoff = -dstoffset;
+ sp->ttis[1].tt_isdst = TRUE;
+ sp->ttis[1].tt_abbrind = stdlen + 1;
+ }
+ } else {
+ dstlen = 0;
+ sp->typecnt = 1; /* only standard time */
+ sp->timecnt = 0;
+ sp->ttis[0].tt_gmtoff = -stdoffset;
+ sp->ttis[0].tt_isdst = 0;
+ sp->ttis[0].tt_abbrind = 0;
+ }
+ sp->charcnt = stdlen + 1;
+ if (dstlen != 0)
+ sp->charcnt += dstlen + 1;
+ if (sp->charcnt > sizeof sp->chars)
+ return -1;
+ cp = sp->chars;
+ (void) strncpy(cp, stdname, stdlen);
+ cp += stdlen;
+ *cp++ = '\0';
+ if (dstlen != 0) {
+ (void) strncpy(cp, dstname, dstlen);
+ *(cp + dstlen) = '\0';
+ }
+ return 0;
+}
+
+static void
+gmtload(sp)
+struct state * const sp;
+{
+ if (tzload(gmt, sp) != 0)
+ (void) tzparse(gmt, sp, TRUE);
+}
+
+#ifndef STD_INSPIRED
+/*
+** A non-static declaration of tzsetwall in a system header file
+** may cause a warning about this upcoming static declaration...
+*/
+static
+#endif /* !defined STD_INSPIRED */
+#ifdef _THREAD_SAFE
+void
+tzsetwall_basic P((void))
+#else
+void
+tzsetwall P((void))
+#endif
+{
+ if (lcl_is_set < 0)
+ return;
+ lcl_is_set = -1;
+
+#ifdef ALL_STATE
+ if (lclptr == NULL) {
+ lclptr = (struct state *) malloc(sizeof *lclptr);
+ if (lclptr == NULL) {
+ settzname(); /* all we can do */
+ return;
+ }
+ }
+#endif /* defined ALL_STATE */
+ if (tzload((char *) NULL, lclptr) != 0)
+ gmtload(lclptr);
+ settzname();
+}
+
+#ifdef _THREAD_SAFE
+void
+tzsetwall P((void))
+{
+ pthread_mutex_lock(&lcl_mutex);
+ tzsetwall_basic();
+ pthread_mutex_unlock(&lcl_mutex);
+}
+#endif
+
+#ifdef _THREAD_SAFE
+static void
+tzset_basic P((void))
+#else
+void
+tzset P((void))
+#endif
+{
+ register const char * name;
+
+ name = getenv("TZ");
+ if (name == NULL) {
+ tzsetwall();
+ return;
+ }
+
+ if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
+ return;
+ lcl_is_set = (strlen(name) < sizeof(lcl_TZname));
+ if (lcl_is_set)
+ (void) strcpy(lcl_TZname, name);
+
+#ifdef ALL_STATE
+ if (lclptr == NULL) {
+ lclptr = (struct state *) malloc(sizeof *lclptr);
+ if (lclptr == NULL) {
+ settzname(); /* all we can do */
+ return;
+ }
+ }
+#endif /* defined ALL_STATE */
+ if (*name == '\0') {
+ /*
+ ** User wants it fast rather than right.
+ */
+ lclptr->leapcnt = 0; /* so, we're off a little */
+ lclptr->timecnt = 0;
+ lclptr->ttis[0].tt_gmtoff = 0;
+ lclptr->ttis[0].tt_abbrind = 0;
+ (void) strcpy(lclptr->chars, gmt);
+ } else if (tzload(name, lclptr) != 0)
+ if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
+ (void) gmtload(lclptr);
+ settzname();
+}
+
+#ifdef _THREAD_SAFE
+void
+tzset P((void))
+{
+ pthread_mutex_lock(&lcl_mutex);
+ tzset_basic();
+ pthread_mutex_unlock(&lcl_mutex);
+}
+#endif
+
+/*
+** The easy way to behave "as if no library function calls" localtime
+** is to not call it--so we drop its guts into "localsub", which can be
+** freely called. (And no, the PANS doesn't require the above behavior--
+** but it *is* desirable.)
+**
+** The unused offset argument is for the benefit of mktime variants.
+*/
+
+/*ARGSUSED*/
+static void
+localsub(timep, offset, tmp)
+const time_t * const timep;
+const long offset;
+struct tm * const tmp;
+{
+ register struct state * sp;
+ register const struct ttinfo * ttisp;
+ register int i;
+ const time_t t = *timep;
+
+ sp = lclptr;
+#ifdef ALL_STATE
+ if (sp == NULL) {
+ gmtsub(timep, offset, tmp);
+ return;
+ }
+#endif /* defined ALL_STATE */
+ if (sp->timecnt == 0 || t < sp->ats[0]) {
+ i = 0;
+ while (sp->ttis[i].tt_isdst)
+ if (++i >= sp->typecnt) {
+ i = 0;
+ break;
+ }
+ } else {
+ for (i = 1; i < sp->timecnt; ++i)
+ if (t < sp->ats[i])
+ break;
+ i = sp->types[i - 1];
+ }
+ ttisp = &sp->ttis[i];
+ /*
+ ** To get (wrong) behavior that's compatible with System V Release 2.0
+ ** you'd replace the statement below with
+ ** t += ttisp->tt_gmtoff;
+ ** timesub(&t, 0L, sp, tmp);
+ */
+ timesub(&t, ttisp->tt_gmtoff, sp, tmp);
+ tmp->tm_isdst = ttisp->tt_isdst;
+ tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
+#ifdef TM_ZONE
+ tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
+#endif /* defined TM_ZONE */
+}
+
+#ifdef _THREAD_SAFE
+struct tm *
+localtime_r(timep, p_tm)
+const time_t * const timep;
+struct tm *p_tm;
+{
+ pthread_mutex_lock(&lcl_mutex);
+ tzset();
+ localsub(timep, 0L, p_tm);
+ pthread_mutex_unlock(&lcl_mutex);
+ return(p_tm);
+}
+#endif
+
+struct tm *
+localtime(timep)
+const time_t * const timep;
+{
+#ifdef _THREAD_SAFE
+ static struct pthread_mutex _localtime_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static pthread_mutex_t localtime_mutex = &_localtime_mutex;
+ static pthread_key_t localtime_key = -1;
+ struct tm *p_tm;
+
+ pthread_mutex_lock(&localtime_mutex);
+ if (localtime_key < 0) {
+ if (pthread_key_create(&localtime_key, free) < 0) {
+ pthread_mutex_unlock(&localtime_mutex);
+ return(NULL);
+ }
+ }
+ pthread_mutex_unlock(&localtime_mutex);
+ p_tm = pthread_getspecific(localtime_key);
+ if (p_tm == NULL) {
+ if ((p_tm = (struct tm *)malloc(sizeof(struct tm))) == NULL)
+ return(NULL);
+ pthread_setspecific(localtime_key, p_tm);
+ }
+ pthread_mutex_lock(&lcl_mutex);
+ tzset();
+ localsub(timep, 0L, p_tm);
+ pthread_mutex_unlock(&lcl_mutex);
+ return p_tm;
+#else
+ tzset();
+ localsub(timep, 0L, &tm);
+ return &tm;
+#endif
+}
+
+/*
+** gmtsub is to gmtime as localsub is to localtime.
+*/
+
+static void
+gmtsub(timep, offset, tmp)
+const time_t * const timep;
+const long offset;
+struct tm * const tmp;
+{
+#ifdef _THREAD_SAFE
+ pthread_mutex_lock(&gmt_mutex);
+#endif
+ if (!gmt_is_set) {
+ gmt_is_set = TRUE;
+#ifdef ALL_STATE
+ gmtptr = (struct state *) malloc(sizeof *gmtptr);
+ if (gmtptr != NULL)
+#endif /* defined ALL_STATE */
+ gmtload(gmtptr);
+ }
+#ifdef _THREAD_SAFE
+ pthread_mutex_unlock(&gmt_mutex);
+#endif
+ timesub(timep, offset, gmtptr, tmp);
+#ifdef TM_ZONE
+ /*
+ ** Could get fancy here and deliver something such as
+ ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero,
+ ** but this is no time for a treasure hunt.
+ */
+ if (offset != 0)
+ tmp->TM_ZONE = wildabbr;
+ else {
+#ifdef ALL_STATE
+ if (gmtptr == NULL)
+ tmp->TM_ZONE = gmt;
+ else tmp->TM_ZONE = gmtptr->chars;
+#endif /* defined ALL_STATE */
+#ifndef ALL_STATE
+ tmp->TM_ZONE = gmtptr->chars;
+#endif /* State Farm */
+ }
+#endif /* defined TM_ZONE */
+}
+
+struct tm *
+gmtime(timep)
+const time_t * const timep;
+{
+#ifdef _THREAD_SAFE
+ static struct pthread_mutex _gmtime_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static pthread_mutex_t gmtime_mutex = &_gmtime_mutex;
+ static pthread_key_t gmtime_key = -1;
+ struct tm *p_tm;
+
+ pthread_mutex_lock(&gmtime_mutex);
+ if (gmtime_key < 0) {
+ if (pthread_key_create(&gmtime_key, free) < 0) {
+ pthread_mutex_unlock(&gmtime_mutex);
+ return(NULL);
+ }
+ }
+ pthread_mutex_unlock(&gmtime_mutex);
+ if ((p_tm = pthread_getspecific(gmtime_key)) != 0) {
+ return(NULL);
+ } else if (p_tm == NULL) {
+ if ((p_tm = (struct tm *)malloc(sizeof(struct tm))) == NULL) {
+ return(NULL);
+ }
+ pthread_setspecific(gmtime_key, p_tm);
+ }
+ gmtsub(timep, 0L, p_tm);
+ return(p_tm);
+#else
+ gmtsub(timep, 0L, &tm);
+ return &tm;
+#endif
+}
+
+#ifdef _THREAD_SAFE
+struct tm *
+gmtime_r(const time_t * timep, struct tm * tm)
+{
+ gmtsub(timep, 0L, tm);
+ return(tm);
+}
+#endif
+
+#ifdef STD_INSPIRED
+
+struct tm *
+offtime(timep, offset)
+const time_t * const timep;
+const long offset;
+{
+ gmtsub(timep, offset, &tm);
+ return &tm;
+}
+
+#endif /* defined STD_INSPIRED */
+
+static void
+timesub(timep, offset, sp, tmp)
+const time_t * const timep;
+const long offset;
+register const struct state * const sp;
+register struct tm * const tmp;
+{
+ register const struct lsinfo * lp;
+ register long days;
+ register long rem;
+ register int y;
+ register int yleap;
+ register const int * ip;
+ register long corr;
+ register int hit;
+ register int i;
+
+ corr = 0;
+ hit = 0;
+#ifdef ALL_STATE
+ i = (sp == NULL) ? 0 : sp->leapcnt;
+#endif /* defined ALL_STATE */
+#ifndef ALL_STATE
+ i = sp->leapcnt;
+#endif /* State Farm */
+ while (--i >= 0) {
+ lp = &sp->lsis[i];
+ if (*timep >= lp->ls_trans) {
+ if (*timep == lp->ls_trans) {
+ hit = ((i == 0 && lp->ls_corr > 0) ||
+ lp->ls_corr > sp->lsis[i - 1].ls_corr);
+ if (hit)
+ while (i > 0 &&
+ sp->lsis[i].ls_trans ==
+ sp->lsis[i - 1].ls_trans + 1 &&
+ sp->lsis[i].ls_corr ==
+ sp->lsis[i - 1].ls_corr + 1) {
+ ++hit;
+ --i;
+ }
+ }
+ corr = lp->ls_corr;
+ break;
+ }
+ }
+ days = *timep / SECSPERDAY;
+ rem = *timep % SECSPERDAY;
+#ifdef mc68k
+ if (*timep == 0x80000000) {
+ /*
+ ** A 3B1 muffs the division on the most negative number.
+ */
+ days = -24855;
+ rem = -11648;
+ }
+#endif /* defined mc68k */
+ rem += (offset - corr);
+ while (rem < 0) {
+ rem += SECSPERDAY;
+ --days;
+ }
+ while (rem >= SECSPERDAY) {
+ rem -= SECSPERDAY;
+ ++days;
+ }
+ tmp->tm_hour = (int) (rem / SECSPERHOUR);
+ rem = rem % SECSPERHOUR;
+ tmp->tm_min = (int) (rem / SECSPERMIN);
+ /*
+ ** A positive leap second requires a special
+ ** representation. This uses "... ??:59:60" et seq.
+ */
+ tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
+ tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
+ if (tmp->tm_wday < 0)
+ tmp->tm_wday += DAYSPERWEEK;
+ y = EPOCH_YEAR;
+#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
+ while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
+ register int newy;
+
+ newy = y + days / DAYSPERNYEAR;
+ if (days < 0)
+ --newy;
+ days -= (newy - y) * DAYSPERNYEAR +
+ LEAPS_THRU_END_OF(newy - 1) -
+ LEAPS_THRU_END_OF(y - 1);
+ y = newy;
+ }
+ tmp->tm_year = y - TM_YEAR_BASE;
+ tmp->tm_yday = (int) days;
+ ip = mon_lengths[yleap];
+ for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
+ days = days - (long) ip[tmp->tm_mon];
+ tmp->tm_mday = (int) (days + 1);
+ tmp->tm_isdst = 0;
+#ifdef TM_GMTOFF
+ tmp->TM_GMTOFF = offset;
+#endif /* defined TM_GMTOFF */
+}
+
+char *
+ctime(timep)
+const time_t * const timep;
+{
+/*
+** Section 4.12.3.2 of X3.159-1989 requires that
+** The ctime funciton converts the calendar time pointed to by timer
+** to local time in the form of a string. It is equivalent to
+** asctime(localtime(timer))
+*/
+ return asctime(localtime(timep));
+}
+
+/*
+** Adapted from code provided by Robert Elz, who writes:
+** The "best" way to do mktime I think is based on an idea of Bob
+** Kridle's (so its said...) from a long time ago.
+** [kridle@xinet.com as of 1996-01-16.]
+** It does a binary search of the time_t space. Since time_t's are
+** just 32 bits, its a max of 32 iterations (even at 64 bits it
+** would still be very reasonable).
+*/
+
+#ifndef WRONG
+#define WRONG (-1)
+#endif /* !defined WRONG */
+
+/*
+** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
+*/
+
+static int
+increment_overflow(number, delta)
+int * number;
+int delta;
+{
+ int number0;
+
+ number0 = *number;
+ *number += delta;
+ return (*number < number0) != (delta < 0);
+}
+
+static int
+normalize_overflow(tensptr, unitsptr, base)
+int * const tensptr;
+int * const unitsptr;
+const int base;
+{
+ register int tensdelta;
+
+ tensdelta = (*unitsptr >= 0) ?
+ (*unitsptr / base) :
+ (-1 - (-1 - *unitsptr) / base);
+ *unitsptr -= tensdelta * base;
+ return increment_overflow(tensptr, tensdelta);
+}
+
+static int
+tmcomp(atmp, btmp)
+register const struct tm * const atmp;
+register const struct tm * const btmp;
+{
+ register int result;
+
+ if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
+ (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
+ (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
+ (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
+ (result = (atmp->tm_min - btmp->tm_min)) == 0)
+ result = atmp->tm_sec - btmp->tm_sec;
+ return result;
+}
+
+static time_t
+time2(tmp, funcp, offset, okayp)
+struct tm * const tmp;
+void (* const funcp) P((const time_t*, long, struct tm*));
+const long offset;
+int * const okayp;
+{
+ register const struct state * sp;
+ register int dir;
+ register int bits;
+ register int i, j ;
+ register int saved_seconds;
+ time_t newt;
+ time_t t;
+ struct tm yourtm, mytm;
+
+ *okayp = FALSE;
+ yourtm = *tmp;
+ if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
+ return WRONG;
+ if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
+ return WRONG;
+ if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
+ return WRONG;
+ /*
+ ** Turn yourtm.tm_year into an actual year number for now.
+ ** It is converted back to an offset from TM_YEAR_BASE later.
+ */
+ if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
+ return WRONG;
+ while (yourtm.tm_mday <= 0) {
+ if (increment_overflow(&yourtm.tm_year, -1))
+ return WRONG;
+ i = yourtm.tm_year + (1 < yourtm.tm_mon);
+ yourtm.tm_mday += year_lengths[isleap(i)];
+ }
+ while (yourtm.tm_mday > DAYSPERLYEAR) {
+ i = yourtm.tm_year + (1 < yourtm.tm_mon);
+ yourtm.tm_mday -= year_lengths[isleap(i)];
+ if (increment_overflow(&yourtm.tm_year, 1))
+ return WRONG;
+ }
+ for ( ; ; ) {
+ i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
+ if (yourtm.tm_mday <= i)
+ break;
+ yourtm.tm_mday -= i;
+ if (++yourtm.tm_mon >= MONSPERYEAR) {
+ yourtm.tm_mon = 0;
+ if (increment_overflow(&yourtm.tm_year, 1))
+ return WRONG;
+ }
+ }
+ if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
+ return WRONG;
+ if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
+ /*
+ ** We can't set tm_sec to 0, because that might push the
+ ** time below the minimum representable time.
+ ** Set tm_sec to 59 instead.
+ ** This assumes that the minimum representable time is
+ ** not in the same minute that a leap second was deleted from,
+ ** which is a safer assumption than using 58 would be.
+ */
+ if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
+ return WRONG;
+ saved_seconds = yourtm.tm_sec;
+ yourtm.tm_sec = SECSPERMIN - 1;
+ } else {
+ saved_seconds = yourtm.tm_sec;
+ yourtm.tm_sec = 0;
+ }
+ /*
+ ** Divide the search space in half
+ ** (this works whether time_t is signed or unsigned).
+ */
+ bits = TYPE_BIT(time_t) - 1;
+ /*
+ ** If time_t is signed, then 0 is just above the median,
+ ** assuming two's complement arithmetic.
+ ** If time_t is unsigned, then (1 << bits) is just above the median.
+ */
+ t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
+ for ( ; ; ) {
+ (*funcp)(&t, offset, &mytm);
+ dir = tmcomp(&mytm, &yourtm);
+ if (dir != 0) {
+ if (bits-- < 0)
+ return WRONG;
+ if (bits < 0)
+ --t; /* may be needed if new t is minimal */
+ else if (dir > 0)
+ t -= ((time_t) 1) << bits;
+ else t += ((time_t) 1) << bits;
+ continue;
+ }
+ if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
+ break;
+ /*
+ ** Right time, wrong type.
+ ** Hunt for right time, right type.
+ ** It's okay to guess wrong since the guess
+ ** gets checked.
+ */
+ /*
+ ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
+ */
+ sp = (const struct state *)
+ (((void *) funcp == (void *) localsub) ?
+ lclptr : gmtptr);
+#ifdef ALL_STATE
+ if (sp == NULL)
+ return WRONG;
+#endif /* defined ALL_STATE */
+ for (i = sp->typecnt - 1; i >= 0; --i) {
+ if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
+ continue;
+ for (j = sp->typecnt - 1; j >= 0; --j) {
+ if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
+ continue;
+ newt = t + sp->ttis[j].tt_gmtoff -
+ sp->ttis[i].tt_gmtoff;
+ (*funcp)(&newt, offset, &mytm);
+ if (tmcomp(&mytm, &yourtm) != 0)
+ continue;
+ if (mytm.tm_isdst != yourtm.tm_isdst)
+ continue;
+ /*
+ ** We have a match.
+ */
+ t = newt;
+ goto label;
+ }
+ }
+ return WRONG;
+ }
+label:
+ newt = t + saved_seconds;
+ if ((newt < t) != (saved_seconds < 0))
+ return WRONG;
+ t = newt;
+ (*funcp)(&t, offset, tmp);
+ *okayp = TRUE;
+ return t;
+}
+
+static time_t
+time1(tmp, funcp, offset)
+struct tm * const tmp;
+void (* const funcp) P((const time_t *, long, struct tm *));
+const long offset;
+{
+ register time_t t;
+ register const struct state * sp;
+ register int samei, otheri;
+ int okay;
+
+ if (tmp->tm_isdst > 1)
+ tmp->tm_isdst = 1;
+ t = time2(tmp, funcp, offset, &okay);
+#ifdef PCTS
+ /*
+ ** PCTS code courtesy Grant Sullivan (grant@osf.org).
+ */
+ if (okay)
+ return t;
+ if (tmp->tm_isdst < 0)
+ tmp->tm_isdst = 0; /* reset to std and try again */
+#endif /* defined PCTS */
+#ifndef PCTS
+ if (okay || tmp->tm_isdst < 0)
+ return t;
+#endif /* !defined PCTS */
+ /*
+ ** We're supposed to assume that somebody took a time of one type
+ ** and did some math on it that yielded a "struct tm" that's bad.
+ ** We try to divine the type they started from and adjust to the
+ ** type they need.
+ */
+ /*
+ ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
+ */
+ sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
+ lclptr : gmtptr);
+#ifdef ALL_STATE
+ if (sp == NULL)
+ return WRONG;
+#endif /* defined ALL_STATE */
+ for (samei = sp->typecnt - 1; samei >= 0; --samei) {
+ if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
+ continue;
+ for (otheri = sp->typecnt - 1; otheri >= 0; --otheri) {
+ if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
+ continue;
+ tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
+ sp->ttis[samei].tt_gmtoff;
+ tmp->tm_isdst = !tmp->tm_isdst;
+ t = time2(tmp, funcp, offset, &okay);
+ if (okay)
+ return t;
+ tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
+ sp->ttis[samei].tt_gmtoff;
+ tmp->tm_isdst = !tmp->tm_isdst;
+ }
+ }
+ return WRONG;
+}
+
+time_t
+mktime(tmp)
+struct tm * const tmp;
+{
+ time_t mktime_return_value;
+#ifdef _THREAD_SAFE
+ pthread_mutex_lock(&lcl_mutex);
+#endif
+ tzset();
+ mktime_return_value = time1(tmp, localsub, 0L);
+#ifdef _THREAD_SAFE
+ pthread_mutex_unlock(&lcl_mutex);
+#endif
+ return(mktime_return_value);
+}
+
+#ifdef STD_INSPIRED
+
+time_t
+timelocal(tmp)
+struct tm * const tmp;
+{
+ tmp->tm_isdst = -1; /* in case it wasn't initialized */
+ return mktime(tmp);
+}
+
+time_t
+timegm(tmp)
+struct tm * const tmp;
+{
+ tmp->tm_isdst = 0;
+ return time1(tmp, gmtsub, 0L);
+}
+
+time_t
+timeoff(tmp, offset)
+struct tm * const tmp;
+const long offset;
+{
+ tmp->tm_isdst = 0;
+ return time1(tmp, gmtsub, offset);
+}
+
+#endif /* defined STD_INSPIRED */
+
+#ifdef CMUCS
+
+/*
+** The following is supplied for compatibility with
+** previous versions of the CMUCS runtime library.
+*/
+
+long
+gtime(tmp)
+struct tm * const tmp;
+{
+ const time_t t = mktime(tmp);
+
+ if (t == WRONG)
+ return -1;
+ return t;
+}
+
+#endif /* defined CMUCS */
+
+/*
+** XXX--is the below the right way to conditionalize??
+*/
+
+#ifdef STD_INSPIRED
+
+/*
+** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
+** shall correspond to "Wed Dec 31 23:59:59 GMT 1986", which
+** is not the case if we are accounting for leap seconds.
+** So, we provide the following conversion routines for use
+** when exchanging timestamps with POSIX conforming systems.
+*/
+
+static long
+leapcorr(timep)
+time_t * timep;
+{
+ register struct state * sp;
+ register struct lsinfo * lp;
+ register int i;
+
+ sp = lclptr;
+ i = sp->leapcnt;
+ while (--i >= 0) {
+ lp = &sp->lsis[i];
+ if (*timep >= lp->ls_trans)
+ return lp->ls_corr;
+ }
+ return 0;
+}
+
+time_t
+time2posix(t)
+time_t t;
+{
+ tzset();
+ return t - leapcorr(&t);
+}
+
+time_t
+posix2time(t)
+time_t t;
+{
+ time_t x;
+ time_t y;
+
+ tzset();
+ /*
+ ** For a positive leap second hit, the result
+ ** is not unique. For a negative leap second
+ ** hit, the corresponding time doesn't exist,
+ ** so we return an adjacent second.
+ */
+ x = t + leapcorr(&t);
+ y = x - leapcorr(&x);
+ if (y < t) {
+ do {
+ x++;
+ y = x - leapcorr(&x);
+ } while (y < t);
+ if (t != y)
+ return x - 1;
+ } else if (y > t) {
+ do {
+ --x;
+ y = x - leapcorr(&x);
+ } while (y > t);
+ if (t != y)
+ return x + 1;
+ }
+ return x;
+}
+
+#endif /* defined STD_INSPIRED */
diff --git a/lib/libc/stdtime/private.h b/lib/libc/stdtime/private.h
new file mode 100644
index 0000000..d8fa906
--- /dev/null
+++ b/lib/libc/stdtime/private.h
@@ -0,0 +1,218 @@
+#ifndef PRIVATE_H
+
+#define PRIVATE_H
+/*
+** This file is in the public domain, so clarified as of
+** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+/* Stuff moved from Makefile.inc to reduce clutter */
+#ifndef TM_GMTOFF
+#define TM_GMTOFF tm_gmtoff
+#define TM_ZONE tm_zone
+#define STD_INSPIRED 1
+#define PCTS 1
+#define HAVE_LONG_DOUBLE 1
+#define HAVE_STRERROR 1
+#define HAVE_UNISTD_H 1
+#define LOCALE_HOME _PATH_LOCALE
+#define TZDIR "/usr/share/zoneinfo"
+#endif /* ndef TM_GMTOFF */
+
+/*
+** This header is for use ONLY with the time conversion code.
+** There is no guarantee that it will remain unchanged,
+** or that it will remain at all.
+** Do NOT copy it to any system include directory.
+** Thank you!
+*/
+
+/*
+** ID
+*/
+
+#ifndef lint
+#ifndef NOID
+/*
+static char privatehid[] = "@(#)private.h 7.43";
+*/
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*
+** Defaults for preprocessor symbols.
+** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
+*/
+
+#ifndef HAVE_ADJTIME
+#define HAVE_ADJTIME 1
+#endif /* !defined HAVE_ADJTIME */
+
+#ifndef HAVE_GETTEXT
+#define HAVE_GETTEXT 0
+#endif /* !defined HAVE_GETTEXT */
+
+#ifndef HAVE_SETTIMEOFDAY
+#define HAVE_SETTIMEOFDAY 3
+#endif /* !defined HAVE_SETTIMEOFDAY */
+
+#ifndef HAVE_STRERROR
+#define HAVE_STRERROR 0
+#endif /* !defined HAVE_STRERROR */
+
+#ifndef HAVE_UNISTD_H
+#define HAVE_UNISTD_H 1
+#endif /* !defined HAVE_UNISTD_H */
+
+#ifndef HAVE_UTMPX_H
+#define HAVE_UTMPX_H 0
+#endif /* !defined HAVE_UTMPX_H */
+
+#ifndef LOCALE_HOME
+#define LOCALE_HOME "/usr/lib/locale"
+#endif /* !defined LOCALE_HOME */
+
+/*
+** Nested includes
+*/
+
+#include "sys/types.h" /* for time_t */
+#include "stdio.h"
+#include "errno.h"
+#include "string.h"
+#include "limits.h" /* for CHAR_BIT */
+#include "time.h"
+#include "stdlib.h"
+
+#if HAVE_GETTEXT - 0
+#include "libintl.h"
+#endif /* HAVE_GETTEXT - 0 */
+
+#if HAVE_UNISTD_H - 0
+#include "unistd.h" /* for F_OK and R_OK */
+#endif /* HAVE_UNISTD_H - 0 */
+
+#if !(HAVE_UNISTD_H - 0)
+#ifndef F_OK
+#define F_OK 0
+#endif /* !defined F_OK */
+#ifndef R_OK
+#define R_OK 4
+#endif /* !defined R_OK */
+#endif /* !(HAVE_UNISTD_H - 0) */
+
+/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
+#define is_digit(c) ((unsigned)(c) - '0' <= 9)
+
+/*
+** Workarounds for compilers/systems.
+*/
+
+#ifndef P
+#ifdef __STDC__
+#define P(x) x
+#endif /* defined __STDC__ */
+#ifndef __STDC__
+#define P(x) ()
+#endif /* !defined __STDC__ */
+#endif /* !defined P */
+
+/*
+** SunOS 4.1.1 headers lack FILENAME_MAX.
+*/
+
+#ifndef FILENAME_MAX
+
+#ifndef MAXPATHLEN
+#ifdef unix
+#include "sys/param.h"
+#endif /* defined unix */
+#endif /* !defined MAXPATHLEN */
+
+#ifdef MAXPATHLEN
+#define FILENAME_MAX MAXPATHLEN
+#endif /* defined MAXPATHLEN */
+#ifndef MAXPATHLEN
+#define FILENAME_MAX 1024 /* Pure guesswork */
+#endif /* !defined MAXPATHLEN */
+
+#endif /* !defined FILENAME_MAX */
+
+/*
+** Finally, some convenience items.
+*/
+
+#ifndef TRUE
+#define TRUE 1
+#endif /* !defined TRUE */
+
+#ifndef FALSE
+#define FALSE 0
+#endif /* !defined FALSE */
+
+#ifndef TYPE_BIT
+#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
+#endif /* !defined TYPE_BIT */
+
+#ifndef TYPE_SIGNED
+#define TYPE_SIGNED(type) (((type) -1) < 0)
+#endif /* !defined TYPE_SIGNED */
+
+#ifndef INT_STRLEN_MAXIMUM
+/*
+** 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 / 100 + 1 + TYPE_SIGNED(type))
+#endif /* !defined INT_STRLEN_MAXIMUM */
+
+/*
+** INITIALIZE(x)
+*/
+
+#ifndef GNUC_or_lint
+#ifdef lint
+#define GNUC_or_lint
+#endif /* defined lint */
+#ifndef lint
+#ifdef __GNUC__
+#define GNUC_or_lint
+#endif /* defined __GNUC__ */
+#endif /* !defined lint */
+#endif /* !defined GNUC_or_lint */
+
+#ifndef INITIALIZE
+#ifdef GNUC_or_lint
+#define INITIALIZE(x) ((x) = 0)
+#endif /* defined GNUC_or_lint */
+#ifndef GNUC_or_lint
+#define INITIALIZE(x)
+#endif /* !defined GNUC_or_lint */
+#endif /* !defined INITIALIZE */
+
+/*
+** For the benefit of GNU folk...
+** `_(MSGID)' uses the current locale's message library string for MSGID.
+** The default is to use gettext if available, and use MSGID otherwise.
+*/
+
+#ifndef _
+#if HAVE_GETTEXT - 0
+#define _(msgid) gettext(msgid)
+#else /* !(HAVE_GETTEXT - 0) */
+#define _(msgid) msgid
+#endif /* !(HAVE_GETTEXT - 0) */
+#endif /* !defined _ */
+
+#ifndef TZ_DOMAIN
+#define TZ_DOMAIN "tz"
+#endif /* !defined TZ_DOMAIN */
+
+/*
+** UNIX was a registered trademark of UNIX System Laboratories in 1993.
+*/
+
+#endif /* !defined PRIVATE_H */
diff --git a/lib/libc/stdtime/strftime.3 b/lib/libc/stdtime/strftime.3
new file mode 100644
index 0000000..27c826a
--- /dev/null
+++ b/lib/libc/stdtime/strftime.3
@@ -0,0 +1,212 @@
+.\" 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.
+.\" 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.
+.\"
+.\" @(#)strftime.3 8.1 (Berkeley) 6/4/93
+.\"
+.Dd June 4, 1993
+.Dt STRFTIME 3
+.Os
+.Sh NAME
+.Nm strftime
+.Nd format date and time
+.Sh SYNOPSIS
+.Fd #include <time.h>
+.Ft size_t
+.Fn strftime "char *buf" "size_t maxsize" "const char *format" "const struct tm *timeptr"
+.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
+null character, is not more than
+.Fa maxsize ,
+.Fn strftime
+returns the number of characters in the array, not counting the
+terminating null.
+Otherwise, zero is returned and the buffer contents is indeterminate.
+.Pp
+Each conversion specification is replaced by the characters as
+follows which are then copied into the buffer.
+.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, where the abbreviation
+is the first three characters.
+.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, where the abbreviation is
+the first three characters.
+.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
+(the format is similar with produced by
+.Xr asctime 3 ) .
+.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*
+POSIX locale extensions.
+The sequences
+%Ec %EC %Ex %Ey %EY
+%Od %Oe %OH %OI %Om %OM
+%OS %Ou %OU %OV %Ow %OW %Oy
+are supposed to provide alternate
+representations.
+.It Cm %e
+is replaced by the day of month as a decimal number (1-31); single
+digits are preceded by a blank.
+.It Cm \&%H
+is replaced by the hour (24-hour clock) as a decimal number (00-23).
+.It Cm %h
+the same as %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 %E*.
+.It Cm %p
+is replaced by national representation of either
+"ante meridiem"
+or
+"post meridiem"
+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 (the first
+Monday as the first day of week 1) as a
+decimal number (01-53).
+.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 %+
+is replaced by national representation of the date and time
+(the format is similar with produced by
+.Xr date 1 ) .
+.It Cm %%
+is replaced by
+.Ql % .
+.El
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr printf 1 ,
+.Xr ctime 3 ,
+.Xr printf 3
+.Sh STANDARDS
+The
+.Fn strftime
+function
+conforms to
+.St -ansiC .
+The
+.Ql %s
+conversion specification is an extension.
+.Sh BUGS
+There is no conversion specification for the phase of the moon.
diff --git a/lib/libc/stdtime/strftime.c b/lib/libc/stdtime/strftime.c
new file mode 100644
index 0000000..b44ff68
--- /dev/null
+++ b/lib/libc/stdtime/strftime.c
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#ifdef LIBC_RCS
+static const char rcsid[] =
+ "$Id$";
+#endif
+
+#ifndef lint
+#ifndef NOID
+static const char elsieid[] = "@(#)strftime.c 7.38";
+/*
+** 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 "private.h"
+
+#ifndef LIBC_SCCS
+#ifndef lint
+static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
+#endif /* !defined lint */
+#endif /* !defined LIBC_SCCS */
+
+#include "tzfile.h"
+#include <fcntl.h>
+#include <locale.h>
+#include <sys/stat.h>
+#include "setlocale.h"
+
+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;
+};
+
+static struct lc_time_T localebuf;
+static int using_locale;
+
+#define Locale (using_locale ? &localebuf : &C_time_locale)
+
+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 (ctime-compatible)
+ ** Note that
+ ** "%a %b %d %H:%M:%S %Y"
+ ** is used by Solaris 2.3.
+ */
+ "%a %b %e %X %Y",
+
+ /* am */
+ "AM",
+
+ /* pm */
+ "PM",
+
+ /* date_fmt */
+ "%a %b %e %X %Z %Y"
+};
+
+static char * _add P((const char *, char *, const char *));
+static char * _conv P((int, const char *, char *, const char *));
+static char * _fmt P((const char *, const struct tm *, char *, const char *));
+static char * _secs P((const struct tm *, char *, const char *));
+
+size_t strftime P((char *, size_t, const char *, const struct tm *));
+
+extern char * tzname[];
+
+size_t
+strftime(s, maxsize, format, t)
+ char *const s;
+ const size_t maxsize;
+ const char *const format;
+ const struct tm *const t;
+{
+ char *p;
+
+ tzset();
+ p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize);
+ if (p == s + maxsize)
+ return 0;
+ *p = '\0';
+ return p - s;
+}
+
+static char *
+_fmt(format, t, pt, ptlim)
+ const char *format;
+ const struct tm *const t;
+ char *pt;
+ const char *const ptlim;
+{
+ for ( ; *format; ++format) {
+ if (*format == '%') {
+label:
+ switch (*++format) {
+ case '\0':
+ --format;
+ break;
+ case 'A':
+ pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
+ "?" : Locale->weekday[t->tm_wday],
+ pt, ptlim);
+ continue;
+ case 'a':
+ pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
+ "?" : Locale->wday[t->tm_wday],
+ pt, ptlim);
+ continue;
+ case 'B':
+ pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
+ "?" : Locale->month[t->tm_mon],
+ pt, ptlim);
+ continue;
+ case 'b':
+ case 'h':
+ pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
+ "?" : Locale->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, 5/24/93)
+ */
+ pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
+ "%02d", pt, ptlim);
+ continue;
+ case 'c':
+ pt = _fmt(Locale->c_fmt, t, pt, ptlim);
+ continue;
+ case 'D':
+ pt = _fmt("%m/%d/%y", t, pt, ptlim);
+ continue;
+ case 'd':
+ pt = _conv(t->tm_mday, "%02d", pt, ptlim);
+ continue;
+ case 'E':
+ case 'O':
+ /*
+ ** POSIX locale extensions, a la
+ ** Arnold Robbins' strftime version 3.0.
+ ** The sequences
+ ** %Ec %EC %Ex %Ey %EY
+ ** %Od %oe %OH %OI %Om %OM
+ ** %OS %Ou %OU %OV %Ow %OW %Oy
+ ** are supposed to provide alternate
+ ** representations.
+ ** (ado, 5/24/93)
+ */
+ goto label;
+ case 'e':
+ pt = _conv(t->tm_mday, "%2d", pt, ptlim);
+ continue;
+ case 'H':
+ pt = _conv(t->tm_hour, "%02d", pt, ptlim);
+ continue;
+ case 'I':
+ pt = _conv((t->tm_hour % 12) ?
+ (t->tm_hour % 12) : 12,
+ "%02d", pt, ptlim);
+ continue;
+ case 'j':
+ pt = _conv(t->tm_yday + 1, "%03d", 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, 5/24/93)
+ */
+ pt = _conv(t->tm_hour, "%2d", 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, 5/24/93)
+ */
+ pt = _conv((t->tm_hour % 12) ?
+ (t->tm_hour % 12) : 12,
+ "%2d", pt, ptlim);
+ continue;
+ case 'M':
+ pt = _conv(t->tm_min, "%02d", pt, ptlim);
+ continue;
+ case 'm':
+ pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
+ continue;
+ case 'n':
+ pt = _add("\n", pt, ptlim);
+ continue;
+ case 'p':
+ pt = _add((t->tm_hour >= 12) ?
+ Locale->pm :
+ Locale->am,
+ pt, ptlim);
+ continue;
+ case 'R':
+ pt = _fmt("%H:%M", t, pt, ptlim);
+ continue;
+ case 'r':
+ pt = _fmt("%I:%M:%S %p", t, pt, ptlim);
+ continue;
+ case 'S':
+ pt = _conv(t->tm_sec, "%02d", pt, ptlim);
+ continue;
+ case 's':
+ pt = _secs(t, pt, ptlim);
+ continue;
+ case 'T':
+ pt = _fmt("%H:%M:%S", t, pt, ptlim);
+ continue;
+ case 't':
+ pt = _add("\t", pt, ptlim);
+ continue;
+ case 'U':
+ pt = _conv((t->tm_yday + 7 - t->tm_wday) / 7,
+ "%02d", pt, ptlim);
+ continue;
+ case 'u':
+ /*
+ ** From Arnold Robbins' strftime version 3.0:
+ ** "ISO 8601: Weekday as a decimal number
+ ** [1 (Monday) - 7]"
+ ** (ado, 5/24/93)
+ */
+ pt = _conv((t->tm_wday == 0) ? 7 : t->tm_wday,
+ "%d", pt, ptlim);
+ continue;
+ case 'V':
+ /*
+ ** 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). The method for
+ ** determining the week number is as specified
+ ** by ISO 8601 (to wit: if the week containing
+ ** January 1 has four or more days in the new
+ ** year, then it is week 1, otherwise it is
+ ** week 53 of the previous year and the next
+ ** week is week 1)."
+ ** (ado, 5/24/93)
+ */
+ /*
+ ** XXX--If January 1 falls on a Friday,
+ ** January 1-3 are part of week 53 of the
+ ** previous year. By analogy, if January
+ ** 1 falls on a Thursday, are December 29-31
+ ** of the PREVIOUS year part of week 1???
+ ** (ado 5/24/93)
+ */
+ /*
+ ** You are understood not to expect this.
+ */
+ {
+ int i;
+
+ i = (t->tm_yday + 10 - (t->tm_wday ?
+ (t->tm_wday - 1) : 6)) / 7;
+ if (i == 0) {
+ /*
+ ** What day of the week does
+ ** January 1 fall on?
+ */
+ i = t->tm_wday -
+ (t->tm_yday - 1);
+ /*
+ ** Fri Jan 1: 53
+ ** Sun Jan 1: 52
+ ** Sat Jan 1: 53 if previous
+ ** year a leap
+ ** year, else 52
+ */
+ if (i == TM_FRIDAY)
+ i = 53;
+ else if (i == TM_SUNDAY)
+ i = 52;
+ else i = isleap(t->tm_year +
+ TM_YEAR_BASE) ?
+ 53 : 52;
+#ifdef XPG4_1994_04_09
+ /*
+ ** As of 4/9/94, though,
+ ** XPG4 calls for 53
+ ** unconditionally.
+ */
+ i = 53;
+#endif /* defined XPG4_1994_04_09 */
+ }
+ pt = _conv(i, "%02d", pt, ptlim);
+ }
+ continue;
+ case 'v':
+ /*
+ ** From Arnold Robbins' strftime version 3.0:
+ ** "date as dd-bbb-YYYY"
+ ** (ado, 5/24/93)
+ */
+ pt = _fmt("%e-%b-%Y", t, pt, ptlim);
+ continue;
+ case 'W':
+ pt = _conv((t->tm_yday + 7 -
+ (t->tm_wday ?
+ (t->tm_wday - 1) : 6)) / 7,
+ "%02d", pt, ptlim);
+ continue;
+ case 'w':
+ pt = _conv(t->tm_wday, "%d", pt, ptlim);
+ continue;
+ case 'X':
+ pt = _fmt(Locale->X_fmt, t, pt, ptlim);
+ continue;
+ case 'x':
+ pt = _fmt(Locale->x_fmt, t, pt, ptlim);
+ continue;
+ case 'y':
+ pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
+ "%02d", pt, ptlim);
+ continue;
+ case 'Y':
+ pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d",
+ pt, ptlim);
+ continue;
+ case 'Z':
+ if (t->tm_zone != NULL)
+ pt = _add(t->tm_zone, pt, ptlim);
+ else
+ if (t->tm_isdst == 0 || t->tm_isdst == 1) {
+ pt = _add(tzname[t->tm_isdst],
+ pt, ptlim);
+ } else pt = _add("?", pt, ptlim);
+ continue;
+ case '+':
+ pt = _fmt(Locale->date_fmt, t, pt, ptlim);
+ continue;
+ 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 *
+_secs(t, pt, ptlim)
+ const struct tm *t;
+ char *pt;
+ const char *ptlim;
+{
+ char buf[INT_STRLEN_MAXIMUM(int) + 1];
+ register time_t s;
+ struct tm tmp;
+
+ /* Make a copy, mktime(3) modifies the tm struct. */
+ tmp = *t;
+ s = mktime(&tmp);
+ (void) sprintf(buf, "%ld", s);
+ 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;
+}
+
+int
+__time_load_locale(const char *name)
+{
+ static char * locale_buf;
+ static char locale_buf_C[] = "C";
+
+ int fd;
+ char * lbuf;
+ char * p;
+ const char ** ap;
+ const char * plim;
+ char filename[PATH_MAX];
+ struct stat st;
+ size_t namesize;
+ size_t bufsize;
+ int save_using_locale;
+
+ save_using_locale = using_locale;
+ using_locale = 0;
+
+ if (name == NULL)
+ goto no_locale;
+
+ if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
+ return 0;
+
+ /*
+ ** If the locale name is the same as our cache, use the cache.
+ */
+ lbuf = locale_buf;
+ if (lbuf != NULL && strcmp(name, lbuf) == 0) {
+ p = lbuf;
+ for (ap = (const char **) &localebuf;
+ ap < (const char **) (&localebuf + 1);
+ ++ap)
+ *ap = p += strlen(p) + 1;
+ using_locale = 1;
+ return 0;
+ }
+ /*
+ ** Slurp the locale file into the cache.
+ */
+ namesize = strlen(name) + 1;
+
+ if (!_PathLocale)
+ goto no_locale;
+ /* Range checking not needed, 'name' size is limited */
+ strcpy(filename, _PathLocale);
+ strcat(filename, "/");
+ strcat(filename, name);
+ strcat(filename, "/LC_TIME");
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ goto no_locale;
+ if (fstat(fd, &st) != 0)
+ goto bad_locale;
+ if (st.st_size <= 0)
+ goto bad_locale;
+ bufsize = namesize + st.st_size;
+ locale_buf = NULL;
+ lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
+ malloc(bufsize) : realloc(lbuf, bufsize);
+ if (lbuf == NULL)
+ 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;
+ if (close(fd) != 0)
+ goto bad_lbuf;
+ /*
+ ** Parse the locale file into localebuf.
+ */
+ if (plim[-1] != '\n')
+ goto bad_lbuf;
+ for (ap = (const char **) &localebuf;
+ ap < (const char **) (&localebuf + 1);
+ ++ap) {
+ if (p == plim)
+ goto reset_locale;
+ *ap = p;
+ while (*p != '\n')
+ ++p;
+ *p++ = '\0';
+ }
+ /*
+ ** Record the successful parse in the cache.
+ */
+ locale_buf = lbuf;
+
+ using_locale = 1;
+ return 0;
+
+reset_locale:
+ /*
+ * XXX - This may not be the correct thing to do in this case.
+ * setlocale() assumes that we left the old locale alone.
+ */
+ locale_buf = locale_buf_C;
+ localebuf = C_time_locale;
+ save_using_locale = 0;
+bad_lbuf:
+ free(lbuf);
+bad_locale:
+ (void) close(fd);
+no_locale:
+ using_locale = save_using_locale;
+ return -1;
+}
diff --git a/lib/libc/stdtime/time2posix.3 b/lib/libc/stdtime/time2posix.3
new file mode 100644
index 0000000..38bb1ab
--- /dev/null
+++ b/lib/libc/stdtime/time2posix.3
@@ -0,0 +1,114 @@
+.Dd May 1, 1996
+.Dt TIME2POSIX 3
+.Os
+.Sh NAME
+.Nm time2posix ,
+.Nm posix2time
+.Nd convert seconds since the Epoch
+.Sh SYNOPSIS
+.Fd #include <time.h>
+.Ft time_t
+.Fn time2posix "const time_t *t"
+.Ft time_t
+.Fn posix2time "const time_t *t"
+.Sh DESCRIPTION
+.St -p1003.1-88
+legislates that a time_t value of
+536457599 shall correspond to "Wed Dec 31 23:59:59 GMT 1986."
+This effectively implies that POSIX time_t's cannot include leap
+seconds and,
+therefore,
+that the system time must be adjusted as each leap occurs.
+.Pp
+If the time package is configured with leap-second support
+enabled,
+however,
+no such adjustment is needed and
+time_t values continue to increase over leap events
+(as a true `seconds since...' value).
+This means that these values will differ from those required by POSIX
+by the net number of leap seconds inserted since the Epoch.
+.Pp
+Typically this is not a problem as the type time_t is intended
+to be
+(mostly)
+opaque\(emtime_t values should only be obtained-from and
+passed-to functions such as
+.Xr time 2 ,
+.Xr localtime 3 ,
+.Xr mktime 3
+and
+.Xr difftime 3 .
+However,
+.Std -p1003.1-88
+gives an arithmetic
+expression for directly computing a time_t value from a given date/time,
+and the same relationship is assumed by some
+(usually older)
+applications.
+Any programs creating/dissecting time_t's
+using such a relationship will typically not handle intervals
+over leap seconds correctly.
+.Pp
+The
+.Fn time2posix
+and
+.Fn posix2time
+functions are provided to address this time_t mismatch by converting
+between local time_t values and their POSIX equivalents.
+This is done by accounting for the number of time-base changes that
+would have taken place on a POSIX system as leap seconds were inserted
+or deleted.
+These converted values can then be used in lieu of correcting the older
+applications,
+or when communicating with POSIX-compliant systems.
+.Pp
+The
+.Fn time2posix
+function is single-valued.
+That is,
+every local time_t
+corresponds to a single POSIX time_t.
+The
+.Fn posix2time
+function is less well-behaved:
+for a positive leap second hit the result is not unique,
+and for a negative leap second hit the corresponding
+POSIX time_t doesn't exist so an adjacent value is returned.
+Both of these are good indicators of the inferiority of the
+POSIX representation.
+.Pp
+The following table summarizes the relationship between time_t
+and its conversion to,
+and back from,
+the POSIX representation over the leap second inserted at the end of June,
+1993.
+.ta \w'93/06/30 'u +\w'23:59:59 'u +\w'A+0 'u +\w'X=time2posix(T) 'u
+DATE TIME T X=time2posix(T) posix2time(X)
+93/06/30 23:59:59 A+0 B+0 A+0
+93/06/30 23:59:60 A+1 B+1 A+1 or A+2
+93/07/01 00:00:00 A+2 B+1 A+1 or A+2
+93/07/01 00:00:01 A+3 B+2 A+3
+
+A leap second deletion would look like...
+
+DATE TIME T X=time2posix(T) posix2time(X)
+??/06/30 23:59:58 A+0 B+0 A+0
+??/07/01 00:00:00 A+1 B+2 A+1
+??/07/01 00:00:01 A+2 B+3 A+2
+.Pp
+ [Note: posix2time(B+1) => A+0 or A+1]
+.Pp
+If leap-second support is not enabled,
+local time_t's and
+POSIX time_t's are equivalent,
+and both
+.Fn time2posix
+and
+.Fn posix2time
+degenerate to the identity function.
+.Sh "SEE ALSO"
+.Xr difftime 3 ,
+.Xr localtime 3 ,
+.Xr mktime 3 ,
+.Xr time 3
diff --git a/lib/libc/stdtime/tzfile.5 b/lib/libc/stdtime/tzfile.5
new file mode 100644
index 0000000..f894390
--- /dev/null
+++ b/lib/libc/stdtime/tzfile.5
@@ -0,0 +1,122 @@
+.Dd September 13, 1994
+.Dt TZFILE 5
+.Os FreeBSD 2.0
+.Sh NAME
+.Nm tzfile
+.Nd timezone information
+.Sh SYNOPSIS
+.Fd #include <tzfile.h>
+.Sh DESCRIPTION
+The time zone information files used by
+.Xr tzset 3
+begin with bytes reserved for future use,
+followed by four four-byte values of type
+.Fa long ,
+written in a ``standard'' byte order
+(the high-order byte of the value is written first).
+These values are,
+in order:
+.Pp
+.Bl -tag -compact -width tzh_ttisstdcnt
+.It Li tzh_ttisstdcnt
+The number of standard/wall indicators stored in the file.
+.It Li tzh_leapcnt
+The number of leap seconds for which data is stored in the file.
+.It Li tzh_timecnt
+The number of ``transition times'' for which data is stored
+in the file.
+.It Li tzh_typecnt
+The number of ``local time types'' for which data is stored
+in the file (must not be zero).
+.It Li tzh_charcnt
+The number of characters of ``time zone abbreviation strings''
+stored in the file.
+.El
+.Pp
+The above header is followed by
+.Li tzh_timecnt
+four-byte values of type
+.Fa long ,
+sorted in ascending order.
+These values are written in ``standard'' byte order.
+Each is used as a transition time (as returned by
+.Xr time 3 )
+at which the rules for computing local time change.
+Next come
+.Li tzh_timecnt
+one-byte values of type
+.Fa "unsigned char" ;
+each one tells which of the different types of ``local time'' types
+described in the file is associated with the same-indexed transition time.
+These values serve as indices into an array of
+.Fa ttinfo
+structures that appears next in the file;
+these structures are defined as follows:
+.Pp
+.Bd -literal -offset indent
+struct ttinfo {
+ long tt_gmtoff;
+ int tt_isdst;
+ unsigned int tt_abbrind;
+};
+.Ed
+.Pp
+Each structure is written as a four-byte value for
+.Li tt_gmtoff
+of type
+.Fa long ,
+in a standard byte order, followed by a one-byte value for
+.Li tt_isdst
+and a one-byte value for
+.Li tt_abbrind .
+In each structure,
+.Li tt_gmtoff
+gives the number of seconds to be added to GMT,
+.Li tt_isdst
+tells whether
+.Li tm_isdst
+should be set by
+.Xr localtime 3
+and
+.Li tt_abbrind
+serves as an index into the array of time zone abbreviation characters
+that follow the
+.Li ttinfo
+structure(s) in the file.
+.Pp
+Then there are
+.Li tzh_leapcnt
+pairs of four-byte values, written in standard byte order;
+the first value of each pair gives the time
+(as returned by
+.Xr time 3 )
+at which a leap second occurs;
+the second gives the
+.Em total
+number of leap seconds to be applied after the given time.
+The pairs of values are sorted in ascending order by time.
+.Pp
+Finally there are
+.Li tzh_ttisstdcnt
+standard/wall indicators, each stored as a one-byte value;
+they tell whether the transition times associated with local time types
+were specified as standard time or wall clock time,
+and are used when a time zone file is used in handling POSIX-style
+time zone environment variables.
+.Pp
+.Nm localtime
+uses the first standard-time
+.Li ttinfo
+structure in the file
+(or simply the first
+.Li ttinfo
+structure in the absence of a standard-time structure)
+if either
+.Li tzh_timecnt
+is zero or the time argument is less than the first transition time recorded
+in the file.
+.Sh SEE ALSO
+.Xr ctime 3 ,
+.Xr time2posix 3 ,
+.Xr zic 8
+.\" @(#)tzfile.5 7.2
diff --git a/lib/libc/stdtime/tzfile.h b/lib/libc/stdtime/tzfile.h
new file mode 100644
index 0000000..58cdc3d
--- /dev/null
+++ b/lib/libc/stdtime/tzfile.h
@@ -0,0 +1,187 @@
+#ifndef TZFILE_H
+
+#define TZFILE_H
+
+/*
+** This file is in the public domain, so clarified as of
+** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+/*
+** This header is for use ONLY with the time conversion code.
+** There is no guarantee that it will remain unchanged,
+** or that it will remain at all.
+** Do NOT copy it to any system include directory.
+** Thank you!
+*/
+
+/*
+** ID
+*/
+
+#ifndef lint
+#ifndef NOID
+/*
+static char tzfilehid[] = "@(#)tzfile.h 7.8";
+*/
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*
+** Information about time zone files.
+*/
+
+#ifndef TZDIR
+#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
+#endif /* !defined TZDIR */
+
+#ifndef TZDEFAULT
+#define TZDEFAULT "/etc/localtime"
+#endif /* !defined TZDEFAULT */
+
+#ifndef TZDEFRULES
+#define TZDEFRULES "posixrules"
+#endif /* !defined TZDEFRULES */
+
+/*
+** Each file begins with. . .
+*/
+
+struct tzhead {
+ char tzh_reserved[20]; /* reserved for future use */
+ char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
+ char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
+ char tzh_leapcnt[4]; /* coded number of leap seconds */
+ char tzh_timecnt[4]; /* coded number of transition times */
+ char tzh_typecnt[4]; /* coded number of local time types */
+ char tzh_charcnt[4]; /* coded number of abbr. chars */
+};
+
+/*
+** . . .followed by. . .
+**
+** tzh_timecnt (char [4])s coded transition times a la time(2)
+** tzh_timecnt (unsigned char)s types of local time starting at above
+** tzh_typecnt repetitions of
+** one (char [4]) coded GMT offset in seconds
+** one (unsigned char) used to set tm_isdst
+** one (unsigned char) that's an abbreviation list index
+** tzh_charcnt (char)s '\0'-terminated zone abbreviations
+** tzh_leapcnt repetitions of
+** one (char [4]) coded leap second transition times
+** one (char [4]) total correction after above
+** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
+** time is standard time, if FALSE,
+** transition time is wall clock time
+** if absent, transition times are
+** assumed to be wall clock time
+** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
+** time is GMT, if FALSE,
+** transition time is local time
+** if absent, transition times are
+** assumed to be local time
+*/
+
+/*
+** In the current implementation, "tzset()" refuses to deal with files that
+** exceed any of the limits below.
+*/
+
+#ifndef TZ_MAX_TIMES
+/*
+** The TZ_MAX_TIMES value below is enough to handle a bit more than a
+** year's worth of solar time (corrected daily to the nearest second) or
+** 138 years of Pacific Presidential Election time
+** (where there are three time zone transitions every fourth year).
+*/
+#define TZ_MAX_TIMES 370
+#endif /* !defined TZ_MAX_TIMES */
+
+#ifndef TZ_MAX_TYPES
+#ifndef NOSOLAR
+#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
+#endif /* !defined NOSOLAR */
+#ifdef NOSOLAR
+/*
+** Must be at least 14 for Europe/Riga as of Jan 12 1995,
+** as noted by Earl Chew <earl@hpato.aus.hp.com>.
+*/
+#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
+#endif /* !defined NOSOLAR */
+#endif /* !defined TZ_MAX_TYPES */
+
+#ifndef TZ_MAX_CHARS
+#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
+ /* (limited by what unsigned chars can hold) */
+#endif /* !defined TZ_MAX_CHARS */
+
+#ifndef TZ_MAX_LEAPS
+#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
+#endif /* !defined TZ_MAX_LEAPS */
+
+#define SECSPERMIN 60
+#define MINSPERHOUR 60
+#define HOURSPERDAY 24
+#define DAYSPERWEEK 7
+#define DAYSPERNYEAR 365
+#define DAYSPERLYEAR 366
+#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
+#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
+#define MONSPERYEAR 12
+
+#define TM_SUNDAY 0
+#define TM_MONDAY 1
+#define TM_TUESDAY 2
+#define TM_WEDNESDAY 3
+#define TM_THURSDAY 4
+#define TM_FRIDAY 5
+#define TM_SATURDAY 6
+
+#define TM_JANUARY 0
+#define TM_FEBRUARY 1
+#define TM_MARCH 2
+#define TM_APRIL 3
+#define TM_MAY 4
+#define TM_JUNE 5
+#define TM_JULY 6
+#define TM_AUGUST 7
+#define TM_SEPTEMBER 8
+#define TM_OCTOBER 9
+#define TM_NOVEMBER 10
+#define TM_DECEMBER 11
+
+#define TM_YEAR_BASE 1900
+
+#define EPOCH_YEAR 1970
+#define EPOCH_WDAY TM_THURSDAY
+
+/*
+** Accurate only for the past couple of centuries;
+** that will probably do.
+*/
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+
+#ifndef USG
+
+/*
+** Use of the underscored variants may cause problems if you move your code to
+** certain System-V-based systems; for maximum portability, use the
+** underscore-free variants. The underscored variants are provided for
+** backward compatibility only; they may disappear from future versions of
+** this file.
+*/
+
+#define SECS_PER_MIN SECSPERMIN
+#define MINS_PER_HOUR MINSPERHOUR
+#define HOURS_PER_DAY HOURSPERDAY
+#define DAYS_PER_WEEK DAYSPERWEEK
+#define DAYS_PER_NYEAR DAYSPERNYEAR
+#define DAYS_PER_LYEAR DAYSPERLYEAR
+#define SECS_PER_HOUR SECSPERHOUR
+#define SECS_PER_DAY SECSPERDAY
+#define MONS_PER_YEAR MONSPERYEAR
+
+#endif /* !defined USG */
+
+#endif /* !defined TZFILE_H */
diff --git a/lib/libc/string/Makefile.inc b/lib/libc/string/Makefile.inc
index 55db696..e95d87d 100644
--- a/lib/libc/string/Makefile.inc
+++ b/lib/libc/string/Makefile.inc
@@ -1,92 +1,101 @@
# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id: Makefile.inc,v 1.9 1997/02/22 15:03:21 peter Exp $
-.PATH: ${.CURDIR}/${MACHINE}/string ${.CURDIR}/string
+.PATH: ${.CURDIR}/../libc/${MACHINE}/string ${.CURDIR}/../libc/string
+CFLAGS += -I${.CURDIR}/../libc/locale
# machine-independent string sources
SRCS+= memccpy.c strcasecmp.c strcoll.c strdup.c strerror.c \
- strftime.c strmode.c strtok.c strxfrm.c swab.c
+ strmode.c strtok.c strxfrm.c
# machine-dependent string sources
-.include "${.CURDIR}/${MACHINE}/string/Makefile.inc"
+.include "${.CURDIR}/../libc/${MACHINE}/string/Makefile.inc"
# If no machine specific bzero(3), build one out of memset(3).
-.if empty(SRCS:Mbzero.s)
+.if empty(SRCS:Mbzero.S)
OBJS+= bzero.o
bzero.o: memset.c
${CC} -DBZERO ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET}
@${LD} -x -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
bzero.po: memset.c
${CC} -DBZERO ${CFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
@${LD} -X -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
.endif
# If no machine specific memmove(3), build one out of bcopy(3).
-.if empty(SRCS:Mmemmove.s)
+.if empty(SRCS:Mmemmove.S)
OBJS+= memmove.o
memmove.o: bcopy.c
${CC} -DMEMMOVE ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET}
@${LD} -x -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
memmove.po: bcopy.c
${CC} -DMEMMOVE ${CFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
@${LD} -X -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
.endif
# If no machine specific memcpy(3), build one out of bcopy(3).
-.if empty(SRCS:Mmemcpy.s)
+.if empty(SRCS:Mmemmove.S)
OBJS+= memcpy.o
memcpy.o: bcopy.c
${CC} -DMEMCOPY ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET}
@${LD} -x -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
memcpy.po: bcopy.c
${CC} -DMEMCOPY ${CFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
@${LD} -X -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
.endif
# If no machine specific strchr(3), build one out of index(3).
-.if empty(SRCS:Mstrchr.s)
+.if empty(SRCS:Mstrchr.S)
OBJS+= strchr.o
strchr.o: index.c
${CC} -DSTRCHR ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET}
@${LD} -x -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
strchr.po: index.c
${CC} -DSTRCHR ${CFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
@${LD} -X -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
.endif
# If no machine specific strrchr(3), build one out of rindex(3).
-.if empty(SRCS:Mstrrchr.s)
+.if empty(SRCS:Mstrrchr.S)
OBJS+= strrchr.o
strrchr.o: rindex.c
${CC} -DSTRRCHR ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET}
@${LD} -x -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
strrchr.po: rindex.c
${CC} -DSTRRCHR ${CFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
@${LD} -X -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
.endif
-
-MAN3+= bcmp.0 bcopy.0 bstring.0 bzero.0 ffs.0 index.0 memccpy.0 memchr.0 \
- memcmp.0 memcpy.0 memmove.0 memset.0 rindex.0 strcasecmp.0 strcat.0 \
- strchr.0 strcmp.0 strcoll.0 strcpy.0 strcspn.0 strftime.0 string.0 \
- strlen.0 strmode.0 strdup.0 strerror.0 strpbrk.0 strrchr.0 strsep.0 \
- strspn.0 strstr.0 strtok.0 strxfrm.0 swab.0
-
+#
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN3+= string/bcmp.3 string/bcopy.3 string/bstring.3 string/bzero.3 \
+ string/ffs.3 string/index.3 string/memccpy.3 string/memchr.3 \
+ string/memcmp.3 string/memcpy.3 string/memmove.3 string/memset.3 \
+ string/rindex.3 string/strcasecmp.3 string/strcat.3 string/strchr.3 \
+ string/strcmp.3 string/strcoll.3 string/strcpy.3 string/strcspn.3 \
+ string/string.3 string/strlen.3 string/strmode.3 \
+ string/strdup.3 string/strerror.3 string/strpbrk.3 string/strrchr.3 \
+ string/strsep.3 string/strspn.3 string/strstr.3 string/strtok.3 \
+ string/strxfrm.3 string/swab.3
+#
MLINKS+=strcasecmp.3 strncasecmp.3
MLINKS+=strcat.3 strncat.3
MLINKS+=strcmp.3 strncmp.3
MLINKS+=strcpy.3 strncpy.3
-MLINKS+=strerror.3 perror.3
+MLINKS+=strerror.3 perror.3 strerror.3 sys_errlist.3 strerror.3 sys_nerr.3
+.endif
diff --git a/lib/libc/string/memccpy.3 b/lib/libc/string/memccpy.3
index 28d6441..92009bd 100644
--- a/lib/libc/string/memccpy.3
+++ b/lib/libc/string/memccpy.3
@@ -69,4 +69,5 @@ bytes are copied, and a NULL pointer is returned.
.Sh HISTORY
The
.Fn memccpy
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/string/memccpy.c b/lib/libc/string/memccpy.c
index 878e419..c457110 100644
--- a/lib/libc/string/memccpy.c
+++ b/lib/libc/string/memccpy.c
@@ -49,9 +49,10 @@ memccpy(t, f, c, n)
if (n) {
register unsigned char *tp = t;
register const unsigned char *fp = f;
+ register unsigned char uc = c;
do {
- if ((*tp++ = *fp++) == c)
- return (t);
+ if ((*tp++ = *fp++) == uc)
+ return (tp);
} while (--n != 0);
}
return (0);
diff --git a/lib/libc/string/memcmp.3 b/lib/libc/string/memcmp.3
index a859529..4fbee33 100644
--- a/lib/libc/string/memcmp.3
+++ b/lib/libc/string/memcmp.3
@@ -34,6 +34,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)memcmp.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt MEMCMP 3
@@ -60,7 +61,7 @@ bytes long.
The
.Fn memcmp
function
-returns zero if the the two strings are identical,
+returns zero if the two strings are identical,
otherwise returns the difference between the first two differing bytes
(treated as unsigned char values, so that
.Sq Li \e200
diff --git a/lib/libc/string/memset.c b/lib/libc/string/memset.c
index 9c28b7b..99c72dc 100644
--- a/lib/libc/string/memset.c
+++ b/lib/libc/string/memset.c
@@ -84,7 +84,7 @@ memset(dst0, c0, length)
*
* 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;
diff --git a/lib/libc/string/strcasecmp.3 b/lib/libc/string/strcasecmp.3
index f9d27ff..c26740e 100644
--- a/lib/libc/string/strcasecmp.3
+++ b/lib/libc/string/strcasecmp.3
@@ -83,4 +83,5 @@ The
.Fn strcasecmp
and
.Fn strncasecmp
-functions first appeared in 4.4BSD.
+functions first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/string/strcasecmp.c b/lib/libc/string/strcasecmp.c
index f31c297..463c4de 100644
--- a/lib/libc/string/strcasecmp.c
+++ b/lib/libc/string/strcasecmp.c
@@ -33,6 +33,7 @@
#include <sys/cdefs.h>
#include <string.h>
+#include <ctype.h>
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
@@ -40,58 +41,18 @@ static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
typedef unsigned char u_char;
-/*
- * This array is designed for mapping upper and lower case letter
- * together for a case independent comparison. The mappings are
- * based upon ascii character sequences.
- */
-static const u_char charmap[] = {
- '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
- '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
- '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
- '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
- '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
- '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
- '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
-};
-
int
strcasecmp(s1, s2)
const char *s1, *s2;
{
- register const u_char *cm = charmap,
+ register const u_char
*us1 = (const u_char *)s1,
*us2 = (const u_char *)s2;
- while (cm[*us1] == cm[*us2++])
+ while (tolower(*us1) == tolower(*us2++))
if (*us1++ == '\0')
return (0);
- return (cm[*us1] - cm[*--us2]);
+ return (tolower(*us1) - tolower(*--us2));
}
int
@@ -100,13 +61,13 @@ strncasecmp(s1, s2, n)
register size_t n;
{
if (n != 0) {
- register const u_char *cm = charmap,
+ register const u_char
*us1 = (const u_char *)s1,
*us2 = (const u_char *)s2;
do {
- if (cm[*us1] != cm[*us2++])
- return (cm[*us1] - cm[*--us2]);
+ if (tolower(*us1) != tolower(*us2++))
+ return (tolower(*us1) - tolower(*--us2));
if (*us1++ == '\0')
break;
} while (--n != 0);
diff --git a/lib/libc/string/strcat.3 b/lib/libc/string/strcat.3
index 6fe13aa..0d34d58 100644
--- a/lib/libc/string/strcat.3
+++ b/lib/libc/string/strcat.3
@@ -68,7 +68,10 @@ The
function
appends not more than
.Fa count
-characters.
+characters from
+.Fa append ,
+and then adds a terminating
+.Ql \e0.
.Sh RETURN VALUES
The
.Fn strcat
diff --git a/lib/libc/string/strcmp.c b/lib/libc/string/strcmp.c
index 79cfaa8..cf25e50 100644
--- a/lib/libc/string/strcmp.c
+++ b/lib/libc/string/strcmp.c
@@ -51,5 +51,5 @@ strcmp(s1, s2)
while (*s1 == *s2++)
if (*s1++ == 0)
return (0);
- return (*(unsigned char *)s1 - *(unsigned char *)--s2);
+ return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
}
diff --git a/lib/libc/string/strcoll.3 b/lib/libc/string/strcoll.3
index 95774f6..08f48ad 100644
--- a/lib/libc/string/strcoll.3
+++ b/lib/libc/string/strcoll.3
@@ -53,17 +53,15 @@ lexicographically compares the null-terminated strings
.Fa s1
and
.Fa s2
-according to the current locale collation
+according to the current locale collation if any, otherwise call
+.Fa strcmp ,
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 .
.Sh SEE ALSO
-.Xr bcmp 3 ,
-.Xr memcmp 3 ,
.Xr setlocale 3 ,
-.Xr strcasecmp 3 ,
.Xr strcmp 3 ,
.Xr strxfrm 3
.Sh STANDARDS
diff --git a/lib/libc/string/strcoll.c b/lib/libc/string/strcoll.c
index 3b9f42e..259ca23 100644
--- a/lib/libc/string/strcoll.c
+++ b/lib/libc/string/strcoll.c
@@ -1,9 +1,7 @@
/*-
- * 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) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
+ * at Electronni Visti IA, Kiev, Ukraine.
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -13,18 +11,11 @@
* 2. Redistributions in binary form must 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
+ * 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
+ * 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)
@@ -32,22 +23,56 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strcoll.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/cdefs.h>
+#include <stdlib.h>
#include <string.h>
+#include "collate.h"
-/*
- * Compare strings according to LC_COLLATE category of current locale.
- */
int
-strcoll(s1, s2)
- const char *s1, *s2;
+strcoll(s, s2)
+ const char *s, *s2;
{
- /* LC_COLLATE is unimplemented, hence always "C" */
- return (strcmp(s1, s2));
+ int len, len2, prim, prim2, sec, sec2, ret, ret2;
+ char *tt, *t, *tt2, *t2;
+
+ if (__collate_load_error)
+ return strcmp(s, s2);
+
+ len = len2 = 1;
+ ret = ret2 = 0;
+ tt = t = __collate_substitute(s);
+ tt2 = t2 = __collate_substitute(s2);
+ while(*t && *t2) {
+ prim = prim2 = 0;
+ while(*t && !prim) {
+ __collate_lookup(t, &len, &prim, &sec);
+ t += len;
+ }
+ while(*t2 && !prim2) {
+ __collate_lookup(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;
}
diff --git a/lib/libc/string/strdup.3 b/lib/libc/string/strdup.3
index 2f1d5d2..c99b416 100644
--- a/lib/libc/string/strdup.3
+++ b/lib/libc/string/strdup.3
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)strdup.3 8.1 (Berkeley) 6/9/93
+.\" $Id$
.\"
.Dd June 9, 1993
.Dt STRDUP 3
@@ -55,9 +56,10 @@ argument to the function
.Pp
If insufficient memory is available, NULL is returned.
.Sh SEE ALSO
+.Xr free 3 ,
.Xr malloc 3
-.Xr free 3
.Sh HISTORY
The
.Fn strdup
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/string/strdup.c b/lib/libc/string/strdup.c
index 6fa50ce..a1c2eed 100644
--- a/lib/libc/string/strdup.c
+++ b/lib/libc/string/strdup.c
@@ -35,8 +35,6 @@
static char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
-#include <sys/types.h>
-
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@@ -49,8 +47,8 @@ strdup(str)
char *copy;
len = strlen(str) + 1;
- if (!(copy = malloc((u_int)len)))
+ if ((copy = malloc(len)) == NULL)
return (NULL);
- bcopy(str, copy, len);
+ memcpy(copy, str, len);
return (copy);
}
diff --git a/lib/libc/string/strerror.3 b/lib/libc/string/strerror.3
index 784c061..67c22db 100644
--- a/lib/libc/string/strerror.3
+++ b/lib/libc/string/strerror.3
@@ -48,8 +48,8 @@
.Fd #include <stdio.h>
.Ft void
.Fn perror "const char *string"
-.Vt extern char *sys_errlist[];
-.Vt extern int sys_nerr;
+.Vt extern const char * const sys_errlist[];
+.Vt extern const int sys_nerr;
.Fd #include <string.h>
.Ft char *
.Fn strerror "int errnum"
@@ -100,11 +100,11 @@ followed by the error number in decimal.
.Pp
The message strings can be accessed directly using the external
array
-.Fa sys_errlist .
+.Va sys_errlist .
The external value
-.Fa sys_nerr
+.Va sys_nerr
contains a count of the messages in
-.Fa sys_errlist .
+.Va sys_errlist .
The use of these variables is deprecated;
.Fn strerror
should be used instead.
@@ -116,9 +116,15 @@ The
.Fn strerror
and
.Fn perror
-functions first appeared in 4.4BSD.
+functions first appeared in
+.Bx 4.4 .
.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
+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
index 53f374b..5acefd9 100644
--- a/lib/libc/string/strerror.c
+++ b/lib/libc/string/strerror.c
@@ -35,14 +35,13 @@
static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
+#include <stdio.h>
#include <string.h>
char *
strerror(num)
int num;
{
- extern int sys_nerr;
- extern char *sys_errlist[];
#define UPREFIX "Unknown error: "
static char ebuf[40] = UPREFIX; /* 64-bit number + slop */
register unsigned int errnum;
@@ -51,17 +50,22 @@ strerror(num)
errnum = num; /* convert to unsigned */
if (errnum < sys_nerr)
- return(sys_errlist[errnum]);
+ return ((char *)sys_errlist[errnum]);
- /* Do this by hand, so we don't include stdio(3). */
+ /* Do this by hand, so we don't link to stdio(3). */
t = tmp;
+ if (num < 0)
+ errnum = -errnum;
do {
*t++ = "0123456789"[errnum % 10];
} while (errnum /= 10);
+ if (num < 0)
+ *t++ = '-';
for (p = ebuf + sizeof(UPREFIX) - 1;;) {
*p++ = *--t;
if (t <= tmp)
break;
}
- return(ebuf);
+ *p = '\0';
+ return (ebuf);
}
diff --git a/lib/libc/string/string.3 b/lib/libc/string/string.3
index c257d94..462482f 100644
--- a/lib/libc/string/string.3
+++ b/lib/libc/string/string.3
@@ -32,6 +32,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)string.3 8.2 (Berkeley) 12/11/93
+.\" $Id$
.\"
.Dd December 11, 1993
.Dt STRING 3
@@ -114,23 +115,23 @@ 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 strcasecmp 3 ,
.Xr strcat 3 ,
.Xr strchr 3 ,
-.Xr strrchr 3 ,
.Xr strcmp 3 ,
-.Xr strcasecmp 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 strcspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3 ,
-.Xr rindex 3
-.Xr bstring 3
+.Xr strtok 3
.Sh STANDARDS
The
.Fn strcat ,
diff --git a/lib/libc/string/strmode.3 b/lib/libc/string/strmode.3
index 43d0cf1..3efc889 100644
--- a/lib/libc/string/strmode.3
+++ b/lib/libc/string/strmode.3
@@ -146,4 +146,5 @@ always returns 0.
.Sh HISTORY
The
.Fn strmode
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/string/strncmp.c b/lib/libc/string/strncmp.c
index 805b5b0..4b701a9 100644
--- a/lib/libc/string/strncmp.c
+++ b/lib/libc/string/strncmp.c
@@ -48,7 +48,8 @@ strncmp(s1, s2, n)
return (0);
do {
if (*s1 != *s2++)
- return (*(unsigned char *)s1 - *(unsigned char *)--s2);
+ return (*(const unsigned char *)s1 -
+ *(const unsigned char *)(s2 - 1));
if (*s1++ == 0)
break;
} while (--n != 0);
diff --git a/lib/libc/string/strsep.3 b/lib/libc/string/strsep.3
index 938b657..fd10494 100644
--- a/lib/libc/string/strsep.3
+++ b/lib/libc/string/strsep.3
@@ -43,7 +43,7 @@
.Sh SYNOPSIS
.Fd #include <string.h>
.Ft char *
-.Fn strsep "char **stringp" "char *delim"
+.Fn strsep "char **stringp" "const char *delim"
.Sh DESCRIPTION
The
.Fn strsep
@@ -104,4 +104,5 @@ two adjacent delimiter characters, or to be used for more than a single
string at a time.
The
.Fn strsep
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/string/strsep.c b/lib/libc/string/strsep.c
index 18dc398..ddad596 100644
--- a/lib/libc/string/strsep.c
+++ b/lib/libc/string/strsep.c
@@ -41,7 +41,7 @@ static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
/*
* Get next token from string *stringp, where tokens are possibly-empty
- * strings separated by characters from delim.
+ * 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.
diff --git a/lib/libc/string/strspn.3 b/lib/libc/string/strspn.3
index 04c4bdc..e96cbeb 100644
--- a/lib/libc/string/strspn.3
+++ b/lib/libc/string/strspn.3
@@ -47,7 +47,7 @@
.Fn strspn "const char *s" "const char *charset"
.Sh DESCRIPTION
The
-.Fn strcspn
+.Fn strspn
function
spans the initial part of the null-terminated string
.Fa s
diff --git a/lib/libc/string/strxfrm.3 b/lib/libc/string/strxfrm.3
index ccd8bcb..308f942 100644
--- a/lib/libc/string/strxfrm.3
+++ b/lib/libc/string/strxfrm.3
@@ -48,16 +48,25 @@
.Sh DESCRIPTION
The
.Fn strxfrm
-function
-does something horrible (see
-.Tn ANSI
-standard).
-In this implementation it just copies.
+function transforms a null-terminated string pointed to by
+.Fa src
+according to the current locale collation if any,
+then copies not more than
+.Fa n-1
+characters of the resulting string into
+.Fa dst ,
+terminating it with a null character and then returns the resulting length.
+Comparing two strings using
+.Fn strcmp
+after
+.Fn strxfrm
+is equal to comparing
+two original strings with
+.Fn strcoll .
+.Sh BUGS
+Sometimes the behavior of this function is unpredictable.
.Sh SEE ALSO
-.Xr bcmp 3 ,
-.Xr memcmp 3 ,
-.\" .Xr setlocale 3 ,
-.Xr strcasecmp 3 ,
+.Xr setlocale 3 ,
.Xr strcmp 3 ,
.Xr strcoll 3
.Sh STANDARDS
diff --git a/lib/libc/string/strxfrm.c b/lib/libc/string/strxfrm.c
index 0d6fcb4..64b0bcf 100644
--- a/lib/libc/string/strxfrm.c
+++ b/lib/libc/string/strxfrm.c
@@ -1,9 +1,7 @@
/*-
- * 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) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
+ * at Electronni Visti IA, Kiev, Ukraine.
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -13,18 +11,11 @@
* 2. Redistributions in binary form must 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
+ * 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
+ * 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)
@@ -32,36 +23,70 @@
* LIABILITY, OR TORT (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$
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strxfrm.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/cdefs.h>
+#include <stdlib.h>
#include <string.h>
+#include "collate.h"
-/*
- * Transform src, storing the result in dst, such that
- * strcmp() on transformed strings returns what strcoll()
- * on the original untransformed strings would return.
- */
size_t
-strxfrm(dst, src, n)
- register char *dst;
+strxfrm(dest, src, len)
+ char *dest;
const char *src;
- size_t n;
+ size_t len;
{
- register size_t srclen, copysize;
+ int prim, sec, l;
+ char *d = dest, *s, *ss;
+
+ if (len < 1)
+ return 0;
+
+ if (!*src) {
+ *d = '\0';
+ return 0;
+ }
+
+ if (__collate_load_error) {
+ size_t slen = strlen(src);
+
+ if (slen < len) {
+ strcpy(d, src);
+ return slen;
+ }
+ strncpy(d, src, len - 1);
+ d[len - 1] = '\0';
+ return len - 1;
+ }
- /*
- * Since locales are unimplemented, this is just a copy.
- */
- srclen = strlen(src);
- if (n != 0) {
- copysize = srclen < n ? srclen : n - 1;
- (void)memcpy(dst, src, copysize);
- dst[copysize] = 0;
+ ss = s = __collate_substitute(src);
+ prim = sec = 0;
+ while (*s && len > 1) {
+ while (*s && !prim) {
+ __collate_lookup(s, &l, &prim, &sec);
+ s += l;
+ }
+ if (prim) {
+ *d++ = (char)prim;
+ len--;
+ }
+ }
+#if 0
+ s = ss;
+ while (*s && len > 1) {
+ while (*s && !prim) {
+ lookup(s, &l, &prim, &sec);
+ s += l;
+ }
+ if (prim && sec) {
+ *d++ = (char)sec;
+ len--;
+ }
}
- return (srclen);
+#endif /* 0 */
+ *d = '\0';
+ free(ss);
+
+ return d - dest;
}
diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
index c89e36e..fbe9067 100644
--- a/lib/libc/sys/Makefile.inc
+++ b/lib/libc/sys/Makefile.inc
@@ -1,89 +1,131 @@
# @(#)Makefile.inc 8.3 (Berkeley) 10/24/94
+# $Id: Makefile.inc,v 1.33 1997/06/01 09:20:30 peter Exp $
# sys sources
-.PATH: ${.CURDIR}/${MACHINE}/sys ${.CURDIR}/sys
+.PATH: ${.CURDIR}/../libc/${MACHINE}/sys ${.CURDIR}/../libc/sys
# modules with non-default implementations on at least one architecture:
-SRCS+= Ovfork.s brk.s cerror.s exect.s fork.s pipe.s ptrace.s reboot.s \
- sbrk.s setlogin.s sigpending.s sigprocmask.s sigreturn.s \
- sigsuspend.s syscall.s
+SRCS+= Ovfork.S brk.S cerror.S exect.S fork.S pipe.S ptrace.S reboot.S \
+ rfork.S sbrk.S setlogin.S sigpending.S sigprocmask.S sigreturn.S \
+ sigsuspend.S syscall.S
# glue to provide compatibility between GCC 1.X and 2.X
SRCS+= ftruncate.c lseek.c mmap.c truncate.c
# modules with default implementations on all architectures:
-ASM= accept.o access.o acct.o adjtime.o bind.o chdir.o chflags.o chmod.o \
- chown.o chroot.o close.o connect.o dup.o dup2.o execve.o fchdir.o \
- fchflags.o fchmod.o fchown.o fcntl.o flock.o fpathconf.o fstat.o \
- fstatfs.o fsync.o getdirentries.o getdtablesize.o getegid.o \
+ASM= access.o acct.o adjtime.o chdir.o chflags.o chmod.o \
+ chown.o chroot.o \
+ clock_getres.o clock_gettime.o clock_settime.o \
+ getdtablesize.o getegid.o \
geteuid.o getfh.o getfsstat.o getgid.o getgroups.o getitimer.o \
- getpeername.o getpgrp.o getpid.o getppid.o getpriority.o \
- getrlimit.o getrusage.o getsockname.o getsockopt.o gettimeofday.o \
- getuid.o ioctl.o kill.o ktrace.o lfs_bmapv.o lfs_markv.o \
- lfs_segclean.o lfs_segwait.o link.o listen.o lstat.o \
- madvise.o mincore.o mkdir.o mkfifo.o mknod.o mlock.o mount.o \
- mprotect.o msync.o munlock.o munmap.o nfssvc.o open.o \
- pathconf.o profil.o quotactl.o read.o \
- readlink.o readv.o recvfrom.o recvmsg.o rename.o revoke.o rmdir.o \
- select.o sendmsg.o sendto.o setegid.o seteuid.o setgid.o \
- setgroups.o setitimer.o setpgid.o setpriority.o setrlimit.o \
- setsid.o setsockopt.o settimeofday.o setuid.o shutdown.o \
- sigaction.o sigaltstack.o socket.o socketpair.o stat.o statfs.o \
- swapon.o symlink.o sync.o umask.o undelete.o unlink.o unmount.o \
- utimes.o vadvise.o wait4.o write.o writev.o __syscall.o __sysctl.o
-
-PSEUDO= _exit.o _getlogin.o
-
-OBJS+= ${ASM} ${PSEUDO}
-POBJS+= ${ASM:.o=.po} ${PSEUDO:.o=.po}
-CLEANFILES+=${ASM} ${PSEUDO} ${POBJS}
-
-${ASM}: ${.CURDIR}/${MACHINE}/SYS.h /usr/include/sys/syscall.h
- @echo creating ${.PREFIX}.o ${.PREFIX}.po
- @printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' | \
- ${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
- @${LD} -x -r ${.PREFIX}.o
- @mv a.out ${.PREFIX}.o
- @printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' | \
- ${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
- @${LD} -x -r ${.PREFIX}.po
- @mv a.out ${.PREFIX}.po
-
-${PSEUDO}: ${.CURDIR}/${MACHINE}/SYS.h /usr/include/sys/syscall.h
- @echo creating ${.PREFIX}.o ${.PREFIX}.po
- @printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
- ${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
- @${LD} -x -r ${.PREFIX}.o
- @mv a.out ${.PREFIX}.o
- @printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
- ${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
- @${LD} -x -r ${.PREFIX}.po
- @mv a.out ${.PREFIX}.po
-
-MAN2+= accept.0 access.0 acct.0 adjtime.0 bind.0 brk.0 chdir.0 chflags.0 \
- chmod.0 chown.0 chroot.0 close.0 connect.0 dup.0 execve.0 _exit.0 \
- fcntl.0 flock.0 fork.0 fsync.0 getdirentries.0 getdtablesize.0 \
- getfh.0 getfsstat.0 getgid.0 getgroups.0 getitimer.0 getlogin.0 \
- getpeername.0 getpgrp.0 getpid.0 getpriority.0 getrlimit.0 \
- getrusage.0 getsockname.0 getsockopt.0 gettimeofday.0 getuid.0 \
- intro.0 ioctl.0 kill.0 ktrace.0 link.0 listen.0 lseek.0 \
- mkdir.0 mkfifo.0 mknod.0 madvise.0 mincore.0 mlock.0 mmap.0 \
- mount.0 mprotect.0 msync.0 munmap.0 \
- nfssvc.0 open.0 pathconf.0 pipe.0 profil.0 ptrace.0 quotactl.0 \
- munmap.0 nfssvc.0 open.0 pipe.0 profil.0 ptrace.0 quotactl.0 \
- read.0 readlink.0 reboot.0 recv.0 rename.0 revoke.0 rmdir.0 \
- select.0 send.0 setgroups.0 setpgid.0 setsid.0 setuid.0 shutdown.0 \
- sigaction.0 sigpending.0 sigprocmask.0 sigreturn.0 sigaltstack.0 \
- sigstack.0 sigsuspend.0 socket.0 socketpair.0 stat.0 statfs.0 \
- swapon.0 symlink.0 sync.0 syscall.0 truncate.0 umask.0 unlink.0 \
- undelete.0 utimes.0 vfork.0 wait.0 write.0
+ getpgrp.o getpid.o getppid.o getpriority.o \
+ getrlimit.o getrusage.o gettimeofday.o \
+ getuid.o issetugid.o kill.o ktrace.o lchown.o \
+ lfs_bmapv.o lfs_markv.o \
+ lfs_segclean.o lfs_segwait.o link.o lstat.o \
+ madvise.o mincore.o minherit.o mkdir.o mlock.o \
+ mount.o \
+ mprotect.o msgsys.o msync.o munlock.o munmap.o \
+ ntp_adjtime.o pathconf.o profil.o quotactl.o \
+ readlink.o rename.o revoke.o rmdir.o \
+ rtprio.o semsys.o setegid.o seteuid.o \
+ setgid.o \
+ setgroups.o setitimer.o setpgid.o setpriority.o \
+ setregid.o setreuid.o setrlimit.o \
+ setsid.o settimeofday.o setuid.o shmsys.o \
+ stat.o statfs.o \
+ swapon.o symlink.o sync.o sysarch.o \
+ umask.o undelete.o unlink.o unmount.o utimes.o utrace.o \
+ vadvise.o __syscall.o __sysctl.o \
+ modnext.o modstat.o modfnext.o modfind.o \
+ kldload.o kldunload.o kldfind.o kldnext.o kldstat.o kldfirstmod.o
+
+# Syscalls renamed as _thread_sys_{syscall} when building libc_r.
+ASMR= accept.o bind.o close.o connect.o dup.o dup2.o \
+ execve.o fchdir.o fchflags.o fchmod.o fchown.o fcntl.o \
+ flock.o fpathconf.o fstat.o fstatfs.o fsync.o getdirentries.o \
+ getpeername.o getsockname.o getsockopt.o ioctl.o listen.o \
+ mkfifo.o mknod.o nanosleep.o nfssvc.o open.o read.o readv.o \
+ recvfrom.o recvmsg.o select.o sendmsg.o sendto.o setsockopt.o \
+ shutdown.o sigaction.o sigaltstack.o signanosleep.o socket.o \
+ socketpair.o \
+ wait4.o write.o writev.o
+
+PSEUDO= _getlogin.o
+
+# Pseudo syscalls that are renamed as _thread_sys_{pseudo} when
+# building libc_r.
+PSEUDOR= _exit.o
+
+OBJS+= ${ASM} ${ASMR} ${PSEUDO} ${PSEUDOR}
+
+SASM= ${ASM:S/.o/.S/}
+
+SASMR= ${ASMR:S/.o/.S/}
+
+SPSEUDO= ${PSEUDO:S/.o/.S/}
+
+SPSEUDOR= ${PSEUDOR:S/.o/.S/}
+
+SRCS+= ${SASM} ${SASMR} ${SPSEUDO} ${SPSEUDOR}
+
+# Generated files
+CLEANFILES+= ${SASM} ${SASMR} ${SPSEUDO} ${SPSEUDOR}
+
+${SASM}:
+ printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' > ${.TARGET}
+
+${SASMR}:
+ printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX})\n' > ${.TARGET}
+
+${SPSEUDO}:
+ printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' \
+ > ${.TARGET}
+
+${SPSEUDOR}:
+ printf '#include "SYS.h"\nPPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' \
+ > ${.TARGET}
+
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN2+= sys/accept.2 sys/access.2 sys/acct.2 sys/adjtime.2 sys/bind.2 \
+ sys/brk.2 sys/chdir.2 sys/chflags.2 sys/chmod.2 sys/chown.2 \
+ sys/chroot.2 sys/clock_gettime.2 sys/close.2 sys/connect.2 sys/dup.2 \
+ sys/execve.2 \
+ sys/_exit.2 sys/fcntl.2 sys/flock.2 sys/fork.2 sys/fsync.2 \
+ sys/getdirentries.2 sys/getdtablesize.2 sys/getfh.2 sys/getfsstat.2 \
+ sys/getgid.2 sys/getgroups.2 sys/getitimer.2 sys/getlogin.2 \
+ sys/getpeername.2 sys/getpgrp.2 sys/getpid.2 sys/getpriority.2 \
+ sys/getrlimit.2 sys/getrusage.2 sys/getsockname.2 sys/getsockopt.2 \
+ sys/gettimeofday.2 sys/getuid.2 sys/intro.2 sys/ioctl.2 \
+ sys/issetugid.2 sys/kill.2 \
+ sys/ktrace.2 sys/link.2 sys/listen.2 sys/lseek.2 sys/mkdir.2 \
+ sys/mkfifo.2 sys/mknod.2 sys/madvise.2 sys/mincore.2 sys/minherit.2 \
+ sys/mlock.2 \
+ sys/mmap.2 sys/mount.2 sys/mprotect.2 sys/msync.2 sys/munmap.2 \
+ sys/nanosleep.2 \
+ sys/ptrace.2 sys/nfssvc.2 sys/open.2 sys/pathconf.2 sys/pipe.2 \
+ sys/profil.2 sys/quotactl.2 sys/read.2 sys/readlink.2 sys/reboot.2 \
+ sys/recv.2 sys/rename.2 sys/revoke.2 sys/rfork.2 sys/rmdir.2 \
+ sys/rtprio.2 sys/select.2 \
+ sys/semctl.2 sys/semget.2 sys/semop.2 \
+ sys/send.2 sys/setgroups.2 \
+ sys/setpgid.2 sys/setregid.2 sys/setreuid.2 \
+ sys/setsid.2 sys/setuid.2 sys/shmat.2 sys/shmctl.2 sys/shmget.2 \
+ sys/shutdown.2 \
+ sys/sigaction.2 sys/sigpending.2 sys/sigprocmask.2 sys/sigreturn.2 \
+ sys/sigaltstack.2 sys/sigstack.2 sys/sigsuspend.2 sys/socket.2 \
+ sys/socketpair.2 sys/stat.2 sys/statfs.2 sys/swapon.2 sys/symlink.2 \
+ sys/sync.2 sys/syscall.2 sys/truncate.2 sys/umask.2 sys/unlink.2 \
+ sys/undelete.2 sys/utimes.2 sys/vfork.2 sys/wait.2 sys/write.2
MLINKS+=brk.2 sbrk.2
MLINKS+=dup.2 dup2.2
MLINKS+=chdir.2 fchdir.2
MLINKS+=chflags.2 fchflags.2
MLINKS+=chmod.2 fchmod.2
-MLINKS+=chown.2 fchown.2
+MLINKS+=chown.2 fchown.2 chown.2 lchown.2
+MLINKS+=clock_gettime.2 clock_settime.2 clock_gettime.2 clock_getres.2
MLINKS+=getgid.2 getegid.2
MLINKS+=getitimer.2 setitimer.2
MLINKS+=getlogin.2 setlogin.2
@@ -97,14 +139,18 @@ MLINKS+=intro.2 errno.2
MLINKS+=lseek.2 seek.2
MLINKS+=mlock.2 munlock.2
MLINKS+=mount.2 unmount.2
+MLINKS+=nanosleep.2 signanosleep.2
MLINKS+=pathconf.2 fpathconf.2
MLINKS+=read.2 readv.2
MLINKS+=recv.2 recvfrom.2 recv.2 recvmsg.2
MLINKS+=send.2 sendmsg.2 send.2 sendto.2
+MLINKS+=setpgid.2 setpgrp.2
MLINKS+=setuid.2 setegid.2 setuid.2 seteuid.2 setuid.2 setgid.2
+MLINKS+=shmat.2 shmdt.2
MLINKS+=stat.2 fstat.2 stat.2 lstat.2
MLINKS+=statfs.2 fstatfs.2
MLINKS+=syscall.2 __syscall.2
MLINKS+=truncate.2 ftruncate.2
MLINKS+=wait.2 wait3.2 wait.2 wait4.2 wait.2 waitpid.2
MLINKS+=write.2 writev.2
+.endif
diff --git a/lib/libc/sys/_exit.2 b/lib/libc/sys/_exit.2
index 73e6062..4f6a1c5 100644
--- a/lib/libc/sys/_exit.2
+++ b/lib/libc/sys/_exit.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)_exit.2 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt EXIT 2
@@ -53,7 +54,7 @@ This may entail delays, for example, waiting for output to drain;
a process in this state may not be killed, as it is already dying.
.It
If the parent process of the calling process has an outstanding
-.Xr wait
+.Xr wait 2
call
or catches the
.Dv SIGCHLD
@@ -107,6 +108,11 @@ can never return.
.Xr exit 3
.Sh STANDARDS
The
-.Nm _exit
-function is defined by
-.St -p1003.1-88 .
+.Fn _exit
+function call is expected to conform to
+.St -p1003.1-90 .
+.Sh HISTORY
+An
+.Fn _exit
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/accept.2 b/lib/libc/sys/accept.2
index d475e36..c5d162f 100644
--- a/lib/libc/sys/accept.2
+++ b/lib/libc/sys/accept.2
@@ -129,6 +129,31 @@ by issuing a
call with providing only the control information,
or by calling
.Xr setsockopt 2 .
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn accept
+is implemented as the
+.Va accept
+syscall.
+.Pp
+In the threaded library, the
+.Va accept
+syscall is assembled to
+.Fn _thread_sys_accept
+and
+.Fn accept
+is implemented as a function which locks
+.Va s
+for read and write, then calls
+.Fn _thread_sys_accept .
+If the call to
+.Fn _thread_sys_accept
+would block, a context switch is performed. Before returning,
+.Fn accept
+unlocks
+.Va s .
+.Pp
.Sh RETURN VALUES
The call returns \-1 on error. If it succeeds, it returns a non-negative
integer that is a descriptor for the accepted socket.
@@ -156,11 +181,12 @@ are present to be accepted.
.Sh SEE ALSO
.Xr bind 2 ,
.Xr connect 2 ,
+.Xr getpeername 2 ,
.Xr listen 2 ,
.Xr select 2 ,
.Xr socket 2
.Sh HISTORY
The
-.Nm
+.Fn accept
function appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/access.2 b/lib/libc/sys/access.2
index 0dc9d2e..cf1fe90 100644
--- a/lib/libc/sys/access.2
+++ b/lib/libc/sys/access.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)access.2 8.2 (Berkeley) 4/1/94
+.\" $Id$
.\"
.Dd April 1, 1994
.Dt ACCESS 2
@@ -88,8 +89,6 @@ Access to the file is denied if:
.Bl -tag -width Er
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -121,10 +120,16 @@ An I/O error occurred while reading from or writing to the file system.
.Xr chmod 2 ,
.Xr stat 2
.Sh STANDARDS
-.Fn Access
-conforms to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+The
+.Fn access
+function call is expected to conform to
+.St -p1003.1-90 .
.Sh CAVEAT
.Fn Access
is a potential security hole and
should never be used.
+.Sh HISTORY
+An
+.Fn access
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/acct.2 b/lib/libc/sys/acct.2
index bcd45ca..879a06f 100644
--- a/lib/libc/sys/acct.2
+++ b/lib/libc/sys/acct.2
@@ -86,8 +86,6 @@ will fail if one of the following is true:
The caller is not the super-user.
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -111,5 +109,6 @@ An I/O error occurred while reading from or writing to the file system.
.Xr sa 8
.Sh HISTORY
An
-.Nm
-function call appeared in Version 7 AT&T UNIX.
+.Fn acct
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/adjtime.2 b/lib/libc/sys/adjtime.2
index 84b9ad8..04673ad 100644
--- a/lib/libc/sys/adjtime.2
+++ b/lib/libc/sys/adjtime.2
@@ -40,7 +40,7 @@
.Sh SYNOPSIS
.Fd #include <sys/time.h>
.Ft int
-.Fn adjtime "struct timeval *delta" "struct timeval *olddelta"
+.Fn adjtime "const struct timeval *delta" "struct timeval *olddelta"
.Sh DESCRIPTION
.Fn Adjtime
makes small adjustments to the system time, as returned by
@@ -98,7 +98,7 @@ The process's effective user ID is not that of the super-user.
.Xr date 1 ,
.Xr gettimeofday 2 ,
.Xr timed 8 ,
-.Xr timedc 8 ,
+.Xr timedc 8
.Rs
.%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD"
.%A R. Gusella
@@ -106,6 +106,6 @@ The process's effective user ID is not that of the super-user.
.Re
.Sh HISTORY
The
-.Nm
+.Fn adjtime
function call appeared in
.Bx 4.3 .
diff --git a/lib/libc/sys/bind.2 b/lib/libc/sys/bind.2
index 18512e2..ce6ca0c 100644
--- a/lib/libc/sys/bind.2
+++ b/lib/libc/sys/bind.2
@@ -41,7 +41,7 @@
.Fd #include <sys/types.h>
.Fd #include <sys/socket.h>
.Ft int
-.Fn bind "int s" "struct sockaddr *name" "int namelen"
+.Fn bind "int s" "const struct sockaddr *name" "int namelen"
.Sh DESCRIPTION
.Fn Bind
assigns a name to an unnamed socket.
@@ -62,6 +62,28 @@ needed (using
.Pp
The rules used in name binding vary between communication domains.
Consult the manual entries in section 4 for detailed information.
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn bind
+is implemented as the
+.Va bind
+syscall.
+.Pp
+In the threaded library, the
+.Va bind
+syscall is assembled to
+.Fn _thread_sys_bind
+and
+.Fn bind
+is implemented as a function which locks
+.Va s
+for read and write, then calls
+.Fn _thread_sys_bind .
+Before returning,
+.Fn bind
+unlocks
+.Va s .
.Sh RETURN VALUES
If the bind is successful, a 0 value is returned.
A return value of -1 indicates an error, which is
@@ -82,8 +104,6 @@ is not a socket.
The specified address is not available from the local machine.
.It Bq Er EADDRINUSE
The specified address is already in use.
-.It Bq Er EINVAL
-The socket is already bound to an address.
.It Bq Er EACCES
The requested address is protected, and the current user
has inadequate permission to access it.
@@ -116,11 +136,11 @@ An empty pathname was specified.
.El
.Sh SEE ALSO
.Xr connect 2 ,
+.Xr getsockname 2 ,
.Xr listen 2 ,
-.Xr socket 2 ,
-.Xr getsockname 2
+.Xr socket 2
.Sh HISTORY
The
-.Nm
+.Fn bind
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/brk.2 b/lib/libc/sys/brk.2
index e3c825e..313e47d 100644
--- a/lib/libc/sys/brk.2
+++ b/lib/libc/sys/brk.2
@@ -39,11 +39,11 @@
.Nm sbrk
.Nd change data segment size
.Sh SYNOPSIS
-.Fd #include <sys/types.h>
-.Ft char
-.Fn *brk "const char *addr"
+.Fd #include <unistd.h>
.Ft char *
-.Fn *sbrk "int incr"
+.Fn brk "const char *addr"
+.Ft char *
+.Fn sbrk "int incr"
.Sh DESCRIPTION
.Bf -symbolic
The brk and sbrk functions are historical curiosities
@@ -94,7 +94,7 @@ it will not be possible to set the break
beyond the
.Em rlim_max
value returned from a call to
-.Xr getrlimit ,
+.Xr getrlimit 2 ,
e.g.
.Dq etext + rlp\(->rlim_max.
(see
@@ -102,20 +102,21 @@ e.g.
for the definition of
.Em etext ) .
.Sh RETURN VALUES
-.Nm Brk
+.Fn Brk
returns 0 if successful;
otherwise -1 with
.Va errno
set to indicate why the allocation failed.
-.Nm Sbrk
-returns a pointer to the base of the new storage if successful;
+The
+.Fn sbrk
+function returns a pointer to the base of the new storage if successful;
otherwise -1 with
.Va errno
set to indicate why the allocation failed.
.Sh ERRORS
-.Xr Brk
+.Fn Brk
or
-.Xr sbrk
+.Fn sbrk
will fail and no additional memory will be allocated if
one of the following are true:
.Bl -tag -width [ENOMEM]
@@ -133,15 +134,16 @@ to support the expansion.
.Sh SEE ALSO
.Xr execve 2 ,
.Xr getrlimit 2 ,
-.Xr malloc 3 ,
-.Xr end 3
+.Xr end 3 ,
+.Xr malloc 3
.Sh BUGS
Setting the break may fail due to a temporary lack of
swap space. It is not possible to distinguish this
from a failure caused by exceeding the maximum size of
the data segment without consulting
-.Xr getrlimit .
+.Xr getrlimit 2 .
.Sh HISTORY
A
-.Nm
-function call appeared in Version 7 AT&T UNIX.
+.Fn brk
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/chdir.2 b/lib/libc/sys/chdir.2
index 0b06fa8..215d759 100644
--- a/lib/libc/sys/chdir.2
+++ b/lib/libc/sys/chdir.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)chdir.2 8.2 (Berkeley) 12/11/93
+.\" $Id$
.\"
.Dd December 11, 1993
.Dt CHDIR 2
@@ -82,8 +83,6 @@ one or more of the following are true:
.Bl -tag -width Er
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -118,10 +117,15 @@ is not a valid file descriptor.
.Sh SEE ALSO
.Xr chroot 2
.Sh STANDARDS
-.Fn Chdir
-is expected to conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+The
+.Fn chdir
+function call is expected to conform to
+.St -p1003.1-90 .
.Sh HISTORY
+A
+.Fn chdir
+function call appeared in
+.At v7 .
The
.Fn fchdir
function call
diff --git a/lib/libc/sys/chflags.2 b/lib/libc/sys/chflags.2
index e10d98d..3305b3a 100644
--- a/lib/libc/sys/chflags.2
+++ b/lib/libc/sys/chflags.2
@@ -65,6 +65,8 @@ Do not dump the file.
The file may not be changed.
.It UF_APPEND
The file may only be appended to.
+.It UF_NOUNLINK
+The file may not be renamed or deleted.
.It UF_OPAQUE
The directory is opaque when viewed through a union stack.
.\".It ARCHIVED
@@ -73,18 +75,24 @@ The directory is opaque when viewed through a union stack.
The file may not be changed.
.It SF_APPEND
The file may only be appended to.
+.It SF_NOUNLINK
+The file may not be renamed or deleted.
.El
.Pp
The
.Dq UF_IMMUTABLE
-and
+,
.Dq UF_APPEND
+and
+.Dq UF_NOUNLINK
flags may be set or unset by either the owner of a file or the super-user.
.Pp
The
.Dq SF_IMMUTABLE
-and
+,
.Dq SF_APPEND
+and
+.Dq SF_NOUNLINK
flags may only be set or unset by the super-user.
Attempts by the non-super-user to set the super-user only flags
are silently ignored.
@@ -100,12 +108,10 @@ Otherwise, -1 is returned and the global variable
is set to indicate the error.
.Sh ERRORS
.Fn Chflags
-will fail it:
+will fail if:
.Bl -tag -width Er
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -156,4 +162,5 @@ The
.Nm chflags
and
.Nm fchflags
-functions first appeared in 4.4BSD.
+functions first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/chmod.2 b/lib/libc/sys/chmod.2
index 1075158..a2daf6f 100644
--- a/lib/libc/sys/chmod.2
+++ b/lib/libc/sys/chmod.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)chmod.2 8.1 (Berkeley) 6/4/93
+.\" $Id: chmod.2,v 1.8 1997/02/22 15:03:43 peter Exp $
.\"
.Dd June 4, 1993
.Dt CHMOD 2
@@ -88,17 +89,14 @@ defined in
#define S_ISUID 0004000 /* set user id on execution */
#define S_ISGID 0002000 /* set group id on execution */
-#define S_ISVTX 0001000 /* save swapped text even after use */
+#define S_ISVTX 0001000 /* sticky bit */
.Ed
.Pp
The
-.Dv ISVTX
-(the
-.Em sticky bit )
-indicates to the system which executable files are shareable (the
-default) and the system maintains the program text of the files
-in the swap area. The sticky bit may only be set by the super user
-on shareable executable files.
+.Tn FreeBSD
+VM system totally ignores the sticky bit
+.Pf ( Dv ISVTX
+) for executables.
.Pp
If mode
.Dv ISVTX
@@ -128,8 +126,6 @@ will fail and the file mode will be unchanged if:
.Bl -tag -width Er
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -166,15 +162,20 @@ An I/O error occurred while reading from or writing to the file system.
.El
.Sh SEE ALSO
.Xr chmod 1 ,
-.Xr open 2 ,
.Xr chown 2 ,
+.Xr open 2 ,
.Xr stat 2 ,
.Xr sticky 8
.Sh STANDARDS
-.Fn Chmod
-is expected to conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+The
+.Fn chmod
+function call is expected to conform to
+.St -p1003.1-90 .
.Sh HISTORY
+A
+.Fn chmod
+function call appeared in
+.At v7 .
The
.Fn fchmod
function call
diff --git a/lib/libc/sys/chown.2 b/lib/libc/sys/chown.2
index 8b851e2..af1875c 100644
--- a/lib/libc/sys/chown.2
+++ b/lib/libc/sys/chown.2
@@ -30,20 +30,24 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)chown.2 8.4 (Berkeley) 4/19/94
+.\" $Id: chown.2,v 1.10 1997/03/31 12:37:35 peter Exp $
.\"
.Dd April 19, 1994
.Dt CHOWN 2
.Os BSD 4
.Sh NAME
.Nm chown ,
-.Nm fchown
+.Nm fchown ,
+.Nm lchown
.Nd change owner and group of a file
.Sh SYNOPSIS
.Fd #include <unistd.h>
.Ft int
.Fn chown "const char *path" "uid_t owner" "gid_t group"
.Ft int
-.Fn fchown "int fd" "uid_t owner" "uid_t group"
+.Fn fchown "int fd" "uid_t owner" "gid_t group"
+.Ft int
+.Fn lchown "const char *path" "uid_t owner" "gid_t group"
.Sh DESCRIPTION
The owner ID and group ID of the file
named by
@@ -66,13 +70,22 @@ capability is restricted to the super-user.
clears the set-user-id and set-group-id bits
on the file
to prevent accidental or mischievous creation of
-set-user-id and set-group-id programs.
+set-user-id and set-group-id programs if not executed
+by the super-user.
+.Fn chown
+follows symbolic links to operate on the target of the link
+rather than the link itself.
.Pp
.Fn Fchown
is particularly useful when used in conjunction
with the file locking primitives (see
.Xr flock 2 ) .
.Pp
+.Fn Lchown
+is similar to
+.Fn chown
+but does not follow symbolic links.
+.Pp
One of the owner or group id's
may be left unchanged by specifying it as -1.
.Sh RETURN VALUES
@@ -82,12 +95,12 @@ error code being placed in the global variable
.Va errno .
.Sh ERRORS
.Fn Chown
+and
+.Fn lchown
will fail and the file will be unchanged if:
.Bl -tag -width Er
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -125,15 +138,20 @@ The named file resides on a read-only file system.
An I/O error occurred while reading from or writing to the file system.
.El
.Sh SEE ALSO
-.Xr chown 8 ,
.Xr chgrp 1 ,
.Xr chmod 2 ,
-.Xr flock 2
+.Xr flock 2 ,
+.Xr chown 8
.Sh STANDARDS
-.Fn Chown
-is expected to conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+The
+.Fn chown
+function call is expected to conform to
+.St -p1003.1-90 .
.Sh HISTORY
+A
+.Fn chown
+function call appeared in
+.At v7 .
The
.Fn fchown
function call
@@ -142,7 +160,10 @@ appeared in
.Pp
The
.Fn chown
-and
-.Fn fchown
-functions were changed to follow symbolic links in
+function was changed to follow symbolic links in
.Bx 4.4 .
+The
+.Fn lchown
+function was added in
+.Fx 3.0
+to compensate for the loss of functionality.
diff --git a/lib/libc/sys/chroot.2 b/lib/libc/sys/chroot.2
index d8763fe..10a9b5e 100644
--- a/lib/libc/sys/chroot.2
+++ b/lib/libc/sys/chroot.2
@@ -71,8 +71,8 @@ will fail and the root directory will be unchanged if:
.Bl -tag -width [ENOTDIR]
.It Bq Er ENOTDIR
A component of the path name is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
+.It Bq Er EPERM
+The effective user ID is not the super-user.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -92,6 +92,6 @@ An I/O error occurred while reading from or writing to the file system.
.Xr chdir 2
.Sh HISTORY
The
-.Nm
+.Fn chroot
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/clock_gettime.2 b/lib/libc/sys/clock_gettime.2
new file mode 100644
index 0000000..6894c14
--- /dev/null
+++ b/lib/libc/sys/clock_gettime.2
@@ -0,0 +1,124 @@
+.\" $OpenBSD: clock_gettime.2,v 1.4 1997/05/08 20:21:16 kstailey Exp $
+.\" $Id$
+.\"
+.\" 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.
+.\" 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.
+.\"
+.Dd May 8, 1997
+.Dt CLOCK_GETTIME 2
+.Os BSD 4
+.Sh NAME
+.Nm clock_gettime ,
+.Nm clock_settime ,
+.Nm clock_getres
+.Nd get/set/calibrate date and time
+.Sh SYNOPSIS
+.Fd #include <sys/time.h>
+.Ft int
+.Fn clock_gettime "clockid_t clock_id" "struct timespec *tp"
+.Ft int
+.Fn clock_settime "clockid_t clock_id" "const struct timespec *tp"
+.Ft int
+.Fn clock_getres "clockid_t clock_id" "const struct timespec *tp"
+.Sh DESCRIPTION
+The
+.Fn clock_gettime
+and
+.Fn clock_settime
+allow the calling process to retrieve or set the value used by a clock
+which is specifed by
+.Fa clock_id .
+.Pp
+.Fa clock_id
+can be one of three values: CLOCK_REALTIME for time that increments as
+a wall clock should, CLOCK_VIRTUAL for time that increments only when
+the CPU is running in user mode on behalf of the calling process, or
+CLOCK_PROF for time that increments when the CPU is running in user or
+kernel mode.
+.Pp
+The structure pointed to by
+.Fa tp
+is defined in
+.Ao Pa sys/time.h Ac
+as:
+.Pp
+.Bd -literal
+struct timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* and nanoseconds */
+};
+.Ed
+.Pp
+Only the super-user may set the time of day.
+If the system securelevel is greater than 1 (see
+.Xr init 8 ),
+the time may only be advanced.
+This limitation is imposed to prevent a malicious super-user
+from setting arbitrary time stamps on files.
+The system time can still be adjusted backwards using the
+.Xr adjtime 2
+system call even when the system is secure.
+.Pp
+The resolution (granularity) of a clock is returned by the
+.Fn clock_getres
+call. This value is placed in a (non-NULL)
+.Fa *tp .
+.Sh RETURN
+A 0 return value indicates that the call succeeded.
+A -1 return value indicates an error occurred, and in this
+case an error code is stored into the global variable
+.Va errno .
+.Sh ERRORS
+The following error codes may be set in
+.Va errno :
+.Bl -tag -width [EFAULT]
+.It Bq Er EINVAL
+The
+.Fa clock_id
+was not a valid value.
+.It Bq Er EFAULT
+The
+.Fa *tp
+argument address referenced invalid memory.
+.It Bq Er EPERM
+A user other than the super-user attempted to set the time.
+.El
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr adjtime 2 ,
+.Xr ctime 3 ,
+.Xr timed 8
+.Sh STANDARDS
+The
+.Fn clock_gettime ,
+etc.
+functions conform to
+.St -p1003.1b-93 .
diff --git a/lib/libc/sys/close.2 b/lib/libc/sys/close.2
index 885ac80..1a66e39 100644
--- a/lib/libc/sys/close.2
+++ b/lib/libc/sys/close.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)close.2 8.2 (Berkeley) 4/19/94
+.\" $Id$
.\"
.Dd April 19, 1994
.Dt CLOSE 2
@@ -78,7 +79,7 @@ of the descriptors can be rearranged with
or deleted with
.Fn close
before the
-.Xr execve
+.Xr execve 2
is attempted, but if some of these descriptors will still
be needed if the execve fails, it is necessary to arrange for them
to be closed if the execve succeeds.
@@ -90,6 +91,28 @@ execve; the call
.Dq Li fcntl(d, F_SETFD, 0)
restores the default,
which is to not close the descriptor.
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn close
+is implemented as the
+.Va close
+syscall.
+.Pp
+In the threaded library, the
+.Va close
+syscall is assembled to
+.Fn _thread_sys_close
+and
+.Fn close
+is implemented as a function which locks
+.Va d
+for read and write, then calls
+.Fn _thread_sys_close .
+Before returning,
+.Fn close
+unlocks
+.Va d .
.Sh RETURN VALUES
Upon successful completion, a value of 0 is returned.
Otherwise, a value of -1 is returned and the global integer variable
@@ -107,14 +130,20 @@ An interrupt was received.
.El
.Sh SEE ALSO
.Xr accept 2 ,
+.Xr execve 2 ,
+.Xr fcntl 2 ,
.Xr flock 2 ,
.Xr open 2 ,
.Xr pipe 2 ,
.Xr socket 2 ,
-.Xr socketpair 2 ,
-.Xr execve 2 ,
-.Xr fcntl 2
+.Xr socketpair 2
.Sh STANDARDS
-.Fn Close
-conforms to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+The
+.Fn close
+function call is expected to conform to
+.St -p1003.1-90 .
+.Sh HISTORY
+A
+.Fn close
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/connect.2 b/lib/libc/sys/connect.2
index eb38ab3..f328d86 100644
--- a/lib/libc/sys/connect.2
+++ b/lib/libc/sys/connect.2
@@ -41,7 +41,7 @@
.Fd #include <sys/types.h>
.Fd #include <sys/socket.h>
.Ft int
-.Fn connect "int s" "struct sockaddr *name" "int namelen"
+.Fn connect "int s" "const struct sockaddr *name" "int namelen"
.Sh DESCRIPTION
The parameter
.Fa s
@@ -68,6 +68,30 @@ only once; datagram sockets may use
multiple times to change their association.
Datagram sockets may dissolve the association
by connecting to an invalid address, such as a null address.
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn connect
+is implemented as the
+.Va connect
+syscall.
+.Pp
+In the threaded library, the
+.Va connect
+syscall is assembled to
+.Fn _thread_sys_connect
+and
+.Fn connect
+is implemented as a function which locks
+.Va s
+for read and write, then calls
+.Fn _thread_sys_connect .
+If the call to
+.Fn _thread_sys_connect
+would block, a context switch is performed. Before returning,
+.Fn connect
+unlocks
+.Va s .
.Sh RETURN VALUES
If the connection or binding succeeds, 0 is returned.
Otherwise a -1 is returned, and a more specific error
@@ -79,10 +103,10 @@ The
call fails if:
.Bl -tag -width EADDRNOTAVAILABB
.It Bq Er EBADF
-.Fa S
+.Fa s
is not a valid descriptor.
.It Bq Er ENOTSOCK
-.Fa S
+.Fa s
is a descriptor for a file, not a socket.
.It Bq Er EADDRNOTAVAIL
The specified address is not available on this machine.
@@ -121,8 +145,6 @@ These errors may not apply in future versions of the UNIX IPC domain.
.Bl -tag -width EADDRNOTAVAILABB
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -137,11 +159,12 @@ Too many symbolic links were encountered in translating the pathname.
.El
.Sh SEE ALSO
.Xr accept 2 ,
+.Xr getpeername 2 ,
+.Xr getsockname 2 ,
.Xr select 2 ,
-.Xr socket 2 ,
-.Xr getsockname 2
+.Xr socket 2
.Sh HISTORY
The
-.Nm
+.Fn connect
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/dup.2 b/lib/libc/sys/dup.2
index 8989639..58a967d 100644
--- a/lib/libc/sys/dup.2
+++ b/lib/libc/sys/dup.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)dup.2 8.1 (Berkeley) 6/4/93
+.\" $Id: dup.2,v 1.7 1997/02/22 15:03:49 peter Exp $
.\"
.Dd June 4, 1993
.Dt DUP 2
@@ -91,10 +92,74 @@ In
.Fn dup2 ,
the value of the new descriptor
.Fa newd
-is specified. If this descriptor is already
-in use, the descriptor is first deallocated as if a
+is specified. If this descriptor is already in use and
+.Fa oldd
+!=
+.Fa newd ,
+the descriptor is first deallocated as if a
.Xr close 2
-call had been done first.
+call had been used.
+If
+.Fa oldd
+is not a valid descriptor, then
+.Fa newd
+is not closed.
+If
+.Fa oldd
+==
+.Fa newd
+and
+.Fa oldd
+is a valid descriptor, then
+.Fn dup2
+is successful, and does nothing.
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn dup
+is implemented as the
+.Va dup
+syscall.
+.Pp
+In the threaded library, the
+.Va dup
+syscall is assembled to
+.Fn _thread_sys_dup
+and
+.Fn dup
+is implemented as a function which locks
+.Va oldd
+for read and write, then calls
+.Fn _thread_sys_dup .
+Before returning,
+.Fn dup
+unlocks
+.Va oldd .
+.Pp
+In the non-threaded library
+.Fn dup2
+is implemented as the
+.Va dup2
+syscall.
+.Pp
+In the threaded library, the
+.Va dup2
+syscall is assembled to
+.Fn _thread_sys_dup2
+and
+.Fn dup2
+is implemented as a function which locks both
+.Va oldd
+and
+.Va newd
+for read and write, then calls
+.Fn _thread_sys_dup2 .
+Before returning,
+.Fn dup2
+unlocks
+.Va oldd .
+and
+.Va newd .
.Sh RETURN VALUES
The value -1 is returned if an error occurs in either call.
The external variable
@@ -116,17 +181,24 @@ Too many descriptors are active.
.El
.Sh SEE ALSO
.Xr accept 2 ,
-.Xr open 2 ,
.Xr close 2 ,
.Xr fcntl 2 ,
+.Xr getdtablesize 2 ,
+.Xr open 2 ,
.Xr pipe 2 ,
.Xr socket 2 ,
-.Xr socketpair 2 ,
-.Xr getdtablesize 2
+.Xr socketpair 2
.Sh STANDARDS
-.Fn Dup
+The
+.Fn dup
and
.Fn dup2
-are expected to conform
-to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+function calls are expected to conform to
+.St -p1003.1-90 .
+.Sh HISTORY
+A
+.Fn dup
+and a
+.Fn dup2
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/execve.2 b/lib/libc/sys/execve.2
index ca44793..a4af9bf 100644
--- a/lib/libc/sys/execve.2
+++ b/lib/libc/sys/execve.2
@@ -66,11 +66,9 @@ An interpreter file begins with a line of the form:
.Ed
.Pp
When an interpreter file is
-.\" was .Fn execve Ap d ,
-\fBexecve\fP'd,
+.Sy execve Ap d ,
the system
-.\" was .Fn execve Ap s
-\fBexecve\fP's
+.Sy execve Ap s
runs the specified
.Em interpreter .
If the optional
@@ -78,16 +76,13 @@ If the optional
is specified, it becomes the first argument to the
.Em interpreter ,
and the name of the originally
-.\" was .Fn execve Ap d
-\fBexecve\fP'd
+.Sy execve Ap d
file becomes the second argument;
otherwise, the name of the originally
-.\" was .Fn execve Ap d
-\fBexecve\fP'd
+.Sy execve Ap d
file becomes the first argument. The original arguments are shifted over to
become the subsequent arguments. The zeroth argument, normally the name of the
-.\" was .Fn execve Ap d
-\fBexecve\fP'd
+.Sy execve Ap d
file, is left unchanged.
.Pp
The argument
@@ -184,6 +179,23 @@ and
.Fa argv
points to the array of character pointers
to the arguments themselves.
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn execve
+is implemented as the
+.Va execve
+syscall.
+.Pp
+In the threaded library, the
+.Va execve
+syscall is assembled to
+.Fn _thread_sys_execve
+and
+.Fn execve
+is implemented as a function which performs user-thread
+library re-initialization and then calls
+.Fn _thread_sys_execve .
.Sh RETURN VALUES
As the
.Fn execve
@@ -202,8 +214,6 @@ will fail and return to the calling process if:
.Bl -tag -width [ENAMETOOLONG]
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -231,10 +241,10 @@ is allowed by the imposed maximum
.It Bq Er E2BIG
The number of bytes in the new process's argument list
is larger than the system-imposed limit.
-The limit in the system as released is 20480 bytes
+The limit in the system as released is 65536 bytes
.Pf ( Dv NCARGS
in
-.Ao Pa sys/param.h Ac .
+.Ao Pa sys/param.h Ac ) .
.It Bq Er EFAULT
The new process file is not as long as indicated by
the size values in its header.
@@ -257,12 +267,13 @@ the real
is ``root'', then the program has some of the powers
of a super-user as well.
.Sh SEE ALSO
-.Xr exit 2 ,
+.Xr _exit 2 ,
.Xr fork 2 ,
.Xr execl 3 ,
+.Xr exit 3 ,
.Xr environ 7
.Sh HISTORY
The
-.Nm
+.Fn execve
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/fcntl.2 b/lib/libc/sys/fcntl.2
index f53c02f..877e830 100644
--- a/lib/libc/sys/fcntl.2
+++ b/lib/libc/sys/fcntl.2
@@ -70,7 +70,7 @@ share the same file status flags).
.It
The close-on-exec flag associated with the new file descriptor
is set to remain open across
-.Xr execv 2
+.Xr execve 2
system calls.
.El
.It Dv F_GETFD
@@ -128,9 +128,9 @@ flags are as follows:
.Bl -tag -width O_NONBLOCKX
.It Dv O_NONBLOCK
Non-blocking I/O; if no data is available to a
-.Xr read
+.Xr read 2
call, or if a
-.Xr write
+.Xr write 2
operation would block,
the read or write call returns -1 with the error
.Er EAGAIN .
@@ -170,7 +170,7 @@ taken as a pointer to a
.Fa "struct flock"
(see above).
The information retrieved overwrites the information passed to
-.Nm fcntl
+.Fn fcntl
in the
.Fa flock
structure.
@@ -193,18 +193,18 @@ or exclusive (or write) locks,
as well as remove either type of lock
.Dv (F_UNLCK) .
If a shared or exclusive lock cannot be set,
-.Nm fcntl
+.Fn fcntl
returns immediately with
-.Er EACCES .
+.Er EAGAIN .
.It Dv F_SETLKW
This command is the same as
.Dv F_SETLK
except that if a shared or exclusive lock is blocked by other locks,
the process waits until the request can be satisfied.
If a signal that is to be caught is received while
-.Nm fcntl
+.Fn fcntl
is waiting for a region, the
-.Nm fcntl
+.Fn fcntl
will be interrupted if the signal handler has not specified the
.Dv SA_RESTART
(see
@@ -290,15 +290,17 @@ locks conflicts with the type specified in the request.
This interface follows the completely stupid semantics of System V and
.St -p1003.1-88
that require that all locks associated with a file for a given process are
-removed when \fIany\fP file descriptor for that file is closed by that process.
+removed when
+.Em any
+file descriptor for that file is closed by that process.
This semantic means that applications must be aware of any files that
a subroutine library may access.
For example if an application for updating the password file locks the
password file database while making the update, and then calls
-.Xr getpwname 3
+.Xr getpwnam 3
to retrieve a record,
the lock will be lost because
-.Xr getpwname 3
+.Xr getpwnam 3
opens, reads, and closes the password database.
The database close will release all locks that the process has
associated with the database, even if the library routine never
@@ -330,6 +332,29 @@ This implementation detects that sleeping until a locked region is unlocked
would cause a deadlock and fails with an
.Er EDEADLK
error.
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn fcntl
+is implemented as the
+.Va fcntl
+syscall.
+.Pp
+In the threaded library, the
+.Va fcntl
+syscall is assembled to
+.Fn _thread_sys_fcntl
+and
+.Fn fcntl
+is implemented as a function which disables thread rescheduling, locks
+.Va fd
+for read and write, then calls
+.Fn _thread_sys_fcntl .
+Before returning,
+.Fn fcntl
+unlocks
+.Va fd
+and enables thread rescheduling.
.Sh RETURN VALUES
Upon successful completion, the value returned depends on
.Fa cmd
@@ -354,9 +379,9 @@ is set to indicate the error.
.Fn Fcntl
will fail if:
.Bl -tag -width Er
-.It Bq Er EACCES
+.It Bq Er EAGAIN
The argument
-.Fa arg
+.Fa cmd
is
.Dv F_SETLK ,
the type of lock
@@ -401,12 +426,6 @@ is an exclusive lock
and
.Fa fildes
is not a valid file descriptor open for writing.
-.It Bq Er EMFILE
-.Fa Cmd
-is
-.Dv F_DUPFD
-and the maximum allowed number of file descriptors are currently
-open.
.It Bq Er EDEADLK
The argument
.Fa cmd
@@ -445,7 +464,7 @@ refers to a file that does not support locking.
The argument
.Fa cmd
is
-.Dv F_DUPED
+.Dv F_DUPFD
and the maximum number of file descriptors permitted for the
process are already in use,
or no file descriptors greater than or equal to
@@ -467,15 +486,33 @@ is
and
the process ID given as argument is not in use.
.El
+.Pp
+In addition, if
+.Fa fd
+refers to a descriptor open on a terminal device (as opposed to a
+descriptor open on a socket), a
+.Fa cmd
+of
+.Dv F_SETOWN
+can fail for the same reasons as in
+.Xr tcsetpgrp 3 ,
+and a
+.Fa cmd
+of
+.Dv F_GETOWN
+for the reasons as stated in
+.Xr tcgetpgrp 3 .
.Sh SEE ALSO
.Xr close 2 ,
.Xr execve 2 ,
.Xr flock 2 ,
.Xr getdtablesize 2 ,
.Xr open 2 ,
-.Xr sigvec 2
+.Xr sigvec 2 ,
+.Xr tcgetpgrp 3 ,
+.Xr tcsetpgrp 3
.Sh HISTORY
The
-.Nm
+.Fn fcntl
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/flock.2 b/lib/libc/sys/flock.2
index bb6abb7..466e347 100644
--- a/lib/libc/sys/flock.2
+++ b/lib/libc/sys/flock.2
@@ -39,10 +39,10 @@
.Nd "apply or remove an advisory lock on an open file"
.Sh SYNOPSIS
.Fd #include <sys/file.h>
-.Fd #define LOCK_SH 1 /* shared lock */
-.Fd #define LOCK_EX 2 /* exclusive lock */
-.Fd #define LOCK_NB 4 /* don't block when locking */
-.Fd #define LOCK_UN 8 /* unlock */
+.Fd #define LOCK_SH 0x01 /* shared file lock */
+.Fd #define LOCK_EX 0x02 /* exclusive file lock */
+.Fd #define LOCK_NB 0x04 /* don't block when locking */
+.Fd #define LOCK_UN 0x08 /* unlock file */
.Ft int
.Fn flock "int fd" "int operation"
.Sh DESCRIPTION
@@ -109,6 +109,28 @@ forks and the child explicitly unlocks the file, the parent will
lose its lock.
.Pp
Processes blocked awaiting a lock may be awakened by signals.
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn flock
+is implemented as the
+.Va flock
+syscall.
+.Pp
+In the threaded library, the
+.Va flock
+syscall is assembled to
+.Fn _thread_sys_flock
+and
+.Fn flock
+is implemented as a function which locks
+.Va fd
+for read and write, then calls
+.Fn _thread_sys_flock .
+Before returning,
+.Fn flock
+unlocks
+.Va fd .
.Sh RETURN VALUES
Zero is returned if the operation was successful;
on an error a -1 is returned and an error code is left in
@@ -131,15 +153,19 @@ is an invalid descriptor.
The argument
.Fa fd
refers to an object other than a file.
+.It Bq Er EOPNOTSUPP
+The argument
+.Fa fd
+refers to an object that does not support file locking.
.El
.Sh SEE ALSO
-.Xr open 2 ,
.Xr close 2 ,
.Xr dup 2 ,
.Xr execve 2 ,
-.Xr fork 2
+.Xr fork 2 ,
+.Xr open 2
.Sh HISTORY
The
-.Nm
+.Fn flock
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/fork.2 b/lib/libc/sys/fork.2
index 0c290f6..a0bb0f6 100644
--- a/lib/libc/sys/fork.2
+++ b/lib/libc/sys/fork.2
@@ -59,9 +59,9 @@ for instance, file pointers in file objects are shared between
the child and the parent, so that an
.Xr lseek 2
on a descriptor in the child process can affect a subsequent
-.Xr read
+.Xr read 2
or
-.Xr write
+.Xr write 2
by the parent.
This descriptor copying is also used by the shell to
establish standard input and output for newly created processes
@@ -88,18 +88,33 @@ will fail and no child process will be created if:
.It Bq Er EAGAIN
The system-imposed limit on the total
number of processes under execution would be exceeded.
-This limit is configuration-dependent.
+The limit is given by the
+.Xr sysctl 3
+MIB variable
+.Dv KERN_MAXPROC .
+(The limit is actually one less than this
+except for the super user).
.It Bq Er EAGAIN
-The system-imposed limit
-.Dv MAXUPRC
-.Pq Aq Pa sys/param.h
+The user is not the super user, and
+the system-imposed limit
on the total number of
processes under execution by a single user would be exceeded.
+The limit is given by the
+.Xr sysctl 3
+MIB variable
+.Dv KERN_MAXPROCPERUID .
+.It Bq Er EAGAIN
+The user is not the super user, and
+the soft resource limit corresponding to the resource parameter
+.Dv RLIMIT_NOFILE
+would be exceeded (see
+.Xr getrlimit 2 ) .
.It Bq Er ENOMEM
There is insufficient swap space for the new process.
.El
.Sh SEE ALSO
.Xr execve 2 ,
+.Xr vfork 2 ,
.Xr wait 2
.Sh HISTORY
A
diff --git a/lib/libc/sys/fsync.2 b/lib/libc/sys/fsync.2
index 234ea6e..74105ec 100644
--- a/lib/libc/sys/fsync.2
+++ b/lib/libc/sys/fsync.2
@@ -53,6 +53,28 @@ of buffers for the associated file to be written to a disk.
should be used by programs that require a file to be
in a known state, for example, in building a simple transaction
facility.
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn fsync
+is implemented as the
+.Va fsync
+syscall.
+.Pp
+In the threaded library, the
+.Va fsync
+syscall is assembled to
+.Fn _thread_sys_fsync
+and
+.Fn fsync
+is implemented as a function which locks
+.Va fd
+for read and write, then calls
+.Fn _thread_sys_fsync .
+Before returning,
+.Fn fsync
+unlocks
+.Va fd .
.Sh RETURN VALUES
A 0 value is returned on success. A -1 value indicates
an error.
@@ -72,10 +94,10 @@ An I/O error occurred while reading from or writing to the file system.
.El
.Sh SEE ALSO
.Xr sync 2 ,
-.Xr sync 8 ,
-.Xr update 8
+.Xr update 4 ,
+.Xr sync 8
.Sh HISTORY
The
-.Nm
+.Fn fsync
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/ftruncate.c b/lib/libc/sys/ftruncate.c
index 2f3ae6d..72a6a91 100644
--- a/lib/libc/sys/ftruncate.c
+++ b/lib/libc/sys/ftruncate.c
@@ -37,6 +37,11 @@ static char sccsid[] = "@(#)ftruncate.c 8.1 (Berkeley) 6/17/93";
#include <sys/types.h>
#include <sys/syscall.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/*
* This function provides 64-bit offset padding that
@@ -48,5 +53,16 @@ ftruncate(fd, length)
off_t length;
{
+#ifdef _THREAD_SAFE
+ int retval;
+ if (_thread_fd_lock(fd, FD_RDWR, NULL,__FILE__,__LINE__) != 0) {
+ retval = -1;
+ } else {
+ retval = __syscall((quad_t)SYS_ftruncate, fd, 0, length);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return(retval);
+#else
return(__syscall((quad_t)SYS_ftruncate, fd, 0, length));
+#endif
}
diff --git a/lib/libc/sys/getdirentries.2 b/lib/libc/sys/getdirentries.2
index 532bec1..be85934 100644
--- a/lib/libc/sys/getdirentries.2
+++ b/lib/libc/sys/getdirentries.2
@@ -38,7 +38,8 @@
.Nm getdirentries
.Nd "get directory entries in a filesystem independent format"
.Sh SYNOPSIS
-.Fd #include <sys/dirent.h>
+.Fd #include <sys/types.h>
+.Fd #include <dirent.h>
.Ft int
.Fn getdirentries "int fd" "char *buf" "int nbytes" "long *basep"
.Sh DESCRIPTION
@@ -65,11 +66,11 @@ The data in the buffer is a series of
.Em dirent
structures each containing the following entries:
.Bd -literal -offset indent
-unsigned long d_fileno;
-unsigned short d_reclen;
-unsigned char d_type;
-unsigned char d_namlen;
-char d_name[MAXNAMELEN + 1]; /* see below */
+u_int32_t d_fileno;
+u_int16_t d_reclen;
+u_int8_t d_type;
+u_int8_t d_namelen;
+char d_name[MAXNAMELEN + 1]; /* see below */
.Ed
.Pp
The
@@ -126,6 +127,28 @@ The current position pointer should only be set to a value returned by
a value returned in the location pointed to by
.Fa basep ,
or zero.
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn getdirentries
+is implemented as the
+.Va getdirentries
+syscall.
+.Pp
+In the threaded library, the
+.Va getdirentries
+syscall is assembled to
+.Fn _thread_sys_getdirentries
+and
+.Fn getdirentries
+is implemented as a function which locks
+.Va fd
+for read and write, then calls
+.Fn _thread_sys_getdirentries .
+Before returning,
+.Fn getdirentries
+unlocks
+.Va fd .
.Sh RETURN VALUES
If successful, the number of bytes actually transferred is returned.
Otherwise, -1 is returned and the global variable
@@ -135,24 +158,25 @@ is set to indicate the error.
.Fn Getdirentries
will fail if:
.Bl -tag -width [EFAULT]
-.It EBADF
+.It Bq Er EBADF
.Fa fd
is not a valid file descriptor open for reading.
-.It EFAULT
+.It Bq Er EFAULT
Either
.Fa buf
or
.Fa basep
point outside the allocated address space.
-.It EIO
+.It Bq Er EIO
An
.Tn I/O
error occurred while reading from or writing to the file system.
.El
.Sh SEE ALSO
-.Xr open 2 ,
-.Xr lseek 2
+.Xr lseek 2 ,
+.Xr open 2
.Sh HISTORY
The
-.Nm getdirentries
-function first appeared in 4.4BSD.
+.Fn getdirentries
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/getfh.2 b/lib/libc/sys/getfh.2
index ab73d5a..44ac7e7 100644
--- a/lib/libc/sys/getfh.2
+++ b/lib/libc/sys/getfh.2
@@ -38,10 +38,10 @@
.Nm getfh
.Nd get file handle
.Sh SYNOPSIS
-.Fd #include <sys/types.h>
+.Fd #include <sys/param.h>
.Fd #include <sys/mount.h>
.Ft int
-.Fn getfh "char *path" "fhandle_t *fhp"
+.Fn getfh "const char *path" "fhandle_t *fhp"
.Sh DESCRIPTION
.Fn Getfh
returns a file handle for the specified file or directory
@@ -61,9 +61,6 @@ fails if one or more of the following are true:
A component of the path prefix of
.Fa path
is not a directory.
-.It Bq EINVAL
-.Fa path
-contains a character with the high-order bit set.
.It Bq ENAMETOOLONG
The length of a component of
.Fa path
@@ -91,6 +88,7 @@ error occurred while reading from or writing to the file system.
.El
.Sh HISTORY
The
-.Nm getfh
+.Fn getfh
function
-first appeared in 4.4BSD.
+first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/getfsstat.2 b/lib/libc/sys/getfsstat.2
index b25261c..011a815 100644
--- a/lib/libc/sys/getfsstat.2
+++ b/lib/libc/sys/getfsstat.2
@@ -51,27 +51,32 @@ is a pointer to
.Xr statfs
structures defined as follows:
.Bd -literal
-typedef quad fsid_t;
+typedef struct fsid { int32_t val[2]; } fsid_t; /* file system id type */
-#define MFSNAMELEN 16 /* length of fs type name, including null */
-#define MNAMELEN 90 /* length of buffer for returned name */
+/*
+ * file system statistics
+ */
+
+#define MFSNAMELEN 16 /* length of fs type name, including null */
+#define MNAMELEN 90 /* length of buffer for returned name */
struct statfs {
- short f_type; /* filesystem type number */
- short f_flags; /* copy of mount flags */
- long f_bsize; /* fundamental file system block size */
- long f_iosize; /* optimal transfer block size */
- long f_blocks; /* total data blocks in file system */
- long f_bfree; /* free blocks in fs */
- long f_bavail; /* free blocks avail to non-superuser */
- long f_files; /* total file nodes in file system */
- long f_ffree; /* free file nodes in fs */
- fsid_t f_fsid; /* file system id */
- uid_t f_owner; /* user that mounted the filesystem */
- long f_spare[4]; /* spare for later */
- char f_fstypename[MFSNAMELEN]; /* fs type name */
- char f_mntonname[MNAMELEN]; /* directory on which mounted */
- char f_mntfromname[MNAMELEN];/* mounted filesystem */
+ long f_spare2; /* placeholder */
+ long f_bsize; /* fundamental file system block size */
+ long f_iosize; /* optimal transfer block size */
+ long f_blocks; /* total data blocks in file system */
+ long f_bfree; /* free blocks in fs */
+ long f_bavail; /* free blocks avail to non-superuser */
+ long f_files; /* total file nodes in file system */
+ long f_ffree; /* free file nodes in fs */
+ fsid_t f_fsid; /* file system id */
+ uid_t f_owner; /* user that mounted the filesystem */
+ int f_type; /* type of filesystem (see below) */
+ int f_flags; /* copy of mount flags */
+ long f_spare[2]; /* spare for later */
+ char f_fstypename[MFSNAMELEN];/* fs type name */
+ char f_mntonname[MNAMELEN];/* directory on which mounted */
+ char f_mntfromname[MNAMELEN];/* mounted filesystem */
};
.Ed
.Pp
@@ -161,5 +166,6 @@ error occurred while reading from or writing to the filesystem.
.Xr mount 8
.Sh HISTORY
The
-.Nm getfsstat
-function first appeared in 4.4BSD.
+.Fn getfsstat
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/getgid.2 b/lib/libc/sys/getgid.2
index 52519d7..bf58d18 100644
--- a/lib/libc/sys/getgid.2
+++ b/lib/libc/sys/getgid.2
@@ -40,6 +40,7 @@
.Nd get group process identification
.Sh SYNOPSIS
.Fd #include <sys/types.h>
+.Fd #include <unistd.h>
.Ft gid_t
.Fn getgid void
.Ft gid_t
@@ -69,11 +70,13 @@ functions are always successful, and no return value is reserved to
indicate an error.
.Sh SEE ALSO
.Xr getuid 2 ,
-.Xr setregid 2 ,
-.Xr setgid 3
+.Xr issetugid 2 ,
+.Xr setgid 2 ,
+.Xr setregid 2
.Sh STANDARDS
-.Fn Getgid
+The
+.Fn getgid
and
.Fn getegid
-conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+function calls are expected to conform to
+.St -p1003.1-90 .
diff --git a/lib/libc/sys/getgroups.2 b/lib/libc/sys/getgroups.2
index 1428d83..ea73890 100644
--- a/lib/libc/sys/getgroups.2
+++ b/lib/libc/sys/getgroups.2
@@ -85,6 +85,6 @@ an invalid address.
.Xr initgroups 3
.Sh HISTORY
The
-.Nm
+.Fn getgroups
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/getitimer.2 b/lib/libc/sys/getitimer.2
index f39501d..c210248 100644
--- a/lib/libc/sys/getitimer.2
+++ b/lib/libc/sys/getitimer.2
@@ -46,7 +46,7 @@
.Ft int
.Fn getitimer "int which" "struct itimerval *value"
.Ft int
-.Fn setitimer "int which" "struct itimerval *value" "struct itimerval *ovalue"
+.Fn setitimer "int which" "const struct itimerval *value" "struct itimerval *ovalue"
.Sh DESCRIPTION
The system provides each process with three interval timers,
defined in
@@ -155,11 +155,12 @@ parameter specified a time that was too large
to be handled.
.El
.Sh SEE ALSO
+.Xr gettimeofday 2 ,
.Xr select 2 ,
.Xr sigvec 2 ,
-.Xr gettimeofday 2
+.Xr clocks 7
.Sh HISTORY
The
-.Nm
+.Fn getitimer
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/getlogin.2 b/lib/libc/sys/getlogin.2
index 5b351ca..6154890 100644
--- a/lib/libc/sys/getlogin.2
+++ b/lib/libc/sys/getlogin.2
@@ -66,6 +66,50 @@ This 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).
+.Pp
+.Em NOTE:
+There is only one `login name' per `session .
+.Pp
+It is
+.Em CRITICALLY
+important to ensure that
+.Fn setlogin
+is only ever called after the process has taken adequate steps to ensure
+that it is detached from its parent's session.
+Making a
+.Fn setsid
+system call is the
+.Em ONLY
+way to do this. The
+.Fn daemon
+library call calls
+.Fn setsid
+which is an ideal way of detaching from a controlling terminal and
+forking into the background.
+.Pp
+In particular, doing a
+.Fn "ioctl" "ttyfd" "TIOCNOTTY" "..."
+or
+.Fn "setpgrp" "..."
+is
+.Em NOT
+sufficient.
+.Pp
+Once a parent process does a
+.Fn setsid
+call, it is acceptable for some child of that process to then do a
+.Fn setlogin
+even though it is not the session leader, but beware that ALL processes
+in the session will change their login name at the same time, even the
+parent.
+.Pp
+This is not the same as the traditional UNIX behavior of inheriting privilege.
+.Pp
+Since the
+.Fn setlogin
+system call is restricted to the super-user, it is assumed that (like
+all other privileged programs) the programmer has taken adequate
+precautions to prevent security violations.
.Sh RETURN VALUES
If a call to
.Fn getlogin
@@ -96,20 +140,14 @@ Login names are limited to
.Dv MAXLOGNAME
(from
.Ao Pa sys/param.h Ac )
-characters, currently 12.
+characters, currently 17 including null.
.It Bq Er EPERM
The caller tried to set the login name and was not the super-user.
.El
.Sh SEE ALSO
-.Xr setsid 2
+.Xr setsid 2 ,
+.Xr daemon 3
.Sh BUGS
-Login names are limited in length by
-.Fn setlogin .
-However, lower limits are placed on login names elsewhere in the system
-.Pf ( Dv UT_NAMESIZE
-in
-.Ao Pa utmp.h Ac ) .
-.Pp
In earlier versions of the system,
.Fn getlogin
failed unless the process was associated with a login terminal.
@@ -123,4 +161,5 @@ Portable programs should probably still make this check.
.Sh HISTORY
The
.Fn getlogin
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/getpeername.2 b/lib/libc/sys/getpeername.2
index d89488c..b9b6a03 100644
--- a/lib/libc/sys/getpeername.2
+++ b/lib/libc/sys/getpeername.2
@@ -38,6 +38,8 @@
.Nm getpeername
.Nd get name of connected peer
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
.Ft int
.Fn getpeername "int s" "struct sockaddr *name" "int *namelen"
.Sh DESCRIPTION
@@ -53,7 +55,29 @@ the amount of space pointed to by
On return it contains the actual size of the name
returned (in bytes).
The name is truncated if the buffer provided is too small.
-.Sh DIAGNOSTICS
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn getpeername
+is implemented as the
+.Va getpeername
+syscall.
+.Pp
+In the threaded library, the
+.Va getpeername
+syscall is assembled to
+.Fn _thread_sys_getpeername
+and
+.Fn getpeername
+is implemented as a function which locks
+.Va s
+for read and write, then calls
+.Fn _thread_sys_getpeername .
+Before returning,
+.Fn getpeername
+unlocks
+.Va s .
+.Sh RETURN VALUES
A 0 is returned if the call succeeds, -1 if it fails.
.Sh ERRORS
The call succeeds unless:
@@ -80,10 +104,10 @@ process address space.
.Sh SEE ALSO
.Xr accept 2 ,
.Xr bind 2 ,
-.Xr socket 2 ,
-.Xr getsockname 2
+.Xr getsockname 2 ,
+.Xr socket 2
.Sh HISTORY
The
-.Nm
+.Fn getpeername
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/getpgrp.2 b/lib/libc/sys/getpgrp.2
index 88812b7..9780b19 100644
--- a/lib/libc/sys/getpgrp.2
+++ b/lib/libc/sys/getpgrp.2
@@ -67,15 +67,15 @@ are used to get/set the process group of the control terminal.
.Xr termios 4
.Sh HISTORY
The
-.Nm
+.Fn getpgrp
function call appeared in
.Bx 4.0 .
.Sh STANDARDS
The
.Fn getpgrp
-function conforms to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
-.Sh COMPATABILITY
+function call is expected to conform to
+.St -p1003.1-90 .
+.Sh COMPATIBILITY
This version of
.Fn getpgrp
differs from past Berkeley versions by not taking a
@@ -87,15 +87,18 @@ This incompatibility is required by
From the
.St -p1003.1-88
Rationale:
-.sp
-4.3BSD provides a
+.Pp
+.Bx 4.3
+provides a
.Fn getpgrp
function that returns the process group ID for a specified process.
Although this function is used to support job control, all known
job-control shells always specify the calling process with this
function.
-Thus, the simpler System V
+Thus, the simpler
+.At V
.Fn getpgrp
-suffices, and the added complexity of the 4.3BSD
+suffices, and the added complexity of the
+.Bx 4.3
.Fn getpgrp
has been omitted from POSIX.1.
diff --git a/lib/libc/sys/getpid.2 b/lib/libc/sys/getpid.2
index 5f77706..b57fd60 100644
--- a/lib/libc/sys/getpid.2
+++ b/lib/libc/sys/getpid.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)getpid.2 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt GETPID 2
@@ -63,10 +64,16 @@ and
functions are always successful, and no return value is reserved to
indicate an error.
.Sh SEE ALSO
-.Xr gethostid 2
+.Xr gethostid 3
.Sh STANDARDS
-.Fn Getpid
+The
+.Fn getpid
and
.Fn getppid
-conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+function calls are expected to conform to
+.St -p1003.1-90 .
+.Sh HISTORY
+A
+.Fn getpid
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/getpriority.2 b/lib/libc/sys/getpriority.2
index aa151a0..fdb0a1e 100644
--- a/lib/libc/sys/getpriority.2
+++ b/lib/libc/sys/getpriority.2
@@ -137,6 +137,6 @@ A non super-user attempted to lower a process priority.
.Xr renice 8
.Sh HISTORY
The
-.Nm
+.Fn getpriority
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/getrlimit.2 b/lib/libc/sys/getrlimit.2
index 9aa3c8e..6725520 100644
--- a/lib/libc/sys/getrlimit.2
+++ b/lib/libc/sys/getrlimit.2
@@ -45,7 +45,7 @@
.Ft int
.Fn getrlimit "int resource" "struct rlimit *rlp"
.Ft int
-.Fn setrlimit "int resource" "struct rlimit *rlp"
+.Fn setrlimit "int resource" "const struct rlimit *rlp"
.Sh DESCRIPTION
Limits on the consumption of system resources by the current process
and each process it creates may be obtained with the
@@ -60,7 +60,7 @@ parameter is one of the following:
.Bl -tag -width RLIMIT_FSIZEAA
.It Li RLIMIT_CORE
The largest size (in bytes)
-.Xr core
+.Xr core 5
file that may be created.
.It Li RLIMIT_CPU
The maximum amount of cpu time (in seconds) to be used by
@@ -102,8 +102,8 @@ its resource limit). The
structure is used to specify the hard and soft limits on a resource,
.Bd -literal -offset indent
struct rlimit {
- quad_t rlim_cur; /* current (soft) limit */
- quad_t rlim_max; /* hard limit */
+ rlim_t rlim_cur; /* current (soft) limit */
+ rlim_t rlim_max; /* maximum value for rlim_cur */
};
.Ed
.Pp
@@ -171,21 +171,13 @@ raised the maximum limit value, and the caller is not the super-user.
.El
.Sh SEE ALSO
.Xr csh 1 ,
-.Xr quota 2 ,
+.Xr quota 1 ,
+.Xr quotactl 2 ,
.Xr sigaltstack 2 ,
.Xr sigvec 2 ,
.Xr sysctl 3
-.Sh BUGS
-There should be
-.Ic limit
-and
-.Ic unlimit
-commands in
-.Xr sh 1
-as well as in
-.Xr csh .
.Sh HISTORY
The
-.Nm
+.Fn getrlimit
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/getrusage.2 b/lib/libc/sys/getrusage.2
index 9d1657c..0f92569 100644
--- a/lib/libc/sys/getrusage.2
+++ b/lib/libc/sys/getrusage.2
@@ -38,6 +38,7 @@
.Nm getrusage
.Nd get information about resource utilization
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
.Fd #include <sys/time.h>
.Fd #include <sys/resource.h>
.Fd #define RUSAGE_SELF 0
@@ -62,7 +63,7 @@ the following structure:
struct rusage {
struct timeval ru_utime; /* user time used */
struct timeval ru_stime; /* system time used */
- long ru_maxrss; /* integral max resident set size */
+ long ru_maxrss; /* max resident set size */
long ru_ixrss; /* integral shared text memory size */
long ru_idrss; /* integral unshared data size */
long ru_isrss; /* integral unshared stack size */
@@ -93,6 +94,9 @@ an \*(lqintegral\*(rq value indicating the amount of memory used
by the text segment
that was also shared among other processes. This value is expressed
in units of kilobytes * ticks-of-execution.
+Ticks are statistics clock ticks.
+The statistics clock has a frequency of
+sysconf(_SC_CLOCK_TCK) ticks per second.
.It Fa ru_idrss
an integral value of the amount of unshared memory residing in the
data segment of a process (expressed in units of
@@ -137,10 +141,16 @@ and
account only for real
I/O; data supplied by the caching mechanism is charged only
to the first process to read or write the data.
+.Sh RETURN VALUES
+Uponsuccessful completion,
+.Fn getrusage
+returns 0. Otherwise, a value of -1 is returned and
+.Va errno
+is set to indicate the error.
.Sh ERRORS
-.Fn Getrusage
-returns -1 on error.
-The possible errors are:
+The
+.Fn getrusage
+function will fail if:
.Bl -tag -width Er
.It Bq Er EINVAL
The
@@ -153,12 +163,13 @@ parameter is not in a valid part of the process address space.
.El
.Sh SEE ALSO
.Xr gettimeofday 2 ,
-.Xr wait 2
+.Xr wait 2 ,
+.Xr clocks 7
.Sh BUGS
There is no way to obtain information about a child process
that has not yet terminated.
.Sh HISTORY
The
-.Nm
+.Fn getrusage
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/getsockname.2 b/lib/libc/sys/getsockname.2
index d56e404..bbd9f93 100644
--- a/lib/libc/sys/getsockname.2
+++ b/lib/libc/sys/getsockname.2
@@ -38,6 +38,8 @@
.Nm getsockname
.Nd get socket name
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
.Ft int
.Fn getsockname "int s" "struct sockaddr *name" "int *namelen"
.Sh DESCRIPTION
@@ -51,7 +53,29 @@ the amount of space pointed to by
.Fa name .
On return it contains the actual size of the name
returned (in bytes).
-.Sh DIAGNOSTICS
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn getsockname
+is implemented as the
+.Va getsockname
+syscall.
+.Pp
+In the threaded library, the
+.Va getsockname
+syscall is assembled to
+.Fn _thread_sys_getsockname
+and
+.Fn getsockname
+is implemented as a function which locks
+.Va fd
+for read and write, then calls
+.Fn _thread_sys_getsockname .
+Before returning,
+.Fn getsockname
+unlocks
+.Va fd .
+.Sh RETURN VALUES
A 0 is returned if the call succeeds, -1 if it fails.
.Sh ERRORS
The call succeeds unless:
@@ -75,6 +99,7 @@ process address space.
.El
.Sh SEE ALSO
.Xr bind 2 ,
+.Xr getpeername 2 ,
.Xr socket 2
.Sh BUGS
Names bound to sockets in the UNIX domain are inaccessible;
@@ -82,6 +107,6 @@ Names bound to sockets in the UNIX domain are inaccessible;
returns a zero length name.
.Sh HISTORY
The
-.Nm
+.Fn getsockname
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/getsockopt.2 b/lib/libc/sys/getsockopt.2
index 8362d5e..ff9ca90 100644
--- a/lib/libc/sys/getsockopt.2
+++ b/lib/libc/sys/getsockopt.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)getsockopt.2 8.4 (Berkeley) 5/2/95
+.\" $Id: getsockopt.2,v 1.8 1997/02/22 15:03:53 peter Exp $
.\"
.Dd May 2, 1995
.Dt GETSOCKOPT 2
@@ -189,7 +190,7 @@ is performed.
If the socket promises reliable delivery of data and
.Dv SO_LINGER is set,
the system will block the process on the
-.Xr close
+.Xr close 2
attempt until it is able to transmit the data or until it decides it
is unable to deliver the information (a timeout period, termed the
linger interval, is specified in seconds in the
@@ -200,7 +201,7 @@ is requested).
If
.Dv SO_LINGER
is disabled and a
-.Xr close
+.Xr close 2
is issued, the system will process the close in a manner that allows
the process to continue as quickly as possible.
.Pp
@@ -214,9 +215,9 @@ With protocols that support out-of-band data, the
option
requests that out-of-band data be placed in the normal data input queue
as received; it will then be accessible with
-.Xr recv
+.Xr recv 2
or
-.Xr read
+.Xr read 2
calls without the
.Dv MSG_OOB
flag.
@@ -228,7 +229,11 @@ are options to adjust the normal
buffer sizes allocated for output and input buffers, respectively.
The buffer size may be increased for high-volume connections,
or may be decreased to limit the possible backlog of incoming data.
-The system places an absolute limit on these values.
+The system places an absolute maximum on these values, which is accessible
+through the
+.Xr sysctl 3
+MIB variable
+.Dq Li kern.maxsockbuf .
.Pp
.Dv SO_SNDLOWAT
is an option to set the minimum count for output operations.
@@ -261,7 +266,7 @@ wait until they have received the smaller of the low water mark value
or the requested amount.
Receive calls may still return less than the low water mark if an error
occurs, a signal is caught, or the type of data next in the receive queue
-is different than that returned.
+is different from that which was returned.
.Pp
.Dv SO_SNDTIMEO
is an option to set a timeout value for output operations.
@@ -308,6 +313,49 @@ returns any pending error on the socket and clears
the error status.
It may be used to check for asynchronous errors on connected
datagram sockets or for other asynchronous errors.
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn getsockopt
+is implemented as the
+.Va getsockopt
+syscall.
+.Pp
+In the threaded library, the
+.Va getsockopt
+syscall is assembled to
+.Fn _thread_sys_getsockopt
+and
+.Fn getsockopt
+is implemented as a function which locks
+.Va s
+for read and write, then calls
+.Fn _thread_sys_getsockopt .
+Before returning,
+.Fn getsockopt
+unlocks
+.Va s .
+.Pp
+In the non-threaded library
+.Fn setsockopt
+is implemented as the
+.Va setsockopt
+syscall.
+.Pp
+In the threaded library, the
+.Va setsockopt
+syscall is assembled to
+.Fn _thread_sys_setsockopt
+and
+.Fn setsockopt
+is implemented as a function which locks
+.Va s
+for read and write, then calls
+.Fn _thread_sys_setsockopt .
+Before returning,
+.Fn setsockopt
+unlocks
+.Va s .
.Sh RETURN VALUES
A 0 is returned if the call succeeds, -1 if it fails.
.Sh ERRORS
@@ -336,12 +384,14 @@ is not in a valid part of the process address space.
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr socket 2 ,
-.Xr getprotoent 3
-.Xr protocols 5
+.Xr getprotoent 3 ,
+.Xr sysctl 3 ,
+.Xr protocols 5 ,
+.Xr sysctl 8
.Sh BUGS
Several of the socket options should be handled at lower levels of the system.
.Sh HISTORY
The
-.Nm
+.Fn getsockopt
system call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/gettimeofday.2 b/lib/libc/sys/gettimeofday.2
index b4d0429..06ee8b1 100644
--- a/lib/libc/sys/gettimeofday.2
+++ b/lib/libc/sys/gettimeofday.2
@@ -43,7 +43,7 @@
.Ft int
.Fn gettimeofday "struct timeval *tp" "struct timezone *tzp"
.Ft int
-.Fn settimeofday "struct timeval *tp" "struct timezone *tzp"
+.Fn settimeofday "const struct timeval *tp" "const struct timezone *tzp"
.Sh DESCRIPTION
.Bf -symbolic
Note: timezone is no longer used; this information is kept outside
@@ -74,13 +74,13 @@ as:
.Pp
.Bd -literal
struct timeval {
- long tv_sec; /* seconds since Jan. 1, 1970 */
+ long tv_sec; /* seconds */
long tv_usec; /* and microseconds */
};
struct timezone {
- int tz_minuteswest; /* of Greenwich */
- int tz_dsttime; /* type of dst correction to apply */
+ int tz_minuteswest; /* minutes west of Greenwich */
+ int tz_dsttime; /* type of dst correction */
};
.Ed
.Pp
@@ -119,9 +119,10 @@ A user other than the super-user attempted to set the time.
.Xr date 1 ,
.Xr adjtime 2 ,
.Xr ctime 3 ,
+.Xr clocks 7 ,
.Xr timed 8
.Sh HISTORY
The
-.Nm
+.Fn gettimeofday
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/getuid.2 b/lib/libc/sys/getuid.2
index 23b1763..9808cb2 100644
--- a/lib/libc/sys/getuid.2
+++ b/lib/libc/sys/getuid.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)getuid.2 8.1 (Berkeley) 6/4/93
+.\" $Id: getuid.2,v 1.5 1997/02/22 15:03:54 peter Exp $
.\"
.Dd June 4, 1993
.Dt GETUID 2
@@ -71,10 +72,21 @@ functions are always successful, and no return value is reserved to
indicate an error.
.Sh SEE ALSO
.Xr getgid 2 ,
-.Xr setreuid 2
+.Xr issetugid 2 ,
+.Xr setgid 2 ,
+.Xr setreuid 2 ,
+.Xr setuid 2
.Sh STANDARDS
-.Fn Geteuid
+The
+.Fn geteuid
and
.Fn getuid
-conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+function calls are expected to conform to
+.St -p1003.1-90 .
+.Sh HISTORY
+A
+.Fn getuid
+and a
+.Fn geteuid
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/intro.2 b/lib/libc/sys/intro.2
index ddda2ba..ee46085 100644
--- a/lib/libc/sys/intro.2
+++ b/lib/libc/sys/intro.2
@@ -46,13 +46,50 @@ their error returns, and other common definitions and concepts.
.\".Sy System call restart
.\".Pp
.\"<more later...>
-.Sh DIAGNOSTICS
-Nearly all of the system calls provide an error number in the external
-variable
-.Va errno ,
-which is defined as:
+.Sh RETURN VALUES
+Nearly all of the system calls provide an error number referenced via
+the external identifier errno. This identifier is defined in
+.Aq Pa sys/errno.h
+for non-threaded programs as:
.Pp
-.Dl extern int errno
+.Dl extern int errno;
+.Pp
+and for threaded programs as:
+.Pp
+.Dl extern int * __error();
+.Dl #define errno (* __error())
+.Pp
+A threaded program must be compiled with
+.Va _THREAD_SAFE
+defined so that the preprocessor will output the appropriate errno
+definition to the compiler. Failure to do so will mean that error
+variables will not be thread specific.
+.Pp
+The threaded library implementation of
+.Va __error()
+returns a pointer to a field in the thread specific structure for
+threads other than the initial thread. For the initial thread,
+.Va __error()
+returns a pointer to a global
+.Va errno
+variable that is compatible with that used by non-threaded programs.
+This allows the initial thread to call functions in libraries which have
+not been compiled with
+.Va _THREAD_SAFE .
+Programmers should ensure that threads other than the initial thread only
+call functions in libraries that have been compiled with
+.Va _THREAD_SAFE .
+.Pp
+Programmers should include
+.Aq Pa sys/errno.h
+to obtain the definition of
+.Va errno
+rather than coding the definition as an external reference directly. It is
+planned that the
+.Va extern int errno
+definition will eventually be replaced by the threaded definition so that
+all libraries will have a thread-aware treatment of
+.Va errno .
.Pp
When a system call detects an error,
it returns an integer value
@@ -108,7 +145,7 @@ loaded on a drive.
.It Er 7 E2BIG Em "Arg list too long" .
The number of bytes used for the argument and environment
list of the new process exceeded the current limit
-of 20480 bytes
+of 65536 bytes
.Pf ( Dv NCARGS
in
.Aq Pa sys/param.h ) .
@@ -121,12 +158,12 @@ executable file.
A file descriptor argument was out of range, referred to no open file,
or a read (write) request was made to a file that was only open for
writing (reading).
-.sp
+.Pp
.It Er 10 ECHILD Em "\&No child processes" .
A
-.Xr wait
+.Xr wait 2
or
-.Xr waitpid
+.Xr waitpid 2
function was executed by a process that had no existing or unwaited-for
child processes.
.It Er 11 EDEADLK Em "Resource deadlock avoided" .
@@ -152,7 +189,7 @@ in a manner which would have conflicted with the request.
.It Er 17 EEXIST Em "File exists" .
An existing file was mentioned in an inappropriate context,
for instance, as the new link name in a
-.Xr link
+.Xr link 2
function.
.It Er 18 EXDEV Em "Improper link" .
A hard link to a file on another file system
@@ -170,9 +207,9 @@ An attempt was made to open a directory with write mode specified.
.It Er 22 EINVAL Em "Invalid argument" .
Some invalid argument was supplied. (For example,
specifying an undefined signal to a
-.Xr signal
+.Xr signal 3
or
-.Xr kill
+.Xr kill 2
function).
.It Er 23 ENFILE Em "Too many open files in system" .
Maximum number of file descriptors allowable on the system
@@ -192,7 +229,7 @@ special device for which the operation was inappropriate.
The new process was a pure procedure (shared text) file
which was open for writing by another process, or
while the pure procedure file was being executed an
-.Xr open
+.Xr open 2
call requested write access.
.It Er 27 EFBIG Em "File too large" .
The size of a file exceeded the maximum (about
@@ -201,7 +238,7 @@ The size of a file exceeded the maximum (about
bytes).
.It Er 28 ENOSPC Em "Device out of space" .
A
-.Xr write
+.Xr write 2
to an ordinary file, the creation of a
directory or symbolic link, or the creation of a directory
entry failed because no more disk blocks were available
@@ -210,7 +247,7 @@ created file failed because no more inodes were available
on the file system.
.It Er 29 ESPIPE Em "Illegal seek" .
An
-.Xr lseek
+.Xr lseek 2
function was issued on a socket, pipe or
.Tn FIFO .
.It Er 30 EROFS Em "Read-only file system" .
@@ -289,7 +326,7 @@ addresses with
Internet protocols.
.It Er 48 EADDRINUSE Em "Address already in use" .
Only one usage of each address is normally permitted.
-.sp
+.Pp
.It Er 49 EADDRNOTAVAIL Em "Cannot assign requested address" .
Normally results from an attempt to create a socket with an
address not on this machine.
@@ -310,12 +347,12 @@ An operation on a socket or pipe was not performed because
the system lacked sufficient buffer space or because a queue was full.
.It Er 56 EISCONN Em "Socket is already connected" .
A
-.Xr connect
+.Xr connect 2
request was made on an already connected socket; or,
a
-.Xr sendto
+.Xr sendto 2
or
-.Xr sendmsg
+.Xr sendmsg 2
request on a connected socket specified a destination
when already connected.
.It Er 57 ENOTCONN Em "Socket is not connected" .
@@ -329,9 +366,9 @@ had already been shut down with a previous
call.
.It Er 60 ETIMEDOUT Em "Operation timed out" .
A
-.Xr connect
+.Xr connect 2
or
-.Xr send
+.Xr send 2
request failed because the connected party did not
properly respond after a period of time. (The timeout
period is dependent on the communication protocol.)
@@ -363,7 +400,7 @@ was supplied to a remove directory or rename call.
The quota system ran out of table entries.
.It Er 69 EDQUOT Em "Disc quota exceeded" .
A
-.Xr write
+.Xr write 2
to an ordinary file, the creation of a
directory or symbolic link, or the creation of a directory
entry failed because the user's quota of disk blocks was
@@ -417,7 +454,7 @@ A new process is created by a currently active process; (see
The parent process ID of a process is initially the process ID of its creator.
If the creating process exits,
the parent process ID of each child is set to the ID of a system process,
-.Xr init .
+.Xr init 8 .
.It Process Group
Each active process is a member of a process group that is identified by
a non-negative integer called the process group ID. This is the process
@@ -465,7 +502,7 @@ as the group,
but is in a different process group.
Note that when a process exits, the parent process for its children
is changed to be
-.Xr init ,
+.Nm init ,
which is in a separate session.
Not all members of an orphaned process group are necessarily orphaned
processes (those whose creating process has exited).
@@ -555,8 +592,7 @@ excluding 0 (NUL) and the
.Tn ASCII
code for
.Ql \&/
-(slash). (The parity bit,
-bit 7, must be 0.)
+(slash).
.Pp
Note that it is generally unwise to use
.Ql \&* ,
diff --git a/lib/libc/sys/ioctl.2 b/lib/libc/sys/ioctl.2
index 36ce6ff..a1d5f79 100644
--- a/lib/libc/sys/ioctl.2
+++ b/lib/libc/sys/ioctl.2
@@ -68,6 +68,28 @@ Macros and defines used in specifying an ioctl
.Fa request
are located in the file
.Ao Pa sys/ioctl.h Ac .
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn ioctl
+is implemented as the
+.Va ioctl
+syscall.
+.Pp
+In the threaded library, the
+.Va ioctl
+syscall is assembled to
+.Fn _thread_sys_ioctl
+and
+.Fn ioctl
+is implemented as a function which locks
+.Va d
+for read and write, then calls
+.Fn _thread_sys_ioctl .
+Before returning,
+.Fn ioctl
+unlocks
+.Va d .
.Sh RETURN VALUES
If an error has occurred, a value of -1 is returned and
.Va errno
@@ -98,9 +120,10 @@ is not valid.
.Xr mt 1 ,
.Xr execve 2 ,
.Xr fcntl 2 ,
-.Xr tty 4 ,
-.Xr intro 4
+.Xr intro 4 ,
+.Xr tty 4
.Sh HISTORY
An
-.Nm
-function call appeared in Version 7 AT&T UNIX.
+.Fn ioctl
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/issetugid.2 b/lib/libc/sys/issetugid.2
new file mode 100644
index 0000000..943aa7d
--- /dev/null
+++ b/lib/libc/sys/issetugid.2
@@ -0,0 +1,94 @@
+.\" $OpenBSD: issetugid.2,v 1.7 1997/02/18 00:16:09 deraadt Exp $
+.\"
+.\" 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.
+.\" 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.
+.\"
+.\" $Id: issetugid.2,v 1.3 1997/04/01 18:45:57 mpp Exp $
+.\"
+.Dd August, 25 1996
+.Dt ISSETUGID 2
+.Os
+.Sh NAME
+.Nm issetugid
+.Nd is current process tainted by uid or gid changes
+.Sh SYNOPSIS
+.Fd #include <unistd.h>
+.Ft int
+.Fn issetugid void
+.Sh DESCRIPTION
+The
+.Fn issetugid
+function returns 1 if the process environment or memory address space
+is considered ``tainted'', and returns 0 otherwise.
+.Pp
+A process is tainted if it was created as a result of an
+.Xr execve 2
+system call which had either of the setuid or setgid bits set (and extra
+privileges were given as a result) or if it has changed any of it's real,
+effective or saved user or group ID's since it began execution.
+.Pp
+This system call exists so that library routines (eg: libc, libtermcap)
+can reliably determine if it is safe to use information
+that was obtained from the user, in particular the results from
+.Xr getenv 3
+should be viewed with suspicion if it is used to control operation.
+.Pp
+A ``tainted'' status is inherited by child processes as a result of the
+.Xr fork 2
+system call (or other library code that calls fork, such as
+.Xr popen 3 ) .
+.Pp
+It is assumed that a program that clears all privileges as it prepares
+to execute another will also reset the environment, hence the ``tainted''
+status will not be passed on. This is important for programs such as
+.Xr su 1
+which begin setuid but need to be able to create an untainted process.
+.Sh ERRORS
+The
+.Fn issetugid
+function is always successful, and no return value is reserved to
+indicate an error.
+.Sh SEE ALSO
+.Xr execve 2 ,
+.Xr fork 2 ,
+.Xr setgid 2 ,
+.Xr setegid 2 ,
+.Xr seteuid 2 ,
+.Xr setregid 2 ,
+.Xr setreuid 2 ,
+.Xr setuid 2
+.Sh HISTORY
+A
+.Fn issetugid
+function call first appeared in
+.Ox 2.0
+and was also implemented in
+.Fx 3.0 .
diff --git a/lib/libc/sys/kill.2 b/lib/libc/sys/kill.2
index a20afd3..6234bc1 100644
--- a/lib/libc/sys/kill.2
+++ b/lib/libc/sys/kill.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)kill.2 8.3 (Berkeley) 4/19/94
+.\" $Id: kill.2,v 1.6 1997/02/22 15:03:55 peter Exp $
.\"
.Dd April 19, 1994
.Dt KILL 2
@@ -38,6 +39,7 @@
.Nm kill
.Nd send signal to a process
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
.Fd #include <signal.h>
.Ft int
.Fn kill "pid_t pid" "int sig"
@@ -119,13 +121,17 @@ When signaling a process group, this error is returned if any members
of the group could not be signaled.
.El
.Sh SEE ALSO
-.Xr getpid 2 ,
.Xr getpgrp 2 ,
+.Xr getpid 2 ,
.Xr killpg 2 ,
.Xr sigaction 2
.Sh STANDARDS
The
.Fn kill
-function is expected to
-conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+function call is expected to conform to
+.St -p1003.1-90 .
+.Sh HISTORY
+A
+.Fn kill
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/ktrace.2 b/lib/libc/sys/ktrace.2
index 9fe61f8..8f41a52 100644
--- a/lib/libc/sys/ktrace.2
+++ b/lib/libc/sys/ktrace.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)ktrace.2 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt KTRACE 2
@@ -38,7 +39,9 @@
.Nm ktrace
.Nd process tracing
.Sh SYNOPSIS
-.Fd #include <sys/types.h>
+.Fd #include <sys/param.h>
+.Fd #include <sys/time.h>
+.Fd #include <sys/uio.h>
.Fd #include <sys/ktrace.h>
.Ft int
.Fn ktrace "const char *tracefile" "int ops" "int trpoints" "int pid"
@@ -52,7 +55,7 @@ Only the super-user can trace setuid or setgid programs.
The
.Ar tracefile
gives the pathname of the file to be used for tracing.
-The file must exist and be writable by the calling process.
+The file must exist and be a regular file writable by the calling process.
All trace records are always appended to the file,
so the file must be truncated to zero length to discard
previous trace data.
@@ -138,8 +141,6 @@ will fail if:
.Bl -tag -width ENAMETOOLONGAA
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -153,8 +154,8 @@ 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
.Sh SEE ALSO
-.Xr ktrace 1 ,
-.Xr kdump 1
+.Xr kdump 1 ,
+.Xr ktrace 1
.Sh HISTORY
A
.Nm ktrace
diff --git a/lib/libc/sys/link.2 b/lib/libc/sys/link.2
index d160786..e0bc45e 100644
--- a/lib/libc/sys/link.2
+++ b/lib/libc/sys/link.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)link.2 8.3 (Berkeley) 1/12/94
+.\" $Id$
.\"
.Dd January 12, 1994
.Dt LINK 2
@@ -74,7 +75,6 @@ both
and
.Fa name2
must be in the same file system.
-Unless the caller is the super-user,
.Fa name1
may not be a directory.
.Sh RETURN VALUES
@@ -88,8 +88,6 @@ will fail and no link will be created if:
.Bl -tag -width Ar
.It Bq Er ENOTDIR
A component of either path prefix is not a directory.
-.It Bq Er EINVAL
-Either pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of either pathname exceeded 255 characters,
or entire length of either path name exceeded 1023 characters.
@@ -113,8 +111,7 @@ does exist.
.It Bq Er EPERM
The file named by
.Fa name1
-is a directory and the effective
-user ID is not super-user.
+is a directory.
.It Bq Er EXDEV
The link named by
.Fa name2
@@ -145,7 +142,18 @@ is outside the process's allocated address space.
.Xr symlink 2 ,
.Xr unlink 2
.Sh STANDARDS
-.Fn Link
-is expected to
-conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+The
+.Fn link
+function call is expected to conform to
+.St -p1003.1-90 .
+.Sh HISTORY
+A
+.Fn link
+function call appeared in
+.At v7 .
+.Pp
+The
+.Fn link
+system call traditionally allows the super-user to link directories which
+corrupts the filesystem coherency. This implementation no longer permits
+it.
diff --git a/lib/libc/sys/listen.2 b/lib/libc/sys/listen.2
index 0dd2060..a9b503f 100644
--- a/lib/libc/sys/listen.2
+++ b/lib/libc/sys/listen.2
@@ -29,15 +29,17 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)listen.2 8.2 (Berkeley) 12/11/93
+.\" From: @(#)listen.2 8.2 (Berkeley) 12/11/93
+.\" $Id: listen.2,v 1.9 1997/02/22 15:03:59 peter Exp $
.\"
-.Dd December 11, 1993
+.Dd November 3, 1995
.Dt LISTEN 2
.Os BSD 4.2
.Sh NAME
.Nm listen
.Nd listen for connections on a socket
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
.Fd #include <sys/socket.h>
.Ft int
.Fn listen "int s" "int backlog"
@@ -68,6 +70,41 @@ receive an error with an indication of
.Er ECONNREFUSED ,
or, if the underlying protocol supports retransmission,
the request may be ignored so that retries may succeed.
+.Pp
+The
+.Xr sysctl 3
+MIB variable
+.Dq Li kern.somaxconn
+specifies a hard limit on
+.Fa backlog ;
+if a value greater than
+.Li kern.somaxconn
+or less than zero is specified,
+.Fa backlog
+is silently forced to
+.Li kern.somaxconn .
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn listen
+is implemented as the
+.Va listen
+syscall.
+.Pp
+In the threaded library, the
+.Va listen
+syscall is assembled to
+.Fn _thread_sys_listen
+and
+.Fn listen
+is implemented as a function which locks
+.Va s
+for read and write, then calls
+.Fn _thread_sys_listen .
+Before returning,
+.Fn listen
+unlocks
+.Va s .
.Sh RETURN VALUES
A 0 return value indicates success; -1 indicates an error.
.Sh ERRORS
@@ -89,13 +126,17 @@ The socket is not of a type that supports the operation
.Sh SEE ALSO
.Xr accept 2 ,
.Xr connect 2 ,
-.Xr socket 2
-.Sh BUGS
-The
-.Fa backlog
-is currently limited (silently) to 5.
+.Xr socket 2 ,
+.Xr sysctl 3 ,
+.Xr sysctl 8
.Sh HISTORY
The
-.Nm
+.Fn listen
function call appeared in
.Bx 4.2 .
+The ability to configure the maximum
+.Fa backlog
+at run-time, and to use a negative
+.Fa backlog
+to request the maximum allowable value, was introduced in
+.Fx 2.2 .
diff --git a/lib/libc/sys/lseek.2 b/lib/libc/sys/lseek.2
index ef38451..39a37fa 100644
--- a/lib/libc/sys/lseek.2
+++ b/lib/libc/sys/lseek.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)lseek.2 8.3 (Berkeley) 4/19/94
+.\" $Id$
.\"
.Dd April 19, 1994
.Dt LSEEK 2
@@ -56,7 +57,8 @@ The argument
must be an open
file descriptor.
.Fn Lseek
-repositions the file pointer
+repositions the file position pointer associated with the file
+descriptor
.Fa fildes
as follows:
.Bl -item -offset indent
@@ -108,7 +110,7 @@ is set to indicate
the error.
.Sh ERRORS
.Fn Lseek
-will fail and the file pointer will remain unchanged if:
+will fail and the file position pointer will remain unchanged if:
.Bl -tag -width [EINVAL]
.It Bq Er EBADF
.Em Fildes
@@ -130,6 +132,10 @@ is incorrect English, but is maintained for historical reasons.
.Sh STANDARDS
The
.Fn lseek
-function
-conforms to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+function call is expected to conform to
+.St -p1003.1-90 .
+.Sh HISTORY
+A
+.Fn lseek
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/lseek.c b/lib/libc/sys/lseek.c
index 52208d1..8896ad8 100644
--- a/lib/libc/sys/lseek.c
+++ b/lib/libc/sys/lseek.c
@@ -37,6 +37,11 @@ static char sccsid[] = "@(#)lseek.c 8.1 (Berkeley) 6/17/93";
#include <sys/types.h>
#include <sys/syscall.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+#endif
/*
* This function provides 64-bit offset padding that
@@ -48,7 +53,17 @@ lseek(fd, offset, whence)
off_t offset;
int whence;
{
- extern off_t __syscall();
+#ifdef _THREAD_SAFE
+ off_t offs;
+ if (_thread_fd_lock(fd, FD_RDWR, NULL,__FILE__,__LINE__) != 0) {
+ offs = -1;
+ } else {
+ offs = __syscall((quad_t) SYS_lseek,fd, 0, offset, whence);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return(offs);
+#else
return(__syscall((quad_t)SYS_lseek, fd, 0, offset, whence));
+#endif
}
diff --git a/lib/libc/sys/madvise.2 b/lib/libc/sys/madvise.2
index d0676ab..fc71765 100644
--- a/lib/libc/sys/madvise.2
+++ b/lib/libc/sys/madvise.2
@@ -30,15 +30,19 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)madvise.2 8.1 (Berkeley) 6/9/93
+.\" $Id$
.\"
-.Dd June 9, 1993
+.Dd Jul 19, 1996
.Dt MADVISE 2
.Os
.Sh NAME
.Nm madvise
.Nd give advise about use of memory
.Sh SYNOPSIS
-.Fn madvise "caddr_t addr" "int len" "int behav"
+.Fd #include <sys/types.h>
+.Fd #include <sys/mman.h>
+.Ft int
+.Fn madvise "caddr_t addr" "size_t len" "int behav"
.Sh DESCRIPTION
The
.Fn madvise
@@ -46,21 +50,78 @@ system call
allows a process that has knowledge of its memory behavior
to describe it to the system.
The known behaviors are given in
-.Pa <sys/mman.h> :
+.Aq Pa sys/mman.h :
.Bd -literal
-#define MADV_NORMAL 0 /* no further special treatment */
-#define MADV_RANDOM 1 /* expect random page references */
-#define MADV_SEQUENTIAL 2 /* expect sequential references */
-#define MADV_WILLNEED 3 /* will need these pages */
-#define MADV_DONTNEED 4 /* don't need these pages */
-#define MADV_SPACEAVAIL 5 /* insure that resources are reserved */
+#define MADV_NORMAL 0 /* no further special treatment */
+#define MADV_RANDOM 1 /* expect random page references */
+#define MADV_SEQUENTIAL 2 /* expect sequential references */
+#define MADV_WILLNEED 3 /* will need these pages */
+#define MADV_DONTNEED 4 /* don't need these pages */
+#define MADV_FREE 5 /* data is now unimportant */
.Ed
+.Pp
+.Bl -tag -width MADV_SEQUENTIAL
+.It Dv MADV_NORMAL
+Tells the system to revert to the default paging
+behavior.
+.It Dv MADV_RANDOM
+Is a hint that pages will be accessed randomly, and prefetching
+is likely not advantageous.
+.It Dv MADV_SEQUENTIAL
+Causes the VM system to depress the priority of
+pages immediately preceeding a given page when it is faulted in.
+.It Dv MADV_WILLNEED
+Causes pages that are in a given virtual address range
+to temporarily have higher priority, and if they are in
+memory, decrease the likelihood of them being freed. Additionally,
+the pages that are already in memory will be immediately mapped into
+the process, thereby eliminating unnecessary overhead of going through
+the entire process of faulting the pages in. This WILL NOT fault
+pages in from backing store, but quickly map the pages already in memory
+into the calling process.
+.It Dv MADV_DONTNEED
+Allows the VM system to decrease the in-memory priority
+of pages in the specified range. Additionally future references to
+this address range will incur a page fault.
+.Dv MADV_FREE
+gives the VM system the freedom to free pages,
+and tells the system that information in the specified page range
+is no longer important. This is an efficient way of allowing
+.Xr malloc 3
+to free pages anywhere in the address space, while keeping the address space
+valid. The next time that the page is referenced, the page might be demand
+zeroed, or might contain the data that was there before the
+.Dv MADV_FREE
+call.
+References made to that address space range will not make the VM system
+page the information back in from backing store until the page is
+modified again.
+.El
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn madvise
+returns 0. Otherwise a value of -1 is returned and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The
+.Fn madvise
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The virtual address range specified by the
+.Fa addr
+and
+.Fa len
+arguments is not valid.
+.El
.Sh SEE ALSO
-.Xr msync 2 ,
-.Xr munmap 2 ,
+.Xr mincore 2 ,
.Xr mprotect 2 ,
-.Xr mincore 2
+.Xr msync 2 ,
+.Xr munmap 2 .
.Sh HISTORY
The
-.Nm madvise
-function first appeared in 4.4BSD.
+.Fn madvise
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/mincore.2 b/lib/libc/sys/mincore.2
index 4e73c2a..9c694f4 100644
--- a/lib/libc/sys/mincore.2
+++ b/lib/libc/sys/mincore.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)mincore.2 8.1 (Berkeley) 6/9/93
+.\" $Id$
.\"
.Dd June 9, 1993
.Dt MINCORE 2
@@ -38,7 +39,10 @@
.Nm mincore
.Nd get advise about use of memory
.Sh SYNOPSIS
-.Fn mincore "caddr_t addr" "int len" "char *vec"
+.Fd #include <sys/types.h>
+.Fd #include <sys/mman.h>
+.Ft int
+.Fn mincore "caddr_t addr" "size_t len" "char *vec"
.Sh DESCRIPTION
The
.Fn mincore
@@ -50,12 +54,35 @@ in the character array
.Fa vec ,
with a value of 1 meaning
that the page is in-core.
+.Sh RETURN VALUES
+Upson successful completion,
+.Fn mincore
+returns 0 and
+.Fa vec
+is updated to relect the page status. Otherwise a value of -1
+is returned and
+.Va error
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The virtial address range specified by the
+.Fa addr
+and
+.Fa len
+arguments is not valid.
+.It Bq Er EFAULT
+The
+.Fa vec
+argument points to an illegal address.
+.El
.Sh SEE ALSO
-.Xr msync 2 ,
-.Xr munmap 2 ,
-.Xr mprotect 2 ,
.Xr madvise 2 ,
+.Xr mprotect 2 ,
+.Xr msync 2 ,
+.Xr munmap 2
.Sh HISTORY
The
.Fn mincore
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/minherit.2 b/lib/libc/sys/minherit.2
new file mode 100644
index 0000000..a8ebed3
--- /dev/null
+++ b/lib/libc/sys/minherit.2
@@ -0,0 +1,94 @@
+.\" $Id$
+.\"
+.\" 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.
+.\" 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.
+.\"
+.\" @(#)minherit.2 8.1 (Berkeley) 6/9/93
+.\"
+.Dd Feb 17, 1996
+.Dt MINHERIT 2
+.Os
+.Sh NAME
+.Nm minherit
+.Nd control the inheritance of pages
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/mman.h>
+.Ft int
+.Fn minherit "caddr_t addr" "size_t len" "int inherit"
+.Sh DESCRIPTION
+The
+.Fn minherit
+system call
+changes the specified pages to have the inheritance characteristic
+.Fa inherit .
+Not all implementations will guarantee that the inheritance characteristic
+can be set on a page basis;
+the granularity of changes may be as large as an entire region.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn minherit
+returns 0. Otherwise, a value of -1 is returned and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The
+.Fn minherit
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The virtual address range specified by the
+.Fa addr
+and
+.Fa len
+arguments is not valid.
+.It Bq Er EACESS
+The flags specified by the
+.Fa inherit
+argument were not valid for the pages specified
+by the
+.Fa addr
+and
+.Fa len
+arguments.
+.El
+.Sh SEE ALSO
+.Xr fork 2 ,
+.Xr madvise 2 ,
+.Xr mincore 2 ,
+.Xr mprotect 2 ,
+.Xr msync 2 ,
+.Xr munmap 2 ,
+.Xr rfork 2
+.Sh HISTORY
+The
+.Fn minherit
+function first appeared in OpenBSD.
diff --git a/lib/libc/sys/mkdir.2 b/lib/libc/sys/mkdir.2
index 4bf11be..1dc6ef5 100644
--- a/lib/libc/sys/mkdir.2
+++ b/lib/libc/sys/mkdir.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)mkdir.2 8.2 (Berkeley) 12/11/93
+.\" $Id$
.\"
.Dd December 11, 1993
.Dt MKDIR 2
@@ -46,7 +47,7 @@ The directory
.Fa path
is created with the access permissions specified by
.Fa mode
-and restricted by the the
+and restricted by the
.Xr umask 2
of the calling process.
.Pp
@@ -63,8 +64,6 @@ will fail and no directory will be created if:
.Bl -tag -width ENAMETOOLO
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -108,6 +107,7 @@ points outside the process's allocated address space.
.Xr stat 2 ,
.Xr umask 2
.Sh STANDARDS
-.Fn Mkdir
-conforms to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+The
+.Fn mkdir
+function call is expected to conform to
+.St -p1003.1-90 .
diff --git a/lib/libc/sys/mkfifo.2 b/lib/libc/sys/mkfifo.2
index 6f7686e..b39bf9c 100644
--- a/lib/libc/sys/mkfifo.2
+++ b/lib/libc/sys/mkfifo.2
@@ -67,8 +67,6 @@ will fail and no fifo will be created if:
The kernel has not been configured to support fifo's.
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -115,10 +113,11 @@ points outside the process's allocated address space.
.El
.Sh SEE ALSO
.Xr chmod 2 ,
+.Xr mknod 2,
.Xr stat 2 ,
.Xr umask 2
.Sh STANDARDS
The
-.Nm mkfifo
-function call conforms to
-.St -p1003.1-88 .
+.Fn mkfifo
+function call is expected to conform to
+.St -p1003.1-90 .
diff --git a/lib/libc/sys/mknod.2 b/lib/libc/sys/mknod.2
index d77ccbc..2fa6342 100644
--- a/lib/libc/sys/mknod.2
+++ b/lib/libc/sys/mknod.2
@@ -42,25 +42,19 @@
.Ft int
.Fn mknod "const char *path" "mode_t mode" "dev_t dev"
.Sh DESCRIPTION
-The device special file
+The filesystem node
.Fa path
-is created with the major and minor
-device numbers extracted from
-.Fa mode.
-The access permissions of
-.Fa path
-are descendant from the
-.Xr umask 2
-of the parent process.
+is created with the file type and access permissions specified in
+.Fa mode .
+The access permissions are modified by the process's umask value.
.Pp
If
.Fa mode
indicates a block or character special file,
.Fa dev
-is a configuration dependent specification of a character or block
-I/O device and the superblock of the device. If
-.Fa mode
-does not indicate a block special or character special device,
+is a configuration dependent specification denoting a particular device
+on the system.
+Otherwise,
.Fa dev
is ignored.
.Pp
@@ -77,8 +71,6 @@ will fail and the file will be not created if:
.Bl -tag -width Er
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -119,9 +111,11 @@ points outside the process's allocated address space.
.El
.Sh SEE ALSO
.Xr chmod 2 ,
+.Xr mkfifo 2 ,
.Xr stat 2 ,
.Xr umask 2
.Sh HISTORY
A
-.Nm
-function call appeared in Version 6 AT&T UNIX.
+.Fn mknod
+function call appeared in
+.At v6 .
diff --git a/lib/libc/sys/mlock.2 b/lib/libc/sys/mlock.2
index 90bb7c7..15ce741 100644
--- a/lib/libc/sys/mlock.2
+++ b/lib/libc/sys/mlock.2
@@ -47,7 +47,7 @@
.Fn munlock "caddr_t addr" "size_t len"
.Sh DESCRIPTION
The
-.Nm mlock
+.Fn mlock
system call
locks into memory the physical pages associated with the virtual address
range starting at
@@ -56,9 +56,9 @@ for
.Fa len
bytes.
The
-.Nm munlock
+.Fn munlock
call unlocks pages previously locked by one or more
-.Nm mlock
+.Fn mlock
calls.
For both, the
.Fa addr
@@ -70,7 +70,7 @@ to be so.
The entire range must be allocated.
.Pp
After an
-.Nm mlock
+.Fn mlock
call, the indicated pages will cause neither a non-resident page
nor address-translation fault until they are unlocked.
They may still cause protection-violation faults or TLB-miss faults on
@@ -81,12 +81,12 @@ Multiple processes may have the same physical pages locked via their own
virtual address mappings.
A single process may likewise have pages multiply-locked via different virtual
mappings of the same pages or via nested
-.Nm mlock
+.Fn mlock
calls on the same address range.
Unlocking is performed explicitly by
-.Nm munlock
+.Fn munlock
or implicitly by a call to
-.Nm munmap
+.Fn munmap
which deallocates the unmapped address range.
Locked mappings are not inherited by the child process after a
.Xr fork 2 .
@@ -94,7 +94,7 @@ Locked mappings are not inherited by the child process after a
Since physical memory is a potentially scarce resource, processes are
limited in how much they can lock down.
A single process can
-.Nm mlock
+.Fn mlock
the minimum of
a system-wide ``wired pages'' limit and
the per-process
@@ -138,11 +138,11 @@ Some portion of the indicated address range is not locked.
.Xr getpagesize 3
.Sh BUGS
Unlike The Sun implementation, multiple
-.Nm mlock
+.Fn mlock
calls on the same address range require the corresponding number of
-.Nm munlock
+.Fn munlock
calls to actually unlock the pages, i.e.
-.Nm mlock
+.Fn mlock
nests.
This should be considered a consequence of the implementation
and not a feature.
@@ -158,4 +158,5 @@ The
.Fn mlock
and
.Fn munlock
-functions first appeared in 4.4BSD.
+functions first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/mmap.2 b/lib/libc/sys/mmap.2
index 7313134..17a3603 100644
--- a/lib/libc/sys/mmap.2
+++ b/lib/libc/sys/mmap.2
@@ -31,7 +31,7 @@
.\"
.\" @(#)mmap.2 8.4 (Berkeley) 5/11/95
.\"
-.Dd "May 11, 1995"
+.Dd May 11, 1995
.Dt MMAP 2
.Os BSD 4
.Sh NAME
@@ -44,7 +44,7 @@
.Fn mmap "caddr_t addr" "size_t len" "int prot" "int flags" "int fd" "off_t offset"
.Sh DESCRIPTION
The
-.Nm mmap
+.Fn mmap
function causes the pages starting at
.Fa addr
and continuing for at most
@@ -113,7 +113,7 @@ parameter is ignored.
Do not permit the system to select a different address than the one
specified.
If the specified address cannot be used,
-.Nm mmap
+.Fn mmap
will fail.
If MAP_FIXED is specified,
.Fa addr
@@ -124,7 +124,7 @@ Notify the kernel that the region may contain semaphores and that special
handling may be necessary.
.It Dv MAP_INHERIT
Permit regions to be inherited across
-.Xr exec 2
+.Xr execve 2
system calls.
.It Dv MAP_PRIVATE
Modifications are private.
@@ -147,9 +147,9 @@ the file descriptor argument specifies a file or device to which swapping
should be done.
.Sh RETURN VALUES
Upon successful completion,
-.Nm mmap
+.Fn mmap
returns a pointer to the mapped region.
-Otherwise, a value of -1 is returned and
+Otherwise, a value of MAP_FAILED is returned and
.Va errno
is set to indicate the error.
.Sh ERRORS
@@ -179,25 +179,27 @@ was not open for writing.
.Fa Fd
is not a valid open file descriptor.
.It Bq Er EINVAL
-.\"One of
-.\".Dv MAP_ANON
-.\"or
-.\".Dv MAP_FILE
-.\"was not specified as part of the
-.\".Fa flags
-.\"parameter.
.Dv MAP_FIXED
was specified and the
.Fa addr
-parameter was not page aligned or was outside of the
-valid address range for a process.
-.Dv MAP_ANON was specified and
+parameter was not page aligned, or part of the desired address space
+resides out of the valid address space for a user process.
+.It Bq Er EINVAL
+.Fa Len
+was negative.
+.It Bq Er EINVAL
+.Dv MAP_ANON
+was specified and the
+.Fa fd
+parameter was not -1.
+.It Bq Er EINVAL
+.Dv MAP_ANON
+has not been specified and
.Fa fd
-was not \-1.
-.Fa Fd
did not reference a regular or character special file.
-.Fa Len
-was less than zero.
+.It Bq Er EINVAL
+.Fa Offset
+was not page-aligned. (See BUGS below.)
.It Bq Er ENOMEM
.Dv MAP_FIXED
was specified and the
@@ -206,9 +208,34 @@ parameter wasn't available.
.Dv MAP_ANON
was specified and insufficient memory was available.
.Sh "SEE ALSO"
-.Xr getpagesize 2 ,
+.Xr madvise 2 ,
+.Xr mincore 2 ,
+.Xr mlock 2 ,
+.Xr mprotect 2 ,
.Xr msync 2 ,
+.Xr munlock 2 ,
.Xr munmap 2 ,
-.Xr mprotect 2 ,
-.Xr madvise 2 ,
-.Xr mincore 2
+.Xr getpagesize 3
+.Sh BUGS
+.Ar len
+is limited to 2GB. Mmapping slightly more than 2GB doesn't work, but
+it is possible to map a window of size (filesize % 2GB) for file sizes
+of slightly less than 2G, 4GB, 6GB and 8GB.
+.Pp
+The limit is imposed for a variety of reasons. Most of them have to do
+with
+.Tn FreeBSD
+not wanting to use 64 bit offsets in the VM system due to
+the extreme performance penalty. So
+.Tn FreeBSD
+uses 32bit page indexes and
+this gives
+.Tn FreeBSD
+a maximum of 8TB filesizes. It's actually bugs in
+the filesystem code that causes the limit to be further restricted to
+1TB (loss of precision when doing blockno calculations).
+.Pp
+Another reason for the 2GB limit is that filesystem metadata can
+reside at negative offsets.
+.Pp
+We currently can only deal with page aligned file offsets.
diff --git a/lib/libc/sys/mount.2 b/lib/libc/sys/mount.2
index 0d95386..e42b8ff 100644
--- a/lib/libc/sys/mount.2
+++ b/lib/libc/sys/mount.2
@@ -42,7 +42,7 @@
.Fd #include <sys/param.h>
.Fd #include <sys/mount.h>
.Ft int
-.Fn mount "int type" "const char *dir" "int flags" "caddr_t data"
+.Fn mount "const char *name" "const char *dir" "int flags" "void *data"
.Ft int
.Fn unmount "const char *dir" "int flags"
.Sh DESCRIPTION
@@ -83,10 +83,20 @@ Even the super-user may not write on it.
Do not allow files to be executed from the filesystem.
.It Dv MNT_NOSUID
Do not honor setuid or setgid bits on files when executing them.
+.It Dv MNT_NOATIME
+Disable update of file access times.
.It Dv MNT_NODEV
Do not interpret special files on the filesystem.
.It Dv MNT_SYNCHRONOUS
All I/O to the filesystem should be done synchronously.
+.It Dv MNT_ASYNC
+All I/O to the filesystem should be done asynchronously.
+.It Dv MNT_WANTRDWR
+Upgrade a mounted read-only filesystem to read-write if MNT_UPDATE
+is also specified.
+.It Dv MNT_FORCE
+Fore a read-write mount even if the filesystem appears to be unclean.
+Dangerous.
.El
.Pp
The flag
@@ -97,7 +107,12 @@ This allows the mount flags to be changed without requiring
that the filesystem be unmounted and remounted.
Some filesystems may not allow all flags to be changed.
For example,
-most filesystems will not allow a change from read-write to read-only.
+many filesystems will not allow a change from read-write to read-only.
+.Pp
+The flag
+.Dv MNT_RELOAD
+causes the vfs subsystem to update its data structures pertaining to
+the specified already mounted filesystem.
.Pp
The
.Fa type
@@ -133,8 +148,9 @@ The
.Fa flags
argument may specify
.Dv MNT_FORCE
-to specify that the filesystem should be forcibly unmounted even if files are
-still active.
+to specify that the filesystem should be forcibly unmounted or made read-only
+(if MNT_UPDATE and MNT_RDONLY are also specified)
+even if files are still active.
Active special devices continue to work,
but any further accesses to any other active files result in errors
even if the filesystem is later remounted.
@@ -146,14 +162,16 @@ and the variable
.Va errno
is set to indicate the error.
.Pp
-.Nm Umount
-returns the value 0 if the umount succeeded; otherwise -1 is returned
+The
+.Fn umount
+function returns the value 0 if the umount succeeded; otherwise -1 is returned
and the variable
.Va errno
is set to indicate the error.
.Sh ERRORS
-.Fn Mount
-will fail when one of the following occurs:
+The
+.Fn mount
+function will fail when one of the following occurs:
.Bl -tag -width [ENOTBLK]
.It Bq Er EPERM
The caller is not the super-user.
@@ -173,8 +191,6 @@ is not a directory,
or a path prefix of
.Ar special
is not a directory.
-.It Bq Er EINVAL
-A pathname contains a character with the high-order bit set.
.It Bq Er EBUSY
Another process currently holds a reference to
.Fa dir .
@@ -250,8 +266,9 @@ cylinder group information.
points outside the process's allocated address space.
.El
.Pp
-.Nm Umount
-may fail with one of the following errors:
+The
+.Fn umount
+function may fail with one of the following errors:
.Bl -tag -width [ENOTBLK]
.It Bq Er EPERM
The caller is not the super-user.
@@ -283,13 +300,15 @@ or
mount can also fail if the maximum number of filesystems are currently
mounted.
.Sh SEE ALSO
+.Xr mfs 8 ,
.Xr mount 8 ,
-.Xr umount 8 ,
-.Xr sysctl 8
+.Xr sysctl 8 ,
+.Xr umount 8
.Sh BUGS
Some of the error codes need translation to more obvious messages.
.Sh HISTORY
.Fn Mount
and
.Fn umount
-function calls appeared in Version 6 AT&T UNIX.
+function calls appeared in
+.At v6 .
diff --git a/lib/libc/sys/mprotect.2 b/lib/libc/sys/mprotect.2
index bb2b9ad..d4e28d7 100644
--- a/lib/libc/sys/mprotect.2
+++ b/lib/libc/sys/mprotect.2
@@ -38,7 +38,10 @@
.Nm mprotect
.Nd control the protection of pages
.Sh SYNOPSIS
-.Fn mprotect "caddr_t addr" "int len" "int prot"
+.Fd #include <sys/types.h>
+.Fd #include <sys/mman.h>
+.Ft int
+.Fn mprotect "caddr_t addr" "size_t len" "int prot"
.Sh DESCRIPTION
The
.Fn mprotect
@@ -47,12 +50,38 @@ changes the specified pages to have protection
.Fa prot .
Not all implementations will guarantee protection on a page basis;
the granularity of protection changes may be as large as an entire region.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn mprotect
+returns 0. Otherwise a value of -1 is returned
+and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The
+.Fn mprotect
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The virtual address range specified by the
+.Fa addr
+and
+.Fa len
+arguments is not valid.
+.It Bq Er EACCES
+The calling process was not allowed to change
+the protection to the value specified by
+the
+.Fa prot
+argument.
+.El
.Sh SEE ALSO
-.Xr msync 2 ,
-.Xr munmap 2 ,
.Xr madvise 2 ,
-.Xr mincore 2
+.Xr mincore 2 ,
+.Xr msync 2 ,
+.Xr munmap 2
.Sh HISTORY
The
.Fn mprotect
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/msync.2 b/lib/libc/sys/msync.2
index 2e648c4..425a507 100644
--- a/lib/libc/sys/msync.2
+++ b/lib/libc/sys/msync.2
@@ -38,7 +38,10 @@
.Nm msync
.Nd synchronize a mapped region
.Sh SYNOPSIS
-.Fn msync "caddr_t addr" "int len"
+.Fd #include <sys/types.h>
+.Fd #include <sys/mman.h>
+.Ft int
+.Fn msync "caddr_t addr" "size_t len" "int flags"
.Sh DESCRIPTION
The
.Fn msync
@@ -57,34 +60,38 @@ is non-zero, only the pages containing
and
.Fa len
succeeding locations will be examined.
-Any required synchronization of memory caches
-will also take place at this time.
-Filesystem operations on a file that is mapped for shared modifications
-are unpredictable except after an
-.Fn msync .
+The
+.Fa flags
+argument may be specified as follows:
+.Bd -literal
+MS_ASYNC Return immediately (not currently implemented)
+MS_INVALIDATE Invalidate all cached data
+.Ed
+.Sh RETURN VALUES
+If any errors occur, -1 is returned and errno is set to indicate the
+error. Otherwise, a 0 value is returned.
.Sh ERRORS
-The following errors may be reported:
+.Fn msync
+will fail if:
.Bl -tag -width Er
.It Bq Er EINVAL
-The
-.Fa addr
-parameter was not page aligned.
-.It Bq Er EINVAL
-The
.Fa addr
-parameter did not specify an address part of a mapped region.
+is not a multiple of the hardware page size.
.It Bq Er EINVAL
-The
.Fa len
-parameter was negative.
+is too large or negative.
+.It Bq Er EINVAL
+.Fa flags
+was both MS_ASYNC and MS_INVALIDATE. Only one of these flags is allowed.
.It Bq Er EIO
An I/O error occured while writing to the file system.
.Sh SEE ALSO
.Xr madvise 2 ,
-.Xr munmap 2 ,
+.Xr mincore 2 ,
.Xr mprotect 2 ,
-.Xr mincore 2
+.Xr munmap 2
.Sh HISTORY
The
.Fn msync
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/munmap.2 b/lib/libc/sys/munmap.2
index 97692af..ffa2371 100644
--- a/lib/libc/sys/munmap.2
+++ b/lib/libc/sys/munmap.2
@@ -38,6 +38,9 @@
.Nm munmap
.Nd remove a mapping
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/mman.h>
+.Ft int
.Fn munmap "caddr_t addr" "size_t len"
.Sh DESCRIPTION
The
@@ -48,7 +51,7 @@ and causes further references to addresses within the range
to generate invalid memory references.
.Sh RETURN VALUES
Upon successful completion,
-.Nm munmap
+.Fn munmap
returns zero.
Otherwise, a value of -1 is returned and
.Va errno
@@ -66,13 +69,14 @@ parameter was negative, or
some part of the region being unmapped is outside the
valid address range for a process.
.Sh "SEE ALSO"
-.Xr getpagesize 2 ,
+.Xr madvise 2 ,
+.Xr mincore 2 ,
+.Xr mprotect 2 ,
.Xr msync 2 ,
.Xr munmap 2 ,
-.Xr mprotect 2 ,
-.Xr madvise 2 ,
-.Xr mincore 2
+.Xr getpagesize 3
.Sh HISTORY
The
.Fn munmap
-function first appeared in 4.4BSD.
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/nanosleep.2 b/lib/libc/sys/nanosleep.2
new file mode 100644
index 0000000..598ce1b
--- /dev/null
+++ b/lib/libc/sys/nanosleep.2
@@ -0,0 +1,119 @@
+.\" $Id: nanosleep.2,v 1.1 1997/05/12 12:15:35 peter Exp $
+.\" $OpenBSD: nanosleep.2,v 1.1 1997/04/20 20:56:20 tholo Exp $
+.\" $NetBSD: nanosleep.2,v 1.1 1997/04/17 18:12:02 jtc Exp $
+.\"
+.\" 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.
+.\" 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.
+.\"
+.\" @(#)sleep.3 8.1 (Berkeley) 6/4/93
+.\"
+.Dd April 17, 1997
+.Dt NANOSLEEP 2
+.Os
+.Sh NAME
+.Nm nanosleep ,
+.Nm signanosleep
+.Sh SYNOPSIS
+.Fd #include <time.h>
+.Ft int
+.Fn nanosleep "const struct timespec *rqtp" "struct timespec *rmtp"
+.Pp
+.Fd #include <signal.h>
+.Fd #include <time.h>
+.Ft int
+.Fn signanosleep "const struct timespec *rqtp" "struct timespec *rmtp" "sigset_t *mask"
+.Sh DESCRIPTION
+.Fn Nanosleep
+causes the process to sleep for the specified time. An unmasked signal will
+cause it to terminate the sleep early, regardless of the
+.Dv SA_RESTART
+value on the interrupting signal.
+.Pp
+The
+.Fn signanosleep
+function temporarily (and atomically) sets the signal mask of the process
+for the duration of the system call so that specific signals can be
+nominated to cause an early termination of the sleep.
+.Sh RETURN VALUE
+If the
+.Fn nanosleep
+function returns because the requested time has elapsed, the value
+returned will be zero.
+.Pp
+If the
+.Fn nanosleep
+function returns due to the delivery of a signal, the value returned
+will be the -1, and the global variable
+.Va errno
+will be set to indicate the interruption.
+If
+.Fa rmtp
+is
+.Pf non- Dv NULL ,
+the timespec structure it references is updated to contain the
+unslept amount (the request time minus the time actually slept).
+.Sh ERRORS
+If any of the following conditions occur, the
+.Nm
+function shall return -1 and set
+.Va errno
+to the corresponding value.
+.Bl -tag -width Er
+.It Bq Er EFAULT
+Either
+.Fa rqtp
+or
+.Fa rmtp
+points to memory that is not a valid part of the process
+address space.
+.It Bq Er EINTR
+.Nm
+was interrupted by the delivery of a signal.
+.It Bq Er EINVAL
+.Fa rqtp
+specified a nanosecond value less than zero or greater than 1000 million.
+.It Bq Er ENOSYS
+.Nm
+is not supported by this implementation.
+.El
+.Sh SEE ALSO
+.Xr sigsuspend 2
+.Xr sleep 3
+.Sh STANDARDS
+The
+.Fn nanosleep
+function conforms to
+.St -p1003.1b-93 .
+.Pp
+The
+.Fn signanosleep
+function is an extenstion that first appeared in
+.Fx 3.0
diff --git a/lib/libc/sys/nfssvc.2 b/lib/libc/sys/nfssvc.2
index 0c8038f..b2f481e 100644
--- a/lib/libc/sys/nfssvc.2
+++ b/lib/libc/sys/nfssvc.2
@@ -38,8 +38,11 @@
.Nm nfssvc
.Nd NFS services
.Sh SYNOPSIS
-.Fd #include <unistd.h>
+.Fd #include <sys/param.h>
+.Fd #include <sys/mount.h>
+.Fd #include <nfs/rpcv2.h>
.Fd #include <nfs/nfs.h>
+.Fd #include <unistd.h>
.Ft int
.Fn nfssvc "int flags" "void *argstructp"
.Sh DESCRIPTION
@@ -86,10 +89,13 @@ struct nfsd_cargs {
uid_t ncd_authuid; /* Effective uid */
int ncd_authtype; /* Type of authenticator */
int ncd_authlen; /* Length of authenticator string */
- char *ncd_authstr; /* Authenticator string */
+ u_char *ncd_authstr; /* Authenticator string */
+ int ncd_verflen; /* and the verifier */
+ u_char *ncd_verfstr;
+ NFSKERBKEY_T ncd_key; /* Session key */
};
.Ed
-.sp
+.Pp
structure.
The initial call has only the
.Dv NFSSVC_MNTD
@@ -135,10 +141,15 @@ struct nfsd_srvargs {
u_long nsd_haddr; /* Ip address of client */
struct ucred nsd_cr; /* Cred. uid maps to */
int nsd_authlen; /* Length of auth string (ret) */
- char *nsd_authstr; /* Auth string (ret) */
+ u_char *nsd_authstr; /* Auth string (ret) */
+ int nsd_verflen; /* and the verfier */
+ u_char *nsd_verfstr;
+ struct timeval nsd_timestamp; /* timestamp from verifier */
+ u_long nsd_ttl; /* credential ttl (sec) */
+ NFSKERBKEY_T nsd_key; /* Session key */
};
.Ed
-.sp
+.Pp
to enter the kernel as an
.Xr nfsd 8
daemon.
@@ -186,12 +197,12 @@ with the flag
and a pointer to a
.Bd -literal
struct nfsd_args {
- int sock; /* Socket to serve */
- caddr_t name; /* Client address for connection based sockets */
- int namelen; /* Length of name */
+ int sock; /* Socket to serve */
+ caddr_t name; /* Client address for connection based sockets */
+ int namelen;/* Length of name */
};
.Ed
-.sp
+.Pp
to pass a server side
.Tn NFS
socket into the kernel for servicing by the
@@ -199,7 +210,7 @@ socket into the kernel for servicing by the
daemons.
.Sh RETURN VALUES
Normally
-.Nm nfssvc
+.Fn nfssvc
does not return unless the server
is terminated by a signal when a value of 0 is returned.
Otherwise, -1 is returned and the global variable
@@ -215,16 +226,17 @@ as explained above.
The caller is not the super-user.
.El
.Sh SEE ALSO
-.Xr nfsd 8 ,
.Xr mount_nfs 8 ,
+.Xr nfsd 8 ,
.Xr nfsiod 8
.Sh HISTORY
The
-.Nm nfssvc
-function first appeared in 4.4BSD.
+.Fn nfssvc
+function first appeared in
+.Bx 4.4 .
.Sh BUGS
The
-.Nm nfssvc
+.Fn nfssvc
system call is designed specifically for the
.Tn NFS
support daemons and as such is specific to their requirements.
@@ -234,5 +246,5 @@ support, since
is not really an error.
Several fields of the argument structures are assumed to be valid and
sometimes to be unchanged from a previous call, such that
-.Nm nfssvc
+.Fn nfssvc
must be used with extreme care.
diff --git a/lib/libc/sys/open.2 b/lib/libc/sys/open.2
index dea59fc..11d2906 100644
--- a/lib/libc/sys/open.2
+++ b/lib/libc/sys/open.2
@@ -136,7 +136,7 @@ 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
-.Xr execve
+.Xr execve 2
system calls; see
.Xr close 2
and
@@ -146,6 +146,33 @@ The system imposes a limit on the number of file descriptors
open simultaneously by one process.
.Xr Getdtablesize 2
returns the current system limit.
+.Pp
+.Sh IMPLEMENTATION NOTES
+In the non-threaded library
+.Fn open
+is implemented as the
+.Va open
+syscall.
+.Pp
+In the threaded library, the
+.Va open
+syscall is assembled to
+.Fn _thread_sys_open
+and
+.Fn open
+is implemented as a function which disables thread rescheduling
+and calls
+.Fn _thread_sys_open .
+Before returning,
+.Fn open
+enables thread rescheduling.
+.Sh RETURN VALUES
+If successful,
+.Fn open
+returns a non-negative integer, termed a file descriptor.
+It returns -1 on failure, and sets
+.Va errno
+to indicate the error.
.Sh ERRORS
The named file is opened unless:
.Bl -tag -width Er
@@ -188,7 +215,7 @@ special file, and the device associated with this special file
does not exist.
.It Bq Er EINTR
The
-.Nm
+.Fn open
operation was interrupted by a signal.
.It Bq Er EOPNOTSUPP
.Dv O_SHLOCK
@@ -249,9 +276,10 @@ An attempt was made to open a socket (not currently implemented).
.Xr getdtablesize 2 ,
.Xr lseek 2 ,
.Xr read 2 ,
-.Xr write 2 ,
-.Xr umask 2
+.Xr umask 2 ,
+.Xr write 2
.Sh HISTORY
An
-.Nm
-function call appeared in Version 6 AT&T UNIX.
+.Fn open
+function call appeared in
+.At v6 .
diff --git a/lib/libc/sys/pathconf.2 b/lib/libc/sys/pathconf.2
index 1b4fbc4..f8500e3 100644
--- a/lib/libc/sys/pathconf.2
+++ b/lib/libc/sys/pathconf.2
@@ -55,12 +55,12 @@ value of a configurable system limit or option variable associated
with a pathname or file descriptor.
.Pp
For
-.Nm pathconf ,
+.Fn pathconf ,
the
.Fa path
argument is the name of a file or directory.
For
-.Nm fpathconf ,
+.Fn fpathconf ,
the
.Fa fd
argument is an open file descriptor.
@@ -98,9 +98,9 @@ Returns the terminal character disabling value.
.El
.Sh RETURN VALUES
If the call to
-.Nm pathconf
+.Fn pathconf
or
-.Nm fpathconf
+.Fn fpathconf
is not successful, \-1 is returned and
.Va errno
is set appropriately.
@@ -111,9 +111,9 @@ is not modified.
Otherwise, the current variable value is returned.
.Sh ERRORS
If any of the following conditions occur, the
-.Nm pathconf
+.Fn pathconf
and
-.Nm fpathconf
+.Fn fpathconf
functions shall return -1 and set
.Va errno
to the corresponding value.
@@ -157,7 +157,8 @@ An I/O error occurred while reading from or writing to the file system.
.Xr sysctl 3
.Sh HISTORY
The
-.Nm pathconf
+.Fn pathconf
and
-.Nm fpathconf
-functions first appeared in 4.4BSD.
+.Fn fpathconf
+functions first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/pipe.2 b/lib/libc/sys/pipe.2
index 51b7364..d50c94f 100644
--- a/lib/libc/sys/pipe.2
+++ b/lib/libc/sys/pipe.2
@@ -48,12 +48,13 @@ function
creates a
.Em pipe ,
which is an object allowing
-unidirectional data flow,
+bidirectional data flow,
and allocates a pair of file descriptors.
-The first descriptor connects to the
+.Pp
+By convention, the first descriptor is normally used as the
.Em read end
of the pipe,
-and the second connects to the
+and the second is normally the
.Em write end ,
so that data written to
.Fa fildes[1]
@@ -69,7 +70,7 @@ the read end of the pipe.
The pipe itself persists until all its associated descriptors are
closed.
.Pp
-A pipe whose read or write end has been closed is considered
+A pipe that has had an end closed is considered
.Em widowed .
Writing on such a pipe causes the writing process to receive
a
@@ -79,9 +80,10 @@ Widowing a pipe is the only way to deliver end-of-file to a reader:
after the reader consumes any buffered data, reading a widowed pipe
returns a zero count.
.Pp
-Pipes are really a special case of the
-.Xr socketpair 2
-call and, in fact, are implemented as such in the system.
+The bidirectional nature of this implementation of pipes is not
+portable to older systems, so it is recommended to use the convention
+for using the endpoints in the traditional manner when using a
+pipe in one direction.
.Sh RETURN VALUES
On successful creation of the pipe, zero is returned. Otherwise,
a value of -1 is returned and the variable
@@ -105,11 +107,13 @@ space.
.El
.Sh SEE ALSO
.Xr sh 1 ,
-.Xr read 2 ,
-.Xr write 2 ,
.Xr fork 2 ,
-.Xr socketpair 2
+.Xr read 2 ,
+.Xr socketpair 2 ,
+.Xr write 2
.Sh HISTORY
A
-.Nm
-function call appeared in Version 6 AT&T UNIX.
+.Fn pipe
+function call appeared in Version 3 AT&T UNIX.
+.Pp
+Bidirectional pipes were first used on Unix System V release 4.
diff --git a/lib/libc/sys/profil.2 b/lib/libc/sys/profil.2
index 670e343..100b8f4 100644
--- a/lib/libc/sys/profil.2
+++ b/lib/libc/sys/profil.2
@@ -33,14 +33,16 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)profil.2 8.1 (Berkeley) 6/4/93
+.\" $Id: profil.2,v 1.6 1997/04/11 18:47:07 bde Exp $
.\"
-.Dd "June 4, 1993"
+.Dd June 4, 1993
.Dt PROFIL 2
.Os
.Sh NAME
.Nm profil
.Nd control process profiling
.Sh SYNOPSIS
+.Fd #include <unistd.h>
.Ft int
.Fn profil "char *samples" "int size" "int offset" "int scale"
.Sh DESCRIPTION
@@ -49,10 +51,12 @@ The
function enables or disables
program counter profiling of the current process.
If profiling is enabled,
-then at every clock tick,
+then at every profiling clock tick,
the kernel updates an appropriate count in the
.Fa samples
buffer.
+The frequency of the profiling clock is recorded
+in the header in the profiling output file.
.Pp
The buffer
.Fa samples
@@ -62,7 +66,7 @@ bytes and is divided into
a series of 16-bit bins.
Each bin counts the number of times the program counter
was in a particular address range in the process
-when a clock tick occurred while profiling was enabled.
+when a profiling clock tick occurred while profiling was enabled.
For a given program counter address,
the number of the corresponding bin is given
by the relation:
@@ -115,8 +119,11 @@ contains an invalid address.
.El
.Sh SEE ALSO
.Xr gprof 1
-.\" .Sh HISTORY
-.\" wish I knew... probably v7.
+.Sh HISTORY
+A
+.Fn profil
+function call appeared in
+.At v7 .
.Sh BUGS
This routine should be named
.Fn profile .
diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2
new file mode 100644
index 0000000..48468a5
--- /dev/null
+++ b/lib/libc/sys/ptrace.2
@@ -0,0 +1,293 @@
+.\" $Id: ptrace.2,v 1.9 1997/02/22 15:04:13 peter Exp $
+.\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $
+.\"
+.\" This file is in the public domain.
+.Dd January 20, 1996
+.Dt PTRACE 2
+.Os FreeBSD 2
+.Sh NAME
+.Nm ptrace
+.Nd process tracing and debugging
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ptrace.h>
+.Ft int
+.Fn ptrace "int request" "pid_t pid" "caddr_t addr" "int data"
+.Sh DESCRIPTION
+.Fn ptrace
+provides tracing and debugging facilities. It allows one process (the
+.Em tracing
+process) to control another (the
+.Em traced
+process). Most of the time, the traced process runs normally, but when
+it receives a signal
+.Po
+see
+.Xr sigaction 2
+.Pc ,
+it stops. The tracing process is expected to notice this via
+.Xr wait 2
+or the delivery of a
+.Dv SIGCHLD
+signal, examine the state of the stopped process, and cause it to
+terminate or continue as appropriate.
+.Fn ptrace
+is the mechanism by which all this happens.
+.Pp
+The
+.Fa request
+argument specifies what operation is being performed; the meaning of
+the rest of the arguments depends on the operation, but except for one
+special case noted below, all
+.Fn ptrace
+calls are made by the tracing process, and the
+.Fa pid
+argument specifies the process ID of the traced process.
+.Fa request
+can be:
+.Bl -tag -width 12n
+.It Dv PT_TRACE_ME
+This request is the only one used by the traced process; it declares
+that the process expects to be traced by its parent. All the other
+arguments are ignored. (If the parent process does not expect to trace
+the child, it will probably be rather confused by the results; once the
+traced process stops, it cannot be made to continue except via
+.Eo \&
+.Fn ptrace
+.Ec \&.)
+When a process has used this request and calls
+.Xr execve 2
+or any of the routines built on it
+.Po
+such as
+.Xr execv 3
+.Pc ,
+it will stop before executing the first instruction of the new image.
+Also, any setuid or setgid bits on the executable being executed will
+be ignored.
+.It Dv PT_READ_I , Dv PT_READ_D
+These requests read a single
+.Li int
+of data from the traced process' address space. Traditionally,
+.Fn ptrace
+has allowed for machines with distinct address spaces for instruction
+and data, which is why there are two requests: conceptually,
+.Dv PT_READ_I
+reads from the instruction space and
+.Dv PT_READ_D
+reads from the data space. In the current
+.Tn FreeBSD
+implementation, these
+two requests are completely identical. The
+.Fa addr
+argument specifies the address (in the traced process' virtual address
+space) at which the read is to be done. This address does not have to
+meet any alignment constraints. The value read is returned as the
+return value from
+.Eo \&
+.Fn ptrace
+.Ec .
+.It Dv PT_WRITE_I , Dv PT_WRITE_D
+These requests parallel
+.Dv PT_READ_I
+and
+.Dv PT_READ_D ,
+except that they write rather than read. The
+.Fa data
+argument supplies the value to be written.
+.It Dv PT_READ_U
+This request reads an
+.Li int
+from the traced process' user structure. The
+.Fa addr
+argument specifies the location of the int relative to the base of the
+user structure; it will usually be an integer value cast to
+.Li caddr_t
+either explicitly or via the presence of a prototype for
+.Eo \&
+.Fn ptrace
+.Ec .
+Unlike
+.Dv PT_READ_I
+and
+.Dv PT_READ_D ,
+.Fa addr
+must be aligned on an
+.Li int
+boundary. The value read is returned as the return value from
+.Eo \&
+.Fn ptrace
+.Ec .
+.It Dv PT_WRITE_U
+This request writes an
+.Li int
+into the traced process' user structure.
+.Fa addr
+specifies the offset, just as for
+.Dv PT_READ_U ,
+and
+.Fa data
+specifies the value to be written, just as for
+.Dv PT_WRITE_I
+and
+.Dv PT_WRITE_D .
+.It Dv PT_CONTINUE
+The traced process continues execution.
+.Fa addr
+is an address specifying the place where execution is to be resumed (a
+new value for the program counter), or
+.Li (caddr_t)1
+to indicate that execution is to pick up where it left off.
+.Fa data
+provides a signal number to be delivered to the traced process as it
+resumes execution, or 0 if no signal is to be sent.
+.It Dv PT_KILL
+The traced process terminates, as if
+.Dv PT_CONTINUE
+had been used with
+.Dv SIGKILL
+given as the signal to be delivered.
+.It Dv PT_ATTACH
+This request allows a process to gain control of an otherwise unrelated
+process and begin tracing it. It does not need any cooperation from
+the to-be-traced process. In this case,
+.Fa pid
+specifies the process ID of the to-be-traced process, and the other two
+arguments are ignored. This request requires that the target process
+must have the same real UID as the tracing process, and that it must
+not be executing a setuid or setgid executable. (If the tracing
+process is running as root, these restrictions do not apply.) The
+tracing process will see the newly-traced process stop and may then
+control it as if it had been traced all along.
+.It Dv PT_DETACH
+This request is like PT_CONTINUE, except that it does not allow
+specifying an alternate place to continue execution, and after it
+succeeds, the traced process is no longer traced and continues
+execution normally.
+.El
+.Pp
+Additionally, machine-specific requests can exist. On the i386, these
+are:
+.Bl -tag -width 12n
+.It Dv PT_GETREGS
+This request reads the traced process' machine registers into the
+.Dq Li "struct reg"
+(defined in
+.Aq Pa machine/reg.h )
+pointed to by
+.Fa addr .
+.It Dv PT_SETREGS
+This request is the converse of
+.Dv PT_GETREGS ;
+it loads the traced process' machine registers from the
+.Dq Li "struct reg"
+(defined in
+.Aq Pa machine/reg.h )
+pointed to by
+.Fa addr .
+.It Dv PT_GETFPREGS
+This request reads the traced process' floating-point registers into
+the
+.Dq Li "struct fpreg"
+(defined in
+.Aq Pa machine/reg.h )
+pointed to by
+.Fa addr .
+.It Dv PT_SETFPREGS
+This request is the converse of
+.Dv PT_GETFPREGS ;
+it loads the traced process' floating-point registers from the
+.Dq Li "struct fpreg"
+(defined in
+.Aq Pa machine/reg.h )
+pointed to by
+.Fa addr .
+.El
+.Sh RETURN VALUES
+Some requests can cause
+.Fn ptrace
+to return
+.Li -1
+as a non-error value; to disambiguate,
+.Va errno
+can be set to 0 before the call and checked afterwards.
+.Sh ERRORS
+The
+.Fn ptrace
+function may fail if:
+.Bl -tag -width 4n
+.It Bq Er ESRCH
+.Bl -bullet -compact
+.It
+No process having the specified process ID exists.
+.El
+.It Bq Er EINVAL
+.Bl -bullet -compact
+.It
+A process attempted to use
+.Dv PT_ATTACH
+on itself.
+.It
+The
+.Fa request
+was not one of the legal requests.
+.It
+The
+.Fa addr
+to
+.Dv PT_READ_U
+or
+.Dv PT_WRITE_U
+was not
+.Li int Ns \&-aligned.
+.It
+The signal number (in
+.Fa data )
+to
+.Dv PT_CONTINUE
+was neither 0 nor a legal signal number.
+.It
+.Dv PT_GETREGS ,
+.Dv PT_SETREGS ,
+.Dv PT_GETFPREGS ,
+or
+.Dv PT_SETFPREGS
+was attempted on a process with no valid register set. (This is
+normally true only of system processes.)
+.El
+.It Bq Er EBUSY
+.Bl -bullet -compact
+.It
+.Dv PT_ATTACH
+was attempted on a process that was already being traced.
+.It
+A request attempted to manipulate a process that was being traced by
+some process other than the one making the request.
+.It
+A request (other than
+.Dv PT_ATTACH )
+specified a process that wasn't stopped.
+.El
+.It Bq Er EPERM
+.Bl -bullet -compact
+.It
+A request (other than
+.Dv PT_ATTACH )
+attempted to manipulate a process that wasn't being traced at all.
+.It
+An attempt was made to use
+.Dv PT_ATTACH
+on a process in violation of the requirements listed under
+.Dv PT_ATTACH
+above.
+.El
+.Sh SEE ALSO
+.Xr execve 2 ,
+.Xr sigaction 2 ,
+.Xr wait 2 ,
+.Xr execv 3
+.Sh HISTORY
+A
+.Fn ptrace
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/quotactl.2 b/lib/libc/sys/quotactl.2
index 1bcdb8b..fc7b667 100644
--- a/lib/libc/sys/quotactl.2
+++ b/lib/libc/sys/quotactl.2
@@ -41,7 +41,8 @@
.Nm quotactl
.Nd manipulate filesystem quotas
.Sh SYNOPSIS
-.Fd #include <ufs/quota.h> /* for ufs quotas */
+.Fd #include <sys/types.h>
+.Fd #include <ufs/ufs/quota.h>
.Ft int
.Fn quotactl "const char *path" "int cmd" "int id" "char *addr"
.Sh DESCRIPTION
@@ -156,8 +157,6 @@ The quota table cannot be expanded.
.It Bq Er EINVAL
.Fa Cmd
or the command type is invalid.
-.It Bq Er EINVAL
-A pathname contains a character with the high-order bit set.
.It Bq Er EACCES
In
.Dv Q_QUOTAON ,
@@ -208,6 +207,6 @@ and
.Xr getrlimit 2 .
.Sh HISTORY
The
-.Nm quotactl
+.Fn quotactl
function call appeared in
.Bx 4.3 Reno .
diff --git a/lib/libc/sys/read.2 b/lib/libc/sys/read.2
index b94341a..723c1bd 100644
--- a/lib/libc/sys/read.2
+++ b/lib/libc/sys/read.2
@@ -70,8 +70,8 @@ structure is defined as:
.Pp
.Bd -literal -offset indent -compact
struct iovec {
- void *iov_base;
- size_t iov_len;
+ char *iov_base; /* Base address. */
+ size_t iov_len; /* Length. */
};
.Ed
.Pp
@@ -107,6 +107,53 @@ The system guarantees to read the number of bytes requested if
the descriptor references a normal file that has that many bytes left
before the end-of-file, but in no other case.
.Pp
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn read
+is implemented as the
+.Va read
+syscall.
+.Pp
+In the threaded library, the
+.Va read
+syscall is assembled to
+.Fn _thread_sys_read
+and
+.Fn read
+is implemented as a function which locks
+.Va d
+for read, then calls
+.Fn _thread_sys_read .
+If the call to
+.Fn _thread_sys_read
+would block, a context switch is performed. Before returning,
+.Fn read
+unlocks
+.Va d .
+.Pp
+In the non-threaded library
+.Fn readv
+is implemented as the
+.Va readv
+syscall.
+.Pp
+In the threaded library, the
+.Va readv
+syscall is assembled to
+.Fn _thread_sys_readv
+and
+.Fn readv
+is implemented as a function which locks
+.Va d
+for read, then calls
+.Fn _thread_sys_readv .
+If the call to
+.Fn _thread_sys_readv
+would block, a context switch is performed. Before returning,
+.Fn readv
+unlocks
+.Va d .
.Sh RETURN VALUES
If successful, the
number of bytes actually read is returned. Upon reading end-of-file,
@@ -173,9 +220,10 @@ points outside the process's allocated address space.
.Xr socket 2 ,
.Xr socketpair 2
.Sh STANDARDS
-.Fn Read
-is expected to conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+The
+.Fn read
+function call is expected to conform to
+.St -p1003.1-90 .
.Sh HISTORY
The
.Fn readv
@@ -183,7 +231,6 @@ function call
appeared in
.Bx 4.2 .
A
-.Nm read
-function call
-appeared in
-Version 6 AT&T UNIX.
+.Fn read
+function call appeared in
+.At v6 .
diff --git a/lib/libc/sys/readlink.2 b/lib/libc/sys/readlink.2
index 4827110..8443de2 100644
--- a/lib/libc/sys/readlink.2
+++ b/lib/libc/sys/readlink.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)readlink.2 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt READLINK 2
@@ -49,8 +50,9 @@ in the buffer
.Fa buf ,
which has size
.Fa bufsiz .
-.Nm Readlink
-does not append a
+The
+.Fn readlink
+function does not append a
.Dv NUL
character to
.Fa buf .
@@ -65,8 +67,6 @@ will fail if:
.Bl -tag -width ENAMETOOLONG
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -85,12 +85,12 @@ An I/O error occurred while reading from the file system.
extends outside the process's allocated address space.
.El
.Sh SEE ALSO
-.Xr stat 2 ,
.Xr lstat 2 ,
-.Xr symlink 2
-.Xr symlink 7 ,
+.Xr stat 2 ,
+.Xr symlink 2 ,
+.Xr symlink 7
.Sh HISTORY
The
-.Nm
+.Fn readlink
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/reboot.2 b/lib/libc/sys/reboot.2
index 317c139..1eda9b3 100644
--- a/lib/libc/sys/reboot.2
+++ b/lib/libc/sys/reboot.2
@@ -62,7 +62,7 @@ The default, causing the system to reboot in its usual fashion.
Interpreted by the bootstrap program itself, causing it to
prompt on the console as to what file should be booted.
Normally, the system is booted from the file
-.Dq Em xx Ns No (0,0)vmunix ,
+.Dq Em xx Ns No (0,0)kernel ,
where
.Em xx
is the default disk name,
@@ -81,6 +81,9 @@ for more information.
.It Dv RB_HALT
the processor is simply halted; no reboot takes place.
This option should be used with caution.
+.It Dv RB_POWEROFF
+After halting, the shutdown code will do what it can to turn
+of the power. This requires hardware support.
.It Dv RB_INITNAME
An option allowing the specification of an init program (see
.Xr init 8 )
@@ -123,7 +126,7 @@ program in the newly booted system.
When no options are given (i.e.,
.Dv RB_AUTOBOOT
is used), the system is
-rebooted from file ``vmunix'' in the root file system of unit 0
+rebooted from file ``kernel'' in the root file system of unit 0
of a disk chosen in a processor specific way.
An automatic consistency check of the disks is normally performed
(see
@@ -140,7 +143,6 @@ variable
The caller is not the super-user.
.El
.Sh SEE ALSO
-.Xr kadb 4 ,
.Xr crash 8 ,
.Xr halt 8 ,
.Xr init 8 ,
@@ -153,6 +155,6 @@ nor
.Dv RB_KDB .
.Sh HISTORY
The
-.Nm
+.Fn reboot
function call appeared in
.Bx 4.0 .
diff --git a/lib/libc/sys/recv.2 b/lib/libc/sys/recv.2
index 9ed24a3..fdf02e3 100644
--- a/lib/libc/sys/recv.2
+++ b/lib/libc/sys/recv.2
@@ -200,6 +200,34 @@ and
set to
.Dv SCM_RIGHTS .
.Pp
+Process credentials can also be passed as ancillary data for
+.Dv AF_UNIX
+domain sockets using a
+.Fa cmsg_type
+of
+.Dv SCM_CREDS.
+In this case,
+.Fa cmsg_data
+should be a structure of type
+.Fa cmsgcred ,
+which is defined in
+.Ao Pa sys/socket.h Ac
+as follows:
+.Pp
+.Bd -literal
+struct cmsgcred {
+ pid_t cmcred_pid; /* PID of sending process */
+ uid_t cmcred_uid; /* real UID of sending process */
+ uid_t cmcred_euid; /* effective UID of sending process */
+ gid_t cmcred_gid; /* real GID of sending process */
+ short cmcred_ngroups; /* number or groups */
+ gid_t cmcred_groups[CMGROUP_MAX]; /* groups */
+};
+.Ed
+.Pp
+The kernel will fill in the credential information of the sending process
+and deliver it to the receiver.
+.Pp
The
.Fa msg_flags
field is set on return according to the message received.
@@ -252,12 +280,12 @@ address space.
.El
.Sh SEE ALSO
.Xr fcntl 2 ,
+.Xr getsockopt 2 ,
.Xr read 2 ,
.Xr select 2 ,
-.Xr getsockopt 2 ,
.Xr socket 2
.Sh HISTORY
The
-.Nm
+.Fn recv
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/rename.2 b/lib/libc/sys/rename.2
index be47d58..d9e1b83 100644
--- a/lib/libc/sys/rename.2
+++ b/lib/libc/sys/rename.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)rename.2 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt RENAME 2
@@ -105,8 +106,6 @@ indicates the reason for the failure.
will fail and neither of the argument files will be
affected if:
.Bl -tag -width ENAMETOOLONG
-.It Bq Er EINVAL
-Either pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of either pathname exceeded 255 characters,
or the entire length of either path name exceeded 1023 characters.
@@ -191,9 +190,10 @@ or
is a directory and is not empty.
.El
.Sh SEE ALSO
-.Xr open 2
+.Xr open 2 ,
.Xr symlink 7
.Sh STANDARDS
-.Fn Rename
-conforms to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+The
+.Fn rename
+function call is expected to conform to
+.St -p1003.1-90 .
diff --git a/lib/libc/sys/revoke.2 b/lib/libc/sys/revoke.2
index e782874..b64c9dc 100644
--- a/lib/libc/sys/revoke.2
+++ b/lib/libc/sys/revoke.2
@@ -41,11 +41,12 @@
.Nm revoke
.Nd revoke file access
.Sh SYNOPSIS
+.Fd #include <unistd.h>
.Ft int
-.Fn revoke "char *path"
+.Fn revoke "const char *path"
.Sh DESCRIPTION
The
-.Nm revoke
+.Fn revoke
function invalidates all current open file descriptors in the system
for the file named by
.Fa path .
@@ -63,7 +64,7 @@ is called as if all open references to the file had been closed.
.Pp
Access to a file may be revoked only by its owner or the super user.
The
-.Nm revoke
+.Fn revoke
function is currently supported only for block and character special
device files.
It is normally used to prepare a terminal device for a new login session,
@@ -100,6 +101,6 @@ The caller is neither the owner of the file nor the super user.
.Xr close 2
.Sh HISTORY
The
-.Nm revoke
+.Fn revoke
function was introduced in
.Bx 4.3 Reno .
diff --git a/lib/libc/sys/rfork.2 b/lib/libc/sys/rfork.2
new file mode 100644
index 0000000..4a54149
--- /dev/null
+++ b/lib/libc/sys/rfork.2
@@ -0,0 +1,137 @@
+.\"
+.\" This manual page is taken directly from Plan9, and modified to
+.\" describe the actual BSD implementation. Permission for
+.\" use of this page comes from Rob Pike <rob@plan9.att.com>.
+.\"
+.Dd Jan 12, 1996
+.Dt RFORK 2
+.Os
+.Sh NAME
+.Nm rfork
+.Nd manipulate process resources
+.Sh SYNOPSIS
+.Fd #include <unistd.h>
+.Ft int
+.Fn rfork "int flags"
+.Sh DESCRIPTION
+Forking, vforking or rforking are the only ways new processes are created.
+The
+.Fa flags
+argument to
+.Fn rfork
+selects which resources of the
+invoking process (parent) are shared
+by the new process (child) or initialized to
+their default values.
+The resources include
+the open file descriptor table (which, when shared, permits processes
+to open and close files for other processes),
+and open files.
+.Fa Flags
+is the logical OR of some subset of:
+.Bl -tag -width "RFCNAMEG" -compact -offset indent
+.It RFPROC
+If set a new process is created; otherwise changes affect the
+current process.
+The current implementation requires this flag to always be set.
+.It RFNOWAIT
+If set, the child process will be dissociated from the parent. Upon
+exit the child will not leave a status for the parent to collect.
+See
+.Xr wait 2 .
+.It RFFDG
+If set, the invoker's file descriptor table (see
+.Xr intro 2
+) is copied; otherwise the two processes share a
+single table.
+.It RFCFDG
+If set, the new process starts with a clean file descriptor table.
+Is mutually exclusive with
+.Dv RFFDG .
+.It RFMEM
+If set, the kernel will force sharing of the entire address space.
+The child
+will then inherit all the shared segments the parent process owns. Other segment
+types will be unaffected. Subsequent forks by the parent will then
+propagate the shared data and bss between children. The stack segment
+is always split. May be set only with
+.Dv RFPROC .
+.El
+.Pp
+File descriptors in a shared file descriptor table are kept
+open until either they are explicitly closed
+or all processes sharing the table exit.
+.Pp
+If
+.Dv RFPROC
+is set, the
+value returned in the parent process
+is the process id
+of the child process; the value returned in the child is zero.
+Without
+.Dv RFPROC ,
+the return value is zero.
+Process id's range from 1 to the maximum integer
+.Ft ( int )
+value.
+.Fn Rfork
+will sleep, if necessary, until required process resources are available.
+.Pp
+.Fn Fork
+can be implemented as a call to
+.Fn rfork "RFFDG|RFPROC"
+but isn't for backwards compatibility.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn rfork
+returns a value
+of 0 to the child process and 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.
+.Sh ERRORS
+.Fn Rfork
+will fail and no child process will be created if:
+.Bl -tag -width [EAGAIN]
+.It Bq Er EAGAIN
+The system-imposed limit on the total
+number of processes under execution would be exceeded.
+The limit is given by the
+.Xr sysctl 3
+MIB variable
+.Dv KERN_MAXPROC .
+(The limit is actually one less than this
+except for the super user).
+.It Bq Er EAGAIN
+The user is not the super user, and
+the system-imposed limit
+on the total number of
+processes under execution by a single user would be exceeded.
+The limit is given by the
+.Xr sysctl 3
+MIB variable
+.Dv KERN_MAXPROCPERUID .
+.It Bq Er EAGAIN
+The user is not the super user, and
+the soft resource limit corresponding to the resource parameter
+.Dv RLIMIT_NOFILE
+would be exceeded (see
+.Xr getrlimit 2 ) .
+.It Bq Er EINVAL
+The RFPROC flag was not specified.
+.It Bq Er EINVAL
+Both the RFFDG and the RFCFDG flags were specified.
+.It Bq Er ENOMEM
+There is insufficient swap space for the new process.
+.El
+.Sh SEE ALSO
+.Xr fork 2 ,
+.Xr intro 2 ,
+.Xr minherit 2 ,
+.Xr vfork 2
+.Sh HISTORY
+The
+.Fn rfork
+function call first appeared in Plan9.
diff --git a/lib/libc/sys/rmdir.2 b/lib/libc/sys/rmdir.2
index 29f8833..51235f6 100644
--- a/lib/libc/sys/rmdir.2
+++ b/lib/libc/sys/rmdir.2
@@ -60,8 +60,6 @@ The named file is removed unless:
.Bl -tag -width [ENAMETOOLONG]
.It Bq Er ENOTDIR
A component of the path is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -101,6 +99,6 @@ points outside the process's allocated address space.
.Xr unlink 2
.Sh HISTORY
The
-.Nm
+.Fn rmdir
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/rtprio.2 b/lib/libc/sys/rtprio.2
new file mode 100644
index 0000000..9e7c1c9
--- /dev/null
+++ b/lib/libc/sys/rtprio.2
@@ -0,0 +1,108 @@
+.\" Copyright (c) 1994, Henrik Vestergaard Draboel
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 Henrik Vestergaard Draboel.
+.\" 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 AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (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: rtprio.2,v 1.8 1997/02/22 15:04:17 peter Exp $
+.\"
+.Dd July 23, 1994
+.Dt RTPRIO 2
+.Sh NAME
+.Nm rtprio
+.Nd examine or modify a process realtime or idle priority
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/rtprio.h>
+.Ft int
+.Fn rtprio "int function" "pid_t pid" "struct rtprio *rtp"
+.Sh DESCRIPTION
+.Fn rtprio
+is used to lookup or change the realtime or idle priority of a process.
+
+.Fa function
+specifies the operation to be performed. RTP_LOOKUP to lookup the current priority,
+and RTP_SET to set the priority.
+.Fa pid
+specifies the process to be used, 0 for the current process.
+
+.Fa *rtp
+is a pointer to a struct rtprio which is used to specify the priority and priority type.
+This structure has the following form:
+.Bd -literal
+struct rtprio {
+ u_short type;
+ u_short prio;
+};
+.Ed
+.Pp
+The value of the
+.Nm type
+field may be RTP_PRIO_REALTIME for realtime priorities,
+RTP_PRIO_NORMAL for normal priorities, and RTP_PRIO_IDLE for idle priorities.
+The priority specified by the
+.Nm prio
+field ranges between 0 and
+.Dv RTP_PRIO_MAX (usually 31) .
+0 is the highest possible priority.
+
+Realtime and idle priority is inherited through fork() and exec().
+
+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.
+.Sh RETURN VALUES
+.Fn rtprio
+will return 0 for success and -1 for all errors. The global variable
+.Va errno
+will be set to indicate the error.
+.Sh ERRORS
+.Fn rtprio
+will fail if
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The specified
+.Fa prio
+was out of range.
+.It Bq Er EPERM
+The calling process 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.
+.It Bq Er ESRCH
+The specified process was not found.
+.Sh AUTHOR
+The original author was Henrik Vestergaard Draboel - hvd@terry.ping.dk. This
+implementation in
+.Tn FreeBSD
+was substantially rewritten by David Greenman.
+.Sh SEE ALSO
+.Xr nice 1 ,
+.Xr ps 1 ,
+.Xr rtprio 1 ,
+.Xr setpriority 2 ,
+.Xr nice 3 ,
+.Xr renice 8
diff --git a/lib/libc/sys/select.2 b/lib/libc/sys/select.2
index 3de5b5e..c9a332dc 100644
--- a/lib/libc/sys/select.2
+++ b/lib/libc/sys/select.2
@@ -104,7 +104,7 @@ If
is a non-nil pointer, it specifies a maximum interval to wait for the
selection to complete. If
.Fa timeout
-is a nil pointer, the select blocks indefinitely. To affect a poll, the
+is a nil pointer, the select blocks indefinitely. To effect a poll, the
.Fa timeout
argument should be non-nil, pointing to a zero-valued timeval structure.
.Pp
@@ -140,6 +140,9 @@ before any of the selected events occurred.
.It Bq Er EINVAL
The specified time limit is invalid. One of its components is
negative or too large.
+.It Bq Er EINVAL
+.Fa nfds
+was invalid.
.El
.Sh SEE ALSO
.Xr accept 2 ,
@@ -149,26 +152,31 @@ negative or too large.
.Xr read 2 ,
.Xr recv 2 ,
.Xr send 2 ,
-.Xr write 2
-.Sh BUGS
-Although the provision of
-.Xr getdtablesize 2
-was intended to allow user programs to be written independent
-of the kernel limit on the number of open files, the dimension
-of a sufficiently large bit field for select remains a problem.
-The default size
+.Xr write 2 ,
+.Xr clocks 7
+.Sh NOTES
+The default size of
.Dv FD_SETSIZE
-(currently 256) is somewhat larger than
-the current kernel limit to the number of open files.
-However, in order to accommodate programs which might potentially
-use a larger number of open files with select, it is possible
-to increase this size within a program by providing
-a larger definition of
+is currently 256.
+In order to accomodate programs which might potentially
+use a larger number of open files with
+.Fn select
+, it is possible
+to increase this size by having the program define
.Dv FD_SETSIZE
-before the inclusion of
+before the inclusion of any header which includes
.Aq Pa sys/types.h .
.Pp
-.Fn Select
+If
+.Fa nfds
+is greater than the number of open files,
+.Fn select
+is not guaranteed to examine the unused file descriptors. For historical
+reasons,
+.Fn select
+will always examine the first 256 descriptors.
+.Sh BUGS
+.Fn select
should probably return the time remaining from the original timeout,
if any, by modifying the time value in place.
This may be implemented in future versions of the system.
@@ -178,6 +186,6 @@ by the
call.
.Sh HISTORY
The
-.Nm
+.Fn select
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/semctl.2 b/lib/libc/sys/semctl.2
new file mode 100644
index 0000000..5855a7d
--- /dev/null
+++ b/lib/libc/sys/semctl.2
@@ -0,0 +1,173 @@
+.\"
+.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.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 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.
+.\"
+.\" $Id: semctl.2,v 1.6 1997/02/22 15:04:18 peter Exp $
+.\"
+.Dd September 12, 1995
+.Dt SEMCTL 2
+.Os FreeBSD
+.Sh NAME
+.Nm semctl
+.Nd control operations on a semaphore set
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Fd #include <sys/sem.h>
+.Ft int
+.Fn semctl "int semid" "int semnum" "int cmd" "union semun arg"
+.Sh DESCRIPTION
+.Fn Semctl
+performs the operation indicated by
+.Fa cmd
+on the semaphore set indicated by
+.Fa semid .
+For the commands that use the
+.Fa arg
+parameter,
+.Fa "union semun"
+is defined as follows:
+.Bd -literal
+.\"
+.\" From <sys/sem.h>:
+.\"
+union semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
+ u_short *array; /* array for GETALL & SETALL */
+};
+.Ed
+.Pp
+Commands are performed as follows:
+.\"
+.\" This section based on Stevens, _Advanced Programming in the UNIX
+.\" Environment_.
+.\"
+.Bl -tag -width IPC_RMIDXXX
+.It Dv IPC_STAT
+Fetch the semaphore set's
+.Fa "struct semid_ds" ,
+storing it in the memory pointed to by
+.Fa arg.buf .
+.It Dv IPC_SET
+Changes the
+.Fa sem_perm.uid ,
+.Fa sem_perm.gid ,
+and
+.Fa sem_perm.mode
+members of the semaphore set's
+.Fa "struct semid_ds"
+to match those of the struct pointed to by
+.Fa arg.buf .
+The calling process's effective uid must
+match either
+.Fa sem_perm.uid
+or
+.Fa sem_perm.cuid ,
+or it must have superuser privileges.
+.It IPC_RMID
+Immediately removes the semaphore set from the system. The calling
+process's effective uid must equal the semaphore set's
+.Fa sem_perm.uid
+or
+.Fa sem_perm.cuid ,
+or the process must have superuser privileges.
+.It Dv GETVAL
+Return the value of semaphore number
+.Fa semnum .
+.It Dv SETVAL
+Set the value of semaphore number
+.Fa semnum
+to
+.Fa arg.val .
+.It Dv GETPID
+Return the pid of the last process to perform an operation on
+semaphore number
+.Fa semnum .
+.It Dv GETNCNT
+Return the number of processes waiting for semaphore number
+.Fa semnum Ns 's
+value to become greater than its current value.
+.It Dv GETZCNT
+Return the number of processes waiting for semaphore number
+.Fa semnum Ns 's
+value to become 0.
+.It Dv GETALL
+Fetch the value of all of the semaphores in the set into the
+array pointed to by
+.Fa arg.array .
+.It Dv SETALL
+Set the values of all of the semaphores in the set to the values
+in the array pointed to by
+.Fa arg.array .
+.El
+.Pp
+The
+.Fa "struct semid_ds"
+is defined as follows:
+.Bd -literal
+.\"
+.\" Taken straight from <sys/sem.h>.
+.\"
+struct semid_ds {
+ struct ipc_perm sem_perm; /* operation permission struct */
+ struct sem *sem_base; /* pointer to first semaphore in set */
+ u_short sem_nsems; /* number of sems in set */
+ time_t sem_otime; /* last operation time */
+ long sem_pad1; /* SVABI/386 says I need this here */
+ time_t sem_ctime; /* last change time */
+ /* Times measured in secs since */
+ /* 00:00:00 GMT, Jan. 1, 1970 */
+ long sem_pad2; /* SVABI/386 says I need this here */
+ long sem_pad3[4]; /* SVABI/386 says I need this here */
+};
+.Ed
+.Sh RETURN VALUES
+On success, when
+.Fa cmd
+is one of GETVAL, GETNCNT, or GETZCNT,
+.Fn semctl
+returns the corresponding value; otherwise, 0 is returned.
+On failure, -1 is returned, and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Fn Semctl
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+No semaphore set corresponds to
+.Fa semid .
+.It Bq Er EINVAL
+.Fa semnum
+is not in the range of valid semaphores for given semaphore set.
+.It Bq Er EPERM
+The calling process's effective uid does not match the uid of
+the semaphore set's owner or creator.
+.It Bq Er EACCES
+Permission denied due to mismatch between operation and mode of
+semaphore set.
+.Sh SEE ALSO
+.Xr semget 2 ,
+.Xr semop 2
diff --git a/lib/libc/sys/semget.2 b/lib/libc/sys/semget.2
new file mode 100644
index 0000000..ed69cfc
--- /dev/null
+++ b/lib/libc/sys/semget.2
@@ -0,0 +1,137 @@
+.\"
+.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.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 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.
+.\"
+.\" $Id: semget.2,v 1.4 1997/02/22 15:04:19 peter Exp $
+.\"
+.Dd September 12, 1995
+.Dt SEMGET 2
+.Os FreeBSD
+.Sh NAME
+.Nm semget
+.Nd obtain a semaphore id
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Fd #include <sys/sem.h>
+.Ft int
+.Fn semget "key_t key" "int nsems" "int flag"
+.Sh DESCRIPTION
+Based on the values of
+.Fa key
+and
+.Fa flag ,
+.Fn semget
+returns the identifier of a newly created or previously existing
+set of semaphores.
+.\"
+.\" This is copied verbatim from the shmget manpage. Perhaps
+.\" it should go in a common manpage, such as .Xr ipc 2
+.\"
+The key
+is analogous to a filename: it provides a handle that names an
+IPC object. There are three ways to specify a key:
+.Bl -bullet
+.It
+IPC_PRIVATE may be specified, in which case a new IPC object
+will be created.
+.It
+An integer constant may be specified. If no IPC object corresponding
+to
+.Fa key
+is specified and the IPC_CREAT bit is set in
+.Fa flag ,
+a new one will be created.
+.It
+.Fn ftok
+may be used to generate a key from a pathname. See
+.Xr ftok 3 .
+.El
+.\"
+.\" Likewise for this section, except SHM_* becomes SEM_*.
+.\"
+.Pp
+The mode of a newly created IPC object is determined by
+.Em OR Ns 'ing
+the following constants into the
+.Fa flag
+parameter:
+.Bl -tag -width XSEM_WXX6XXX
+.It Dv SEM_R
+Read access for user.
+.It Dv SEM_A
+Alter access for user.
+.It Dv (SEM_R>>3)
+Read access for group.
+.It Dv (SEM_A>>3)
+Alter access for group.
+.It Dv (SEM_R>>6)
+Read access for other.
+.It Dv (SEM_A>>6)
+Alter access for other.
+.El
+.Pp
+If a new set of semaphores is being created,
+.Fa nsems
+is used to indicate the number of semaphores the set should contain.
+Otherwise,
+.Fa nsems
+may be specified as 0.
+.Sh RETURN VALUES
+.Fn Semget
+returns the id of a semaphore set if successful; otherwise, -1
+is returned and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Fn Semget
+will fail if:
+.Bl -tag -width Er
+.\" ipcperm could fail (we're opening to read and write, as it were)
+.It Bq Er EACCES
+Access permission failure.
+.\"
+.\" sysv_sem.c is quite explicit about these, so I'm pretty sure
+.\" this is accurate
+.\"
+.It Bq Er EEXIST
+IPC_CREAT and IPC_EXCL were specified, and a semaphore set
+corresponding to
+.Fa key
+already exists.
+.It Bq Er EINVAL
+The number of semaphores requested exceeds the system imposed maximum
+per set.
+.It Bq Er ENOSPC
+Insufficiently many semaphores are available.
+.It Bq Er ENOSPC
+The kernel could not allocate a
+.Fa "struct semid_ds" .
+.It Bq Er ENOENT
+No semaphore set was found corresponding to
+.Fa key ,
+and IPC_CREAT was not specified.
+.Sh SEE ALSO
+.Xr semctl 2 ,
+.Xr semop 2
diff --git a/lib/libc/sys/semop.2 b/lib/libc/sys/semop.2
new file mode 100644
index 0000000..06dfa3b
--- /dev/null
+++ b/lib/libc/sys/semop.2
@@ -0,0 +1,192 @@
+.\"
+.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.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 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.
+.\"
+.\" $Id: semop.2,v 1.5 1997/02/22 15:04:21 peter Exp $
+.\"
+.Dd September 22, 1995
+.Dt SEMOP 2
+.Os FreeBSD
+.Sh NAME
+.Nm semop
+.Nd atomic array of operations on a semaphore set
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Fd #include <sys/sem.h>
+.Ft int
+.Fn semop "int semid" "struct sembuf array[]" "unsigned nops"
+.Sh DESCRIPTION
+.Fn Semop
+atomically performs the array of operations indicated by
+.Fa array
+on the semaphore set indicated by
+.Fa semid .
+The length of
+.Fa array
+is indicated by
+.Fa nops .
+Each operation is encoded in a
+.Fa "struct sembuf" ,
+which is defined as follows:
+.Bd -literal
+.\"
+.\" From <sys/sem.h>
+.\"
+struct sembuf {
+ u_short sem_num; /* semaphore # */
+ short sem_op; /* semaphore operation */
+ short sem_flg; /* operation flags */
+};
+.Ed
+.Pp
+For each element in
+.Fa array ,
+.Fa sem_op
+and
+.Fa sem_flg
+determine an operation to be performed on semaphore number
+.Fa sem_num
+in the set. The values SEM_UNDO and IPC_NOWAIT may be
+.Em OR Ns 'ed
+into the
+.Fa sem_flg
+member in order to modify the behavior of the given operation.
+.Pp
+The operation performed depends as follows on the value of
+.Fa sem_op :
+.\"
+.\" This section is based on the description of semop() in
+.\" Stevens, _Advanced Programming in the UNIX Environment_.
+.\"
+.Bl -bullet
+.It
+When
+.Fa sem_op
+is positive, the semaphore's value is incremented by
+.Fa sem_op Ns 's
+value. If SEM_UNDO is specified, the semaphore's adjust on exit
+value is decremented by
+.Fa sem_op Ns 's
+value. A positive value for
+.Fa sem_op
+generally corresponds to a process releasing a resource
+associated with the semaphore.
+.It
+The behavior when
+.Fa sem_op
+is negative depends on the current value of the semaphore:
+.Bl -bullet
+.It
+If the current value of the semaphore is greater than or equal to
+the absolute value of
+.Fa sem_op ,
+then the value is decremented by the absolute value of
+.Fa sem_op .
+If SEM_UNDO is specified, the semaphore's adjust on exit
+value is incremented by the absolute value of
+.Fa sem_op .
+.It
+If the current value of the semaphore is less than
+.Fa sem_op Ns 's
+value, one of the following happens:
+.\" XXX a *second* sublist?
+.Bl -bullet
+.It
+If IPC_NOWAIT was specified, then
+.Fn semop
+returns immediately with a return value of EAGAIN.
+.It
+If some other process has removed the semaphore with the IPC_RMID
+option of
+.Fn semctl ,
+then
+.Fn semop
+returns immediately with a return value of EINVAL.
+.It
+Otherwise, the calling process is put to sleep until the semaphore's
+value is greater than or equal to the absolute value of
+.Fa sem_op .
+When this condition becomes true, the semaphore's value is decremented
+by the absolute value of
+.Fa sem_op ,
+and the semaphore's adjust on exit value is incremented by the
+absolute value of
+.Fa sem_op .
+.El
+.Pp
+A negative value for
+.Fa sem_op
+generally means that a process is waiting for a resource to become
+available.
+.El
+.Pp
+.It
+When
+.Fa sem_op
+is zero, the process waits for the semaphore's value to become zero.
+If it is already zero, the call to
+.Fn semop
+can return immediately. Otherwise, the calling process is put to
+sleep until the semaphore's value becomes zero.
+.El
+.Pp
+For each semaphore a process has in use, the kernel maintains an
+`adjust on exit' value, as alluded to earlier. When a process
+exits, either voluntarily or involuntarily, the adjust on exit value
+for each semaphore is added to the semaphore's value. This can
+be used to insure that a resource is released if a process terminates
+unexpectedly.
+.Sh RETURN VALUES
+On success,
+.Fn semop
+returns 0; otherwise, -1 is returned and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Fn Semop
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+No semaphore set corresponds to
+.Fa semid .
+.It Bq Er EACCES
+Permission denied due to mismatch between operation and mode of
+semaphore set.
+.It Bq Er EAGAIN
+The semaphore's value was less than
+.Fa sem_op ,
+and IPC_NOWAIT was specified.
+.It Bq Er E2BIG
+Too many operations were specified.
+.It Bq Er EFBIG
+.\"
+.\" I'd have thought this would be EINVAL, but the source says
+.\" EFBIG.
+.\"
+.Fa sem_num
+was not in the range of valid semaphores for the set.
+.Sh SEE ALSO
+.Xr semctl 2 ,
+.Xr semget 2
diff --git a/lib/libc/sys/send.2 b/lib/libc/sys/send.2
index 9dc285b..57fcfb3 100644
--- a/lib/libc/sys/send.2
+++ b/lib/libc/sys/send.2
@@ -29,9 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)send.2 8.2 (Berkeley) 2/21/94
+.\" From: @(#)send.2 8.2 (Berkeley) 2/21/94
+.\" $Id$
.\"
-.Dd February 21, 1994
+.Dd February 15, 1995
.Dt SEND 2
.Os BSD 4.2
.Sh NAME
@@ -94,8 +95,11 @@ The
.Fa flags
parameter may include one or more of the following:
.Bd -literal
-#define MSG_OOB 0x1 /* process out-of-band data */
-#define MSG_DONTROUTE 0x4 /* bypass routing, use direct interface */
+#define MSG_OOB 0x1 /* process out-of-band data */
+#define MSG_PEEK 0x2 /* peek at incoming message */
+#define MSG_DONTROUTE 0x4 /* bypass routing, use direct interface */
+#define MSG_EOR 0x8 /* data completes record */
+#define MSG_EOF 0x100 /* data completes transaction */
.Ed
.Pp
The flag
@@ -107,6 +111,20 @@ data on sockets that support this notion (e.g.
the underlying protocol must also support
.Dq out-of-band
data.
+.Dv MSG_EOR
+is used to indicate a record mark for protocols which support the
+concept.
+.Dv MSG_EOF
+requests that the sender side of a socket be shut down, and that an
+appropriate indication be sent at the end of the specified data;
+this flag is only implemented for
+.Dv SOCK_STREAM
+sockets in the
+.Dv PF_INET
+protocol family, and is used to implement Transaction
+.Tn TCP
+(see
+.Xr ttcp 4 ) .
.Dv MSG_DONTROUTE
is usually used only by diagnostic or routing programs.
.Pp
@@ -124,9 +142,13 @@ if an error occurred.
and
.Fn sendmsg
fail if:
-.Bl -tag -width [EMSGSIZE]
+.Bl -tag -width Er
.It Bq Er EBADF
An invalid descriptor was specified.
+.It Bq Er EACCES
+The destination address is a broadcast address, and
+.Dv SO_BROADCAST
+has not been set on the socket.
.It Bq Er ENOTSOCK
The argument
.Fa s
@@ -146,16 +168,18 @@ The operation may succeed when buffers become available.
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.
.El
.Sh SEE ALSO
.Xr fcntl 2 ,
+.Xr getsockopt 2 ,
.Xr recv 2 ,
.Xr select 2 ,
-.Xr getsockopt 2 ,
.Xr socket 2 ,
.Xr write 2
.Sh HISTORY
The
-.Nm
+.Fn send
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/setgroups.2 b/lib/libc/sys/setgroups.2
index e20b47e..bce9e1a 100644
--- a/lib/libc/sys/setgroups.2
+++ b/lib/libc/sys/setgroups.2
@@ -78,6 +78,6 @@ address space.
.Xr initgroups 3
.Sh HISTORY
The
-.Nm
+.Fn setgroups
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/setpgid.2 b/lib/libc/sys/setpgid.2
index 141c203..4490edf 100644
--- a/lib/libc/sys/setpgid.2
+++ b/lib/libc/sys/setpgid.2
@@ -77,9 +77,10 @@ of the calling process.
.Sh SEE ALSO
.Xr getpgrp 2
.Sh STANDARDS
-.Fn Setpgid
-conforms to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+The
+.Fn setpgid
+function call is expected to conform to
+.St -p1003.1-90 .
.Sh COMPATIBILITY
.Fn Setpgrp
is identical to
diff --git a/lib/libc/sys/setregid.2 b/lib/libc/sys/setregid.2
new file mode 100644
index 0000000..0b8343b
--- /dev/null
+++ b/lib/libc/sys/setregid.2
@@ -0,0 +1,92 @@
+.\" 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.
+.\" 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.
+.\"
+.\" @(#)setregid.2 8.2 (Berkeley) 4/16/94
+.\"
+.Dd April 16, 1994
+.Dt SETREGID 2
+.Os BSD 4.2
+.Sh NAME
+.Nm setregid
+.Nd set real and effective group ID
+.Sh SYNOPSIS
+.Fd #include <unistd.h>
+.Ft int
+.Fn setregid "gid_t rgid" "gid_t egid"
+.Sh DESCRIPTION
+The real and effective group ID's of the current process
+are set to the arguments.
+Unprivileged users may change the real group
+ID to the effective group ID and vice-versa; only the super-user may
+make other changes.
+.Pp
+Supplying a value of -1 for either the real or effective
+group ID forces the system to substitute the current
+ID in place of the -1 parameter.
+.Pp
+The
+.Fn setregid
+function was intended to allow swapping
+the real and effective group IDs
+in set-group-ID programs to temporarily relinquish the set-group-ID value.
+This function did not work correctly,
+and its purpose is now better served by the use of the
+.Fn setegid
+function (see
+.Xr setuid 2 ) .
+.Pp
+When setting the real and effective group IDs to the same value,
+the standard
+.Fn setgid
+function is preferred.
+.Sh RETURN VALUES
+Upon successful completion, a value of 0 is returned. Otherwise,
+a value of -1 is returned and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width [EPERM]
+.It Bq Er EPERM
+The current process is not the super-user and a change
+other than changing the effective group-id to the real group-id
+was specified.
+.El
+.Sh SEE ALSO
+.Xr getgid 2 ,
+.Xr issetugid 2 ,
+.Xr setegid 2 ,
+.Xr setgid 2 ,
+.Xr setuid 2
+.Sh HISTORY
+The
+.Fn setregid
+system call appeared in
+.Bx 4.2 .
diff --git a/lib/libc/sys/setreuid.2 b/lib/libc/sys/setreuid.2
new file mode 100644
index 0000000..1736879
--- /dev/null
+++ b/lib/libc/sys/setreuid.2
@@ -0,0 +1,90 @@
+.\" 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.
+.\" 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.
+.\"
+.\" @(#)setreuid.2 8.2 (Berkeley) 4/16/94
+.\"
+.Dd April 16, 1994
+.Dt SETREUID 2
+.Os BSD 4
+.Sh NAME
+.Nm setreuid
+.Nd set real and effective user ID's
+.Sh SYNOPSIS
+.Fd #include <unistd.h>
+.Ft int
+.Fn setreuid "uid_t ruid" "uid_t euid"
+.Sh DESCRIPTION
+The real and effective user IDs of the
+current process are set according to the arguments.
+If
+.Fa ruid
+or
+.Fa euid
+is -1, the current uid is filled in by the system.
+Unprivileged users may change the real user
+ID to the effective user ID and vice-versa; only the super-user may
+make other changes.
+.Pp
+The
+.Fn setreuid
+function has been used to swap the real and effective user IDs
+in set-user-ID programs to temporarily relinquish the set-user-ID value.
+This purpose is now better served by the use of the
+.Fn seteuid
+function (see
+.Xr setuid 2 ) .
+.Pp
+When setting the real and effective user IDs to the same value,
+the standard
+.Fn setuid
+function is preferred.
+.Sh RETURN VALUES
+Upon successful completion, a value of 0 is returned. Otherwise,
+a value of -1 is returned and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width [EPERM]
+.It Bq Er EPERM
+The current process is not the super-user and a change
+other than changing the effective user-id to the real user-id
+was specified.
+.El
+.Sh SEE ALSO
+.Xr getuid 2 ,
+.Xr issetugid 2 ,
+.Xr seteuid 2 ,
+.Xr setuid 2
+.Sh HISTORY
+The
+.Fn setreuid
+system call appeared in
+.Bx 4.2 .
diff --git a/lib/libc/sys/setsid.2 b/lib/libc/sys/setsid.2
index 48ac6a0..73d437d 100644
--- a/lib/libc/sys/setsid.2
+++ b/lib/libc/sys/setsid.2
@@ -31,36 +31,39 @@
.\"
.\" @(#)setsid.2 8.1 (Berkeley) 6/4/93
.\"
-.Dd "June 4, 1993"
+.Dd June 4, 1993
.Dt SETSID 2
.Os
.Sh NAME
.Nm setsid
.Nd create session and set process group ID
.Sh SYNOPSIS
-.Fd #include <sys/types.h>
+.Fd #include <unistd.h>
.Ft pid_t
.Fn setsid "void"
.Sh DESCRIPTION
The
-.Nm setsid
+.Fn setsid
function creates a new session.
The calling process is the session leader of the new session, is the
process group leader of a new process group and has no controlling
terminal.
The calling process is the only process in either the session or the
process group.
-.Pp
+.Sh RETURN VALUES
Upon successful completion, the
-.Nm setsid
+.Fn setsid
function returns the value of the process group ID of the new process
group, which is the same as the process ID of the calling process.
-.Sh ERRORS
If an error occurs,
-.Nm setsid
+.Fn setsid
returns -1 and the global variable
.Va errno
-is set to indicate the error, as follows:
+is set to indicate the error.
+.Sh ERRORS
+The
+.Fn setsid
+function will fail if:
.Bl -tag -width Er
.It Bq Er EPERM
The calling process is already a process group leader, or the process
@@ -68,12 +71,12 @@ group ID of a process other than the calling process matches the process
ID of the calling process.
.El
.Sh SEE ALSO
-.Xr setpgid 3 ,
+.Xr setpgid 2 ,
.Xr tcgetpgrp 3 ,
.Xr tcsetpgrp 3
.Sh STANDARDS
The
-.Nm setsid
+.Fn setsid
function is expected to be compliant with the
-.St -p1003.1-88
+.St -p1003.1-90
specification.
diff --git a/lib/libc/sys/setuid.2 b/lib/libc/sys/setuid.2
index 383a8f5..1f24fb0 100644
--- a/lib/libc/sys/setuid.2
+++ b/lib/libc/sys/setuid.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)setuid.2 8.1 (Berkeley) 6/4/93
+.\" $Id: setuid.2,v 1.10 1997/04/01 18:58:38 mpp Exp $
.\"
.Dd June 4, 1993
.Dt SETUID 2
@@ -58,9 +59,22 @@ function
sets the real and effective
user IDs and the saved set-user-ID of the current process
to the specified value.
+.\" Comment out next block for !_POSIX_SAVED_IDS
+.\" The real user ID and the saved set-user-ID are changed only if the
+.\" effective user ID is that of the super user.
+.\" I.e.
+.\" .Fn setuid
+.\" function is equal to
+.\" .Fn seteuid
+.\" function if the effective user ID is not that of the super user.
+.\" End of block
The
.Fn setuid
function is permitted if the specified ID is equal to the real user ID
+.\" Comment out next line for !_POSIX_SAVED_IDS
+.\" or the saved set-user-ID
+.\" Next line is for Appendix B.4.2.2 case.
+or the effective user ID
of the process, or if the effective user ID is that of the super user.
.Pp
The
@@ -69,9 +83,22 @@ function
sets the real and effective
group IDs and the saved set-group-ID of the current process
to the specified value.
+.\" Comment out next block for !_POSIX_SAVED_IDS
+.\" The real group ID and the saved set-group-ID are changed only if the
+.\" effective user ID is that of the super user.
+.\" I.e.
+.\" .Fn setgid
+.\" function is equal to
+.\" .Fn setegid
+.\" function if the effective user ID is not that of the super user.
+.\" End of block
The
.Fn setgid
function is permitted if the specified ID is equal to the real group ID
+.\" Comment out next line for !_POSIX_SAVED_IDS
+.\" or the saved set-groupd-ID
+.\" Next line is for Appendix B.4.2.2 case.
+or the effective group ID
of the process, or if the effective user ID is that of the super user.
.Pp
The
@@ -99,18 +126,23 @@ If the user is not the super user, or the uid
specified is not the real, effective ID, or saved ID,
these functions return \-1.
.Sh SEE ALSO
+.Xr getgid 2 ,
.Xr getuid 2 ,
-.Xr getgid 2
+.Xr issetugid 2 ,
+.Xr setregid 2 ,
+.Xr setreuid 2
.Sh STANDARDS
The
.Fn setuid
and
.Fn setgid
functions are compliant with the
-.St -p1003.1-88
+.St -p1003.1-90
specification with
.Li _POSIX_SAVED_IDS
-not defined.
+.\" Uncomment next line for !_POSIX_SAVED_IDS
+not
+defined with the permitted extensions from Appendix B.4.2.2.
The
.Fn seteuid
and
@@ -120,3 +152,10 @@ functions are extensions based on the
concept of
.Li _POSIX_SAVED_IDS ,
and have been proposed for a future revision of the standard.
+.Sh HISTORY
+A
+.Fn setuid
+and a
+.Fn setgid
+function calls appeared in
+.At v7 .
diff --git a/lib/libc/sys/shmat.2 b/lib/libc/sys/shmat.2
new file mode 100644
index 0000000..e3f87c9
--- /dev/null
+++ b/lib/libc/sys/shmat.2
@@ -0,0 +1,110 @@
+.\"
+.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.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 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.
+.\"
+.\" $Id: shmat.2,v 1.5 1997/02/22 15:04:25 peter Exp $
+.\"
+.Dd August 2, 1995
+.Dt SHMAT 2
+.Os FreeBSD
+.Sh NAME
+.Nm shmat ,
+.Nm shmdt
+.Nd attach or detach shared memory
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Fd #include <sys/shm.h>
+.Ft void *
+.Fn shmat "int shmid" "void *addr" "int flag"
+.Ft int
+.Fn shmdt "void *addr"
+.Sh DESCRIPTION
+.Fn Shmat
+attaches the shared memory segment identified by
+.Fa shmid
+to the calling process's address space. The address where the segment
+is attached is determined as follows:
+.\"
+.\" These are cribbed almost exactly from Stevens, _Advanced Programming in
+.\" the UNIX Environment_.
+.\"
+.Bl -bullet
+.It
+If
+.Fa addr
+is 0, the segment is attached at an address selected by the
+kernel.
+.It
+If
+.Fa addr
+is nonzero and SHM_RND is not specified in
+.Fa flag ,
+the segment is attached the specified address.
+.It
+If
+.Fa addr
+is specified and SHM_RND is specified,
+.Fa addr
+is rounded down to the nearest multiple of SHMLBA.
+.El
+.Pp
+.Fn Shmdt
+detaches the shared memory segment at the address specified by
+.Fa addr
+from the calling process's address space.
+.Sh RETURN VALUES
+Upon success,
+.Fn shmat
+returns the address where the segment is attached; otherwise, -1
+is returned and
+.Va errno
+is set to indicate the error.
+.Pp
+Upon success,
+.Fn shmdt
+returns 0; otherwise, -1 is returned and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Fn Shmat
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+No shared memory segment was found corresponding to
+.Fa shmid .
+.It Bq Er EINVAL
+.Fa addr
+was not an acceptable address.
+.El
+.Pp
+.Fn Shmdt
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+.Fa addr
+does not point to a shared memory segment.
+.Sh "SEE ALSO"
+.Xr shmctl 2 ,
+.Xr shmget 2
diff --git a/lib/libc/sys/shmctl.2 b/lib/libc/sys/shmctl.2
new file mode 100644
index 0000000..123a02d
--- /dev/null
+++ b/lib/libc/sys/shmctl.2
@@ -0,0 +1,136 @@
+.\"
+.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.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 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.
+.\"
+.\" $Id: shmctl.2,v 1.5 1997/02/22 15:04:26 peter Exp $
+.\"
+.Dd July 17, 1995
+.Dt SHMCTL 2
+.Os FreeBSD
+.Sh NAME
+.Nm shmctl
+.Nd shared memory control
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Fd #include <sys/shm.h>
+.Ft int
+.Fn shmctl "int shmid" "int cmd" "struct shmid_ds *buf"
+.Sh DESCRIPTION
+Performs the action specified by
+.Fa cmd
+on the shared memory segment identified by
+.Fa shmid :
+.Bl -tag -width SHM_UNLOCKX
+.It Dv IPC_STAT
+Fetch the segment's
+.Fa "struct shmid_ds" ,
+storing it in the memory pointed to by
+.Fa buf .
+.\"
+.\" XXX need to make sure that this is correct for FreeBSD
+.\"
+.It Dv IPC_SET
+Changes the
+.Fa shm_perm.uid ,
+.Fa shm_perm.gid ,
+and
+.Fa shm_perm.mode
+members of the segment's
+.Fa "struct shmid_ds"
+to match those of the struct pointed to by
+.Fa buf .
+The calling process's effective uid must
+match either
+.Fa shm_perm.uid
+or
+.Fa shm_perm.cuid ,
+or it must have superuser privileges.
+.It Dv IPC_RMID
+Removes the segment from the system. The removal will not take
+effect until all processes having attached the segment have exited;
+however, once the IPC_RMID operation has taken place, no further
+processes will be allowed to attach the segment. For the operation
+to succeed, the calling process's effective uid must match
+.Fa shm_perm.uid
+or
+.Fa shm_perm.cuid ,
+or the process must have superuser privileges.
+.\" .It Dv SHM_LOCK
+.\" Locks the segment in memory. The calling process must have
+.\" superuser privileges. Not implemented in FreeBSD.
+.\" .It Dv SHM_UNLOCK
+.\" Unlocks the segment from memory. The calling process must
+.\" have superuser privileges. Not implemented in FreeBSD.
+.El
+.Pp
+The
+.Fa "shmid_ds"
+struct is defined as follows:
+.\"
+.\" I fiddled with the spaces a bit to make it fit well when viewed
+.\" with nroff, but otherwise it's straight from sys/shm.h
+.\"
+.Bd -literal
+struct shmid_ds {
+ struct ipc_perm shm_perm; /* operation permission structure */
+ int shm_segsz; /* size of segment in bytes */
+ pid_t shm_lpid; /* process ID of last shared memory op */
+ pid_t shm_cpid; /* process ID of creator */
+ short shm_nattch; /* number of current attaches */
+ time_t shm_atime; /* time of last shmat() */
+ time_t shm_dtime; /* time of last shmdt() */
+ time_t shm_ctime; /* time of last change by shmctl() */
+ void *shm_internal; /* sysv stupidity */
+};
+.Ed
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn shmctl
+returns 0. Otherwise, it returns -1 and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Fn Shmctl
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Invalid operation, or
+no shared memory segment was found corresponding to
+.Fa shmid .
+.\"
+.\" XXX I think the following is right: ipcperm() only returns EPERM
+.\" when an attempt is made to modify (IPC_M) by a non-creator
+.\" non-owner
+.It Bq Er EPERM
+The calling process's effective uid does not match the uid of
+the shared memory segment's owner or creator.
+.It Bq Er EACCES
+Permission denied due to mismatch between operation and mode of
+shared memory segment.
+.Sh "SEE ALSO"
+.Xr shmat 2 ,
+.Xr shmdt 2 ,
+.Xr shmget 2 ,
+.Xr ftok 3
diff --git a/lib/libc/sys/shmget.2 b/lib/libc/sys/shmget.2
new file mode 100644
index 0000000..1f8da15
--- /dev/null
+++ b/lib/libc/sys/shmget.2
@@ -0,0 +1,138 @@
+.\"
+.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.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 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.
+.\"
+.\" $Id: shmget.2,v 1.5 1997/02/22 15:04:26 peter Exp $
+.\"
+.Dd July 3, 1995
+.Dt SHMGET 2
+.Os FreeBSD
+.Sh NAME
+.Nm shmget
+.Nd obtain a shared memory identifier
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Fd #include <sys/shm.h>
+.Ft int
+.Fn shmget "key_t key" "int size" "int flag"
+.Sh DESCRIPTION
+Based on the values of
+.Fa key
+and
+.Fa flag ,
+.Fn shmget
+returns the identifier of a newly created or previously existing shared
+memory segment.
+.\"
+.\" The following bit about keys and modes also applies to semaphores
+.\" and message queues.
+.\"
+The key
+is analogous to a filename: it provides a handle that names an
+IPC object. There are three ways to specify a key:
+.Bl -bullet
+.It
+IPC_PRIVATE may be specified, in which case a new IPC object
+will be created.
+.It
+An integer constant may be specified. If no IPC object corresponding
+to
+.Fa key
+is specified and the IPC_CREAT bit is set in
+.Fa flag ,
+a new one will be created.
+.It
+.Fn ftok
+may be used to generate a key from a pathname. See
+.Xr ftok 3 .
+.El
+.Pp
+The mode of a newly created IPC object is determined by
+.Em OR Ns 'ing
+the following constants into the
+.Fa flag
+parameter:
+.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)
+Read access for group.
+.It Dv (SHM_W>>3)
+Write access for group.
+.It Dv (SHM_R>>6)
+Read access for other.
+.It Dv (SHM_W>>6)
+Write access for other.
+.El
+.\"
+.\" XXX - we should also mention how uid, euid, and gid affect ownership
+.\" and use
+.\"
+.\" end section about keys and modes
+.\"
+.Pp
+When creating a new shared memory segment,
+.Fa size
+indicates the desired size of the new segment in bytes. The size
+of the segment may be rounded up to a multiple convenient to the
+kernel (i.e., the page size).
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn shmget
+returns the positive integer identifier of a shared memory segment.
+Otherwise, -1 is returned and
+.Va errno
+set to indicate the error.
+.Sh ERRORS
+.Fn Shmget
+will fail if:
+.Bl -tag -width Er
+.\"
+.\" XXX What about ipcperm failing?
+.\"
+.It Bq Er EINVAL
+Size specified is greater than the size of the previously existing segment.
+Size specified is less than the system imposed minimum, or greater than
+the system imposed maximum.
+.It Bq Er ENOENT
+No shared memory segment was found matching
+.Fa key ,
+and IPC_CREAT was not specified.
+.It Bq Er ENOSPC
+The kernel was unable to allocate enough memory to
+satisfy the request.
+.It Bq Er EEXIST
+IPC_CREAT and IPC_EXCL were specified, and a shared memory segment
+corresponding to
+.Fa key
+already exists.
+.Pp
+.Sh "SEE ALSO"
+.Xr shmat 2 ,
+.Xr shmctl 2 ,
+.Xr shmdt 2 ,
+.Xr ftok 3
diff --git a/lib/libc/sys/shutdown.2 b/lib/libc/sys/shutdown.2
index 976f958..b83763f 100644
--- a/lib/libc/sys/shutdown.2
+++ b/lib/libc/sys/shutdown.2
@@ -38,6 +38,7 @@
.Nm shutdown
.Nd shut down part of a full-duplex connection
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
.Fd #include <sys/socket.h>
.Ft int
.Fn shutdown "int s" "int how"
@@ -57,7 +58,7 @@ is 1, further sends will be disallowed.
If
.Fa how
is 2, further sends and receives will be disallowed.
-.Sh DIAGNOSTICS
+.Sh RETURN VALUES
A 0 is returned if the call succeeds, -1 if it fails.
.Sh ERRORS
The call succeeds unless:
@@ -76,6 +77,6 @@ The specified socket is not connected.
.Xr socket 2
.Sh HISTORY
The
-.Nm
+.Fn shutdown
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/sigaction.2 b/lib/libc/sys/sigaction.2
index d48b640..cf51196 100644
--- a/lib/libc/sys/sigaction.2
+++ b/lib/libc/sys/sigaction.2
@@ -41,16 +41,17 @@
.Fd #include <signal.h>
.Bd -literal
struct sigaction {
- void (*sa_handler)();
- sigset_t sa_mask;
- int sa_flags;
+ void (*sa_handler)(); /* signal handler */
+ sigset_t sa_mask; /* signal mask to apply */
+ int sa_flags; /* see signal options below */
};
.Ed
-.Fn sigaction "int sig" "struct sigaction *act" "struct sigaction *oact"
+.Ft int
+.Fn sigaction "int sig" "const struct sigaction *act" "struct sigaction *oact"
.Sh DESCRIPTION
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
+the signal is normally 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
@@ -68,7 +69,7 @@ of the process. This may be changed, on a per-handler basis,
so that signals are taken on a special
.Em "signal stack" .
.Pp
-Signal routines execute with the signal that caused their
+Signal routines normally execute with the signal that caused their
invocation
.Em blocked ,
but other signals may yet occur.
@@ -117,7 +118,8 @@ the signal to be delivered, and
the signal mask associated with the handler to be invoked.
.Pp
.Fn Sigaction
-assigns an action for a specific signal.
+assigns an action for a signal specified by
+.Fa sig .
If
.Fa act
is non-zero, it
@@ -131,7 +133,7 @@ If
is non-zero, the previous handling information for the signal
is returned to the user.
.Pp
-Once a signal handler is installed, it remains installed
+Once a signal handler is installed, it normally remains installed
until another
.Fn sigaction
call is made, or an
@@ -178,7 +180,16 @@ bit is set in
the system will deliver the signal to the process on a
.Em "signal stack" ,
specified with
-.Xr sigstack 2 .
+.Xr sigaltstack 2 .
+If the
+.Dv SA_NODEFER
+bit is set, further occurrences of the delivered signal are not
+masked during the execution of the handler.
+If the
+.Dv SA_RESETHAND
+bit is set, the handler is reset back to
+.Dv SIG_DFL
+at the moment the signal is delivered.
.Pp
If a signal is caught during the system calls listed below,
the call may be forced to terminate
@@ -234,7 +245,7 @@ with names as in the include file
.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" Xr abort 2
+.It Dv SIGABRT No " create core image" Xr abort 3
call (formerly
.Dv SIGIOT )
.It Dv SIGEMT No " create core image" " emulate instruction executed"
@@ -242,7 +253,7 @@ call (formerly
.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" " system call given invalid argument"
+.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"
@@ -270,13 +281,15 @@ is possible on a descriptor (see
.It Dv SIGUSR2 No " terminate process" " User defined signal 2"
.El
.Sh NOTE
-The mask specified in
+The
+.Fa sa_mask
+field specified in
.Fa act
is not allowed to block
.Dv SIGKILL
or
.Dv SIGSTOP .
-This is done silently by the system.
+Any attempt to do so will be silently ignored.
.Sh RETURN VALUES
A 0 value indicated that the call succeeded. A \-1 return value
indicates an error occurred and
@@ -327,9 +340,9 @@ or
.El
.Sh STANDARDS
The
-.Nm sigaction
-function is defined by
-.St -p1003.1-88 .
+.Fn sigaction
+function call is expected to conform to
+.St -p1003.1-90 .
The
.Dv SA_ONSTACK
and
@@ -352,17 +365,22 @@ and
Those signals are available on most
.Tn BSD Ns \-derived
systems.
+The
+.Dv SA_NODEFER
+and
+.Dv SA_RESETHAND
+are intended for backwards compatability with other operating systems.
.Sh SEE ALSO
.Xr kill 1 ,
-.Xr ptrace 2 ,
.Xr kill 2 ,
+.Xr ptrace 2 ,
.Xr sigaction 2 ,
-.Xr sigprocmask 2 ,
-.Xr sigsuspend 2 ,
+.Xr sigaltstack 2 ,
.Xr sigblock 2 ,
-.Xr sigsetmask 2 ,
.Xr sigpause 2 ,
-.Xr sigstack 2 ,
+.Xr sigprocmask 2 ,
+.Xr sigsetmask 2 ,
+.Xr sigsuspend 2 ,
.Xr sigvec 2 ,
.Xr setjmp 3 ,
.Xr siginterrupt 3 ,
diff --git a/lib/libc/sys/sigaltstack.2 b/lib/libc/sys/sigaltstack.2
index 1626025..7ea6113 100644
--- a/lib/libc/sys/sigaltstack.2
+++ b/lib/libc/sys/sigaltstack.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)sigaltstack.2 8.2 (Berkeley) 5/1/95
+.\" $Id: sigaltstack.2,v 1.7 1997/03/12 16:23:36 mpp Exp $
.\"
.Dd May 1, 1995
.Dt SIGALTSTACK 2
@@ -42,7 +43,7 @@
.Fd #include <signal.h>
.Bd -literal
struct sigaltstack {
- caddr_t ss_base;
+ char *ss_sp;
long ss_size;
int ss_flags;
};
@@ -71,15 +72,15 @@ the system arranges a switch to the signal stack for the
duration of the signal handler's execution.
.Pp
If
-.Dv SA_DISABLE
+.Dv SS_DISABLE
is set in
.Fa ss_flags ,
-.Fa ss_base
+.Fa ss_sp
and
.Fa ss_size
are ignored and the signal stack will be disabled.
Trying to disable an active stack will cause
-.Nm
+.Fn sigaltstack
to return -1 with
.Va errno
set to
@@ -95,9 +96,9 @@ is non-zero, the current signal stack state is returned.
The
.Fa ss_flags
field will contain the value
-.Dv SA_ONSTACK
+.Dv SS_ONSTACK
if the process is currently on a signal stack and
-.Dv SA_DISABLE
+.Dv SS_DISABLE
if the signal stack is currently disabled.
.Sh NOTES
The value
@@ -106,7 +107,7 @@ is defined to be the number of bytes/chars that would be used to cover
the usual case when allocating an alternate stack area.
The following code fragment is typically used to allocate an alternate stack.
.Bd -literal -offset indent
-if ((sigstk.ss_base = malloc(SIGSTKSZ)) == NULL)
+if ((sigstk.ss_sp = malloc(SIGSTKSZ)) == NULL)
/* error return */
sigstk.ss_size = SIGSTKSZ;
sigstk.ss_flags = 0;
@@ -158,7 +159,7 @@ Size of alternate stack area is less than or equal to
.Xr setjmp 3
.Sh HISTORY
The predecessor to
-.Nm sigaltstack ,
+.Fn sigaltstack ,
the
.Fn sigstack
system call, appeared in
diff --git a/lib/libc/sys/sigpending.2 b/lib/libc/sys/sigpending.2
index 0c87d4f..e8c6b8d 100644
--- a/lib/libc/sys/sigpending.2
+++ b/lib/libc/sys/sigpending.2
@@ -46,7 +46,7 @@
.Fn sigpending "sigset_t *set"
.Sh DESCRIPTION
The
-.Nm sigpending
+.Fn sigpending
function returns a mask of the signals pending for delivery
to the calling process in the location indicated by
.Fa set .
@@ -60,13 +60,13 @@ indicates an error occurred and
is set to indicated the reason.
.Sh ERRORS
The
-.Nm sigpending
+.Fn sigpending
function does not currently detect any errors.
.Sh SEE ALSO
.Xr sigaction 2 ,
.Xr sigprocmask 2
.Sh STANDARDS
The
-.Nm sigpending
-function is defined by
-.St -p1003.1-88 .
+.Fn sigpending
+function call is expected to conform to
+.St -p1003.1-90 .
diff --git a/lib/libc/sys/sigprocmask.2 b/lib/libc/sys/sigprocmask.2
index 73b014d..af1b574 100644
--- a/lib/libc/sys/sigprocmask.2
+++ b/lib/libc/sys/sigprocmask.2
@@ -110,11 +110,11 @@ has a value other than those listed here.
.Sh SEE ALSO
.Xr kill 2 ,
.Xr sigaction 2 ,
-.Xr sigsetops 3 ,
-.Xr sigsuspend 2
+.Xr sigsuspend 2 ,
+.Xr sigsetops 3
.Sh STANDARDS
The
-.Nm sigprocmask
+.Fn sigprocmask
function call is expected to
conform to
-.St -p1003.1-88 .
+.St -p1003.1-90 .
diff --git a/lib/libc/sys/sigreturn.2 b/lib/libc/sys/sigreturn.2
index f995d11..0e848c3 100644
--- a/lib/libc/sys/sigreturn.2
+++ b/lib/libc/sys/sigreturn.2
@@ -40,14 +40,28 @@
.Sh SYNOPSIS
.Fd #include <signal.h>
.Bd -literal
-struct sigcontext {
- int sc_onstack;
- int sc_mask;
- int sc_sp;
- int sc_fp;
- int sc_ap;
- int sc_pc;
- int sc_ps;
+struct sigcontext {
+ int sc_onstack; /* sigstack state to restore */
+ int sc_mask; /* signal mask to restore */
+ int sc_esp; /* machine state */
+ int sc_ebp;
+ int sc_isp;
+ int sc_eip;
+ int sc_efl;
+ int sc_es;
+ int sc_ds;
+ int sc_cs;
+ int sc_ss;
+ int sc_edi;
+ int sc_esi;
+ int sc_ebx;
+ int sc_edx;
+ int sc_ecx;
+ int sc_eax;
+# define sc_sp sc_esp
+# define sc_fp sc_ebp
+# define sc_pc sc_eip
+# define sc_ps sc_efl
};
.Ed
.Ft int
@@ -92,6 +106,6 @@ raise the privilege level of the process.
.Xr setjmp 3
.Sh HISTORY
The
-.Nm
+.Fn sigreturn
function call appeared in
.Bx 4.3 .
diff --git a/lib/libc/sys/sigstack.2 b/lib/libc/sys/sigstack.2
index 54d1c14..3fbe6e6 100644
--- a/lib/libc/sys/sigstack.2
+++ b/lib/libc/sys/sigstack.2
@@ -46,6 +46,6 @@ function has been deprecated in favor of the interface described in
.Xr sigaltstack 2
.Sh HISTORY
The
-.Nm
+.Fn sigstack
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/sigsuspend.2 b/lib/libc/sys/sigsuspend.2
index 2fa3c8d..885c170 100644
--- a/lib/libc/sys/sigsuspend.2
+++ b/lib/libc/sys/sigsuspend.2
@@ -69,12 +69,12 @@ always terminates by being interrupted, returning -1 with
set to
.Dv EINTR .
.Sh SEE ALSO
-.Xr sigprocmask 2 ,
.Xr sigaction 2 ,
+.Xr signanosleep 2 ,
+.Xr sigprocmask 2 ,
.Xr sigsetops 3
.Sh STANDARDS
The
-.Nm sigsuspend
-function call
-conforms to
-.St -p1003.1-88 .
+.Fn sigsupend
+function call is expected to conform to
+.St -p1003.1-90 .
diff --git a/lib/libc/sys/socket.2 b/lib/libc/sys/socket.2
index a16e3fb..fb6e4fa 100644
--- a/lib/libc/sys/socket.2
+++ b/lib/libc/sys/socket.2
@@ -29,9 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)socket.2 8.1 (Berkeley) 6/4/93
+.\" From: @(#)socket.2 8.1 (Berkeley) 6/4/93
+.\" $Id: socket.2,v 1.6 1997/02/22 15:04:28 peter Exp $
.\"
-.Dd June 4, 1993
+.Dd February 15, 1995
.Dt SOCKET 2
.Os BSD 4.2
.Sh NAME
@@ -56,11 +57,12 @@ These families are defined in the include file
The currently understood formats are
.Pp
.Bd -literal -offset indent -compact
-AF_UNIX (UNIX internal protocols),
-AF_INET (ARPA Internet protocols),
-AF_ISO (ISO protocols),
-AF_NS (Xerox Network Systems protocols), and
-AF_IMPLINK (IMP \*(lqhost at IMP\*(rq link layer).
+PF_LOCAL (Host-internal protocols, formerly called PF_UNIX),
+PF_INET (ARPA Internet protocols),
+PF_ISO (ISO protocols),
+PF_CCITT (ITU-T protocols, like X.25),
+PF_NS (Xerox Network Systems protocols), and
+.\"PF_IMPLINK (IMP \*(lqhost at IMP\*(rq link layer).
.Ed
.Pp
The socket has the indicated
@@ -123,7 +125,8 @@ to pipes. A stream socket must be in a
state before any data may be sent or received
on it. A connection to another socket is created with a
.Xr connect 2
-call. Once connected, data may be transferred using
+call.
+Once connected, data may be transferred using
.Xr read 2
and
.Xr write 2
@@ -131,7 +134,15 @@ calls or some variant of the
.Xr send 2
and
.Xr recv 2
-calls. When a session has been completed a
+calls.
+(Some protocol families, such as the Internet family,
+support the notion of an
+.Dq implied connect,
+which permits data to be sent piggybacked onto a connect operation by
+using the
+.Xr sendto 2
+call.)
+When a session has been completed a
.Xr close 2
may be performed.
Out-of-band data may also be transmitted as described in
@@ -230,7 +241,7 @@ The socket cannot be created until sufficient resources are freed.
.Xr accept 2 ,
.Xr bind 2 ,
.Xr connect 2 ,
-.Xr getprotoent 3 ,
+.Xr getpeername 2 ,
.Xr getsockname 2 ,
.Xr getsockopt 2 ,
.Xr ioctl 2 ,
@@ -241,17 +252,20 @@ The socket cannot be created until sufficient resources are freed.
.Xr send 2 ,
.Xr shutdown 2 ,
.Xr socketpair 2 ,
-.Xr write 2
+.Xr write 2 ,
+.Xr getprotoent 3
.Rs
.%T "An Introductory 4.3 BSD Interprocess Communication Tutorial"
-.%O "reprinted in UNIX Programmer's Supplementary Documents Volume 1"
+.%B PS1
+.%N 7
.Re
.Rs
.%T "BSD Interprocess Communication Tutorial"
-.%O "reprinted in UNIX Programmer's Supplementary Documents Volume 1"
+.%B PS1
+.%N 8
.Re
.Sh HISTORY
The
-.Nm
+.Fn socket
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/socketpair.2 b/lib/libc/sys/socketpair.2
index 1e8ba24..62aef76 100644
--- a/lib/libc/sys/socketpair.2
+++ b/lib/libc/sys/socketpair.2
@@ -58,7 +58,7 @@ are returned in
and
.Fa sv Ns [1] .
The two sockets are indistinguishable.
-.Sh DIAGNOSTICS
+.Sh RETURN VALUES
A 0 is returned if the call succeeds, -1 if it fails.
.Sh ERRORS
The call succeeds unless:
@@ -77,15 +77,15 @@ The address
does not specify a valid part of the
process address space.
.Sh SEE ALSO
+.Xr pipe 2 ,
.Xr read 2 ,
-.Xr write 2 ,
-.Xr pipe 2
+.Xr write 2
.Sh BUGS
This call is currently implemented only for the
.Tn UNIX
domain.
.Sh HISTORY
The
-.Nm
+.Fn socketpair
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/stat.2 b/lib/libc/sys/stat.2
index 6c39663..7b92113 100644
--- a/lib/libc/sys/stat.2
+++ b/lib/libc/sys/stat.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)stat.2 8.4 (Berkeley) 5/1/95
+.\" $Id: stat.2,v 1.11 1997/02/22 15:04:29 peter Exp $
.\"
.Dd May 1, 1995
.Dt STAT 2
@@ -93,21 +94,30 @@ as defined by
and into which information is placed concerning the file.
.Bd -literal
struct stat {
- dev_t st_dev; /* device inode resides on */
- ino_t st_ino; /* inode's number */
- mode_t st_mode; /* inode protection mode */
- nlink_t st_nlink; /* number or hard links to the file */
- uid_t st_uid; /* user-id of owner */
- gid_t st_gid; /* group-id of owner */
- dev_t st_rdev; /* device type, for special file inode */
+ dev_t st_dev; /* inode's device */
+ ino_t st_ino; /* inode's number */
+ mode_t st_mode; /* inode protection mode */
+ nlink_t st_nlink; /* number of hard links */
+ uid_t st_uid; /* user ID of the file's owner */
+ gid_t st_gid; /* group ID of the file's group */
+ dev_t st_rdev; /* device type */
+#ifndef _POSIX_SOURCE
struct timespec st_atimespec; /* time of last access */
struct timespec st_mtimespec; /* time of last data modification */
struct timespec st_ctimespec; /* time of last file status change */
- off_t st_size; /* file size, in bytes */
- quad_t st_blocks; /* blocks allocated for file */
- u_long st_blksize;/* optimal file sys I/O ops blocksize */
- u_long st_flags; /* user defined flags for file */
- u_long st_gen; /* file generation number */
+#else
+ time_t st_atime; /* time of last access */
+ long st_atimensec; /* nsec of last access */
+ time_t st_mtime; /* time of last data modification */
+ long st_mtimensec; /* nsec of last data modification */
+ time_t st_ctime; /* time of last file status change */
+ long st_ctimensec; /* nsec of last file status change */
+#endif
+ off_t st_size; /* file size, in bytes */
+ quad_t st_blocks; /* blocks allocated for file */
+ u_long st_blksize; /* optimal blocksize for I/O */
+ u_long st_flags; /* user defined flags for file */
+ u_long st_gen; /* file generation number */
};
.Ed
.Pp
@@ -146,6 +156,17 @@ and
system calls.
.El
.Pp
+If
+.Dv _POSIX_SOURCE
+is not defined, the time-related fields are defined as:
+.Bd -literal
+#ifndef _POSIX_SOURCE
+#define st_atime st_atimespec.tv_sec
+#define st_mtime st_mtimespec.tv_sec
+#define st_ctime st_ctimespec.tv_sec
+#endif
+.Ed
+.Pp
The size-related fields of the
.Fa struct stat
are as follows:
@@ -170,6 +191,7 @@ has the following bits:
#define S_IFREG 0100000 /* regular */
#define S_IFLNK 0120000 /* symbolic link */
#define S_IFSOCK 0140000 /* socket */
+#define S_IFWHT 0160000 /* whiteout */
#define S_ISUID 0004000 /* set user id on execution */
#define S_ISGID 0002000 /* set group id on execution */
#define S_ISVTX 0001000 /* save swapped text even after use */
@@ -207,8 +229,6 @@ will fail if:
.Bl -tag -width ENAMETOOLONGAA
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -242,13 +262,13 @@ An I/O error occurred while reading from or writing to the file system.
.Sh SEE ALSO
.Xr chmod 2 ,
.Xr chown 2 ,
-.Xr utimes 2
+.Xr utimes 2 ,
.Xr symlink 7
.Sh BUGS
Applying
-.Xr fstat
+.Fn fstat
to a socket (and thus to a pipe)
-returns a zero'd buffer,
+returns a zeroed buffer,
except for the blocksize field,
and a unique device and inode number.
.Sh STANDARDS
@@ -256,11 +276,16 @@ The
.Fn stat
and
.Fn fstat
-function calls are expected to
-conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+function calls are expected to conform to
+.St -p1003.1-90 .
.Sh HISTORY
A
-.Nm lstat
+.Fn stat
+and a
+.Fn fstat
+function call appeared in
+.At v7 .
+A
+.Fn lstat
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/statfs.2 b/lib/libc/sys/statfs.2
index 6db63c6..80164d0 100644
--- a/lib/libc/sys/statfs.2
+++ b/lib/libc/sys/statfs.2
@@ -54,27 +54,32 @@ is a pointer to a
.Fn statfs
structure defined as follows:
.Bd -literal
-typedef quad fsid_t;
+typedef struct fsid { int32_t val[2]; } fsid_t; /* file system id type */
-#define MFSNAMELEN 16 /* length of fs type name, including null */
-#define MNAMELEN 90 /* length of buffer for returned name */
+/*
+ * file system statistics
+ */
+
+#define MFSNAMELEN 16 /* length of fs type name, including null */
+#define MNAMELEN 90 /* length of buffer for returned name */
struct statfs {
- short f_type; /* filesystem type number */
- short f_flags; /* copy of mount flags */
- long f_bsize; /* fundamental file system block size */
- long f_iosize; /* optimal transfer block size */
- long f_blocks; /* total data blocks in file system */
- long f_bfree; /* free blocks in fs */
- long f_bavail; /* free blocks avail to non-superuser */
- long f_files; /* total file nodes in file system */
- long f_ffree; /* free file nodes in fs */
- fsid_t f_fsid; /* file system id */
- uid_t f_owner; /* user that mounted the filesystem */
- long f_spare[4]; /* spare for later */
- char f_fstypename[MFSNAMELEN]; /* fs type name */
- char f_mntonname[MNAMELEN]; /* directory on which mounted */
- char f_mntfromname[MNAMELEN];/* mounted filesystem */
+long f_spare2; /* placeholder */
+long f_bsize; /* fundamental file system block size */
+long f_iosize; /* optimal transfer block size */
+long f_blocks; /* total data blocks in file system */
+long f_bfree; /* free blocks in fs */
+long f_bavail; /* free blocks avail to non-superuser */
+long f_files; /* total file nodes in file system */
+long f_ffree; /* free file nodes in fs */
+fsid_t f_fsid; /* file system id */
+uid_t f_owner; /* user that mounted the filesystem */
+int f_type; /* type of filesystem (see below) */
+int f_flags; /* copy of mount flags */
+long f_spare[2]; /* spare for later */
+char f_fstypename[MFSNAMELEN];/* fs type name */
+char f_mntonname[MNAMELEN]; /* mount point */
+char f_mntfromname[MNAMELEN]; /* mounted filesystem */
};
.Ed
The flags that may be returned include:
@@ -127,9 +132,6 @@ fails if one or more of the following are true:
A component of the path prefix of
.Fa Path
is not a directory.
-.It Bq Er EINVAL
-.Fa path
-contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
The length of a component of
.Fa path
@@ -174,5 +176,6 @@ error occurred while reading from or writing to the file system.
.El
.Sh HISTORY
The
-.Nm statfs
-function first appeared in 4.4BSD.
+.Fn statfs
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/sys/swapon.2 b/lib/libc/sys/swapon.2
index 5f152cc..b684da1 100644
--- a/lib/libc/sys/swapon.2
+++ b/lib/libc/sys/swapon.2
@@ -62,8 +62,6 @@ succeeds unless:
.Bl -tag -width ENAMETOOLONG
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -99,8 +97,8 @@ An I/O error occurred while opening the swap device.
.Fa Special
points outside the process's allocated address space.
.Sh SEE ALSO
-.Xr swapon 8 ,
-.Xr config 8
+.Xr config 8 ,
+.Xr swapon 8
.Sh BUGS
There is no way to stop swapping on a disk so that the pack may be
dismounted.
@@ -108,6 +106,6 @@ dismounted.
This call will be upgraded in future versions of the system.
.Sh HISTORY
The
-.Nm
+.Fn swapon
function call appeared in
.Bx 4.0 .
diff --git a/lib/libc/sys/symlink.2 b/lib/libc/sys/symlink.2
index c404a3d..ce1fa7e 100644
--- a/lib/libc/sys/symlink.2
+++ b/lib/libc/sys/symlink.2
@@ -66,12 +66,6 @@ The symbolic link succeeds unless:
A component of the
.Fa name2
prefix is not a directory.
-.It Bq Er EINVAL
-Either
-.Fa name1
-or
-.Fa name2
-contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of either pathname exceeded 255 characters,
or the entire length of either path name exceeded 1023 characters.
@@ -129,11 +123,14 @@ or
points outside the process's allocated address space.
.El
.Sh SEE ALSO
-.Xr link 2 ,
.Xr ln 1 ,
-.Xr unlink 2
+.Xr link 2 ,
+.Xr lstat 2 ,
+.Xr readlink 2 ,
+.Xr unlink 2 ,
+.Xr symlink 7
.Sh HISTORY
The
-.Nm
+.Fn symlink
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/sync.2 b/lib/libc/sys/sync.2
index 5e79fef..2b2b664 100644
--- a/lib/libc/sys/sync.2
+++ b/lib/libc/sys/sync.2
@@ -53,7 +53,7 @@ As information in the cache is lost after a system crash a
call is issued
frequently
by the user process
-.Xr update 8
+.Xr update 4
(about every 30 seconds).
.Pp
The function
@@ -62,12 +62,13 @@ may be used to synchronize individual file descriptor
attributes.
.Sh SEE ALSO
.Xr fsync 2 ,
-.Xr sync 8 ,
-.Xr update 8
+.Xr update 4 ,
+.Xr sync 8
.Sh BUGS
.Fn Sync
may return before the buffers are completely flushed.
.Sh HISTORY
A
-.Nm
-function call appeared in Version 6 AT&T UNIX.
+.Fn sync
+function call appeared in
+.At v6 .
diff --git a/lib/libc/sys/syscall.2 b/lib/libc/sys/syscall.2
index 2e020ad..f59f2d1 100644
--- a/lib/libc/sys/syscall.2
+++ b/lib/libc/sys/syscall.2
@@ -42,9 +42,9 @@
.Fd #include <sys/syscall.h>
.Fd #include <unistd.h>
.Ft int
-.Fn syscall "int number" "..."
-.Ft int
-.Fn __syscall "quad_t number" "..."
+.Fn syscall "int number" ...
+.Ft off_t
+.Fn __syscall "quad_t number" ...
.Sh DESCRIPTION
.Fn Syscall
performs the system call whose assembly language
@@ -54,7 +54,7 @@ with the specified arguments.
Symbolic constants for system calls can be found in the header file
.Ao Pa sys/syscall.h Ac .
The
-.Nm __syscall
+.Fn __syscall
form should be used when one or more of the parameters is a
64-bit argument to ensure that argument alignment is correct.
This system call is useful for testing new system calls that
@@ -71,6 +71,6 @@ such as
.Xr pipe 2 .
.Sh HISTORY
The
-.Nm syscall
+.Fn syscall
function call appeared in
.Bx 4.0 .
diff --git a/lib/libc/sys/truncate.2 b/lib/libc/sys/truncate.2
index 2a5f3a6..678dcf6 100644
--- a/lib/libc/sys/truncate.2
+++ b/lib/libc/sys/truncate.2
@@ -37,7 +37,7 @@
.Sh NAME
.Nm truncate ,
.Nm ftruncate
-.Nd truncate a file to a specified length
+.Nd truncate or extend a file to a specified length
.Sh SYNOPSIS
.Fd #include <unistd.h>
.Ft int
@@ -50,11 +50,14 @@ causes the file named by
.Fa path
or referenced by
.Fa fd
-to be truncated to at most
+to be truncated or extended to
.Fa length
-bytes in size. If the file previously
+bytes in size. If the file
was larger than this size, the extra data
is lost.
+If the file was smaller than this size,
+it will be extended as if by writing bytes
+with the value zero.
With
.Fn ftruncate ,
the file must be open for writing.
@@ -69,8 +72,6 @@ succeeds unless:
.Bl -tag -width [ENOTDIR]
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -116,8 +117,12 @@ is not open for writing.
.Sh BUGS
These calls should be generalized to allow ranges
of bytes in a file to be discarded.
+.Pp
+Use of
+.Fn truncate
+to extend a file is not portable.
.Sh HISTORY
The
-.Nm
+.Fn truncate
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/truncate.c b/lib/libc/sys/truncate.c
index 0d50cd7..5bfeeb6 100644
--- a/lib/libc/sys/truncate.c
+++ b/lib/libc/sys/truncate.c
@@ -38,13 +38,15 @@ static char sccsid[] = "@(#)truncate.c 8.1 (Berkeley) 6/17/93";
#include <sys/types.h>
#include <sys/syscall.h>
+#include <unistd.h>
+
/*
* This function provides 64-bit offset padding that
* is not supplied by GCC 1.X but is supplied by GCC 2.X.
*/
int
truncate(path, length)
- char *path;
+ const char *path;
off_t length;
{
diff --git a/lib/libc/sys/umask.2 b/lib/libc/sys/umask.2
index cec3f1d..4ac1db8 100644
--- a/lib/libc/sys/umask.2
+++ b/lib/libc/sys/umask.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)umask.2 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt UMASK 2
@@ -78,5 +79,10 @@ function is always successful.
.Sh STANDARDS
The
.Fn umask
-function call is expected to conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+function call is expected to conform to
+.St -p1003.1-90 .
+.Sh HISTORY
+An
+.Fn umask
+function call appeared in
+.At v7 .
diff --git a/lib/libc/sys/unlink.2 b/lib/libc/sys/unlink.2
index 78221bc..8693f95 100644
--- a/lib/libc/sys/unlink.2
+++ b/lib/libc/sys/unlink.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)unlink.2 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt UNLINK 2
@@ -56,6 +57,8 @@ all resources associated with the file are reclaimed.
If one or more process have the file open when the last link is removed,
the link is removed, but the removal of the file is delayed until
all references to it have been closed.
+.Fa path
+may not be a directory.
.Sh RETURN VALUES
Upon successful completion, a value of 0 is returned.
Otherwise, a value of -1 is returned and
@@ -68,8 +71,6 @@ succeeds unless:
.Bl -tag -width ENAMETOOLONGAA
.It Bq Er ENOTDIR
A component of the path prefix is not a directory.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -83,8 +84,7 @@ to be removed.
.It Bq Er ELOOP
Too many symbolic links were encountered in translating the pathname.
.It Bq Er EPERM
-The named file is a directory and the effective user ID
-of the process is not the super-user.
+The named file is a directory.
.It Bq Er EPERM
The directory containing the file is marked sticky,
and neither the containing directory nor the file to be removed
@@ -104,9 +104,16 @@ points outside the process's allocated address space.
.Sh SEE ALSO
.Xr close 2 ,
.Xr link 2 ,
-.Xr rmdir 2
+.Xr rmdir 2 ,
.Xr symlink 7
.Sh HISTORY
An
-.Nm
-function call appeared in Version 6 AT&T UNIX.
+.Fn unlink
+function call appeared in
+.At v6 .
+.Pp
+The
+.Fn unlink
+system call traditionally allows the super-user to unlink directories which
+can damage the filesystem integrity. This implementation no longer permits
+it.
diff --git a/lib/libc/sys/utimes.2 b/lib/libc/sys/utimes.2
index 1ebeb37..531d236 100644
--- a/lib/libc/sys/utimes.2
+++ b/lib/libc/sys/utimes.2
@@ -82,12 +82,10 @@ and the effective user ID of the process does not
match the owner of the file, and is not the super-user, and write
access is denied.
.It Bq Er EFAULT
-.Xr File
+.Fa File
or
.Fa times
points outside the process's allocated address space.
-.It Bq Er EINVAL
-The pathname contains a character with the high-order bit set.
.It Bq Er EIO
An I/O error occurred while reading or writing the affected inode.
.It Bq Er ELOOP
@@ -113,6 +111,6 @@ The file system containing the file is mounted read-only.
.Xr stat 2
.Sh HISTORY
The
-.Nm utimes
+.Fn utimes
function call appeared in
.Bx 4.2 .
diff --git a/lib/libc/sys/vfork.2 b/lib/libc/sys/vfork.2
index 8b6e077..a780cbf 100644
--- a/lib/libc/sys/vfork.2
+++ b/lib/libc/sys/vfork.2
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)vfork.2 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt VFORK 2
@@ -48,16 +49,16 @@ space of the old process, which is horrendously inefficient in a paged
environment. It is useful when the purpose of
.Xr fork 2
would have been to create a new system context for an
-.Xr execve .
+.Xr execve 2 .
.Fn Vfork
differs from
-.Xr fork
+.Xr fork 2
in that the child borrows the parent's memory and thread of
control until a call to
.Xr execve 2
or an exit (either by a call to
-.Xr exit 2
-or abnormally.)
+.Xr exit 3
+or abnormally).
The parent process is suspended while the child is using its resources.
.Pp
.Fn Vfork
@@ -66,7 +67,7 @@ the parent's context.
.Pp
.Fn Vfork
can normally be used just like
-.Xr fork .
+.Xr fork 2 .
It does not work, however, to return while running in the childs context
from the procedure that called
.Fn vfork
@@ -74,36 +75,36 @@ since the eventual return from
.Fn vfork
would then return to a no longer existent stack frame.
Be careful, also, to call
-.Xr _exit
+.Xr _exit 2
rather than
-.Xr exit
+.Xr exit 3
if you can't
-.Xr execve ,
+.Xr execve 2 ,
since
-.Xr exit
+.Xr exit 3
will flush and close standard I/O channels, and thereby mess up the
parent processes standard I/O data structures.
(Even with
-.Xr fork
+.Xr fork 2
it is wrong to call
-.Xr exit
+.Xr exit 3
since buffered data would then be flushed twice.)
.Sh SEE ALSO
-.Xr fork 2 ,
.Xr execve 2 ,
+.Xr fork 2 ,
.Xr sigvec 2 ,
-.Xr wait 2 ,
-.Sh DIAGNOSTICS
+.Xr wait 2
+.Sh RETURN VALUES
Same as for
-.Xr fork .
+.Xr fork 2 .
.Sh BUGS
This system call will be eliminated when proper system sharing
mechanisms are implemented.
Users should not depend on the memory
sharing semantics of
-.Xr vfork
+.Xr vfork 2
as it will, in that case, be made synonymous to
-.Xr fork .
+.Xr fork 2 .
.Pp
To avoid a possible deadlock situation,
processes that are children in the middle
@@ -121,6 +122,6 @@ are allowed
and input attempts result in an end-of-file indication.
.Sh HISTORY
The
-.Nm
+.Fn vfork
function call appeared in
.Bx 3.0 .
diff --git a/lib/libc/sys/wait.2 b/lib/libc/sys/wait.2
index c0077b1..d348361 100644
--- a/lib/libc/sys/wait.2
+++ b/lib/libc/sys/wait.2
@@ -156,7 +156,7 @@ One of the first three macros will evaluate to a non-zero (true) value:
True if the process terminated normally by a call to
.Xr _exit 2
or
-.Xr exit 2 .
+.Xr exit 3 .
.It Fn WIFSIGNALED status
True if the process terminated due to receipt of a signal.
.It Fn WIFSTOPPED status
@@ -178,7 +178,7 @@ is true, evaluates to the low-order 8 bits
of the argument passed to
.Xr _exit 2
or
-.Xr exit 2
+.Xr exit 3
by the child.
.It Fn WTERMSIG status
If
@@ -287,9 +287,11 @@ and the ability to restart a pending
.Fn wait
call are extensions to the POSIX interface.
.Sh SEE ALSO
-.Xr exit 2 ,
-.Xr sigaction 2
+.Xr _exit 2 ,
+.Xr sigaction 2 ,
+.Xr exit 3
.Sh HISTORY
A
-.Nm
-function call appeared in Version 6 AT&T UNIX.
+.Fn wait
+function call appeared in
+.At v6 .
diff --git a/lib/libc/sys/write.2 b/lib/libc/sys/write.2
index de2d3ae..f8d8063 100644
--- a/lib/libc/sys/write.2
+++ b/lib/libc/sys/write.2
@@ -70,8 +70,8 @@ structure is defined as:
.Pp
.Bd -literal -offset indent -compact
struct iovec {
- void *iov_base;
- size_t iov_len;
+ char *iov_base; /* Base address. */
+ size_t iov_len; /* Length. */
};
.Ed
.Pp
@@ -115,6 +115,53 @@ and
may write fewer bytes than requested;
the return value must be noted,
and the remainder of the operation should be retried when possible.
+.Sh IMPLEMENTATION NOTES
+.Pp
+In the non-threaded library
+.Fn write
+is implemented as the
+.Va write
+syscall.
+.Pp
+In the threaded library, the
+.Va write
+syscall is assembled to
+.Fn _thread_sys_write
+and
+.Fn write
+is implemented as a function which locks
+.Va d
+for read and write, then calls
+.Fn _thread_sys_write .
+If the call to
+.Fn _thread_sys_write
+would block, a context switch is performed. Before returning,
+.Fn write
+unlocks
+.Va d .
+.Pp
+In the non-threaded library
+.Fn writev
+is implemented as the
+.Va writev
+syscall.
+.Pp
+In the threaded library, the
+.Va writev
+syscall is assembled to
+.Fn _thread_sys_writev
+and
+.Fn writev
+is implemented as a function which locks
+.Va d
+for read and write, then calls
+.Fn _thread_sys_writev .
+If the call to
+.Fn _thread_sys_writev
+would block, a context switch is performed. Before returning,
+.Fn writev
+unlocks
+.Va d .
.Sh RETURN VALUES
Upon successful completion the number of bytes which were written
is returned. Otherwise a -1 is returned and the global variable
@@ -134,7 +181,7 @@ An attempt is made to write to a pipe that is not open
for reading by any process.
.It Bq Er EPIPE
An attempt is made to write to a socket of type
-.DV SOCK_STREAM
+.Dv SOCK_STREAM
that is not connected to a peer socket.
.It Bq Er EFBIG
An attempt was made to write a file that exceeds the process's
@@ -189,9 +236,10 @@ array overflowed a 32-bit integer.
.Xr pipe 2 ,
.Xr select 2
.Sh STANDARDS
-.Fn Write
-is expected to conform to IEEE Std 1003.1-1988
-.Pq Dq Tn POSIX .
+The
+.Fn write
+function call is expected to conform to
+.St -p1003.1-90 .
.Sh HISTORY
The
.Fn writev
@@ -199,7 +247,6 @@ function call
appeared in
.Bx 4.2 .
A
-.Nm write
-function call
-appeared in
-Version 6 AT&T UNIX.
+.Fn write
+function call appeared in
+.At v6 .
diff --git a/lib/libc/xdr/Makefile.inc b/lib/libc/xdr/Makefile.inc
new file mode 100644
index 0000000..a60acf4
--- /dev/null
+++ b/lib/libc/xdr/Makefile.inc
@@ -0,0 +1,44 @@
+# @(#)Makefile 5.11 (Berkeley) 9/6/90
+# $Id$
+
+.PATH: ${.CURDIR}/../libc/xdr ${.CURDIR}/.
+SRCS+= xdr.c xdr_array.c xdr_float.c xdr_mem.c \
+ xdr_rec.c xdr_reference.c xdr_stdio.c xdr_sizeof.c
+
+# Only build man pages with libc.
+.if ${LIB} == "c"
+MAN3+= xdr/xdr.3
+
+MLINKS+= 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 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
+.endif
diff --git a/lib/libc/xdr/xdr.3 b/lib/libc/xdr/xdr.3
new file mode 100644
index 0000000..f64e5b1
--- /dev/null
+++ b/lib/libc/xdr/xdr.3
@@ -0,0 +1,825 @@
+.\" @(#)xdr.3n 2.2 88/08/03 4.0 RPCSRC; from 1.16 88/03/14 SMI
+.\" $Id: xdr.3,v 1.3 1996/10/05 22:26:44 wosch Exp $
+.\"
+.TH XDR 3 "16 February 1988"
+.SH NAME
+xdr \- library routines for external data representation
+.SH SYNOPSIS AND DESCRIPTION
+.LP
+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.
+.LP
+.ft B
+.nf
+.sp .5
+xdr_array(xdrs, arrp, sizep, maxsize, elsize, elproc)
+\s-1XDR\s0 *xdrs;
+char **arrp;
+u_int *sizep, maxsize, elsize;
+xdrproc_t elproc;
+.fi
+.ft R
+.IP
+A filter primitive that translates between variable-length
+arrays
+and their corresponding external representations. The
+parameter
+.I arrp
+is the address of the pointer to the array, while
+.I sizep
+is the address of the element count of the array;
+this element count cannot exceed
+.IR maxsize .
+The parameter
+.I elsize
+is the
+.I sizeof
+each of the array's elements, and
+.I elproc
+is an
+.SM XDR
+filter that translates between
+the array elements' C form, and their external
+representation.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_bool(xdrs, bp)
+\s-1XDR\s0 *xdrs;
+bool_t *bp;
+.fi
+.ft R
+.IP
+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.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_bytes(xdrs, sp, sizep, maxsize)
+\s-1XDR\s0 *xdrs;
+char **sp;
+u_int *sizep, maxsize;
+.fi
+.ft R
+.IP
+A filter primitive that translates between counted byte
+strings and their external representations.
+The parameter
+.I sp
+is the address of the string pointer. The length of the
+string is located at address
+.IR sizep ;
+strings cannot be longer than
+.IR maxsize .
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_char(xdrs, cp)
+\s-1XDR\s0 *xdrs;
+char *cp;
+.fi
+.ft R
+.IP
+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
+.BR xdr_bytes(\|) ,
+.B xdr_opaque(\|)
+or
+.BR xdr_string(\|) .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdr_destroy(xdrs)
+\s-1XDR\s0 *xdrs;
+.fi
+.ft R
+.IP
+A macro that invokes the destroy routine associated with the
+.SM XDR
+stream,
+.IR xdrs .
+Destruction usually involves freeing private data structures
+associated with the stream. Using
+.I xdrs
+after invoking
+.B xdr_destroy(\|)
+is undefined.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_double(xdrs, dp)
+\s-1XDR\s0 *xdrs;
+double *dp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B double
+precision numbers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_enum(xdrs, ep)
+\s-1XDR\s0 *xdrs;
+enum_t *ep;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.BR enum s
+(actually integers) and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_float(xdrs, fp)
+\s-1XDR\s0 *xdrs;
+float *fp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.BR float s
+and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdr_free(proc, objp)
+xdrproc_t proc;
+char *objp;
+.fi
+.ft R
+.IP
+Generic freeing routine. The first argument is the
+.SM 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
+.I not
+freed, but what it points to
+.I is
+freed (recursively).
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+u_int
+xdr_getpos(xdrs)
+\s-1XDR\s0 *xdrs;
+.fi
+.ft R
+.IP
+A macro that invokes the get-position routine
+associated with the
+.SM XDR
+stream,
+.IR xdrs .
+The routine returns an unsigned integer,
+which indicates the position of the
+.SM XDR
+byte stream.
+A desirable feature of
+.SM XDR
+streams is that simple arithmetic works with this number,
+although the
+.SM XDR
+stream instances need not guarantee this.
+.br
+.if t .ne 4
+.LP
+.ft B
+.nf
+.sp .5
+.br
+long *
+xdr_inline(xdrs, len)
+\s-1XDR\s0 *xdrs;
+int len;
+.fi
+.ft R
+.IP
+A macro that invokes the in-line routine associated with the
+.SM XDR
+stream,
+.IR xdrs .
+The routine returns a pointer
+to a contiguous piece of the stream's buffer;
+.I len
+is the byte length of the desired buffer.
+Note: pointer is cast to
+.BR "long *" .
+.IP
+Warning:
+.B xdr_inline(\|)
+may return
+.SM 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.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_int(xdrs, ip)
+\s-1XDR\s0 *xdrs;
+int *ip;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C integers
+and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_long(xdrs, lp)
+\s-1XDR\s0 *xdrs;
+long *lp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B long
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 12
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdrmem_create(xdrs, addr, size, op)
+\s-1XDR\s0 *xdrs;
+char *addr;
+u_int size;
+enum xdr_op op;
+.fi
+.ft R
+.IP
+This routine initializes the
+.SM XDR
+stream object pointed to by
+.IR xdrs .
+The stream's data is written to, or read from,
+a chunk of memory at location
+.I addr
+whose length is no more than
+.I size
+bytes long. The
+.I op
+determines the direction of the
+.SM XDR
+stream
+(either
+.BR \s-1XDR_ENCODE\s0 ,
+.BR \s-1XDR_DECODE\s0 ,
+or
+.BR \s-1XDR_FREE\s0 ).
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_opaque(xdrs, cp, cnt)
+\s-1XDR\s0 *xdrs;
+char *cp;
+u_int cnt;
+.fi
+.ft R
+.IP
+A filter primitive that translates between fixed size opaque
+data
+and its external representation.
+The parameter
+.I cp
+is the address of the opaque object, and
+.I cnt
+is its size in bytes.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_pointer(xdrs, objpp, objsize, xdrobj)
+\s-1XDR\s0 *xdrs;
+char **objpp;
+u_int objsize;
+xdrproc_t xdrobj;
+.fi
+.ft R
+.IP
+Like
+.B xdr_reference(\|)
+execpt that it serializes
+.SM NULL
+pointers, whereas
+.B xdr_reference(\|)
+does not. Thus,
+.B xdr_pointer(\|)
+can represent
+recursive data structures, such as binary trees or
+linked lists.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdrrec_create(xdrs, sendsize, recvsize, handle, readit, writeit)
+\s-1XDR\s0 *xdrs;
+u_int sendsize, recvsize;
+char *handle;
+int (*readit) (\|), (*writeit) (\|);
+.fi
+.ft R
+.IP
+This routine initializes the
+.SM XDR
+stream object pointed to by
+.IR xdrs .
+The stream's data is written to a buffer of size
+.IR sendsize ;
+a value of zero indicates the system should use a suitable
+default. The stream's data is read from a buffer of size
+.IR recvsize ;
+it too can be set to a suitable default by passing a zero
+value.
+When a stream's output buffer is full,
+.I writeit
+is called. Similarly, when a stream's input buffer is empty,
+.I readit
+is called. The behavior of these two routines is similar to
+the
+system calls
+.B read
+and
+.BR write ,
+except that
+.I handle
+is passed to the former routines as the first parameter.
+Note: the
+.SM XDR
+stream's
+.I op
+field must be set by the caller.
+.IP
+Warning: this
+.SM XDR
+stream implements an intermediate record stream.
+Therefore there are additional bytes in the stream
+to provide record boundary information.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+xdrrec_endofrecord(xdrs, sendnow)
+\s-1XDR\s0 *xdrs;
+int sendnow;
+.fi
+.ft R
+.IP
+This routine can be invoked only on
+streams created by
+.BR xdrrec_create(\|) .
+The data in the output buffer is marked as a completed
+record,
+and the output buffer is optionally written out if
+.I sendnow
+is non-zero. This routine returns one if it succeeds, zero
+otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdrrec_eof(xdrs)
+\s-1XDR\s0 *xdrs;
+int empty;
+.fi
+.ft R
+.IP
+This routine can be invoked only on
+streams created by
+.BR 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.
+.br
+.if t .ne 3
+.LP
+.ft B
+.nf
+.sp .5
+xdrrec_skiprecord(xdrs)
+\s-1XDR\s0 *xdrs;
+.fi
+.ft R
+.IP
+This routine can be invoked only on
+streams created by
+.BR xdrrec_create(\|) .
+It tells the
+.SM 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.
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+xdr_reference(xdrs, pp, size, proc)
+\s-1XDR\s0 *xdrs;
+char **pp;
+u_int size;
+xdrproc_t proc;
+.fi
+.ft R
+.IP
+A primitive that provides pointer chasing within structures.
+The parameter
+.I pp
+is the address of the pointer;
+.I size
+is the
+.I sizeof
+the structure that
+.I *pp
+points to; and
+.I proc
+is an
+.SM XDR
+procedure that filters the structure
+between its C form and its external representation.
+This routine returns one if it succeeds, zero otherwise.
+.IP
+Warning: this routine does not understand
+.SM NULL
+pointers. Use
+.B xdr_pointer(\|)
+instead.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_setpos(xdrs, pos)
+\s-1XDR\s0 *xdrs;
+u_int pos;
+.fi
+.ft R
+.IP
+A macro that invokes the set position routine associated with
+the
+.SM XDR
+stream
+.IR xdrs .
+The parameter
+.I pos
+is a position value obtained from
+.BR xdr_getpos(\|) .
+This routine returns one if the
+.SM XDR
+stream could be repositioned,
+and zero otherwise.
+.IP
+Warning: it is difficult to reposition some types of
+.SM XDR
+streams, so this routine may fail with one
+type of stream and succeed with another.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_short(xdrs, sp)
+\s-1XDR\s0 *xdrs;
+short *sp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B short
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdrstdio_create(xdrs, file, op)
+\s-1XDR\s0 *xdrs;
+\s-1FILE\s0 *file;
+enum xdr_op op;
+.fi
+.ft R
+.IP
+This routine initializes the
+.SM XDR
+stream object pointed to by
+.IR xdrs .
+The
+.SM XDR
+stream data is written to, or read from, the Standard
+.B I/O
+stream
+.IR file .
+The parameter
+.I op
+determines the direction of the
+.SM XDR
+stream (either
+.BR \s-1XDR_ENCODE\s0 ,
+.BR \s-1XDR_DECODE\s0 ,
+or
+.BR \s-1XDR_FREE\s0 ).
+.IP
+Warning: the destroy routine associated with such
+.SM XDR
+streams calls
+.B fflush(\|)
+on the
+.I file
+stream, but never
+.BR fclose(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+xdr_string(xdrs, sp, maxsize)
+\s-1XDR\s0
+*xdrs;
+char **sp;
+u_int maxsize;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C strings and
+their
+corresponding external representations.
+Strings cannot be longer than
+.IR maxsize .
+Note:
+.I sp
+is the address of the string's pointer.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_char(xdrs, ucp)
+\s-1XDR\s0 *xdrs;
+unsigned char *ucp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between
+.B unsigned
+C characters and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_int(xdrs, up)
+\s-1XDR\s0 *xdrs;
+unsigned *up;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B unsigned
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_long(xdrs, ulp)
+\s-1XDR\s0 *xdrs;
+unsigned long *ulp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B "unsigned long"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_short(xdrs, usp)
+\s-1XDR\s0 *xdrs;
+unsigned short *usp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B "unsigned short"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 16
+.LP
+.ft B
+.nf
+.sp .5
+xdr_union(xdrs, dscmp, unp, choices, dfault)
+\s-1XDR\s0 *xdrs;
+int *dscmp;
+char *unp;
+struct xdr_discrim *choices;
+bool_t (*defaultarm) (\|); /* may equal \s-1NULL\s0 */
+.fi
+.ft R
+.IP
+A filter primitive that translates between a discriminated C
+.B union
+and its corresponding external representation. It first
+translates the discriminant of the union located at
+.IR dscmp .
+This discriminant is always an
+.BR enum_t .
+Next the union located at
+.I unp
+is translated. The parameter
+.I choices
+is a pointer to an array of
+.B xdr_discrim(\|)
+structures. Each structure contains an ordered pair of
+.RI [ value , proc ].
+If the union's discriminant is equal to the associated
+.IR value ,
+then the
+.I proc
+is called to translate the union. The end of the
+.B xdr_discrim(\|)
+structure array is denoted by a routine of value
+.SM NULL\s0.
+If the discriminant is not found in the
+.I choices
+array, then the
+.I defaultarm
+procedure is called (if it is not
+.SM NULL\s0).
+Returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+xdr_vector(xdrs, arrp, size, elsize, elproc)
+\s-1XDR\s0 *xdrs;
+char *arrp;
+u_int size, elsize;
+xdrproc_t elproc;
+.fi
+.ft R
+.IP
+A filter primitive that translates between fixed-length
+arrays
+and their corresponding external representations. The
+parameter
+.I arrp
+is the address of the pointer to the array, while
+.I size
+is the element count of the array. The parameter
+.I elsize
+is the
+.I sizeof
+each of the array's elements, and
+.I elproc
+is an
+.SM XDR
+filter that translates between
+the array elements' C form, and their external
+representation.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 5
+.LP
+.ft B
+.nf
+.sp .5
+xdr_void(\|)
+.fi
+.ft R
+.IP
+This routine always returns one.
+It may be passed to
+.SM RPC
+routines that require a function parameter,
+where nothing is to be done.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_wrapstring(xdrs, sp)
+\s-1XDR\s0 *xdrs;
+char **sp;
+.fi
+.ft R
+.IP
+A primitive that calls
+.B "xdr_string(xdrs, sp,\s-1MAXUN.UNSIGNED\s0 );"
+where
+.B
+.SM MAXUN.UNSIGNED
+is the maximum value of an unsigned integer.
+.B xdr_wrapstring(\|)
+is handy because the
+.SM RPC
+package passes a maximum of two
+.SM XDR
+routines as parameters, and
+.BR xdr_string(\|) ,
+one of the most frequently used primitives, requires three.
+Returns one if it succeeds, zero otherwise.
+.SH SEE ALSO
+.BR rpc (3)
+.LP
+The following manuals:
+.RS
+.ft I
+eXternal Data Representation Standard: Protocol Specification
+.br
+eXternal Data Representation: Sun Technical Notes
+.ft R
+.br
+.IR "\s-1XDR\s0: External Data Representation Standard" ,
+.SM RFC1014, Sun Microsystems, Inc.,
+.SM USC-ISI\s0.
diff --git a/lib/libc/xdr/xdr.c b/lib/libc/xdr/xdr.c
new file mode 100644
index 0000000..12a787e
--- /dev/null
+++ b/lib/libc/xdr/xdr.c
@@ -0,0 +1,719 @@
+/*
+ * 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 = "from: @(#)xdr.c 1.35 87/08/12";*/
+/*static char *sccsid = "from: @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr.c,v 1.4 1996/12/30 14:07:07 peter Exp $";
+#endif
+
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+/*
+ * 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 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;
+ char *objp;
+{
+ XDR x;
+
+ x.x_op = XDR_FREE;
+ (*proc)(&x, objp);
+}
+
+/*
+ * XDR nothing
+ */
+bool_t
+xdr_void(/* xdrs, addr */)
+ /* XDR *xdrs; */
+ /* caddr_t addr; */
+{
+
+ 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);
+ }
+ 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);
+ }
+ return (FALSE);
+}
+
+
+/*
+ * XDR long integers
+ * same as xdr_u_long - open coded to save a proc call!
+ */
+bool_t
+xdr_long(xdrs, lp)
+ register 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);
+ }
+
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned long integers
+ * same as xdr_long - open coded to save a proc call!
+ */
+bool_t
+xdr_u_long(xdrs, ulp)
+ register 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);
+ }
+ 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)
+ register 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);
+ }
+ 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)
+ register 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);
+ }
+ return (FALSE);
+}
+
+
+/*
+ * XDR short integers
+ */
+bool_t
+xdr_short(xdrs, sp)
+ register 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);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned short integers
+ */
+bool_t
+xdr_u_short(xdrs, usp)
+ register 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);
+ }
+ return (FALSE);
+}
+
+
+/*
+ * XDR 16-bit integers
+ */
+bool_t
+xdr_int16_t(xdrs, int16_p)
+ register 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);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned 16-bit integers
+ */
+bool_t
+xdr_u_int16_t(xdrs, u_int16_p)
+ register 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);
+ }
+ 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)
+ register 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);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR enumerations
+ */
+bool_t
+xdr_enum(xdrs, ep)
+ XDR *xdrs;
+ enum_t *ep;
+{
+#ifndef lint
+ enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
+
+ /*
+ * enums are treated as ints
+ */
+ if (sizeof (enum sizecheck) == sizeof (long)) {
+ return (xdr_long(xdrs, (long *)ep));
+ } else if (sizeof (enum sizecheck) == sizeof (int)) {
+ return (xdr_int(xdrs, (int *)ep));
+ } else if (sizeof (enum sizecheck) == sizeof (short)) {
+ return (xdr_short(xdrs, (short *)ep));
+ } else {
+ return (FALSE);
+ }
+#else
+ (void) (xdr_short(xdrs, (short *)ep));
+ (void) (xdr_int(xdrs, (int *)ep));
+ return (xdr_long(xdrs, (long *)ep));
+#endif
+}
+
+/*
+ * 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)
+ register XDR *xdrs;
+ caddr_t cp;
+ register u_int cnt;
+{
+ register u_int rndup;
+ static 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)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)
+ register XDR *xdrs;
+ char **cpp;
+ register u_int *sizep;
+ u_int maxsize;
+{
+ register char *sp = *cpp; /* sp is the actual string pointer */
+ register 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 = (char *)mem_alloc(nodesize);
+ }
+ if (sp == NULL) {
+ (void) fprintf(stderr, "xdr_bytes: out of memory\n");
+ return (FALSE);
+ }
+ /* fall into ... */
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, sp, nodesize));
+
+ case XDR_FREE:
+ if (sp != NULL) {
+ mem_free(sp, nodesize);
+ *cpp = NULL;
+ }
+ return (TRUE);
+ }
+ 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)
+ register XDR *xdrs;
+ enum_t *dscmp; /* enum to decide which arm to work on */
+ char *unp; /* the union itself */
+ struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
+ xdrproc_t dfault; /* default xdr routine */
+{
+ register 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, LASTUNSIGNED));
+ }
+
+ /*
+ * no match - execute the default xdr routine if there is one
+ */
+ return ((dfault == NULL_xdrproc_t) ? FALSE :
+ (*dfault)(xdrs, unp, LASTUNSIGNED));
+}
+
+
+/*
+ * 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)
+ register XDR *xdrs;
+ char **cpp;
+ u_int maxsize;
+{
+ register 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 */
+ }
+ /* fall through... */
+ case XDR_ENCODE:
+ size = strlen(sp);
+ 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 = (char *)mem_alloc(nodesize);
+ if (sp == NULL) {
+ (void) fprintf(stderr, "xdr_string: out of memory\n");
+ return (FALSE);
+ }
+ sp[size] = 0;
+ /* fall into ... */
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, sp, size));
+
+ case XDR_FREE:
+ mem_free(sp, nodesize);
+ *cpp = NULL;
+ return (TRUE);
+ }
+ 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);
+}
diff --git a/lib/libc/xdr/xdr_array.c b/lib/libc/xdr/xdr_array.c
new file mode 100644
index 0000000..f9c34ab
--- /dev/null
+++ b/lib/libc/xdr/xdr_array.c
@@ -0,0 +1,155 @@
+/*
+ * 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 = "from: @(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_array.c,v 1.4 1996/12/30 14:07:08 peter Exp $";
+#endif
+
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+#define LASTUNSIGNED ((u_int) 0-1)
+
+/*
+ * 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)
+ register 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 */
+{
+ register u_int i;
+ register caddr_t target = *addrp;
+ register u_int c; /* the actual element count */
+ register bool_t stat = TRUE;
+ register u_int nodesize;
+
+ /* like strings, arrays are really counted arrays */
+ if (! xdr_u_int(xdrs, sizep)) {
+ return (FALSE);
+ }
+ c = *sizep;
+ if ((c > maxsize) && (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) {
+ (void) fprintf(stderr,
+ "xdr_array: out of memory\n");
+ return (FALSE);
+ }
+ memset(target, 0, nodesize);
+ break;
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+
+ /*
+ * now we xdr each element of array
+ */
+ for (i = 0; (i < c) && stat; i++) {
+ stat = (*elproc)(xdrs, target, LASTUNSIGNED);
+ 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)
+ register XDR *xdrs;
+ register char *basep;
+ register u_int nelem;
+ register u_int elemsize;
+ register xdrproc_t xdr_elem;
+{
+ register u_int i;
+ register char *elptr;
+
+ elptr = basep;
+ for (i = 0; i < nelem; i++) {
+ if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) {
+ 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..b8c8f60
--- /dev/null
+++ b/lib/libc/xdr/xdr_float.c
@@ -0,0 +1,314 @@
+/*
+ * 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 = "from: @(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_float.c,v 1.3 1996/12/30 14:07:08 peter Exp $";
+#endif
+
+/*
+ * xdr_float.c, Generic XDR routines impelmentation.
+ *
+ * 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 <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <rpc/types.h>
+#include <rpc/xdr.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(__arm32__) || defined(__ppc__)
+#include <machine/endian.h>
+#define IEEEFP
+#endif
+
+#ifdef 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)
+ register XDR *xdrs;
+ register float *fp;
+{
+#ifdef IEEEFP
+ bool_t rv;
+ long tmpl;
+#else
+ 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
+ tmpl = *(int32_t *)fp;
+ return (XDR_PUTLONG(xdrs, &tmpl));
+#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_PUTLONG(xdrs, (long *)&is));
+#endif
+
+ case XDR_DECODE:
+#ifdef IEEEFP
+ rv = XDR_GETLONG(xdrs, &tmpl);
+ *(int32_t *)fp = tmpl;
+ return (rv);
+#else
+ vsp = (struct vax_single *)fp;
+ if (!XDR_GETLONG(xdrs, (long *)&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);
+ }
+ return (FALSE);
+}
+
+#ifdef 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)
+ register XDR *xdrs;
+ double *dp;
+{
+#ifdef IEEEFP
+ register int32_t *i32p;
+ bool_t rv;
+ long tmpl;
+#else
+ register long *lp;
+ struct ieee_double id;
+ struct vax_double vd;
+ register struct dbl_limits *lim;
+ int i;
+#endif
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+#ifdef IEEEFP
+ i32p = (int32_t *)dp;
+#if BYTE_ORDER == BIG_ENDIAN
+ tmpl = *i32p++;
+ rv = XDR_PUTLONG(xdrs, &tmpl);
+ if (!rv)
+ return (rv);
+ tmpl = *i32p;
+ rv = XDR_PUTLONG(xdrs, &tmpl);
+#else
+ tmpl = *(i32p+1);
+ rv = XDR_PUTLONG(xdrs, &tmpl);
+ if (!rv)
+ return (rv);
+ tmpl = *i32p;
+ rv = XDR_PUTLONG(xdrs, &tmpl);
+#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 = (long *)&id;
+ return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+#endif
+
+ case XDR_DECODE:
+#ifdef IEEEFP
+ i32p = (int32_t *)dp;
+#if BYTE_ORDER == BIG_ENDIAN
+ rv = XDR_GETLONG(xdrs, &tmpl);
+ *i32p++ = tmpl;
+ if (!rv)
+ return (rv);
+ rv = XDR_GETLONG(xdrs, &tmpl);
+ *i32p = tmpl;
+#else
+ rv = XDR_GETLONG(xdrs, &tmpl);
+ *(i32p+1) = tmpl;
+ if (!rv)
+ return (rv);
+ rv = XDR_GETLONG(xdrs, &tmpl);
+ *i32p = tmpl;
+#endif
+ return (rv);
+#else
+ lp = (long *)&id;
+ if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(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);
+ }
+ return (FALSE);
+}
diff --git a/lib/libc/xdr/xdr_mem.c b/lib/libc/xdr/xdr_mem.c
new file mode 100644
index 0000000..36b9ada
--- /dev/null
+++ b/lib/libc/xdr/xdr_mem.c
@@ -0,0 +1,242 @@
+/*
+ * 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 = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_mem.c,v 1.4 1996/12/30 14:07:09 peter Exp $";
+#endif
+
+/*
+ * 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 <string.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <netinet/in.h>
+
+static bool_t xdrmem_getlong_aligned();
+static bool_t xdrmem_putlong_aligned();
+static bool_t xdrmem_getlong_unaligned();
+static bool_t xdrmem_putlong_unaligned();
+static bool_t xdrmem_getbytes();
+static bool_t xdrmem_putbytes();
+static u_int xdrmem_getpos(); /* XXX w/64-bit pointers, u_int not enough! */
+static bool_t xdrmem_setpos();
+static int32_t *xdrmem_inline_aligned();
+static int32_t *xdrmem_inline_unaligned();
+static void xdrmem_destroy();
+
+static 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 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)
+ register XDR *xdrs;
+ caddr_t addr;
+ u_int size;
+ enum xdr_op op;
+{
+
+ xdrs->x_op = op;
+ xdrs->x_ops = ((size_t)addr & (sizeof(int32_t) - 1))
+ ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned;
+ xdrs->x_private = xdrs->x_base = addr;
+ xdrs->x_handy = size;
+}
+
+static void
+xdrmem_destroy(/*xdrs*/)
+ /*XDR *xdrs;*/
+{
+
+}
+
+static bool_t
+xdrmem_getlong_aligned(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+
+ if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
+ return (FALSE);
+ *lp = ntohl(*(int32_t *)(xdrs->x_private));
+ xdrs->x_private += sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putlong_aligned(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+
+ if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
+ return (FALSE);
+ *(int32_t *)xdrs->x_private = htonl(*lp);
+ xdrs->x_private += sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_getlong_unaligned(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+ int32_t l;
+
+ if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
+ return (FALSE);
+ memcpy(&l, xdrs->x_private, sizeof(int32_t));
+ *lp = ntohl(l);
+ xdrs->x_private += sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putlong_unaligned(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+ int32_t l;
+
+ if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
+ return (FALSE);
+ l = htonl(*lp);
+ memcpy(xdrs->x_private, &l, sizeof(int32_t));
+ xdrs->x_private += sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_getbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register u_int len;
+{
+
+ if ((xdrs->x_handy -= len) < 0)
+ return (FALSE);
+ memcpy(addr, xdrs->x_private, len);
+ xdrs->x_private += len;
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register u_int len;
+{
+
+ if ((xdrs->x_handy -= len) < 0)
+ return (FALSE);
+ memcpy(xdrs->x_private, addr, len);
+ xdrs->x_private += len;
+ return (TRUE);
+}
+
+static u_int
+xdrmem_getpos(xdrs)
+ register XDR *xdrs;
+{
+
+ /* XXX w/64-bit pointers, u_int not enough! */
+ return ((u_long)xdrs->x_private - (u_long)xdrs->x_base);
+}
+
+static bool_t
+xdrmem_setpos(xdrs, pos)
+ register XDR *xdrs;
+ u_int pos;
+{
+ register caddr_t newaddr = xdrs->x_base + pos;
+ register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
+
+ if ((long)newaddr > (long)lastaddr)
+ return (FALSE);
+ xdrs->x_private = newaddr;
+ xdrs->x_handy = (long)lastaddr - (long)newaddr;
+ return (TRUE);
+}
+
+static int32_t *
+xdrmem_inline_aligned(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ int32_t *buf = 0;
+
+ if (xdrs->x_handy >= len) {
+ xdrs->x_handy -= len;
+ buf = (int32_t *) xdrs->x_private;
+ xdrs->x_private += len;
+ }
+ return (buf);
+}
+
+static int32_t *
+xdrmem_inline_unaligned(xdrs, len)
+ register XDR *xdrs;
+ 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..f54172b
--- /dev/null
+++ b/lib/libc/xdr/xdr_rec.c
@@ -0,0 +1,586 @@
+/*
+ * 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 = "from: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_rec.c,v 1.5 1996/12/30 14:07:10 peter Exp $";
+#endif
+
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <netinet/in.h>
+
+static u_int fix_buf_size();
+static bool_t flush_out();
+static bool_t get_input_bytes();
+static bool_t set_input_fragment();
+static bool_t skip_input_bytes();
+
+static bool_t xdrrec_getlong();
+static bool_t xdrrec_putlong();
+static bool_t xdrrec_getbytes();
+static bool_t xdrrec_putbytes();
+static u_int xdrrec_getpos();
+static bool_t xdrrec_setpos();
+static int32_t *xdrrec_inline();
+static void xdrrec_destroy();
+
+static 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 two-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 {
+ caddr_t tcp_handle;
+ caddr_t the_buffer;
+ /*
+ * out-goung bits
+ */
+ int (*writeit) __P((caddr_t, caddr_t, int));
+ caddr_t out_base; /* output buffer (points to frag header) */
+ caddr_t out_finger; /* next output position */
+ caddr_t out_boundry; /* data cannot up to this address */
+ u_int32_t *frag_header; /* beginning of current fragment */
+ bool_t frag_sent; /* true if buffer sent in middle of record */
+ /*
+ * in-coming bits
+ */
+ int (*readit) __P((caddr_t, caddr_t, int));
+ u_long in_size; /* fixed size of the input buffer */
+ caddr_t in_base;
+ caddr_t in_finger; /* location of next byte to be had */
+ caddr_t 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;
+} RECSTREAM;
+
+
+/*
+ * 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)
+ register XDR *xdrs;
+ register u_int sendsize;
+ register u_int recvsize;
+ caddr_t tcp_handle;
+ int (*readit)(); /* like read, but pass it a tcp_handle, not sock */
+ int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */
+{
+ register RECSTREAM *rstrm =
+ (RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
+
+ if (rstrm == NULL) {
+ (void)fprintf(stderr, "xdrrec_create: out of memory\n");
+ /*
+ * This is bad. Should rework xdrrec_create to
+ * return a handle, and in this case return NULL
+ */
+ return;
+ }
+ /*
+ * adjust sizes and allocate buffer quad byte aligned
+ */
+ rstrm->sendsize = sendsize = fix_buf_size(sendsize);
+ rstrm->recvsize = recvsize = fix_buf_size(recvsize);
+ rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
+ if (rstrm->the_buffer == NULL) {
+ (void)fprintf(stderr, "xdrrec_create: out of memory\n");
+ return;
+ }
+ for (rstrm->out_base = rstrm->the_buffer;
+ (u_long)rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
+ rstrm->out_base++);
+ rstrm->in_base = rstrm->out_base + sendsize;
+ /*
+ * now the rest ...
+ */
+ xdrs->x_ops = &xdrrec_ops;
+ xdrs->x_private = (caddr_t)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 *)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;
+}
+
+
+/*
+ * 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;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register int32_t *buflp = (int32_t *)(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, (caddr_t)&mylong, sizeof(int32_t)))
+ return (FALSE);
+ *lp = (long)ntohl((u_int32_t)mylong);
+ }
+ return (TRUE);
+}
+
+static bool_t
+xdrrec_putlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register int32_t *dest_lp = ((int32_t *)(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 *)(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;
+ register caddr_t addr;
+ register u_int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register int current;
+
+ while (len > 0) {
+ current = 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;
+ register caddr_t addr;
+ register u_int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register long current;
+
+ while (len > 0) {
+ current = (u_long)rstrm->out_boundry -
+ (u_long)rstrm->out_finger;
+ current = (len < current) ? len : current;
+ memcpy(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)
+ register XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ register long pos;
+
+ pos = lseek((int)(long)rstrm->tcp_handle, (off_t) 0, 1);
+ if (pos != -1)
+ 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 = -1;
+ break;
+ }
+ return ((u_int) pos);
+}
+
+static bool_t
+xdrrec_setpos(xdrs, pos)
+ register XDR *xdrs;
+ u_int pos;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ u_int currpos = xdrrec_getpos(xdrs);
+ int delta = currpos - pos;
+ caddr_t newpos;
+
+ if ((int)currpos != -1)
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ newpos = rstrm->out_finger - delta;
+ if ((newpos > (caddr_t)(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;
+ }
+ return (FALSE);
+}
+
+static int32_t *
+xdrrec_inline(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ register 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 *) 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 *) rstrm->in_finger;
+ rstrm->fbtbc -= len;
+ rstrm->in_finger += len;
+ }
+ break;
+ }
+ return (buf);
+}
+
+static void
+xdrrec_destroy(xdrs)
+ register XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+
+ mem_free(rstrm->the_buffer,
+ rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
+ mem_free((caddr_t)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;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+ 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 fuction.
+ * 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;
+{
+ register 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;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register 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_long)len | LAST_FRAG);
+ rstrm->frag_header = (u_int32_t *)rstrm->out_finger;
+ rstrm->out_finger += sizeof(u_int32_t);
+ return (TRUE);
+}
+
+
+/*
+ * Internal useful routines
+ */
+static bool_t
+flush_out(rstrm, eor)
+ register RECSTREAM *rstrm;
+ bool_t eor;
+{
+ register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
+ register u_int32_t len = (u_long)(rstrm->out_finger) -
+ (u_long)(rstrm->frag_header) - sizeof(u_int32_t);
+
+ *(rstrm->frag_header) = htonl(len | eormask);
+ len = (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 *)rstrm->out_base;
+ rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_int32_t);
+ return (TRUE);
+}
+
+static bool_t /* knows nothing about records! Only about input buffers */
+fill_input_buf(rstrm)
+ register RECSTREAM *rstrm;
+{
+ register caddr_t where;
+ u_long i;
+ register long len;
+
+ where = rstrm->in_base;
+ i = (u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT;
+ where += i;
+ len = 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)
+ register RECSTREAM *rstrm;
+ register caddr_t addr;
+ register int len;
+{
+ register long current;
+
+ while (len > 0) {
+ current = (long)rstrm->in_boundry - (long)rstrm->in_finger;
+ if (current == 0) {
+ if (! fill_input_buf(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (len < current) ? len : current;
+ memcpy(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)
+ register RECSTREAM *rstrm;
+{
+ u_int32_t header;
+
+ if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
+ return (FALSE);
+ header = (long)ntohl(header);
+ rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
+ rstrm->fbtbc = header & (~LAST_FRAG);
+ return (TRUE);
+}
+
+static bool_t /* consumes input bytes; knows nothing about records! */
+skip_input_bytes(rstrm, cnt)
+ register RECSTREAM *rstrm;
+ long cnt;
+{
+ register long current;
+
+ while (cnt > 0) {
+ current = (long)rstrm->in_boundry - (long)rstrm->in_finger;
+ if (current == 0) {
+ if (! fill_input_buf(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (cnt < current) ? cnt : current;
+ rstrm->in_finger += current;
+ cnt -= current;
+ }
+ return (TRUE);
+}
+
+static u_int
+fix_buf_size(s)
+ register u_int s;
+{
+
+ if (s < 100)
+ s = 4000;
+ return (RNDUP(s));
+}
diff --git a/lib/libc/xdr/xdr_reference.c b/lib/libc/xdr/xdr_reference.c
new file mode 100644
index 0000000..75607ba
--- /dev/null
+++ b/lib/libc/xdr/xdr_reference.c
@@ -0,0 +1,136 @@
+/*
+ * 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 = "from: @(#)xdr_reference.c 1.11 87/08/11 SMI";*/
+/*static char *sccsid = "from: @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_reference.c,v 1.4 1996/12/30 14:07:11 peter Exp $";
+#endif
+
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+#define LASTUNSIGNED ((u_int) 0-1)
+
+/*
+ * 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)
+ register 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 */
+{
+ register caddr_t loc = *pp;
+ register 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) {
+ (void) fprintf(stderr,
+ "xdr_reference: out of memory\n");
+ return (FALSE);
+ }
+ memset(loc, 0, (int)size);
+ break;
+ }
+
+ stat = (*proc)(xdrs, loc, LASTUNSIGNED);
+
+ 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)
+ register 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..e9c6a19
--- /dev/null
+++ b/lib/libc/xdr/xdr_sizeof.c
@@ -0,0 +1,163 @@
+/*
+ * 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 <rpc/types.h>
+#include <rpc/xdr.h>
+#include <sys/types.h>
+#include <stdlib.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;
+ 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;
+ int len;
+{
+ if (len == 0) {
+ return (NULL);
+ }
+ if (xdrs->x_op != XDR_ENCODE) {
+ return (NULL);
+ }
+ if (len < (int) 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) 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..39eda50
--- /dev/null
+++ b/lib/libc/xdr/xdr_stdio.c
@@ -0,0 +1,189 @@
+/*
+ * 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 = "from: @(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_stdio.c,v 1.3 1996/12/30 14:07:11 peter Exp $";
+#endif
+
+/*
+ * 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 <rpc/types.h>
+#include <stdio.h>
+#include <rpc/xdr.h>
+
+static bool_t xdrstdio_getlong();
+static bool_t xdrstdio_putlong();
+static bool_t xdrstdio_getbytes();
+static bool_t xdrstdio_putbytes();
+static u_int xdrstdio_getpos();
+static bool_t xdrstdio_setpos();
+static int32_t *xdrstdio_inline();
+static void xdrstdio_destroy();
+
+/*
+ * Ops vector for stdio type XDR
+ */
+static 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)
+ register XDR *xdrs;
+ FILE *file;
+ enum xdr_op op;
+{
+
+ xdrs->x_op = op;
+ xdrs->x_ops = &xdrstdio_ops;
+ xdrs->x_private = (caddr_t)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)
+ register XDR *xdrs;
+{
+ (void)fflush((FILE *)xdrs->x_private);
+ /* xx should we close the file ?? */
+}
+
+static bool_t
+xdrstdio_getlong(xdrs, lp)
+ XDR *xdrs;
+ register long *lp;
+{
+
+ if (fread((caddr_t)lp, sizeof(int32_t), 1,
+ (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+ *lp = (long)ntohl((int32_t)*lp);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_putlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+
+ long mycopy = (long)htonl((int32_t)*lp);
+
+ if (fwrite((caddr_t)&mycopy, sizeof(int32_t), 1,
+ (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ caddr_t addr;
+ u_int len;
+{
+
+ if ((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_putbytes(xdrs, addr, len)
+ XDR *xdrs;
+ caddr_t addr;
+ u_int len;
+{
+
+ if ((len != 0) && (fwrite(addr, (int)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);
+}
+
+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..a1c9473
--- /dev/null
+++ b/lib/libc/yp/Makefile.inc
@@ -0,0 +1,17 @@
+# from: @(#)Makefile.inc 5.3 (Berkeley) 2/20/91
+# $Id: Makefile.inc,v 1.5 1997/05/03 03:50:06 jb Exp $
+
+# yp sources
+.PATH: ${.CURDIR}/../libc/yp
+
+SRCS+= xdryp.c yp_xdr.c yplib.c
+CLEANFILES+= yp_xdr.c yp.h
+
+RPCSRC= ${DESTDIR}/usr/include/rpcsvc/yp.x
+RPCGEN= rpcgen
+
+yp_xdr.c: ${RPCSRC} yp.h
+ ${RPCGEN} -c -o ${.TARGET} ${RPCSRC}
+
+yp.h: ${RPCSRC}
+ ${RPCGEN} -h -o ${.TARGET} ${RPCSRC}
diff --git a/lib/libc/yp/xdryp.c b/lib/libc/yp/xdryp.c
new file mode 100644
index 0000000..9268fc2
--- /dev/null
+++ b/lib/libc/yp/xdryp.c
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+#ifndef LINT
+static char *rcsid = "$Id$";
+#endif
+
+#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 in case somebody goes looking for it.
+ */
+typedef struct {
+ char *dptr;
+ int dsize;
+} datum;
+
+bool_t
+xdr_datum(xdrs, objp)
+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(xdrs, objp)
+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(xdr_ypresp_all, (char *)&out);
+ *objp = YP_YPERR;
+ return FALSE;
+ }
+ if(out.more == 0) {
+ xdr_free(xdr_ypresp_all, (char *)&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);
+ 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);
+ 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(xdr_ypresp_all, (char *)&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(xdr_ypresp_all, (char *)&out);
+ *objp = YP_NOMORE;
+ return TRUE;
+ default:
+ xdr_free(xdr_ypresp_all, (char *)&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..2e0223d
--- /dev/null
+++ b/lib/libc/yp/yplib.c
@@ -0,0 +1,1033 @@
+/*
+ * 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.
+ */
+
+#ifndef LINT
+static char *rcsid = "$Id: yplib.c,v 1.28 1997/02/22 15:05:02 peter Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/uio.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>
+
+
+/*
+ * We have to define these here due to clashes between yp_prot.h and
+ * yp.h.
+ */
+
+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;
+};
+
+#include <rpcsvc/ypclnt.h>
+
+#ifndef BINDINGDIR
+#define BINDINGDIR "/var/yp/binding"
+#endif
+#define YPMATCHCACHE
+#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 __P(( struct dom_binding * ));
+struct dom_binding *_ypbindlist;
+static char _yp_domain[MAXHOSTNAMELEN];
+int _yplib_timeout = 10;
+
+#ifdef YPMATCHCACHE
+int _yplib_cache = 5;
+
+static struct ypmatch_ent {
+ struct ypmatch_ent *next;
+ char *map, *key, *val;
+ int keylen, vallen;
+ time_t expire_t;
+} *ypmc;
+
+static void
+ypmatch_add(map, key, keylen, val, vallen)
+ char *map;
+ char *key;
+ int keylen;
+ char *val;
+ int vallen;
+{
+ struct ypmatch_ent *ep;
+ time_t t;
+
+ time(&t);
+
+ for(ep=ypmc; ep; ep=ep->next)
+ if(ep->expire_t < t)
+ break;
+ if(ep==NULL) {
+ ep = (struct ypmatch_ent *)malloc(sizeof *ep);
+ bzero((char *)ep, sizeof *ep);
+ if(ypmc)
+ ep->next = ypmc;
+ ypmc = ep;
+ }
+
+ if(ep->key)
+ free(ep->key);
+ if(ep->val)
+ free(ep->val);
+
+ ep->key = NULL;
+ ep->val = NULL;
+
+ ep->key = (char *)malloc(keylen);
+ if(ep->key==NULL)
+ return;
+
+ ep->val = (char *)malloc(vallen);
+ if(ep->key==NULL) {
+ free(ep->key);
+ ep->key = NULL;
+ return;
+ }
+ ep->keylen = keylen;
+ ep->vallen = vallen;
+
+ bcopy(key, ep->key, ep->keylen);
+ bcopy(val, ep->val, ep->vallen);
+
+ if(ep->map) {
+ if( strcmp(ep->map, map) ) {
+ free(ep->map);
+ ep->map = strdup(map);
+ }
+ } else {
+ ep->map = strdup(map);
+ }
+
+ ep->expire_t = t + _yplib_cache;
+}
+
+static bool_t
+ypmatch_find(map, key, keylen, val, vallen)
+ char *map;
+ char *key;
+ int keylen;
+ char **val;
+ int *vallen;
+{
+ struct ypmatch_ent *ep;
+ time_t t;
+
+ if(ypmc==NULL)
+ return 0;
+
+ time(&t);
+
+ for(ep=ypmc; ep; ep=ep->next) {
+ if(ep->keylen != keylen)
+ continue;
+ if(strcmp(ep->map, map))
+ continue;
+ if(bcmp(ep->key, key, keylen))
+ continue;
+ if(t > ep->expire_t)
+ continue;
+
+ *val = ep->val;
+ *vallen = ep->vallen;
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+char *
+ypbinderr_string(incode)
+ 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(dom, ypdb)
+ 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;
+ int 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);
+ 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;
+ }
+ sprintf(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);
+ ysd->dom_server_addr.sin_addr.s_addr =
+ *(u_long *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr;
+ ysd->dom_server_addr.sin_port =
+ *(u_short *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_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,
+ xdr_domainname, (char *)&dom, 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) {
+ clnt_destroy(client);
+ ysd->dom_vers = -1;
+ sleep(_yplib_timeout/2);
+ goto again;
+ }
+ }
+ clnt_destroy(client);
+
+ bzero((char *)&ysd->dom_server_addr, sizeof ysd->dom_server_addr);
+ ysd->dom_server_addr.sin_family = AF_INET;
+ ysd->dom_server_addr.sin_port =
+ *(u_short *)&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port;
+ ysd->dom_server_addr.sin_addr.s_addr =
+ *(u_long *)&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_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;
+ strcpy(ysd->dom_domain, dom);
+ }
+
+ /* 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_create(&ysd->dom_server_addr,
+ YPPROG, YPVERS, tv, &ysd->dom_socket);
+ 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;
+ }
+
+ if(ypdb!=NULL)
+ *ypdb = ysd;
+ return 0;
+}
+
+static void
+_yp_unbind(ypb)
+ struct dom_binding *ypb;
+{
+ struct sockaddr_in check;
+ int 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;
+}
+
+int
+yp_bind(dom)
+ char *dom;
+{
+ return _yp_dobind(dom, NULL);
+}
+
+void
+yp_unbind(dom)
+ 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;
+}
+
+int
+yp_match(indomain, inmap, inkey, inkeylen, outval, outvallen)
+ 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;
+
+#ifdef YPMATCHCACHE
+ 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);
+ bcopy(yprv.val.valdat_val, *outval, *outvallen);
+ (*outval)[*outvallen] = '\0';
+ return 0;
+ }
+#endif
+
+again:
+ if( _yp_dobind(indomain, &ysd) != 0)
+ return YPERR_DOMAIN;
+
+ tv.tv_sec = _yplib_timeout;
+ tv.tv_usec = 0;
+
+ yprk.domain = indomain;
+ yprk.map = inmap;
+ yprk.key.keydat_val = (char *)inkey;
+ yprk.key.keydat_len = inkeylen;
+
+ bzero((char *)&yprv, sizeof yprv);
+
+ r = clnt_call(ysd->dom_client, YPPROC_MATCH,
+ xdr_ypreq_key, &yprk, 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);
+ bcopy(yprv.val.valdat_val, *outval, *outvallen);
+ (*outval)[*outvallen] = '\0';
+#ifdef YPMATCHCACHE
+ if( strcmp(_yp_domain, indomain)==0 )
+ ypmatch_add(inmap, inkey, inkeylen, *outval, *outvallen);
+#endif
+ }
+
+ xdr_free(xdr_ypresp_val, (char *)&yprv);
+ return r;
+}
+
+int
+yp_get_default_domain(domp)
+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_first(indomain, inmap, outkey, outkeylen, outval, outvallen)
+ 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;
+
+again:
+ if( _yp_dobind(indomain, &ysd) != 0)
+ 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,
+ xdr_ypreq_nokey, &yprnk, 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);
+ bcopy(yprkv.key.keydat_val, *outkey, *outkeylen);
+ (*outkey)[*outkeylen] = '\0';
+ *outvallen = yprkv.val.valdat_len;
+ *outval = (char *)malloc(*outvallen+1);
+ bcopy(yprkv.val.valdat_val, *outval, *outvallen);
+ (*outval)[*outvallen] = '\0';
+ }
+
+ xdr_free(xdr_ypresp_key_val, (char *)&yprkv);
+ return r;
+}
+
+int
+yp_next(indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen)
+ 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;
+
+again:
+ if( _yp_dobind(indomain, &ysd) != 0)
+ 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,
+ xdr_ypreq_key, &yprk, 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);
+ bcopy(yprkv.key.keydat_val, *outkey, *outkeylen);
+ (*outkey)[*outkeylen] = '\0';
+ *outvallen = yprkv.val.valdat_len;
+ *outval = (char *)malloc(*outvallen+1);
+ bcopy(yprkv.val.valdat_val, *outval, *outvallen);
+ (*outval)[*outvallen] = '\0';
+ }
+
+ xdr_free(xdr_ypresp_key_val, (char *)&yprkv);
+ return r;
+}
+
+int
+yp_all(indomain, inmap, incallback)
+ 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;
+
+again:
+
+ if( _yp_dobind(indomain, &ysd) != 0)
+ 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) {
+ 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,
+ xdr_ypreq_nokey, &yprnk,
+ xdr_ypresp_all_seq, &status, tv) != RPC_SUCCESS) {
+ clnt_perror(ysd->dom_client, "yp_next: clnt_call");
+ clnt_destroy(clnt);
+ _yp_unbind(ysd);
+ goto again;
+ }
+
+ clnt_destroy(clnt);
+ savstat = status;
+ xdr_free(xdr_ypresp_all_seq, (char *)&status); /* not really needed... */
+ if(savstat != YP_NOMORE)
+ return ypprot_err(savstat);
+ return 0;
+}
+
+int
+yp_order(indomain, inmap, outorder)
+ 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;
+
+again:
+ if( _yp_dobind(indomain, &ysd) != 0)
+ 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,
+ xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv);
+
+ /*
+ * NIS+ in YP compat mode doesn't support the YPPROC_ORDER
+ * procedure.
+ */
+ if (r == RPC_PROCUNAVAIL) {
+ 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(xdr_ypresp_order, (char *)&ypro);
+ return (r);
+}
+
+int
+yp_master(indomain, inmap, outname)
+ 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;
+again:
+ if( _yp_dobind(indomain, &ysd) != 0)
+ 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,
+ xdr_ypreq_nokey, &yprnk, 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(xdr_ypresp_master, (char *)&yprm);
+ return (r);
+}
+int
+yp_maplist(indomain, outmaplist)
+ 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;
+
+again:
+ if( _yp_dobind(indomain, &ysd) != 0)
+ 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,
+ xdr_domainname,(char *)&indomain,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(xdr_ypresp_maplist, &ypml);*/
+ return (r);
+}
+
+char *
+yperr_string(incode)
+ 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(incode)
+ 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(dom)
+ char **dom;
+{
+ char *unused;
+
+ if( _yp_domain[0]=='\0' )
+ if( yp_get_default_domain(&unused) )
+ return 0;
+
+ if(dom)
+ *dom = _yp_domain;
+
+ if( yp_bind(_yp_domain)==0 ) {
+ yp_unbind(_yp_domain);
+ return 1;
+ }
+ return 0;
+}
diff --git a/lib/libc_r/Makefile b/lib/libc_r/Makefile
new file mode 100644
index 0000000..363f308
--- /dev/null
+++ b/lib/libc_r/Makefile
@@ -0,0 +1,21 @@
+# $Id$
+#
+# All library objects contain rcsid strings by default; they may be
+# excluded as a space-saving measure. To produce a library that does
+# not contain these strings, delete -DLIBC_RCS and -DSYSLIBC_RCS
+# from CFLAGS below. To remove these strings from just the system call
+# stubs, remove just -DSYSLIBC_RCS from CFLAGS.
+LIB=c_r
+SHLIB_MAJOR= 3
+SHLIB_MINOR= 0
+CFLAGS+=-DLIBC_RCS -DSYSLIBC_RCS
+CFLAGS+=-DPTHREAD_KERNEL -D_THREAD_SAFE -I${.CURDIR}/uthread
+AINC= -I${.CURDIR}/../libc/${MACHINE} -I${.CURDIR}/uthread
+PRECIOUSLIB= yes
+
+.include "${.CURDIR}/../libc/Makefile.inc"
+.include "${.CURDIR}/man/Makefile.inc"
+.include "${.CURDIR}/uthread/Makefile.inc"
+.include "${.CURDIR}/sys/Makefile.inc"
+
+.include <bsd.lib.mk>
diff --git a/lib/libc_r/man/Makefile.inc b/lib/libc_r/man/Makefile.inc
new file mode 100644
index 0000000..7d67fb8
--- /dev/null
+++ b/lib/libc_r/man/Makefile.inc
@@ -0,0 +1,17 @@
+# $Id$
+
+# POSIX thread man files
+
+.PATH: ${.CURDIR}/man
+
+MAN3+= pthread_create.3 \
+ pthread_detach.3 \
+ pthread_equal.3 \
+ pthread_exit.3 \
+ pthread_getspecific.3 \
+ pthread_join.3 \
+ pthread_key_create.3 \
+ pthread_key_delete.3 \
+ pthread_once.3 \
+ pthread_self.3 \
+ pthread_setspecific.3
diff --git a/lib/libc_r/man/pthread_create.3 b/lib/libc_r/man/pthread_create.3
new file mode 100644
index 0000000..aa81588
--- /dev/null
+++ b/lib/libc_r/man/pthread_create.3
@@ -0,0 +1,109 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_CREATE 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_create
+.Nd create a new thread
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_create "pthread_t *thread" "const pthread_attr_t *attr" "void *(*start_routine)(void *)" "void *arg"
+.Sh DESCRIPTION
+The
+.Fn pthread_create
+function is used to create a new thread, with attributes specified by
+.Fa attr ,
+within a process. If
+.Fa attr
+is NULL, the default attributes are used. If the attributes specified by
+.Fa attr
+are modified later, the thread's attributes are not affected. Upon
+successful completion
+.Fn pthread_create
+will store the ID of the created thread in the location specified by
+.Fa thread .
+.Pp
+The thread is created executing
+.Fa start_routine
+with
+.Fa arg
+as its sole argument. If the
+.Fa start_routine
+returns, the effect is as if there was an implicit call to
+.Fn pthread_exit
+using the return value of
+.Fa start_toutine
+as the exit status. Note that the thread in which
+.Fn main
+was originally invoked differs from this. When it returns from
+.Fn main ,
+the effect is as if there was an implicit call to
+.Fn exit using the return value of
+.Fn main
+as the exit status.
+.Pp
+The signal state of the new thread is initialized as:
+.Bl -bullet -offset indent
+.It
+The signal mask is inherited from the creating thread.
+.It
+The set of signals pending for the new thread is empty.
+.El
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_create
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+.Fn pthread_create
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EAGAIN
+The system lacked the necessary resources to create another thread, or
+the system-imposed limit on the total number of threads in a process
+[PTHREAD_THREADS_MAX] would be exceeded.
+.It Bq Er EINVAL
+The value specified by
+.Fa attr
+is invalid.
+.El
+.Pp
+.Sh SEE ALSO
+.Xr fork 2 ,
+.Xr pthread_exit 3 ,
+.Xr pthread_join 3
+.Sh STANDARDS
+.Fn pthread_create
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libc_r/man/pthread_detach.3 b/lib/libc_r/man/pthread_detach.3
new file mode 100644
index 0000000..d2a60dd
--- /dev/null
+++ b/lib/libc_r/man/pthread_detach.3
@@ -0,0 +1,79 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_DETACH 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_detach
+.Nd detach a thread
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_detach "pthread_t thread"
+.Sh DESCRIPTION
+The
+.Fn pthread_detach
+function is used to indicate to the implementation that storage for the
+thread
+.Fa thread
+can be reclaimed when the thread terminates. If
+.Fa thread
+has not terminated,
+.Fn pthread_detach
+will not cause it to terminate. The effect of multiple
+.Fn pthread_detach
+calls on the same target thread is unspecified.
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_detach
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+.Fn pthread_detach
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The implementation has detected that the value specified by
+.Fa thread
+does not refer to a joinable thread.
+.It Bq Er ESRCH
+No thread could be found corresponding to that specified by the given
+thread ID,
+.Fa thread .
+.El
+.Pp
+.Sh SEE ALSO
+.Xr pthread_join 3
+.Sh STANDARDS
+.Fn pthread_detach
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libc_r/man/pthread_equal.3 b/lib/libc_r/man/pthread_equal.3
new file mode 100644
index 0000000..3324855
--- /dev/null
+++ b/lib/libc_r/man/pthread_equal.3
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_EQUAL 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_equal
+.Nd compare thread IDs
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_equal "pthread_t t1" "pthread_t t2"
+.Sh DESCRIPTION
+The
+.Fn pthread_equal
+function compares the thread IDs
+.Fa t1
+and
+.Fa t2 .
+.Sh RETURN VALUES
+The
+.Fn pthread_equal
+function will non-zero if the thread IDs
+.Fa t1
+and
+.Fa t2
+correspond to the same thread, otherwise it will return zero.
+.Sh ERRORS
+None.
+.Pp
+.Sh SEE ALSO
+.Xr pthread_create 3 ,
+.Xr pthread_exit 3
+.Sh STANDARDS
+.Fn pthread_equal
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libc_r/man/pthread_exit.3 b/lib/libc_r/man/pthread_exit.3
new file mode 100644
index 0000000..aad365e
--- /dev/null
+++ b/lib/libc_r/man/pthread_exit.3
@@ -0,0 +1,99 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_EXIT 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_exit
+.Nd terminate the calling thread
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft void
+.Fn pthread_exit "void *value_ptr"
+.Sh DESCRIPTION
+The
+.Fn pthread_exit
+function terminates the calling thread and makes the value
+.Fa value_ptr
+available to any successful join with the terminating thread. Any
+cancellation cleanup handlers that have been pushed and are not yet popped
+are popped in the reverse order that they were pushed and then executed.
+After all cancellation handlers have been executed, if the thread has any
+thread-specific data, appropriate destructor functions are called in an
+unspecified order. Thread termination does not release any application
+visible process resources, including, but not limited to, mutexes and
+file descriptors, nor does it perform any process level cleanup
+actions, including, but not limited to, calling
+.Fn atexit
+routines that may exist.
+.Pp
+An implicit call to
+.Fn pthread_exit
+is made when a thread other than the thread in which
+.Fn main
+was first invoked returns from the start routine that was used to create
+it. The function's return value serves as the thread's exit status.
+.Pp
+The behavior of
+.Fn pthread_exit
+is undefied if called from a cancellation handler or destructor function
+that was invoked as the result of an implicit or explicit call to
+.Fn pthread_exit .
+.Pp
+After a thread has terminated, the result of access to local (auto)
+variables of the thread is undefined. Thus, references to local variables
+of the exiting thread should not be used for the
+.Fn pthread_exit
+.Fa value_ptr
+parameter value.
+.Pp
+The process will exit with an exit status of 0 after the last thread has
+been terminated. The behavior is as if the implementation called
+.Fn exit
+with a zero argument at thread termination time.
+.Pp
+.Sh RETURN VALUES
+The
+.Fn pthread_exit
+function cannot return to its caller.
+.Sh ERRORS
+None.
+.Pp
+.Sh SEE ALSO
+.Xr _exit 2 ,
+.Xr exit 2 ,
+.Xr pthread_create 3 ,
+.Xr pthread_join 3
+.Sh STANDARDS
+.Fn pthread_exit
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libc_r/man/pthread_getspecific.3 b/lib/libc_r/man/pthread_getspecific.3
new file mode 100644
index 0000000..b53841e
--- /dev/null
+++ b/lib/libc_r/man/pthread_getspecific.3
@@ -0,0 +1,82 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.\" $Id$
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_GETSPECIFIC 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_getspecific
+.Nd get a thread-specific data value
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft void *
+.Fn pthread_getspecific "pthread_key_t key"
+.Sh DESCRIPTION
+The
+.Fn pthread_getspecific
+function returns the value currently bound to the specified
+.Fa key
+on behalf of the calling thread.
+.Pp
+The effect of calling
+.Fn pthread_getspecific
+with a
+.Fa key
+value not obtained from
+.Fn pthread_key_create
+or after
+.Fa key
+has been deleted with
+.Fn pthread_key_delete
+is undefined.
+.Pp
+.Fn pthread_getspecific
+may be called from a thread-specific data destructor function.
+.Sh RETURN VALUES
+The
+.Fn pthread_getspecific
+function will return the thread-specific data value associated with the given
+.Fa key .
+If no thread-specific data value is associated with
+.Fa key ,
+then the value NULL is returned.
+.Sh ERRORS
+None.
+.Sh SEE ALSO
+.Xr pthread_key_create 3 ,
+.Xr pthread_key_delete 3 ,
+.Xr pthread_setspecific 3
+.Sh STANDARDS
+.Fn pthread_getspecific
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libc_r/man/pthread_join.3 b/lib/libc_r/man/pthread_join.3
new file mode 100644
index 0000000..cabf319
--- /dev/null
+++ b/lib/libc_r/man/pthread_join.3
@@ -0,0 +1,100 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_JOIN 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_join
+.Nd wait for thread termination
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_join "pthread_t thread" "void **value_ptr"
+.Sh DESCRIPTION
+The
+.Fn pthread_join
+function suspends execution of the calling thread until the target
+.Fa thread
+terminates unless the target
+.Fa thread
+has already terminated.
+.Pp
+On return from a successful
+.Fn pthread_join
+call with a non-NULL
+.Fa value_ptr
+argument, the value passed to
+.Fn pthread_exit
+by the terminating thread is stored in the location referenced by
+.Fa value_ptr .
+When a
+.Fn pthread_join
+returns successfully, the target thread has been terminated. The results
+of multiple simultaneous calls to
+.Fn pthread_join
+specifying the same target thread are undefined. If the thread calling
+.Fn pthread_join
+is cancelled, then the target thread is not detached.
+.Pp
+A thread that has exited but remains unjoined counts against
+[_POSIX_THREAD_THREADS_MAX].
+.Pp
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_join
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+.Fn pthread_join
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The implementation has detected that the value specified by
+.Fa thread
+does not refer to a joinable thread.
+.It Bq Er ESRCH
+No thread could be found corresponding to that specified by the given
+thread ID,
+.Fa thread .
+.It Bq Er EDEADLK
+A deadlock was detected or the value of
+.Fa thread
+specifies the calling thread.
+.El
+.Pp
+.Sh SEE ALSO
+.Xr wait 2 ,
+.Xr pthread_create 3
+.Sh STANDARDS
+.Fn pthread_join
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libc_r/man/pthread_key_create.3 b/lib/libc_r/man/pthread_key_create.3
new file mode 100644
index 0000000..25165ce
--- /dev/null
+++ b/lib/libc_r/man/pthread_key_create.3
@@ -0,0 +1,98 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_KEY_CREATE 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_key_create
+.Nd thread-specific data key creation
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_key_create "pthread_key_t *key" "void (*destructor)(void *)"
+.Sh DESCRIPTION
+The
+.Fn pthread_key_create
+function creates a thread-specific data key visible to all threads in the
+process. Key values provided by
+.Fn pthread_key_create
+are opaque objects used to locate thread-specific data. Although the same
+key value may be used by different threads, the values bound to the key
+by
+.Fn pthread_setspecific
+are maintained on a per-thread basis and persist for the life of the calling
+thread.
+.Pp
+Upon key creation, the value NULL is associated with the new key in all
+active threads. Upon thread creation, the value NULL is associated with all
+defined keys in the new thread.
+.Pp
+An optional destructor function may be associated with each key value. At
+thread exit, if a key value has a non-NULL destructor pointer, and the
+thread has a non-NULL value associated with the key, the function pointed
+to is called with the current associated value as its sole argument. The
+order of destructor calls is unspecified if more than one destructor exists
+for a thread when it exits.
+.Pp
+If, after all the destructors have been called for all non-NULL values
+with associated destructors, there are still some non-NULL values with
+associated destructors, then the process is repeated. If, after at least
+[PTHREAD_DESTRUCTOR_ITERATIONS] iterations of destructor calls for
+outstanding non-NULL values, there are still some non-NULL values with
+associated destructors, the implementation stops calling destructors.
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_key_create
+function will store the newly created key value at the location specified by
+.Fa key
+and returns zero. Otherwise an error number will be returned to indicate
+the error.
+.Sh ERRORS
+.Fn pthread_key_create
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EAGAIN
+The system lacked the necessary resources to create another thread-specific
+data key, or the system-imposed limit on the total number of keys per process
+[PTHREAD_KEYS_MAX] would be exceeded.
+.It Bq Er ENOMEM
+Insufficient memory exists to create the key.
+.El
+.Pp
+.Sh SEE ALSO
+.Xr pthread_getspecific 3 ,
+.Xr pthread_key_delete 3 ,
+.Xr pthread_setspecific 3
+.Sh STANDARDS
+.Fn pthread_key_create
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libc_r/man/pthread_key_delete.3 b/lib/libc_r/man/pthread_key_delete.3
new file mode 100644
index 0000000..badfa8c
--- /dev/null
+++ b/lib/libc_r/man/pthread_key_delete.3
@@ -0,0 +1,92 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_KEY_DELETE 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_key_delete
+.Nd delete a thread-specific data key
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_key_delete "pthread_key_t key"
+.Sh DESCRIPTION
+The
+.Fn pthread_key_delete
+function deletes a thread-specific data key previously returned by
+.Fn pthread_key_create .
+The thread-specific data values associated with
+.Fa key
+need not be NULL at the time that
+.Fn pthread_key_delete
+is called. It is the responsibility of the application to free any
+application storage or perform any cleanup actions for data structures
+related to the deleted key or associated thread-specific data in any threads;
+this cleanup can be done either before or after
+.Fn pthread_key_delete
+is called. Any attempt to use
+.Fa key
+following the call to
+.Fn pthread_key_delete
+results in undefined behavior.
+.Pp
+The
+.Fn pthread_key_delete
+function is callable from within destructor functions. Destructor functions
+are not invoked by
+.Fn pthread_key_delete .
+Any destructor function that may have been associated with
+.Fa key
+will no longer be called upon thread exit.
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_key_delete
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+.Fn pthread_key_delete
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa key
+value is invalid.
+.El
+.Pp
+.Sh SEE ALSO
+.Xr pthread_getspecific 3 ,
+.Xr pthread_key_create 3 ,
+.Xr pthread_setspecific 3
+.Sh STANDARDS
+.Fn pthread_key_delete
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libc_r/man/pthread_once.3 b/lib/libc_r/man/pthread_once.3
new file mode 100644
index 0000000..9ade42f
--- /dev/null
+++ b/lib/libc_r/man/pthread_once.3
@@ -0,0 +1,100 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_ONCE 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_once
+.Nd dynamic package initialization
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Pp
+pthread_once
+.Fa once_control
+= PTHREAD_ONCE_INIT;
+.Ft int
+.Fn pthread_once "pthread_once_t *once_control" "void *(*init_routine)(void)"
+.Sh DESCRIPTION
+The first call to
+.Fn pthread_once
+by any thread in a process, with a given
+.Fa once_control ,
+will call the
+.Fn init_routine
+with no arguments. Subsequent calls to
+.Fn pthread_once
+with the same
+.Fa once_control
+will not call the
+.Fn init_routine .
+On return from
+.Fn pthread_once ,
+it is guaranteed that
+.Fn init_routine
+has completed. The
+.Fa once_control
+parameter is used to determine whether the associated initialization
+routine has been called.
+.Pp
+The function
+.Fn pthread_once
+is not a cancellation point. However, if
+.Fn init_routine
+is a cancellation point and is cancelled, the effect on
+.Fa once_control is as if
+.Fn pthread_once
+was never called.
+.Pp
+The constant
+.Fa PTHREAD_ONCE_INIT
+is defined by header
+.Aq Pa pthread.h .
+.Pp
+The behavior of
+.Fn pthread_once
+is undefined if
+.Fa once_control
+has automatic storage duration or is not initialized by
+.Fa PTHREAD_ONCE_INIT .
+.Pp
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_once
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+None.
+.Pp
+.Sh STANDARDS
+.Fn pthread_once
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libc_r/man/pthread_self.3 b/lib/libc_r/man/pthread_self.3
new file mode 100644
index 0000000..9ba0ee6
--- /dev/null
+++ b/lib/libc_r/man/pthread_self.3
@@ -0,0 +1,59 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_SELF 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_self
+.Nd get the calling thread's ID
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft pthread_t
+.Fn pthread_self "void"
+.Sh DESCRIPTION
+The
+.Fn pthread_self
+function returns the thread ID of the calling thread.
+.Sh RETURN VALUES
+The
+.Fn pthread_self
+function returns the thread ID of the calling thread.
+.Sh ERRORS
+None.
+.Pp
+.Sh SEE ALSO
+.Xr pthread_create 3 ,
+.Xr pthread_equal 3
+.Sh STANDARDS
+.Fn pthread_self
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libc_r/man/pthread_setspecific.3 b/lib/libc_r/man/pthread_setspecific.3
new file mode 100644
index 0000000..838b587
--- /dev/null
+++ b/lib/libc_r/man/pthread_setspecific.3
@@ -0,0 +1,91 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_SETSPECIFIC 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_setspecific
+.Nd set a thread-specific data value
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_setspecific "pthread_key_t key" "const void *value"
+.Sh DESCRIPTION
+The
+.Fn pthread_setspecific
+function associates a thread-specific value with a
+.Fa key
+obtained via a previous call to
+.Fn pthread_key_create .
+Different threads man bind different values to the same key. These values are
+typically pointers to blocks of dynamically allocated memory that have been
+reserved for use by the calling thread.
+.Pp
+The effect of calling
+.Fn pthread_setspecific
+with a key value not obtained from
+.Fn pthread_key_create
+or after
+.Fa key
+has been deleted with
+.Fn pthread_key_delete
+is undefined.
+.Pp
+.Fn pthread_setspecific
+may be called from a thread-specific data destructor function, however this
+may result in lost storage or infinite loops.
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_setspecific
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+.Fn pthread_setspecific
+will fail if:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+Insufficient memory exists to associate the value with the
+.Fa key .
+.It Bq Er EINVAL
+The
+.Fa key
+value is invalid.
+.El
+.Pp
+.Sh SEE ALSO
+.Xr pthread_getspecific 3 ,
+.Xr pthread_key_create 3 ,
+.Xr pthread_key_delete 3
+.Sh STANDARDS
+.Fn pthread_setspecific
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libc_r/sys/Makefile.inc b/lib/libc_r/sys/Makefile.inc
new file mode 100644
index 0000000..16fd33d
--- /dev/null
+++ b/lib/libc_r/sys/Makefile.inc
@@ -0,0 +1,5 @@
+# $Id$
+
+.PATH: ${.CURDIR}/sys
+
+SRCS+= __error.c
diff --git a/lib/libc_r/sys/__error.c b/lib/libc_r/sys/__error.c
new file mode 100644
index 0000000..545dfb0
--- /dev/null
+++ b/lib/libc_r/sys/__error.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
+ * Copyright (c) 1994 by Chris Provenzano, proven@mit.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 John Birrell
+ * and Chris Provenzano.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+extern int errno;
+
+int * __error()
+{
+ int *p_errno;
+ if (_thread_run == _thread_initial) {
+ p_errno = &errno;
+ } else {
+ p_errno = &_thread_run->error;
+ }
+ return(p_errno);
+}
+#endif
diff --git a/lib/libc_r/uthread/Makefile.inc b/lib/libc_r/uthread/Makefile.inc
new file mode 100644
index 0000000..3fbc97b
--- /dev/null
+++ b/lib/libc_r/uthread/Makefile.inc
@@ -0,0 +1,93 @@
+# $Id: Makefile.inc,v 1.8 1997/02/22 15:05:31 peter Exp $
+
+# uthread sources
+.PATH: ${.CURDIR}/uthread
+
+SRCS+= \
+ uthread_accept.c \
+ uthread_attr_destroy.c \
+ uthread_attr_init.c \
+ uthread_attr_getdetachstate.c \
+ uthread_attr_getstackaddr.c \
+ uthread_attr_getstacksize.c \
+ uthread_attr_setcreatesuspend_np.c \
+ uthread_attr_setdetachstate.c \
+ uthread_attr_setstackaddr.c \
+ uthread_attr_setstacksize.c \
+ uthread_autoinit.cc \
+ uthread_bind.c \
+ uthread_clean.c \
+ uthread_close.c \
+ uthread_cond.c \
+ uthread_condattr_destroy.c \
+ uthread_condattr_init.c \
+ uthread_connect.c \
+ uthread_create.c \
+ uthread_detach.c \
+ uthread_dup.c \
+ uthread_dup2.c \
+ uthread_equal.c \
+ uthread_execve.c \
+ uthread_exit.c \
+ uthread_fchmod.c \
+ uthread_fchown.c \
+ uthread_fcntl.c \
+ uthread_fd.c \
+ uthread_file.c \
+ uthread_flock.c \
+ uthread_fork.c \
+ uthread_fstat.c \
+ uthread_fstatfs.c \
+ uthread_fsync.c \
+ uthread_getdirentries.c \
+ uthread_getpeername.c \
+ uthread_getprio.c \
+ uthread_getsockname.c \
+ uthread_getsockopt.c \
+ uthread_info.c \
+ uthread_init.c \
+ uthread_ioctl.c \
+ uthread_join.c \
+ uthread_kern.c \
+ uthread_kill.c \
+ uthread_listen.c \
+ uthread_longjmp.c \
+ uthread_mattr_init.c \
+ uthread_mattr_kind_np.c \
+ uthread_multi_np.c \
+ uthread_mutex.c \
+ uthread_mutexattr_destroy.c \
+ uthread_nanosleep.c \
+ uthread_once.c \
+ uthread_open.c \
+ uthread_pipe.c \
+ uthread_queue.c \
+ uthread_read.c \
+ uthread_readv.c \
+ uthread_recvfrom.c \
+ uthread_resume_np.c \
+ uthread_select.c \
+ uthread_self.c \
+ uthread_sendto.c \
+ uthread_seterrno.c \
+ uthread_setjmp.c \
+ uthread_setprio.c \
+ uthread_setsockopt.c \
+ uthread_shutdown.c \
+ uthread_sig.c \
+ uthread_sigaction.c \
+ uthread_sigblock.c \
+ uthread_single_np.c \
+ uthread_sigmask.c \
+ uthread_signal.c \
+ uthread_sigprocmask.c \
+ uthread_sigsetmask.c \
+ uthread_sigsuspend.c \
+ uthread_socket.c \
+ uthread_socketpair.c \
+ uthread_spec.c \
+ uthread_suspend_np.c \
+ uthread_wait4.c \
+ uthread_write.c \
+ uthread_writev.c \
+ uthread_yield.c
diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h
new file mode 100644
index 0000000..e0a0511
--- /dev/null
+++ b/lib/libc_r/uthread/pthread_private.h
@@ -0,0 +1,783 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * Private thread definitions for the uthread kernel.
+ *
+ */
+
+#ifndef _PTHREAD_PRIVATE_H
+#define _PTHREAD_PRIVATE_H
+
+/*
+ * Evaluate the storage class specifier.
+ */
+#ifdef GLOBAL_PTHREAD_PRIVATE
+#define SCLASS
+#else
+#define SCLASS extern
+#endif
+
+/*
+ * Include files.
+ */
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+/*
+ * Kernel fatal error handler macro.
+ */
+#define PANIC(string) _thread_exit(__FILE__,__LINE__,string)
+
+/*
+ * State change macro:
+ */
+#define PTHREAD_NEW_STATE(thrd, newstate) { \
+ (thrd)->state = newstate; \
+ (thrd)->fname = __FILE__; \
+ (thrd)->lineno = __LINE__; \
+}
+
+/*
+ * Queue definitions.
+ */
+struct pthread_queue {
+ struct pthread *q_next;
+ struct pthread *q_last;
+ void *q_data;
+};
+
+/*
+ * Static queue initialization values.
+ */
+#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL }
+
+/*
+ * Mutex definitions.
+ */
+union pthread_mutex_data {
+ void *m_ptr;
+ int m_count;
+};
+
+struct pthread_mutex {
+ enum pthread_mutextype m_type;
+ struct pthread_queue m_queue;
+ struct pthread *m_owner;
+ union pthread_mutex_data m_data;
+ long m_flags;
+};
+
+/*
+ * Flags for mutexes.
+ */
+#define MUTEX_FLAGS_PRIVATE 0x01
+#define MUTEX_FLAGS_INITED 0x02
+#define MUTEX_FLAGS_BUSY 0x04
+
+/*
+ * Static mutex initialization values.
+ */
+#define PTHREAD_MUTEX_INITIALIZER \
+ { MUTEX_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, \
+ NULL, { NULL }, MUTEX_FLAGS_INITED }
+
+struct pthread_mutex_attr {
+ enum pthread_mutextype m_type;
+ long m_flags;
+};
+
+/*
+ * Condition variable definitions.
+ */
+enum pthread_cond_type {
+ COND_TYPE_FAST,
+ COND_TYPE_MAX
+};
+
+struct pthread_cond {
+ enum pthread_cond_type c_type;
+ struct pthread_queue c_queue;
+ void *c_data;
+ long c_flags;
+};
+
+struct pthread_cond_attr {
+ enum pthread_cond_type c_type;
+ long c_flags;
+};
+
+/*
+ * Flags for condition variables.
+ */
+#define COND_FLAGS_PRIVATE 0x01
+#define COND_FLAGS_INITED 0x02
+#define COND_FLAGS_BUSY 0x04
+
+/*
+ * Static cond initialization values.
+ */
+#define PTHREAD_COND_INITIALIZER \
+ { COND_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, NULL, COND_FLAGS_INITED }
+
+/*
+ * Cleanup definitions.
+ */
+struct pthread_cleanup {
+ struct pthread_cleanup *next;
+ void (*routine) ();
+ void *routine_arg;
+};
+
+/*
+ * Scheduling definitions.
+ */
+enum schedparam_policy {
+ SCHED_RR,
+ SCHED_IO,
+ SCHED_FIFO,
+ SCHED_OTHER
+};
+
+struct pthread_attr {
+ enum schedparam_policy schedparam_policy;
+ int prio;
+ int suspend;
+ int flags;
+ void *arg_attr;
+ void (*cleanup_attr) ();
+ void *stackaddr_attr;
+ size_t stacksize_attr;
+};
+
+struct sched_param {
+ int prio;
+ void *no_data;
+};
+
+/*
+ * Thread creation state attributes.
+ */
+#define PTHREAD_CREATE_RUNNING 0
+#define PTHREAD_CREATE_SUSPENDED 1
+
+/*
+ * Miscellaneous definitions.
+ */
+#define PTHREAD_STACK_DEFAULT 65536
+#define PTHREAD_DEFAULT_PRIORITY 64
+#define PTHREAD_MAX_PRIORITY 126
+#define PTHREAD_MIN_PRIORITY 0
+#define _POSIX_THREAD_ATTR_STACKSIZE
+
+/*
+ * Clock resolution in nanoseconds.
+ */
+#define CLOCK_RES_NSEC 10000000
+
+/*
+ * Number of microseconds between incremental priority updates for
+ * threads that are ready to run, but denied being run.
+ */
+#define INC_PRIO_USEC 500000
+
+/*
+ * Time slice period in microseconds.
+ */
+#define TIMESLICE_USEC 100000
+
+struct pthread_key {
+ pthread_mutex_t mutex;
+ long count;
+ void (*destructor) ();
+};
+
+/*
+ * Thread states.
+ */
+enum pthread_state {
+ PS_RUNNING,
+ PS_SIGTHREAD,
+ PS_MUTEX_WAIT,
+ PS_COND_WAIT,
+ PS_FDLR_WAIT,
+ PS_FDLW_WAIT,
+ PS_FDR_WAIT,
+ PS_FDW_WAIT,
+ PS_SELECT_WAIT,
+ PS_SLEEP_WAIT,
+ PS_WAIT_WAIT,
+ PS_SIGWAIT,
+ PS_JOIN,
+ PS_SUSPENDED,
+ PS_DEAD,
+ PS_STATE_MAX
+};
+
+
+/*
+ * File descriptor locking definitions.
+ */
+#define FD_READ 0x1
+#define FD_WRITE 0x2
+#define FD_RDWR (FD_READ | FD_WRITE)
+
+/*
+ * File descriptor table structure.
+ */
+struct fd_table_entry {
+ struct pthread_queue r_queue; /* Read queue. */
+ struct pthread_queue w_queue; /* Write queue. */
+ struct pthread *r_owner; /* Ptr to thread owning read lock. */
+ struct pthread *w_owner; /* Ptr to thread owning write lock. */
+ char *r_fname; /* Ptr to read lock source file name */
+ int r_lineno; /* Read lock source line number. */
+ char *w_fname; /* Ptr to write lock source file name */
+ int w_lineno; /* Write lock source line number. */
+ int r_lockcount; /* Count for FILE read locks. */
+ int w_lockcount; /* Count for FILE write locks. */
+ int flags; /* Flags used in open. */
+};
+
+struct pthread_select_data {
+ int nfds;
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+};
+
+union pthread_wait_data {
+ pthread_mutex_t *mutex;
+ pthread_cond_t *cond;
+ const sigset_t *sigwait; /* Waiting on a signal in sigwait */
+ struct {
+ short fd; /* Used when thread waiting on fd */
+ short branch; /* Line number, for debugging. */
+ char *fname; /* Source file name for debugging.*/
+ } fd;
+ struct pthread_select_data * select_data;
+};
+
+/*
+ * Thread structure.
+ */
+struct pthread {
+ /*
+ * Pointer to the next thread in the thread linked list.
+ */
+ struct pthread *nxt;
+
+ /*
+ * Thread start routine, argument, stack pointer and thread
+ * attributes.
+ */
+ void *(*start_routine)(void *);
+ void *arg;
+ void *stack;
+ struct pthread_attr attr;
+
+ /*
+ * Thread-specific signal handler interface:
+ *
+ * Array of signal actions for this thread.
+ */
+ struct sigaction act[NSIG];
+
+#if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(__i386__)
+ /*
+ * Saved floating point registers on systems where they are not
+ * saved in the signal context.
+ */
+ char saved_fp[108];
+#endif
+
+ /*
+ * Saved signal context used in call to sigreturn by
+ * _thread_kern_sched if sig_saved is TRUE.
+ */
+ struct sigcontext saved_sigcontext;
+
+ /*
+ * Saved jump buffer used in call to longjmp by _thread_kern_sched
+ * if sig_saved is FALSE.
+ */
+ jmp_buf saved_jmp_buf;
+
+ /*
+ * TRUE if the last state saved was a signal context. FALSE if the
+ * last state saved was a jump buffer.
+ */
+ int sig_saved;
+
+ /*
+ * Current signal mask and array of pending signals.
+ */
+ sigset_t sigmask;
+ int sigpend[NSIG];
+
+ /*
+ * Pointer to the parent thread for which the current thread is
+ * a signal handler thread, otherwise NULL if the current thread
+ * is not a signal handler thread.
+ */
+ struct pthread *parent_thread;
+
+ /* Thread state: */
+ enum pthread_state state;
+
+ /* Time that this thread was last made active. */
+ struct timeval last_active;
+
+ /* Time that this thread was last made inactive. */
+ struct timeval last_inactive;
+
+ /*
+ * Number of microseconds accumulated by this thread when
+ * time slicing is active.
+ */
+ long slice_usec;
+
+ /*
+ * Incremental priority accumulated by thread while it is ready to
+ * run but is denied being run.
+ */
+ int inc_prio;
+
+ /*
+ * Time to wake up thread. This is used for sleeping threads and
+ * for any operation which may time out (such as select).
+ */
+ struct timespec wakeup_time;
+
+ /* TRUE if operation has timed out. */
+ int timeout;
+
+ /*
+ * Error variable used instead of errno. The function __error()
+ * returns a pointer to this.
+ */
+ int error;
+
+ /* Join queue for waiting threads: */
+ struct pthread_queue join_queue;
+
+ /*
+ * The current thread can belong to only one queue at a time.
+ *
+ * Pointer to queue (if any) on which the current thread is waiting.
+ */
+ struct pthread_queue *queue;
+
+ /* Pointer to next element in queue. */
+ struct pthread *qnxt;
+
+ /* Wait data. */
+ union pthread_wait_data data;
+
+ /*
+ * Set to TRUE if a blocking operation was
+ * interrupted by a signal:
+ */
+ int interrupted;
+
+ /* Signal number when in state PS_SIGWAIT: */
+ int signo;
+
+ /* Miscellaneous data. */
+ char flags;
+ char pthread_priority;
+ void *ret;
+ const void **specific_data;
+ int specific_data_count;
+
+ /* Cleanup handlers Link List */
+ struct pthread_cleanup *cleanup;
+ char *fname; /* Ptr to source file name */
+ int lineno; /* Source line number. */
+};
+
+/*
+ * Global variables for the uthread kernel.
+ */
+
+/* Kernel thread structure used when there are no running threads: */
+SCLASS struct pthread _thread_kern_thread;
+
+/* Ptr to the thread structure for the running thread: */
+SCLASS struct pthread * volatile _thread_run
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= &_thread_kern_thread;
+#else
+;
+#endif
+
+/*
+ * Ptr to the thread running in single-threaded mode or NULL if
+ * running multi-threaded (default POSIX behaviour).
+ */
+SCLASS struct pthread * volatile _thread_single
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/* Ptr to the first thread in the thread linked list: */
+SCLASS struct pthread * volatile _thread_link_list
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/*
+ * Array of kernel pipe file descriptors that are used to ensure that
+ * no signals are missed in calls to _thread_sys_select.
+ */
+SCLASS int _thread_kern_pipe[2]
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= {
+ -1,
+ -1
+};
+#else
+;
+#endif
+SCLASS int _thread_kern_in_select
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 0;
+#else
+;
+#endif
+
+/* Last time that an incremental priority update was performed: */
+SCLASS struct timeval kern_inc_prio_time
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { 0, 0 };
+#else
+;
+#endif
+
+/* Dead threads: */
+SCLASS struct pthread * volatile _thread_dead
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/* Initial thread: */
+SCLASS struct pthread *_thread_initial
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/* Default thread attributes: */
+SCLASS struct pthread_attr pthread_attr_default
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { SCHED_RR, PTHREAD_DEFAULT_PRIORITY, PTHREAD_CREATE_RUNNING,
+ PTHREAD_CREATE_JOINABLE, NULL, NULL, NULL, PTHREAD_STACK_DEFAULT };
+#else
+;
+#endif
+
+/* Default mutex attributes: */
+SCLASS struct pthread_mutex_attr pthread_mutexattr_default
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { MUTEX_TYPE_FAST, 0 };
+#else
+;
+#endif
+
+/* Default condition variable attributes: */
+SCLASS struct pthread_cond_attr pthread_condattr_default
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { COND_TYPE_FAST, 0 };
+#else
+;
+#endif
+
+/*
+ * Standard I/O file descriptors need special flag treatment since
+ * setting one to non-blocking does all on *BSD. Sigh. This array
+ * is used to store the initial flag settings.
+ */
+SCLASS int _pthread_stdio_flags[3];
+
+/* File table information: */
+SCLASS struct fd_table_entry **_thread_fd_table
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+SCLASS const int dtablecount
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 4096/sizeof(struct fd_table_entry);
+#else
+;
+#endif
+SCLASS int _thread_dtablesize /* Descriptor table size. */
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 1024;
+#else
+;
+#endif
+
+/* Undefine the storage class specifier: */
+#undef SCLASS
+
+/*
+ * Function prototype definitions.
+ */
+__BEGIN_DECLS
+char *__ttyname_basic(int);
+char *__ttyname_r_basic(int, char *, size_t);
+char *ttyname_r(int, char *, size_t);
+int _thread_create(pthread_t *,const pthread_attr_t *,void *(*start_routine)(void *),void *,pthread_t);
+int _thread_fd_lock(int, int, struct timespec *,char *fname,int lineno);
+void _thread_exit(char *, int, char *);
+void _thread_fd_unlock(int, int);
+void *_thread_cleanup(pthread_t);
+void _thread_cleanupspecific(void);
+void _thread_dump_info(void);
+void _thread_init(void);
+void _thread_kern_sched(struct sigcontext *);
+void _thread_kern_sched_state(enum pthread_state,char *fname,int lineno);
+void _thread_kern_set_timeout(struct timespec *);
+void _thread_kern_sig_block(int *);
+void _thread_kern_sig_unblock(int);
+void _thread_sig_handler(int, int, struct sigcontext *);
+void _thread_start(void);
+void _thread_start_sig_handler(void);
+void _thread_seterrno(pthread_t,int);
+void _thread_queue_init(struct pthread_queue *);
+void _thread_queue_enq(struct pthread_queue *, struct pthread *);
+int _thread_queue_remove(struct pthread_queue *, struct pthread *);
+int _thread_fd_table_init(int fd);
+struct pthread *_thread_queue_get(struct pthread_queue *);
+struct pthread *_thread_queue_deq(struct pthread_queue *);
+
+/* #include <signal.h> */
+int _thread_sys_sigaction(int, const struct sigaction *, struct sigaction *);
+int _thread_sys_sigpending(sigset_t *);
+int _thread_sys_sigprocmask(int, const sigset_t *, sigset_t *);
+int _thread_sys_sigsuspend(const sigset_t *);
+int _thread_sys_sigblock(int);
+int _thread_sys_siginterrupt(int, int);
+int _thread_sys_sigpause(int);
+int _thread_sys_sigreturn(struct sigcontext *);
+int _thread_sys_sigsetmask(int);
+int _thread_sys_sigstack(const struct sigstack *, struct sigstack *);
+int _thread_sys_sigvec(int, struct sigvec *, struct sigvec *);
+void _thread_sys_psignal(unsigned int, const char *);
+void (*_thread_sys_signal(int, void (*)(int)))(int);
+
+/* #include <sys/stat.h> */
+#ifdef _SYS_STAT_H_
+int _thread_sys_fchmod(int, mode_t);
+int _thread_sys_fstat(int, struct stat *);
+int _thread_sys_fchflags(int, u_long);
+#endif
+
+/* #include <sys/mount.h> */
+#ifdef _SYS_MOUNT_H_
+int _thread_sys_fstatfs(int, struct statfs *);
+#endif
+int _thread_sys_pipe(int *);
+
+/* #include <sys/socket.h> */
+#ifdef _SYS_SOCKET_H_
+int _thread_sys_accept(int, struct sockaddr *, int *);
+int _thread_sys_bind(int, const struct sockaddr *, int);
+int _thread_sys_connect(int, const struct sockaddr *, int);
+int _thread_sys_getpeername(int, struct sockaddr *, int *);
+int _thread_sys_getsockname(int, struct sockaddr *, int *);
+int _thread_sys_getsockopt(int, int, int, void *, int *);
+int _thread_sys_listen(int, int);
+int _thread_sys_setsockopt(int, int, int, const void *, int);
+int _thread_sys_shutdown(int, int);
+int _thread_sys_socket(int, int, int);
+int _thread_sys_socketpair(int, int, int, int *);
+ssize_t _thread_sys_recv(int, void *, size_t, int);
+ssize_t _thread_sys_recvfrom(int, void *, size_t, int, struct sockaddr *, int *);
+ssize_t _thread_sys_recvmsg(int, struct msghdr *, int);
+ssize_t _thread_sys_send(int, const void *, size_t, int);
+ssize_t _thread_sys_sendmsg(int, const struct msghdr *, int);
+ssize_t _thread_sys_sendto(int, const void *,size_t, int, const struct sockaddr *, int);
+#endif
+
+/* #include <stdio.h> */
+#ifdef _STDIO_H_
+void _thread_flockfile(FILE *fp,char *fname,int lineno);
+void _thread_funlockfile(FILE *fp);
+FILE *_thread_sys_fdopen(int, const char *);
+FILE *_thread_sys_fopen(const char *, const char *);
+FILE *_thread_sys_freopen(const char *, const char *, FILE *);
+FILE *_thread_sys_popen(const char *, const char *);
+FILE *_thread_sys_tmpfile(void);
+char *_thread_sys_ctermid(char *);
+char *_thread_sys_cuserid(char *);
+char *_thread_sys_fgetln(FILE *, size_t *);
+char *_thread_sys_fgets(char *, int, FILE *);
+char *_thread_sys_gets(char *);
+char *_thread_sys_tempnam(const char *, const char *);
+char *_thread_sys_tmpnam(char *);
+int _thread_sys_fclose(FILE *);
+int _thread_sys_feof(FILE *);
+int _thread_sys_ferror(FILE *);
+int _thread_sys_fflush(FILE *);
+int _thread_sys_fgetc(FILE *);
+int _thread_sys_fgetpos(FILE *, fpos_t *);
+int _thread_sys_fileno(FILE *);
+int _thread_sys_fprintf(FILE *, const char *, ...);
+int _thread_sys_fpurge(FILE *);
+int _thread_sys_fputc(int, FILE *);
+int _thread_sys_fputs(const char *, FILE *);
+int _thread_sys_fscanf(FILE *, const char *, ...);
+int _thread_sys_fseek(FILE *, long, int);
+int _thread_sys_fsetpos(FILE *, const fpos_t *);
+int _thread_sys_getc(FILE *);
+int _thread_sys_getchar(void);
+int _thread_sys_getw(FILE *);
+int _thread_sys_pclose(FILE *);
+int _thread_sys_printf(const char *, ...);
+int _thread_sys_putc(int, FILE *);
+int _thread_sys_putchar(int);
+int _thread_sys_puts(const char *);
+int _thread_sys_putw(int, FILE *);
+int _thread_sys_remove(const char *);
+int _thread_sys_rename (const char *, const char *);
+int _thread_sys_scanf(const char *, ...);
+int _thread_sys_setlinebuf(FILE *);
+int _thread_sys_setvbuf(FILE *, char *, int, size_t);
+int _thread_sys_snprintf(char *, size_t, const char *, ...);
+int _thread_sys_sprintf(char *, const char *, ...);
+int _thread_sys_sscanf(const char *, const char *, ...);
+int _thread_sys_ungetc(int, FILE *);
+int _thread_sys_vfprintf(FILE *, const char *, _BSD_VA_LIST_);
+int _thread_sys_vprintf(const char *, _BSD_VA_LIST_);
+int _thread_sys_vscanf(const char *, _BSD_VA_LIST_);
+int _thread_sys_vsnprintf(char *, size_t, const char *, _BSD_VA_LIST_);
+int _thread_sys_vsprintf(char *, const char *, _BSD_VA_LIST_);
+int _thread_sys_vsscanf(const char *, const char *, _BSD_VA_LIST_);
+long _thread_sys_ftell(FILE *);
+size_t _thread_sys_fread(void *, size_t, size_t, FILE *);
+size_t _thread_sys_fwrite(const void *, size_t, size_t, FILE *);
+void _thread_sys_clearerr(FILE *);
+void _thread_sys_perror(const char *);
+void _thread_sys_rewind(FILE *);
+void _thread_sys_setbuf(FILE *, char *);
+void _thread_sys_setbuffer(FILE *, char *, int);
+#endif
+
+/* #include <unistd.h> */
+#ifdef _UNISTD_H_
+char *_thread_sys_ttyname(int);
+int _thread_sys_close(int);
+int _thread_sys_dup(int);
+int _thread_sys_dup2(int, int);
+int _thread_sys_exect(const char *, char * const *, char * const *);
+int _thread_sys_execve(const char *, char * const *, char * const *);
+int _thread_sys_fchdir(int);
+int _thread_sys_fchown(int, uid_t, gid_t);
+int _thread_sys_fsync(int);
+int _thread_sys_ftruncate(int, off_t);
+int _thread_sys_pause(void);
+int _thread_sys_pipe(int *);
+int _thread_sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+off_t _thread_sys_lseek(int, off_t, int);
+pid_t _thread_sys_fork(void);
+pid_t _thread_sys_tcgetpgrp(int);
+ssize_t _thread_sys_read(int, void *, size_t);
+ssize_t _thread_sys_write(int, const void *, size_t);
+void _thread_sys__exit(int);
+#endif
+
+/* #include <fcntl.h> */
+#ifdef _SYS_FCNTL_H_
+int _thread_sys_creat(const char *, mode_t);
+int _thread_sys_fcntl(int, int, ...);
+int _thread_sys_flock(int, int);
+int _thread_sys_open(const char *, int, ...);
+#endif
+
+/* #include <setjmp.h> */
+#ifdef _SETJMP_H_
+int __thread_sys_setjmp(jmp_buf);
+int _thread_sys_setjmp(jmp_buf);
+int _thread_sys_sigsetjmp(sigjmp_buf, int);
+void __thread_sys_longjmp(jmp_buf, int);
+void _thread_sys_longjmp(jmp_buf, int);
+void _thread_sys_longjmperror(void);
+void _thread_sys_siglongjmp(sigjmp_buf, int);
+#endif
+
+/* #include <sys/ioctl.h> */
+#ifdef _SYS_IOCTL_H_
+int _thread_sys_ioctl(int, unsigned long, ...);
+#endif
+
+/* #include <dirent.h> */
+#ifdef _DIRENT_H_
+DIR *___thread_sys_opendir2(const char *, int);
+DIR *_thread_sys_opendir(const char *);
+int _thread_sys_alphasort(const void *, const void *);
+int _thread_sys_scandir(const char *, struct dirent ***,
+ int (*)(struct dirent *), int (*)(const void *, const void *));
+int _thread_sys_closedir(DIR *);
+int _thread_sys_getdirentries(int, char *, int, long *);
+long _thread_sys_telldir(const DIR *);
+struct dirent *_thread_sys_readdir(DIR *);
+void _thread_sys_rewinddir(DIR *);
+void _thread_sys_seekdir(DIR *, long);
+#endif
+
+/* #include <sys/uio.h> */
+#ifdef _SYS_UIO_H_
+ssize_t _thread_sys_readv(int, const struct iovec *, int);
+ssize_t _thread_sys_writev(int, const struct iovec *, int);
+#endif
+
+/* #include <sys/wait.h> */
+#ifdef WNOHANG
+pid_t _thread_sys_wait(int *);
+pid_t _thread_sys_waitpid(pid_t, int *, int);
+pid_t _thread_sys_wait3(int *, int, struct rusage *);
+pid_t _thread_sys_wait4(pid_t, int *, int, struct rusage *);
+#endif
+__END_DECLS
+
+#endif /* !_PTHREAD_PRIVATE_H */
diff --git a/lib/libc_r/uthread/uthread_accept.c b/lib/libc_r/uthread/uthread_accept.c
new file mode 100644
index 0000000..e240cde
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_accept.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+accept(int fd, struct sockaddr * name, int *namelen)
+{
+ int ret;
+
+ /* Lock the file descriptor: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Enter a loop to wait for a connection request: */
+ while ((ret = _thread_sys_accept(fd, name, namelen)) < 0) {
+ /* Check if the socket is to block: */
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ /* Save the socket file descriptor: */
+ _thread_run->data.fd.fd = fd;
+ _thread_run->data.fd.fname = __FILE__;
+ _thread_run->data.fd.branch = __LINE__;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(NULL);
+
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
+
+ /* Check if the wait was interrupted: */
+ if (errno == EINTR) {
+ /* Return an error status: */
+ ret = -1;
+ break;
+ }
+ } else {
+ /*
+ * Another error has occurred, so exit the
+ * loop here:
+ */
+ break;
+ }
+ }
+
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_RDWR);
+
+ /* Check for errors: */
+ if (ret < 0) {
+ }
+ /* Initialise the file descriptor table for the new socket: */
+ else if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the socket: */
+ _thread_sys_close(ret);
+
+ /* Return an error: */
+ ret = -1;
+ }
+ }
+ /* Return the socket file descriptor or -1 on error: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_attr_destroy.c b/lib/libc_r/uthread/uthread_attr_destroy.c
new file mode 100644
index 0000000..1f4b2c8
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_destroy.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_destroy(pthread_attr_t *attr)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL)
+ /* Invalid argument: */
+ ret = EINVAL;
+ else {
+ /* Free the memory allocated to the attribute object: */
+ free(*attr);
+
+ /*
+ * Leave the attribute pointer NULL now that the memory
+ * has been freed:
+ */
+ *attr = NULL;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_attr_getdetachstate.c b/lib/libc_r/uthread/uthread_attr_getdetachstate.c
new file mode 100644
index 0000000..4715cb6
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_getdetachstate.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || detachstate == NULL)
+ ret = EINVAL;
+ else {
+ /* Check if the detached flag is set: */
+ if ((*attr)->flags & PTHREAD_DETACHED)
+ /* Return detached: */
+ *detachstate = PTHREAD_CREATE_DETACHED;
+ else
+ /* Return joinable: */
+ *detachstate = PTHREAD_CREATE_JOINABLE;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_attr_getstackaddr.c b/lib/libc_r/uthread/uthread_attr_getstackaddr.c
new file mode 100644
index 0000000..1850a32
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_getstackaddr.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stackaddr)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stackaddr == NULL)
+ ret = EINVAL;
+ else {
+ /* Return the stack address: */
+ *stackaddr = (*attr)->stackaddr_attr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_attr_getstacksize.c b/lib/libc_r/uthread/uthread_attr_getstacksize.c
new file mode 100644
index 0000000..de81106
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_getstacksize.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stacksize == NULL)
+ ret = EINVAL;
+ else {
+ /* Return the stack size: */
+ *stacksize = (*attr)->stacksize_attr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_attr_init.c b/lib/libc_r/uthread/uthread_attr_init.c
new file mode 100644
index 0000000..c64e29f
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_init.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_init(pthread_attr_t *attr)
+{
+ int ret;
+ pthread_attr_t pattr;
+
+ /* Allocate memory for the attribute object: */
+ if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL)
+ /* Insufficient memory: */
+ ret = ENOMEM;
+ else {
+ /* Initialise the attribute object with the defaults: */
+ memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr));
+
+ /* Return a pointer to the attribute object: */
+ *attr = pattr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_attr_setcreatesuspend.c b/lib/libc_r/uthread/uthread_attr_setcreatesuspend.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_setcreatesuspend.c
diff --git a/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c b/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c
new file mode 100644
index 0000000..afe6b23
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ (*attr)->suspend = PTHREAD_CREATE_SUSPENDED;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_attr_setdetachstate.c b/lib/libc_r/uthread/uthread_attr_setdetachstate.c
new file mode 100644
index 0000000..6ec0dbc
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_setdetachstate.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL ||
+ (detachstate != PTHREAD_CREATE_DETACHED &&
+ detachstate != PTHREAD_CREATE_JOINABLE))
+ ret = EINVAL;
+ else {
+ /* Check if detached state: */
+ if (detachstate == PTHREAD_CREATE_DETACHED)
+ /* Set the detached flag: */
+ (*attr)->flags |= PTHREAD_DETACHED;
+ else
+ /* Reset the detached flag: */
+ (*attr)->flags &= ~PTHREAD_DETACHED;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_attr_setprio.c b/lib/libc_r/uthread/uthread_attr_setprio.c
new file mode 100644
index 0000000..f6d54fc
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_setprio.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_setprio(pthread_attr_t *attr, int priority)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ (*attr)->prio = priority;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_attr_setstackaddr.c b/lib/libc_r/uthread/uthread_attr_setstackaddr.c
new file mode 100644
index 0000000..ce54915
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_setstackaddr.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stackaddr == NULL)
+ ret = EINVAL;
+ else {
+ /* Save the stack address: */
+ (*attr)->stackaddr_attr = stackaddr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_attr_setstacksize.c b/lib/libc_r/uthread/uthread_attr_setstacksize.c
new file mode 100644
index 0000000..94e575e
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_setstacksize.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN)
+ ret = EINVAL;
+ else {
+ /* Save the stack size: */
+ (*attr)->stacksize_attr = stacksize;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_autoinit.cc b/lib/libc_r/uthread/uthread_autoinit.cc
new file mode 100644
index 0000000..1cebd75
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_autoinit.cc
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+
+/*
+ * This module uses the magic of C++ static constructors to initialize the
+ * threads package at program start-up time.
+ *
+ * Note: Because of a bug in certain versions of "/usr/lib/c++rt0.o", you
+ * should _not_ enclose the body of this module in an "#ifdef _THREAD_SAFE"
+ * conditional.
+ */
+
+extern "C" void _thread_init(void);
+
+/*
+ * First, we declare a class with a constructor.
+ */
+class _thread_init_invoker {
+public:
+ _thread_init_invoker(); /* Constructor declaration. */
+};
+
+/*
+ * Here is the definition of the constructor. All it does is call the
+ * threads initialization function, "_thread_init".
+ */
+_thread_init_invoker::_thread_init_invoker()
+{
+ _thread_init();
+}
+
+/*
+ * Here is a single, static instance of our "_thread_init_invoker" class.
+ * The mere existance of this instance will result in its constructor
+ * being called, automatically, at program start-up time.
+ */
+static _thread_init_invoker the_thread_init_invoker;
+
+/*
+ * For the shared version of the threads library, the above is sufficient.
+ * But for the archive version of the library, we need a little bit more.
+ * Namely, we must arrange for this particular module to be pulled in from
+ * the archive library at link time. To accomplish that, we define and
+ * initialize a variable, "_thread_autoinit_dummy_decl". This variable is
+ * referenced (as an extern) from the module "uthread_init.c". So, if
+ * that module is used, then it will create a need for this module as well,
+ * ensuring that this module will be present in the executable.
+ *
+ * We know that, if the user does _anything_ at all with threads, then the
+ * "uthread_init.c" module will be linked in. That is the case because
+ * "uthread_init.c" is the module that defines all of the global variables
+ * used by the threads library. The presence of "uthread_init.c" will, in
+ * turn, force this module to be linked in. And the presence of this module
+ * in the executable will result in the constructor being invoked, and
+ * "_thread_init" being called.
+ */
+extern "C" int _thread_autoinit_dummy_decl; /* Declare with "C" linkage */
+int _thread_autoinit_dummy_decl = 0;
diff --git a/lib/libc_r/uthread/uthread_bind.c b/lib/libc_r/uthread/uthread_bind.c
new file mode 100644
index 0000000..1f7bbec
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_bind.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+bind(int fd, const struct sockaddr * name, int namelen)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_bind(fd, name, namelen);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_clean.c b/lib/libc_r/uthread/uthread_clean.c
new file mode 100644
index 0000000..9319f85
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_clean.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+pthread_cleanup_push(void (*routine) (void *), void *routine_arg)
+{
+ struct pthread_cleanup *new;
+
+ if ((new = (struct pthread_cleanup *) malloc(sizeof(struct pthread_cleanup))) != NULL) {
+ new->routine = routine;
+ new->routine_arg = routine_arg;
+ new->next = _thread_run->cleanup;
+
+ _thread_run->cleanup = new;
+ }
+}
+
+void
+pthread_cleanup_pop(int execute)
+{
+ struct pthread_cleanup *old;
+
+ if ((old = _thread_run->cleanup) != NULL) {
+ _thread_run->cleanup = old->next;
+ if (execute) {
+ old->routine(old->routine_arg);
+ }
+ free(old);
+ }
+}
+
+#endif
diff --git a/lib/libc_r/uthread/uthread_close.c b/lib/libc_r/uthread/uthread_close.c
new file mode 100644
index 0000000..26a8fbf
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_close.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+close(int fd)
+{
+ int flags;
+ int ret;
+ int status;
+ struct stat sb;
+
+ /* Lock the file descriptor while the file is closed: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Get file descriptor status. */
+ fstat(fd, &sb);
+
+ /*
+ * Check if the file should be left as blocking.
+ *
+ * This is so that the file descriptors shared with a parent
+ * process aren't left set to non-blocking if the child
+ * closes them prior to exit. An example where this causes
+ * problems with /bin/sh is when a child closes stdin.
+ *
+ * Setting a file as blocking causes problems if a threaded
+ * parent accesses the file descriptor before the child exits.
+ * Once the threaded parent receives a SIGCHLD then it resets
+ * all of its files to non-blocking, and so it is then safe
+ * to access them.
+ *
+ * Pipes are not set to blocking when they are closed, as
+ * the parent and child will normally close the file
+ * descriptor of the end of the pipe that they are not
+ * using, which would then cause any reads to block
+ * indefinitely.
+ */
+ if ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) && (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0) {
+ /* Get the current flags: */
+ flags = _thread_sys_fcntl(fd, F_GETFL, NULL);
+ /* Clear the nonblocking file descriptor flag: */
+ _thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+ }
+
+ /* Close the file descriptor: */
+ ret = _thread_sys_close(fd);
+
+ /* Free the file descriptor table entry: */
+ free(_thread_fd_table[fd]);
+ _thread_fd_table[fd] = NULL;
+
+ /* Unblock signals again: */
+ _thread_kern_sig_unblock(status);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_cond.c b/lib/libc_r/uthread/uthread_cond.c
new file mode 100644
index 0000000..09ebb4e
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_cond.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * cond_attr)
+{
+ enum pthread_cond_type type;
+ pthread_cond_t pcond;
+ int rval = 0;
+
+ if (cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /*
+ * Check if a pointer to a condition variable attribute
+ * structure was passed by the caller:
+ */
+ if (cond_attr != NULL && *cond_attr != NULL) {
+ /* Default to a fast condition variable: */
+ type = (*cond_attr)->c_type;
+ } else {
+ /* Default to a fast condition variable: */
+ type = COND_TYPE_FAST;
+ }
+
+ /* Process according to condition variable type: */
+ switch (type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Check for no errors: */
+ if (rval == 0) {
+ if ((pcond = (pthread_cond_t)
+ malloc(sizeof(struct pthread_cond))) == NULL) {
+ errno = ENOMEM;
+ rval = -1;
+ } else {
+ /*
+ * Initialise the condition variable
+ * structure:
+ */
+ _thread_queue_init(&pcond->c_queue);
+ pcond->c_flags |= COND_FLAGS_INITED;
+ pcond->c_type = type;
+ *cond = pcond;
+ }
+ }
+ }
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_destroy(pthread_cond_t * cond)
+{
+ int rval = 0;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Check for errors: */
+ if (rval == 0) {
+ /* Destroy the contents of the condition structure: */
+ _thread_queue_init(&(*cond)->c_queue);
+ (*cond)->c_flags = 0;
+ free(*cond);
+ *cond = NULL;
+ }
+ }
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
+{
+ int rval = 0;
+ int status;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /*
+ * Queue the running thread for the condition
+ * variable:
+ */
+ _thread_queue_enq(&(*cond)->c_queue, _thread_run);
+
+ /* Unlock the mutex: */
+ pthread_mutex_unlock(mutex);
+
+ /* Wait forever: */
+ _thread_run->wakeup_time.tv_sec = -1;
+
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_COND_WAIT,
+ __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Lock the mutex: */
+ rval = pthread_mutex_lock(mutex);
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
+ const struct timespec * abstime)
+{
+ int rval = 0;
+ int status;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Set the wakeup time: */
+ _thread_run->wakeup_time.tv_sec = abstime->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = abstime->tv_nsec;
+
+ /* Reset the timeout flag: */
+ _thread_run->timeout = 0;
+
+ /*
+ * Queue the running thread for the condition
+ * variable:
+ */
+ _thread_queue_enq(&(*cond)->c_queue, _thread_run);
+
+ /* Unlock the mutex: */
+ if ((rval = pthread_mutex_unlock(mutex)) != 0) {
+ /*
+ * Cannot unlock the mutex, so remove the
+ * running thread from the condition
+ * variable queue:
+ */
+ _thread_queue_deq(&(*cond)->c_queue);
+ } else {
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_COND_WAIT,
+ __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Lock the mutex: */
+ if ((rval = pthread_mutex_lock(mutex)) != 0) {
+ }
+ /* Check if the wait timed out: */
+ else if (_thread_run->timeout) {
+ /* Return a timeout error: */
+ errno = EAGAIN;
+ rval = -1;
+ }
+ }
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_signal(pthread_cond_t * cond)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Bring the next thread off the condition queue: */
+ if ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
+ /* Allow the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_broadcast(pthread_cond_t * cond)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /*
+ * Enter a loop to bring all threads off the
+ * condition queue:
+ */
+ while ((pthread =
+ _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
+ /* Allow the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_condattr_destroy.c b/lib/libc_r/uthread/uthread_condattr_destroy.c
new file mode 100644
index 0000000..b20f183
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_condattr_destroy.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_condattr_destroy(pthread_condattr_t *attr)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ free(*attr);
+ *attr = NULL;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_condattr_init.c b/lib/libc_r/uthread/uthread_condattr_init.c
new file mode 100644
index 0000000..f94e438
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_condattr_init.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_condattr_init(pthread_condattr_t *attr)
+{
+ int ret;
+ pthread_condattr_t pattr;
+
+ if ((pattr = (pthread_condattr_t)
+ malloc(sizeof(struct pthread_cond_attr))) == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ memcpy(pattr, &pthread_condattr_default,
+ sizeof(struct pthread_cond_attr));
+ *attr = pattr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_connect.c b/lib/libc_r/uthread/uthread_connect.c
new file mode 100644
index 0000000..bf42db3
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_connect.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+connect(int fd, const struct sockaddr * name, int namelen)
+{
+ struct sockaddr tmpname;
+ int ret, tmpnamelen;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ if ((ret = _thread_sys_connect(fd, name, namelen)) < 0) {
+ if (!(_thread_fd_table[fd]->flags & O_NONBLOCK) &&
+ ((errno == EWOULDBLOCK) || (errno == EINPROGRESS) ||
+ (errno == EALREADY) || (errno == EAGAIN))) {
+ _thread_run->data.fd.fd = fd;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(NULL);
+ _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__);
+
+ tmpnamelen = sizeof(tmpname);
+ /* 0 now lets see if it really worked */
+ if (((ret = _thread_sys_getpeername(fd, &tmpname, &tmpnamelen)) < 0) && (errno == ENOTCONN)) {
+
+ /*
+ * Get the error, this function
+ * should not fail
+ */
+ _thread_sys_getsockopt(fd, SOL_SOCKET, SO_ERROR, &errno, &tmpnamelen);
+ }
+ } else {
+ ret = -1;
+ }
+ }
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_create.c b/lib/libc_r/uthread/uthread_create.c
new file mode 100644
index 0000000..e4925a9
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_create.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <machine/reg.h>
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+_thread_create(pthread_t * thread, const pthread_attr_t * attr,
+ void *(*start_routine) (void *), void *arg, pthread_t parent)
+{
+ int i;
+ int ret = 0;
+ int status;
+ pthread_t new_thread;
+ pthread_attr_t pattr;
+ void *stack;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Allocate memory for the thread structure: */
+ if ((new_thread = (pthread_t) malloc(sizeof(struct pthread))) == NULL) {
+ /* Insufficient memory to create a thread: */
+ ret = EAGAIN;
+ } else {
+ /* Check if default thread attributes are required: */
+ if (attr == NULL || *attr == NULL) {
+ /* Use the default thread attributes: */
+ pattr = &pthread_attr_default;
+ } else {
+ pattr = *attr;
+ }
+ /* Check if a stack was specified in the thread attributes: */
+ if ((stack = pattr->stackaddr_attr) != NULL) {
+ }
+ /* Allocate memory for the stack: */
+ else if ((stack = (void *) malloc(pattr->stacksize_attr)) == NULL) {
+ /* Insufficient memory to create a thread: */
+ ret = EAGAIN;
+ free(new_thread);
+ }
+ /* Check for errors: */
+ if (ret != 0) {
+ } else {
+ /* Initialise the thread structure: */
+ memset(new_thread, 0, sizeof(struct pthread));
+ new_thread->slice_usec = -1;
+ new_thread->sig_saved = 0;
+ new_thread->stack = stack;
+ new_thread->start_routine = start_routine;
+ new_thread->arg = arg;
+ if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) {
+ PTHREAD_NEW_STATE(new_thread,PS_SUSPENDED);
+ } else {
+ PTHREAD_NEW_STATE(new_thread,PS_RUNNING);
+ }
+
+ /* Initialise the thread for signals: */
+ new_thread->sigmask = _thread_run->sigmask;
+
+ /*
+ * Enter a loop to initialise the signal handler
+ * array:
+ */
+ for (i = 1; i < NSIG; i++) {
+ /* Default the signal handler: */
+ sigfillset(&new_thread->act[i - 1].sa_mask);
+ new_thread->act[i - 1].sa_handler = _thread_run->act[i - 1].sa_handler;
+ new_thread->act[i - 1].sa_flags = _thread_run->act[i - 1].sa_flags;
+ }
+
+ /* Initialise the jump buffer: */
+ _thread_sys_setjmp(new_thread->saved_jmp_buf);
+
+ /*
+ * Set up new stack frame so that it looks like it
+ * returned from a longjmp() to the beginning of
+ * _thread_start(). Check if this is a user thread:
+ */
+ if (parent == NULL) {
+ /* Use the user start function: */
+#if defined(__FreeBSD__)
+ new_thread->saved_jmp_buf[0]._jb[0] = (long) _thread_start;
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[2] = (long) _thread_start;
+ new_thread->saved_jmp_buf[4 + R_RA] = 0;
+ new_thread->saved_jmp_buf[4 + R_T12] = (long) _thread_start;
+#else
+ new_thread->saved_jmp_buf[0] = (long) _thread_start;
+#endif
+#else
+#error "Don't recognize this operating system!"
+#endif
+ } else {
+ /*
+ * Use the (funny) signal handler start
+ * function:
+ */
+#if defined(__FreeBSD__)
+ new_thread->saved_jmp_buf[0]._jb[0] = (int) _thread_start_sig_handler;
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[2] = (long) _thread_start_sig_handler;
+ new_thread->saved_jmp_buf[4 + R_RA] = 0;
+ new_thread->saved_jmp_buf[4 + R_T12] = (long) _thread_start_sig_handler;
+#else
+ new_thread->saved_jmp_buf[0] = (long) _thread_start_sig_handler;
+#endif
+#else
+#error "Don't recognize this operating system!"
+#endif
+ }
+
+ /* The stack starts high and builds down: */
+#if defined(__FreeBSD__)
+ new_thread->saved_jmp_buf[0]._jb[2] = (int) (new_thread->stack + pattr->stacksize_attr - sizeof(double));
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[4 + R_SP] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
+#else
+ new_thread->saved_jmp_buf[2] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
+#endif
+#else
+#error "Don't recognize this operating system!"
+#endif
+
+ /* Copy the thread attributes: */
+ memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr));
+
+ /*
+ * Check if this thread is to inherit the scheduling
+ * attributes from its parent:
+ */
+ if (new_thread->attr.flags & PTHREAD_INHERIT_SCHED) {
+ /* Copy the scheduling attributes: */
+ new_thread->pthread_priority = _thread_run->pthread_priority;
+ new_thread->attr.prio = _thread_run->pthread_priority;
+ new_thread->attr.schedparam_policy = _thread_run->attr.schedparam_policy;
+ } else {
+ /*
+ * Use just the thread priority, leaving the
+ * other scheduling attributes as their
+ * default values:
+ */
+ new_thread->pthread_priority = new_thread->attr.prio;
+ }
+
+ /* Initialise the join queue for the new thread: */
+ _thread_queue_init(&(new_thread->join_queue));
+
+ /* Initialise hooks in the thread structure: */
+ new_thread->specific_data = NULL;
+ new_thread->cleanup = NULL;
+ new_thread->queue = NULL;
+ new_thread->qnxt = NULL;
+ new_thread->parent_thread = parent;
+ new_thread->flags = 0;
+
+ /* Add the thread to the linked list of all threads: */
+ new_thread->nxt = _thread_link_list;
+ _thread_link_list = new_thread;
+
+ /* Return a pointer to the thread structure: */
+ (*thread) = new_thread;
+
+ /* Check if a parent thread was specified: */
+ if (parent != NULL) {
+ /*
+ * A parent thread was specified, so this is
+ * a signal handler thread which must now
+ * wait for the signal handler to complete:
+ */
+ PTHREAD_NEW_STATE(parent,PS_SIGTHREAD);
+ } else {
+ /* Schedule the new user thread: */
+ _thread_kern_sched(NULL);
+ }
+ }
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the status: */
+ return (ret);
+}
+
+int
+pthread_create(pthread_t * thread, const pthread_attr_t * attr,
+ void *(*start_routine) (void *), void *arg)
+{
+ int ret = 0;
+
+ /*
+ * Call the low level thread creation function which allows a parent
+ * thread to be specified:
+ */
+ ret = _thread_create(thread, attr, start_routine, arg, NULL);
+
+ /* Return the status: */
+ return (ret);
+}
+
+void
+_thread_start(void)
+{
+ /* Run the current thread's start routine with argument: */
+ pthread_exit(_thread_run->start_routine(_thread_run->arg));
+
+ /* This point should never be reached. */
+ PANIC("Thread has resumed after exit");
+}
+
+void
+_thread_start_sig_handler(void)
+{
+ int sig;
+ long arg;
+ void (*sig_routine) (int);
+
+ /*
+ * Cast the argument from 'void *' to a variable that is NO SMALLER
+ * than a pointer (otherwise gcc under NetBSD/Alpha will complain):
+ */
+ arg = (long) _thread_run->arg;
+
+ /* Cast the argument as a signal number: */
+ sig = (int) arg;
+
+ /* Cast a pointer to the signal handler function: */
+ sig_routine = (void (*) (int)) _thread_run->start_routine;
+
+ /* Call the signal handler function: */
+ (*sig_routine) (sig);
+
+ /* Exit the signal handler thread: */
+ pthread_exit(&arg);
+
+ /* This point should never be reached. */
+ PANIC("Signal handler thread has resumed after exit");
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_detach.c b/lib/libc_r/uthread/uthread_detach.c
new file mode 100644
index 0000000..08cace4
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_detach.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_detach(pthread_t * p_pthread)
+{
+ int rval = 0;
+ int status;
+ pthread_t next_thread;
+ pthread_t pthread;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Check for invalid calling parameters: */
+ if (p_pthread == NULL || (pthread = *p_pthread) == NULL) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ }
+ /* Check if the thread has not been detached: */
+ else if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) {
+ /* Flag the thread as detached: */
+ pthread->attr.flags |= PTHREAD_DETACHED;
+
+ /* Enter a loop to bring all threads off the join queue: */
+ while ((next_thread = _thread_queue_deq(&pthread->join_queue)) != NULL) {
+ /* Make the thread run: */
+ PTHREAD_NEW_STATE(next_thread,PS_RUNNING);
+ }
+
+ /*
+ * NULL the thread pointer now that the thread has been
+ * detached:
+ */
+ *p_pthread = NULL;
+ } else {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_dup.c b/lib/libc_r/uthread/uthread_dup.c
new file mode 100644
index 0000000..e6c4598
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_dup.c
@@ -0,0 +1,37 @@
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+dup(int fd)
+{
+ int ret;
+
+ /* Lock the file descriptor: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Perform the 'dup' syscall: */
+ if ((ret = _thread_sys_dup(fd)) < 0) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(ret);
+
+ /* Reset the file descriptor: */
+ ret = -1;
+ } else {
+ /*
+ * Save the file open flags so that they can be
+ * checked later:
+ */
+ _thread_fd_table[ret]->flags = _thread_fd_table[fd]->flags;
+ }
+
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_dup2.c b/lib/libc_r/uthread/uthread_dup2.c
new file mode 100644
index 0000000..6da78f7
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_dup2.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+dup2(int fd, int newfd)
+{
+ int ret;
+
+ /* Lock the file descriptor: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Lock the file descriptor: */
+ if ((ret = _thread_fd_lock(newfd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Perform the 'dup2' syscall: */
+ if ((ret = _thread_sys_dup2(fd, newfd)) < 0) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(ret);
+
+ /* Reset the file descriptor: */
+ ret = -1;
+ } else {
+ /*
+ * Save the file open flags so that they can
+ * be checked later:
+ */
+ _thread_fd_table[ret]->flags = _thread_fd_table[fd]->flags;
+ }
+
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(newfd, FD_RDWR);
+ }
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_equal.c b/lib/libc_r/uthread/uthread_equal.c
new file mode 100644
index 0000000..99ffb5d
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_equal.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_equal(pthread_t t1, pthread_t t2)
+{
+ /* Compare the two thread pointers: */
+ return (t1 == t2);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_execve.c b/lib/libc_r/uthread/uthread_execve.c
new file mode 100644
index 0000000..d12b8ff
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_execve.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+execve(const char *name, char *const * argv, char *const * envp)
+{
+ int flags;
+ int i;
+ int ret;
+ struct sigaction act;
+ struct sigaction oact;
+ struct itimerval itimer;
+
+ /* Disable the interval timer: */
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+ itimer.it_value.tv_sec = 0;
+ itimer.it_value.tv_usec = 0;
+ setitimer(ITIMER_VIRTUAL, &itimer, NULL);
+
+ /* Close the pthread kernel pipe: */
+ _thread_sys_close(_thread_kern_pipe[0]);
+ _thread_sys_close(_thread_kern_pipe[1]);
+
+ /*
+ * Enter a loop to set all file descriptors to blocking
+ * if they were not created as non-blocking:
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Check if this file descriptor is in use: */
+ if (_thread_fd_table[i] != NULL &&
+ !(_thread_fd_table[i]->flags & O_NONBLOCK)) {
+ /* Get the current flags: */
+ flags = _thread_sys_fcntl(i, F_GETFL, NULL);
+ /* Clear the nonblocking file descriptor flag: */
+ _thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+
+ /* Enter a loop to adopt the signal actions for the running thread: */
+ for (i = 1; i < NSIG; i++) {
+ /* Check for signals which cannot be caught: */
+ if (i == SIGKILL || i == SIGSTOP) {
+ /* Don't do anything with these signals. */
+ } else {
+ /*
+ * Check if the running thread is ignoring this
+ * signal:
+ */
+ if (_thread_run->act[i - 1].sa_handler == SIG_IGN) {
+ /* Continue to ignore this signal: */
+ act.sa_handler = SIG_IGN;
+ } else {
+ /* Use the default handler for this signal: */
+ act.sa_handler = SIG_DFL;
+ }
+
+ /* Copy the mask and flags for this signal: */
+ act.sa_mask = _thread_run->act[i - 1].sa_mask;
+ act.sa_flags = _thread_run->act[i - 1].sa_flags;
+
+ /* Change the signal action for the process: */
+ _thread_sys_sigaction(i, &act, &oact);
+ }
+ }
+
+ /* Execute the process: */
+ _thread_sys_sigprocmask(SIG_SETMASK, &_thread_run->sigmask, NULL);
+
+ /* Execute the process: */
+ ret = _thread_sys_execve(name, argv, envp);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_exit.c b/lib/libc_r/uthread/uthread_exit.c
new file mode 100644
index 0000000..15bcfa3
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_exit.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void _exit(int status)
+{
+ int flags;
+ int i;
+ struct itimerval itimer;
+
+ /* Disable the interval timer: */
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+ itimer.it_value.tv_sec = 0;
+ itimer.it_value.tv_usec = 0;
+ setitimer(ITIMER_VIRTUAL, &itimer, NULL);
+
+ /* Close the pthread kernel pipe: */
+ _thread_sys_close(_thread_kern_pipe[0]);
+ _thread_sys_close(_thread_kern_pipe[1]);
+
+ /*
+ * Enter a loop to set all file descriptors to blocking
+ * if they were not created as non-blocking:
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Check if this file descriptor is in use: */
+ if (_thread_fd_table[i] != NULL &&
+ !(_thread_fd_table[i]->flags & O_NONBLOCK)) {
+ /* Get the current flags: */
+ flags = _thread_sys_fcntl(i, F_GETFL, NULL);
+ /* Clear the nonblocking file descriptor flag: */
+ _thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+
+ /* Call the _exit syscall: */
+ _thread_sys__exit(status);
+}
+
+void
+_thread_exit(char *fname, int lineno, char *string)
+{
+ char s[256];
+
+ /* Prepare an error message string: */
+ strcpy(s, "Fatal error '");
+ strcat(s, string);
+ strcat(s, "' at line ? ");
+ strcat(s, "in file ");
+ strcat(s, fname);
+ strcat(s, " (errno = ?");
+ strcat(s, ")\n");
+
+ /* Write the string to the standard error file descriptor: */
+ _thread_sys_write(2, s, strlen(s));
+
+ /* Force this process to exit: */
+ _exit(1);
+}
+
+void
+pthread_exit(void *status)
+{
+ int sig;
+ long l;
+ pthread_t pthread;
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Save the return value: */
+ _thread_run->ret = status;
+
+ while (_thread_run->cleanup != NULL) {
+ pthread_cleanup_pop(1);
+ }
+
+ if (_thread_run->attr.cleanup_attr != NULL) {
+ _thread_run->attr.cleanup_attr(_thread_run->attr.arg_attr);
+ }
+ /* Check if there is thread specific data: */
+ if (_thread_run->specific_data != NULL) {
+ /* Run the thread-specific data destructors: */
+ _thread_cleanupspecific();
+ }
+ /* Check if there are any threads joined to this one: */
+ while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) {
+ /* Wake the joined thread and let it detach this thread: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+
+ /* Check if the running thread is at the head of the linked list: */
+ if (_thread_link_list == _thread_run) {
+ /* There is no previous thread: */
+ _thread_link_list = _thread_run->nxt;
+ } else {
+ /* Point to the first thread in the list: */
+ pthread = _thread_link_list;
+
+ /*
+ * Enter a loop to find the thread in the linked list before
+ * the running thread:
+ */
+ while (pthread != NULL && pthread->nxt != _thread_run) {
+ /* Point to the next thread: */
+ pthread = pthread->nxt;
+ }
+
+ /* Check that a previous thread was found: */
+ if (pthread != NULL) {
+ /*
+ * Point the previous thread to the one after the
+ * running thread:
+ */
+ pthread->nxt = _thread_run->nxt;
+ }
+ }
+
+ /* Check if this is a signal handler thread: */
+ if (_thread_run->parent_thread != NULL) {
+ /*
+ * Enter a loop to search for other threads with the same
+ * parent:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Compare the parent thread pointers: */
+ if (pthread->parent_thread == _thread_run->parent_thread) {
+ /*
+ * The parent thread is waiting on at least
+ * one other signal handler. Exit the loop
+ * now that this is known.
+ */
+ break;
+ }
+ }
+
+ /*
+ * Check if the parent is not waiting on any other signal
+ * handler threads and if it hasn't died in the meantime:
+ */
+ if (pthread == NULL && _thread_run->parent_thread->state != PS_DEAD) {
+ /* Allow the parent thread to run again: */
+ PTHREAD_NEW_STATE(_thread_run->parent_thread,PS_RUNNING);
+ }
+ /* Get the signal number: */
+ l = (long) _thread_run->arg;
+ sig = (int) l;
+
+ /* Unblock the signal from the parent thread: */
+ sigdelset(&_thread_run->parent_thread->sigmask, sig);
+ }
+ /*
+ * This thread will never run again. Add it to the list of dead
+ * threads:
+ */
+ _thread_run->nxt = _thread_dead;
+ _thread_dead = _thread_run;
+
+ /*
+ * The running thread is no longer in the thread link list so it will
+ * now die:
+ */
+ _thread_kern_sched_state(PS_DEAD, __FILE__, __LINE__);
+
+ /* This point should not be reached. */
+ PANIC("Dead thread has resumed");
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fchmod.c b/lib/libc_r/uthread/uthread_fchmod.c
new file mode 100644
index 0000000..ee5dfde
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fchmod.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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/types.h>
+#include <sys/stat.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fchmod(int fd, mode_t mode)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_WRITE, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_fchmod(fd, mode);
+ _thread_fd_unlock(fd, FD_WRITE);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fchown.c b/lib/libc_r/uthread/uthread_fchown.c
new file mode 100644
index 0000000..52f65b8
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fchown.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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/types.h>
+#include <unistd.h>
+#include <dirent.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fchown(int fd, uid_t owner, gid_t group)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_WRITE, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_fchown(fd, owner, group);
+ _thread_fd_unlock(fd, FD_WRITE);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fcntl.c b/lib/libc_r/uthread/uthread_fcntl.c
new file mode 100644
index 0000000..f83ee50
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fcntl.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fcntl(int fd, int cmd,...)
+{
+ int flags = 0;
+ int oldfd;
+ int ret;
+ int status;
+ va_list ap;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Lock the file descriptor: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Initialise the variable argument list: */
+ va_start(ap, cmd);
+
+ /* Process according to file control command type: */
+ switch (cmd) {
+ /* Duplicate a file descriptor: */
+ case F_DUPFD:
+ /*
+ * Get the file descriptor that the caller wants to
+ * use:
+ */
+ oldfd = va_arg(ap, int);
+
+ /* Initialise the file descriptor table entry: */
+ if ((ret = _thread_sys_fcntl(fd, cmd, oldfd)) < 0) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(ret);
+
+ /* Reset the file descriptor: */
+ ret = -1;
+ } else {
+ /*
+ * Save the file open flags so that they can
+ * be checked later:
+ */
+ _thread_fd_table[ret]->flags = _thread_fd_table[fd]->flags;
+ }
+ break;
+ case F_SETFD:
+ break;
+ case F_GETFD:
+ break;
+ case F_GETFL:
+ ret = _thread_fd_table[fd]->flags;
+ break;
+ case F_SETFL:
+ flags = va_arg(ap, int);
+ if ((ret = _thread_sys_fcntl(fd, cmd, flags | O_NONBLOCK)) == 0) {
+ _thread_fd_table[fd]->flags = flags;
+ }
+ break;
+ default:
+ /* Might want to make va_arg use a union */
+ ret = _thread_sys_fcntl(fd, cmd, va_arg(ap, void *));
+ break;
+ }
+
+ /* Free variable arguments: */
+ va_end(ap);
+
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fd.c b/lib/libc_r/uthread/uthread_fd.c
new file mode 100644
index 0000000..1e61bb7
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fd.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+_thread_fd_table_init(int fd)
+{
+ int ret = 0;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Check if the file descriptor is out of range: */
+ if (fd < 0 || fd >= _thread_dtablesize)
+ /* Return a bad file descriptor error: */
+ ret = EBADF;
+
+ /*
+ * Check if memory has already been allocated for this file
+ * descriptor:
+ */
+ else if (_thread_fd_table[fd] != NULL) {
+ /* Memory has already been allocated. */
+ }
+ /* Allocate memory for the file descriptor table entry: */
+ else if ((_thread_fd_table[fd] = (struct fd_table_entry *)
+ malloc(sizeof(struct fd_table_entry))) == NULL)
+ /* Return a bad file descriptor error: */
+ ret = EBADF;
+ else {
+ /* Assume that the operation will succeed: */
+ ret = 0;
+
+ /* Initialise the file locks: */
+ _thread_fd_table[fd]->r_owner = NULL;
+ _thread_fd_table[fd]->w_owner = NULL;
+ _thread_fd_table[fd]->r_fname = NULL;
+ _thread_fd_table[fd]->w_fname = NULL;
+ _thread_fd_table[fd]->r_lineno = 0;;
+ _thread_fd_table[fd]->w_lineno = 0;;
+ _thread_fd_table[fd]->r_lockcount = 0;;
+ _thread_fd_table[fd]->w_lockcount = 0;;
+
+ /* Initialise the read/write queues: */
+ _thread_queue_init(&_thread_fd_table[fd]->r_queue);
+ _thread_queue_init(&_thread_fd_table[fd]->w_queue);
+
+ /* Get the flags for the file: */
+ if (fd >= 3 && (_thread_fd_table[fd]->flags =
+ _thread_sys_fcntl(fd, F_GETFL, 0)) == -1)
+ ret = errno;
+
+ else {
+ /* Check if a stdio descriptor: */
+ if (fd < 3)
+ /*
+ * Use the stdio flags read by
+ * _pthread_init() to avoid
+ * mistaking the non-blocking
+ * flag that, when set on one
+ * stdio fd, is set on all stdio
+ * fds.
+ */
+ _thread_fd_table[fd]->flags =
+ _pthread_stdio_flags[fd];
+
+ /* Make the file descriptor non-blocking: */
+ if (_thread_sys_fcntl(fd, F_SETFL,
+ _thread_fd_table[fd]->flags | O_NONBLOCK) == -1) {
+ /*
+ * Some devices don't support
+ * non-blocking calls (sigh):
+ */
+ if (errno != ENODEV)
+ ret = errno;
+ }
+ }
+
+ /* Check if one of the fcntl calls failed: */
+ if (ret != 0) {
+ /* Free the file descriptor table entry: */
+ free(_thread_fd_table[fd]);
+ _thread_fd_table[fd] = NULL;
+ }
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+void
+_thread_fd_unlock(int fd, int lock_type)
+{
+ int ret;
+ int status;
+
+ /* Block signals while the file descriptor lock is tested: */
+ _thread_kern_sig_block(&status);
+
+ /*
+ * Check that the file descriptor table is initialised for this
+ * entry:
+ */
+ if ((ret = _thread_fd_table_init(fd)) != 0) {
+ } else {
+ /* Check if the running thread owns the read lock: */
+ if (_thread_fd_table[fd]->r_owner == _thread_run) {
+ /* Check the file descriptor and lock types: */
+ if (lock_type == FD_READ || lock_type == FD_RDWR) {
+ /*
+ * Decrement the read lock count for the
+ * running thread:
+ */
+ _thread_fd_table[fd]->r_lockcount--;
+
+ /*
+ * Check if the running thread still has read
+ * locks on this file descriptor:
+ */
+ if (_thread_fd_table[fd]->r_lockcount != 0) {
+ }
+ /*
+ * Get the next thread in the queue for a
+ * read lock on this file descriptor:
+ */
+ else if ((_thread_fd_table[fd]->r_owner = _thread_queue_deq(&_thread_fd_table[fd]->r_queue)) == NULL) {
+ } else {
+ /*
+ * Set the state of the new owner of
+ * the thread to running:
+ */
+ PTHREAD_NEW_STATE(_thread_fd_table[fd]->r_owner,PS_RUNNING);
+
+ /*
+ * Reset the number of read locks.
+ * This will be incremented by the
+ * new owner of the lock when it sees
+ * that it has the lock.
+ */
+ _thread_fd_table[fd]->r_lockcount = 0;
+ }
+ }
+ }
+ /* Check if the running thread owns the write lock: */
+ if (_thread_fd_table[fd]->w_owner == _thread_run) {
+ /* Check the file descriptor and lock types: */
+ if (lock_type == FD_WRITE || lock_type == FD_RDWR) {
+ /*
+ * Decrement the write lock count for the
+ * running thread:
+ */
+ _thread_fd_table[fd]->w_lockcount--;
+
+ /*
+ * Check if the running thread still has
+ * write locks on this file descriptor:
+ */
+ if (_thread_fd_table[fd]->w_lockcount != 0) {
+ }
+ /*
+ * Get the next thread in the queue for a
+ * write lock on this file descriptor:
+ */
+ else if ((_thread_fd_table[fd]->w_owner = _thread_queue_deq(&_thread_fd_table[fd]->w_queue)) == NULL) {
+ } else {
+ /*
+ * Set the state of the new owner of
+ * the thread to running:
+ */
+ PTHREAD_NEW_STATE(_thread_fd_table[fd]->w_owner,PS_RUNNING);
+
+ /*
+ * Reset the number of write locks.
+ * This will be incremented by the
+ * new owner of the lock when it
+ * sees that it has the lock.
+ */
+ _thread_fd_table[fd]->w_lockcount = 0;
+ }
+ }
+ }
+ }
+
+ /* Unblock signals again: */
+ _thread_kern_sig_unblock(status);
+
+ /* Nothing to return. */
+ return;
+}
+
+int
+_thread_fd_lock(int fd, int lock_type, struct timespec * timeout,
+ char *fname, int lineno)
+{
+ int ret;
+ int status;
+
+ /* Block signals while the file descriptor lock is tested: */
+ _thread_kern_sig_block(&status);
+
+ /*
+ * Check that the file descriptor table is initialised for this
+ * entry:
+ */
+ if ((ret = _thread_fd_table_init(fd)) != 0) {
+ } else {
+ /* Check the file descriptor and lock types: */
+ if (lock_type == FD_READ || lock_type == FD_RDWR) {
+ /*
+ * Enter a loop to wait for the file descriptor to be
+ * locked for read for the current thread:
+ */
+ while (_thread_fd_table[fd]->r_owner != _thread_run) {
+ /*
+ * Check if the file descriptor is locked by
+ * another thread:
+ */
+ if (_thread_fd_table[fd]->r_owner != NULL) {
+ /*
+ * Another thread has locked the file
+ * descriptor for read, so join the
+ * queue of threads waiting for a
+ * read lock on this file descriptor:
+ */
+ _thread_queue_enq(&_thread_fd_table[fd]->r_queue, _thread_run);
+
+ /*
+ * Save the file descriptor details
+ * in the thread structure for the
+ * running thread:
+ */
+ _thread_run->data.fd.fd = fd;
+ _thread_run->data.fd.branch = lineno;
+ _thread_run->data.fd.fname = fname;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(timeout);
+
+ /*
+ * Schedule this thread to wait on
+ * the read lock. It will only be
+ * woken when it becomes the next in
+ * the queue and is granted access
+ * to the lock by the thread
+ * that is unlocking the file
+ * descriptor.
+ */
+ _thread_kern_sched_state(PS_FDLR_WAIT, __FILE__, __LINE__);
+
+ /*
+ * Block signals so that the file
+ * descriptor lock can again be
+ * tested:
+ */
+ _thread_kern_sig_block(NULL);
+ } else {
+ /*
+ * The running thread now owns the
+ * read lock on this file descriptor:
+ */
+ _thread_fd_table[fd]->r_owner = _thread_run;
+
+ /*
+ * Reset the number of read locks for
+ * this file descriptor:
+ */
+ _thread_fd_table[fd]->r_lockcount = 0;
+
+ /*
+ * Save the source file details for
+ * debugging:
+ */
+ _thread_fd_table[fd]->r_fname = fname;
+ _thread_fd_table[fd]->r_lineno = lineno;
+ }
+ }
+
+ /* Increment the read lock count: */
+ _thread_fd_table[fd]->r_lockcount++;
+ }
+ /* Check the file descriptor and lock types: */
+ if (lock_type == FD_WRITE || lock_type == FD_RDWR) {
+ /*
+ * Enter a loop to wait for the file descriptor to be
+ * locked for write for the current thread:
+ */
+ while (_thread_fd_table[fd]->w_owner != _thread_run) {
+ /*
+ * Check if the file descriptor is locked by
+ * another thread:
+ */
+ if (_thread_fd_table[fd]->w_owner != NULL) {
+ /*
+ * Another thread has locked the file
+ * descriptor for write, so join the
+ * queue of threads waiting for a
+ * write lock on this file
+ * descriptor:
+ */
+ _thread_queue_enq(&_thread_fd_table[fd]->w_queue, _thread_run);
+
+ /*
+ * Save the file descriptor details
+ * in the thread structure for the
+ * running thread:
+ */
+ _thread_run->data.fd.fd = fd;
+ _thread_run->data.fd.branch = lineno;
+ _thread_run->data.fd.fname = fname;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(timeout);
+
+ /*
+ * Schedule this thread to wait on
+ * the write lock. It will only be
+ * woken when it becomes the next in
+ * the queue and is granted access to
+ * the lock by the thread that is
+ * unlocking the file descriptor.
+ */
+ _thread_kern_sched_state(PS_FDLW_WAIT, __FILE__, __LINE__);
+
+ /*
+ * Block signals so that the file
+ * descriptor lock can again be
+ * tested:
+ */
+ _thread_kern_sig_block(NULL);
+ } else {
+ /*
+ * The running thread now owns the
+ * write lock on this file
+ * descriptor:
+ */
+ _thread_fd_table[fd]->w_owner = _thread_run;
+
+ /*
+ * Reset the number of write locks
+ * for this file descriptor:
+ */
+ _thread_fd_table[fd]->w_lockcount = 0;
+
+ /*
+ * Save the source file details for
+ * debugging:
+ */
+ _thread_fd_table[fd]->w_fname = fname;
+ _thread_fd_table[fd]->w_lineno = lineno;
+ }
+ }
+
+ /* Increment the write lock count: */
+ _thread_fd_table[fd]->w_lockcount++;
+ }
+ }
+
+ /* Unblock signals again: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_file.c b/lib/libc_r/uthread/uthread_file.c
new file mode 100644
index 0000000..0d8e9a3
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_file.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+_thread_flockfile(FILE * fp, char *fname, int lineno)
+{
+ int fd, flags;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ if ((fd = fileno(fp)) >= 0) {
+ if (fp->_flags & __SRW) {
+ flags = FD_READ | FD_WRITE;
+ } else {
+ if (fp->_flags & __SWR) {
+ flags = FD_WRITE;
+ } else {
+ flags = FD_READ;
+ }
+ }
+
+ /* This might fail but POSIX doesn't give a damn. */
+ _thread_fd_lock(fd, flags, NULL, fname, lineno);
+ }
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return;
+}
+
+int
+_thread_ftrylockfile(FILE * fp)
+{
+ int fd = 0;
+ int flags;
+ int status;
+
+ if ((fd = fileno(fp)) >= 0) {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ if (fp->_flags & __SRW) {
+ flags = FD_READ | FD_WRITE;
+ } else {
+ if (fp->_flags & __SWR) {
+ flags = FD_WRITE;
+ } else {
+ flags = FD_READ;
+ }
+ }
+ if (!(_thread_fd_table[fd]->r_owner && _thread_fd_table[fd]->w_owner)) {
+ _thread_fd_lock(fd, flags, NULL, __FILE__, __LINE__);
+ fd = 0;
+ } else {
+ fd = -1;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+ return (fd);
+}
+
+void
+_thread_funlockfile(FILE * fp)
+{
+ int fd, flags;
+ int status;
+
+ if ((fd = fileno(fp)) >= 0) {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ if (fp->_flags & __SRW) {
+ flags = FD_READ | FD_WRITE;
+ } else if (fp->_flags & __SWR) {
+ flags = FD_WRITE;
+ } else {
+ flags = FD_READ;
+ }
+ _thread_fd_unlock(fd, flags);
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+ return;
+}
+
+#endif
diff --git a/lib/libc_r/uthread/uthread_flock.c b/lib/libc_r/uthread/uthread_flock.c
new file mode 100644
index 0000000..4071b54
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_flock.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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/file.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+flock(int fd, int operation)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_flock(fd, operation);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fork.c b/lib/libc_r/uthread/uthread_fork.c
new file mode 100644
index 0000000..19f674d
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fork.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pid_t
+fork(void)
+{
+ int flags;
+ pid_t ret;
+
+ /* Fork a new process: */
+ if ((ret = _thread_sys_fork()) <= 0) {
+ /* Parent process or error. Nothing to do here. */
+ } else {
+ /* Close the pthread kernel pipe: */
+ _thread_sys_close(_thread_kern_pipe[0]);
+ _thread_sys_close(_thread_kern_pipe[1]);
+
+ /* Reset signals pending for the running thread: */
+ memset(_thread_run->sigpend, 0, sizeof(_thread_run->sigpend));
+
+ /*
+ * Create a pipe that is written to by the signal handler to
+ * prevent signals being missed in calls to
+ * _thread_sys_select:
+ */
+ if (_thread_sys_pipe(_thread_kern_pipe) != 0) {
+ /* Cannot create pipe, so abort: */
+ PANIC("Cannot create pthread kernel pipe for forked process");
+ }
+ /* Get the flags for the read pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Make the read pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Get the flags for the write pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Make the write pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ }
+
+ /* Return the process ID: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fstat.c b/lib/libc_r/uthread/uthread_fstat.c
new file mode 100644
index 0000000..fc29e66
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fstat.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fstat(int fd, struct stat * buf)
+{
+ int ret;
+
+ /* Lock the file descriptor for read: */
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ /* Get the file status: */
+ ret = _thread_sys_fstat(fd, buf);
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fstatfs.c b/lib/libc_r/uthread/uthread_fstatfs.c
new file mode 100644
index 0000000..252c8b1
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fstatfs.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fstatfs(int fd, struct statfs * buf)
+{
+ int ret;
+
+ /* Lock the file descriptor for read: */
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ /* Get the file system status: */
+ ret = _thread_sys_fstatfs(fd, buf);
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fsync.c b/lib/libc_r/uthread/uthread_fsync.c
new file mode 100644
index 0000000..51078e5
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fsync.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fsync(int fd)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_fsync(fd);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_getdirentries.c b/lib/libc_r/uthread/uthread_getdirentries.c
new file mode 100644
index 0000000..b75e804
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_getdirentries.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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/types.h>
+#include <dirent.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+getdirentries(int fd, char *buf, int nbytes, long *basep)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_getdirentries(fd, buf, nbytes, basep);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_getpeername.c b/lib/libc_r/uthread/uthread_getpeername.c
new file mode 100644
index 0000000..d3bb4e1
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_getpeername.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+getpeername(int fd, struct sockaddr * peer, int *paddrlen)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_getpeername(fd, peer, paddrlen);
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return ret;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_getprio.c b/lib/libc_r/uthread/uthread_getprio.c
new file mode 100644
index 0000000..85bd261
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_getprio.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_getprio(pthread_t pthread)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread_p;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the first thread in the list: */
+ pthread_p = _thread_link_list;
+
+ /* Enter a loop to search for the thread: */
+ while (pthread_p != NULL && pthread_p != pthread) {
+ /* Point to the next thread: */
+ pthread_p = pthread_p->nxt;
+ }
+
+ /* Check if the thread pointer is NULL: */
+ if (pthread == NULL || pthread_p == NULL) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Get the thread priority: */
+ rval = pthread->pthread_priority;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the thread priority or an error status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_getsockname.c b/lib/libc_r/uthread/uthread_getsockname.c
new file mode 100644
index 0000000..5a8466b
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_getsockname.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+getsockname(int s, struct sockaddr * name, int *namelen)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(s, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_getsockname(s, name, namelen);
+ _thread_fd_unlock(s, FD_READ);
+ }
+ return ret;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_getsockopt.c b/lib/libc_r/uthread/uthread_getsockopt.c
new file mode 100644
index 0000000..fdedd90
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_getsockopt.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+getsockopt(int fd, int level, int optname, void *optval, int *optlen)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_getsockopt(fd, level, optname, optval, optlen);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return ret;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_info.c b/lib/libc_r/uthread/uthread_info.c
new file mode 100644
index 0000000..be25d45
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_info.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+struct s_thread_info {
+ enum pthread_state state;
+ char *name;
+};
+
+/* Static variables: */
+static const struct s_thread_info thread_info[] = {
+ {PS_RUNNING , "Running"},
+ {PS_SIGTHREAD , "Waiting on signal thread"},
+ {PS_MUTEX_WAIT , "Waiting on a mutex"},
+ {PS_COND_WAIT , "Waiting on a condition variable"},
+ {PS_FDLR_WAIT , "Waiting for a file read lock"},
+ {PS_FDLW_WAIT , "Waiting for a file write lock"},
+ {PS_FDR_WAIT , "Waiting for read"},
+ {PS_FDW_WAIT , "Waitingfor write"},
+ {PS_SELECT_WAIT , "Waiting on select"},
+ {PS_SLEEP_WAIT , "Sleeping"},
+ {PS_WAIT_WAIT , "Waiting process"},
+ {PS_SIGWAIT , "Waiting for a signal"},
+ {PS_JOIN , "Waiting to join"},
+ {PS_SUSPENDED , "Suspended"},
+ {PS_DEAD , "Dead"},
+ {PS_STATE_MAX , "Not a real state!"}
+};
+
+void
+_thread_dump_info(void)
+{
+ char s[128];
+ int fd;
+ int i;
+ int j;
+ pthread_t pthread;
+
+ /* Open the dump file for append and create it if necessary: */
+ if ((fd = _thread_sys_open("/tmp/uthread.dump", O_RDWR | O_CREAT | O_APPEND, 0666)) < 0) {
+ /* Can't open the dump file. */
+ } else {
+ /* Output a header for active threads: */
+ strcpy(s, "\n\n=============\nACTIVE THREADS\n\n");
+ _thread_sys_write(fd, s, strlen(s));
+
+ /* Enter a loop to report each thread in the global list: */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Find the state: */
+ for (j = 0; j < (sizeof(thread_info) / sizeof(struct s_thread_info)) - 1; j++)
+ if (thread_info[j].state == pthread->state)
+ break;
+ /* Output a record for the current thread: */
+ sprintf(s, "--------------------\nThread %p prio %3d state %s [%s:%d]\n",
+ pthread, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno);
+ _thread_sys_write(fd, s, strlen(s));
+
+ /* Check if this is the running thread: */
+ if (pthread == _thread_run) {
+ /* Output a record for the running thread: */
+ strcpy(s, "This is the running thread\n");
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ /* Check if this is the initial thread: */
+ if (pthread == _thread_initial) {
+ /* Output a record for the initial thread: */
+ strcpy(s, "This is the initial thread\n");
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /* File descriptor read lock wait: */
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_FDR_WAIT:
+ case PS_FDW_WAIT:
+ /* Write the lock details: */
+ sprintf(s, "fd %d[%s:%d]", pthread->data.fd.fd, pthread->data.fd.fname, pthread->data.fd.branch);
+ _thread_sys_write(fd, s, strlen(s));
+ sprintf(s, "owner %pr/%pw\n", _thread_fd_table[pthread->data.fd.fd]->r_owner, _thread_fd_table[pthread->data.fd.fd]->w_owner);
+ _thread_sys_write(fd, s, strlen(s));
+ break;
+
+ /*
+ * Trap other states that are not explicitly
+ * coded to dump information:
+ */
+ default:
+ /* Nothing to do here. */
+ break;
+ }
+ }
+
+ /* Check if there are no dead threads: */
+ if (_thread_dead == NULL) {
+ /* Output a record: */
+ strcpy(s, "\n\nTHERE ARE NO DEAD THREADS\n");
+ _thread_sys_write(fd, s, strlen(s));
+ } else {
+ /* Output a header for dead threads: */
+ strcpy(s, "\n\nDEAD THREADS\n\n");
+ _thread_sys_write(fd, s, strlen(s));
+
+ /*
+ * Enter a loop to report each thread in the global
+ * dead thread list:
+ */
+ for (pthread = _thread_dead; pthread != NULL; pthread = pthread->nxt) {
+ /* Output a record for the current thread: */
+ sprintf(s, "Thread %p prio %3d [%s:%d]\n", pthread, pthread->pthread_priority,pthread->fname,pthread->lineno);
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ }
+
+ /* Output a header for file descriptors: */
+ strcpy(s, "\n\n=============\nFILE DESCRIPTOR TABLE\n\n");
+ _thread_sys_write(fd, s, strlen(s));
+
+ /* Enter a loop to report file descriptor lock usage: */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /*
+ * Check if memory is allocated for this file
+ * descriptor:
+ */
+ if (_thread_fd_table[i] != NULL) {
+ /* Report the file descriptor lock status: */
+ sprintf(s, "fd[%3d] read owner %p count %d [%s:%d]\n write owner %p count %d [%s:%d]\n",
+ i,
+ _thread_fd_table[i]->r_owner,
+ _thread_fd_table[i]->r_lockcount,
+ _thread_fd_table[i]->r_fname,
+ _thread_fd_table[i]->r_lineno,
+ _thread_fd_table[i]->w_owner,
+ _thread_fd_table[i]->w_lockcount,
+ _thread_fd_table[i]->w_fname,
+ _thread_fd_table[i]->w_lineno);
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ }
+
+ /* Close the dump file: */
+ _thread_sys_close(fd);
+ }
+ return;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_init.c b/lib/libc_r/uthread/uthread_init.c
new file mode 100644
index 0000000..5833cdf
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_init.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+
+/* Allocate space for global thread variables here: */
+#define GLOBAL_PTHREAD_PRIVATE
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <machine/reg.h>
+#include <pthread.h>
+#include "pthread_private.h"
+extern int _thread_autoinit_dummy_decl;
+
+/*
+ * Threaded process initialization
+ */
+void
+_thread_init(void)
+{
+ int flags;
+ int i;
+ struct sigaction act;
+
+ /* Ensure that the auto-initialization routine is linked in: */
+ _thread_autoinit_dummy_decl = 1;
+
+ /* Check if this function has already been called: */
+ if (_thread_initial)
+ /* Only initialise the threaded application once. */
+ return;
+
+ /* Get the standard I/O flags before messing with them : */
+ for (i = 0; i < 3; i++)
+ if ((_pthread_stdio_flags[i] =
+ _thread_sys_fcntl(i,F_GETFL, NULL)) == -1)
+ PANIC("Cannot get stdio flags");
+
+ /*
+ * Create a pipe that is written to by the signal handler to prevent
+ * signals being missed in calls to _thread_sys_select:
+ */
+ if (_thread_sys_pipe(_thread_kern_pipe) != 0) {
+ /* Cannot create pipe, so abort: */
+ PANIC("Cannot create kernel pipe");
+ }
+ /* Get the flags for the read pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel read pipe flags");
+ }
+ /* Make the read pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot make kernel read pipe non-blocking");
+ }
+ /* Get the flags for the write pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel write pipe flags");
+ }
+ /* Make the write pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel write pipe flags");
+ }
+ /* Allocate memory for the thread structure of the initial thread: */
+ else if ((_thread_initial = (pthread_t) malloc(sizeof(struct pthread))) == NULL) {
+ /*
+ * Insufficient memory to initialise this application, so
+ * abort:
+ */
+ PANIC("Cannot allocate memory for initial thread");
+ } else {
+ /* Zero the global kernel thread structure: */
+ memset(&_thread_kern_thread, 0, sizeof(struct pthread));
+ memset(_thread_initial, 0, sizeof(struct pthread));
+
+ /* Default the priority of the initial thread: */
+ _thread_initial->pthread_priority = PTHREAD_DEFAULT_PRIORITY;
+
+ /* Initialise the state of the initial thread: */
+ _thread_initial->state = PS_RUNNING;
+
+ /* Initialise the queue: */
+ _thread_queue_init(&(_thread_initial->join_queue));
+
+ /* Initialise the rest of the fields: */
+ _thread_initial->parent_thread = NULL;
+ _thread_initial->specific_data = NULL;
+ _thread_initial->cleanup = NULL;
+ _thread_initial->queue = NULL;
+ _thread_initial->qnxt = NULL;
+ _thread_initial->nxt = NULL;
+ _thread_initial->flags = 0;
+ _thread_initial->error = 0;
+ _thread_link_list = _thread_initial;
+ _thread_run = _thread_initial;
+
+ /* Enter a loop to get the existing signal status: */
+ for (i = 1; i < NSIG; i++) {
+ /* Check for signals which cannot be trapped: */
+ if (i == SIGKILL || i == SIGSTOP) {
+ }
+ /* Get the signal handler details: */
+ else if (_thread_sys_sigaction(i, NULL, &act) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot read signal handler info");
+ }
+ /* Set the signal handler for the initial thread: */
+ else if (sigaction(i, &act, NULL) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot initialise signal handler for initial thread");
+ }
+ }
+
+ /* Initialise the global signal action structure: */
+ sigfillset(&act.sa_mask);
+ act.sa_handler = (void (*) ()) _thread_sig_handler;
+ act.sa_flags = SA_RESTART;
+
+ /* Enter a loop to initialise the rest of the signals: */
+ for (i = 1; i < NSIG; i++) {
+ /* Check for signals which cannot be trapped: */
+ if (i == SIGKILL || i == SIGSTOP) {
+ }
+ /* Initialise the signal for default handling: */
+ else if (_thread_sys_sigaction(i, &act, NULL) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot initialise signal handler");
+ }
+ }
+
+ /* Get the table size: */
+ if ((_thread_dtablesize = getdtablesize()) < 0) {
+ /*
+ * Cannot get the system defined table size, so abort
+ * this process.
+ */
+ PANIC("Cannot get dtablesize");
+ }
+ /* Allocate memory for the file descriptor table: */
+ if ((_thread_fd_table = (struct fd_table_entry **) malloc(sizeof(struct fd_table_entry *) * _thread_dtablesize)) == NULL) {
+ /*
+ * Cannot allocate memory for the file descriptor
+ * table, so abort this process.
+ */
+ PANIC("Cannot allocate memory for file descriptor table");
+ } else {
+ /*
+ * Enter a loop to initialise the file descriptor
+ * table:
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Initialise the file descriptor table: */
+ _thread_fd_table[i] = NULL;
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * Special start up code for NetBSD/Alpha
+ */
+#if defined(__NetBSD__) && defined(__alpha__)
+int
+main(int argc, char *argv[], char *env);
+
+int
+_thread_main(int argc, char *argv[], char *env)
+{
+ _thread_init();
+ return (main(argc, argv, env));
+}
+#endif
+#else
+/*
+ * A stub for non-threaded programs.
+ */
+void
+_thread_init(void)
+{
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_ioctl.c b/lib/libc_r/uthread/uthread_ioctl.c
new file mode 100644
index 0000000..69df24d
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_ioctl.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdarg.h>
+#include <sys/ioctl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+ioctl(int fd, unsigned long request,...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, request);
+ if (fd < 0 || fd >= _thread_dtablesize)
+ ret = -1;
+ else
+ ret = _thread_sys_ioctl(fd, request, va_arg(ap, char *));
+ va_end(ap);
+ return ret;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_join.c b/lib/libc_r/uthread/uthread_join.c
new file mode 100644
index 0000000..161482e
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_join.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_join(pthread_t pthread, void **thread_return)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread1;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the first thread in the list: */
+ pthread1 = _thread_link_list;
+
+ /* Search for the thread to join to: */
+ while (pthread1 != NULL && pthread1 != pthread) {
+ /* Point to the next thread: */
+ pthread1 = pthread1->nxt;
+ }
+
+ if (pthread1 == NULL) {
+ /* Point to the first thread in the dead thread list: */
+ pthread1 = _thread_dead;
+
+ /* Search for the thread to join to: */
+ while (pthread1 != NULL && pthread1 != pthread) {
+ /* Point to the next thread: */
+ pthread1 = pthread1->nxt;
+ }
+ }
+
+ if (pthread1 == NULL) {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+
+ /* Check if this thread has been detached: */
+ } else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+ }
+ /* Check if the thread is not dead: */
+ else if (pthread->state != PS_DEAD) {
+ /* Add the running thread to the join queue: */
+ _thread_queue_enq(&(pthread->join_queue), _thread_run);
+
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__);
+
+ /* Block signals again: */
+ _thread_kern_sig_block(NULL);
+
+ /* Check if the thread is not detached: */
+ if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) {
+ /* Check if the return value is required: */
+ if (thread_return) {
+ /* Return the thread's return value: */
+ *thread_return = pthread->ret;
+ }
+ } else {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+ }
+ } else {
+ /* Check if the return value is required: */
+ if (thread_return != NULL) {
+ /* Return the thread's return value: */
+ *thread_return = pthread->ret;
+ }
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_kern.c b/lib/libc_r/uthread/uthread_kern.c
new file mode 100644
index 0000000..ba8e250
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_kern.c
@@ -0,0 +1,1739 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/syscall.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* Static variables: */
+static sigset_t sig_to_block = 0xffffffff;
+static sigset_t sig_to_unblock = 0;
+
+/* Static function prototype definitions: */
+static void
+_thread_kern_select(int wait_reqd);
+static void
+_thread_signal(pthread_t pthread, int sig);
+
+void
+_thread_kern_sched(struct sigcontext * scp)
+{
+#ifndef __alpha
+ char *fdata;
+#endif
+ int i;
+ int prio = -1;
+ pthread_t pthread;
+ pthread_t pthread_h = NULL;
+ pthread_t pthread_nxt = NULL;
+ pthread_t pthread_prv = NULL;
+ pthread_t pthread_s = NULL;
+ struct itimerval itimer;
+ struct timespec ts;
+ struct timespec ts1;
+ struct timeval tv;
+ struct timeval tv1;
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Check if this function was called from the signal handler: */
+ if (scp != NULL) {
+ /*
+ * Copy the signal context to the current thread's jump
+ * buffer:
+ */
+ memcpy(&_thread_run->saved_sigcontext, scp, sizeof(_thread_run->saved_sigcontext));
+
+#ifndef __alpha
+ /* Point to the floating point data in the running thread: */
+ fdata = _thread_run->saved_fp;
+
+ /* Save the floating point data: */
+__asm__("fnsave %0": :"m"(*fdata));
+#endif
+
+ /* Flag the signal context as the last state saved: */
+ _thread_run->sig_saved = 1;
+ }
+ /* Save the state of the current thread: */
+ else if (_thread_sys_setjmp(_thread_run->saved_jmp_buf) != 0) {
+ /* Unblock signals (just in case): */
+ _thread_kern_sig_unblock(0);
+
+ /*
+ * This point is reached when a longjmp() is called to
+ * restore the state of a thread.
+ */
+ return;
+ } else {
+ /* Flag the jump buffer was the last state saved: */
+ _thread_run->sig_saved = 0;
+ }
+
+ /* Point to the first dead thread (if there are any): */
+ pthread = _thread_dead;
+
+ /* There is no previous dead thread: */
+ pthread_prv = NULL;
+
+ /* Enter a loop to cleanup after dead threads: */
+ while (pthread != NULL) {
+ /* Save a pointer to the next thread: */
+ pthread_nxt = pthread->nxt;
+
+ /* Check if this thread is one which is running: */
+ if (pthread == _thread_run || pthread == _thread_initial) {
+ /*
+ * Don't destroy the running thread or the initial
+ * thread.
+ */
+ pthread_prv = pthread;
+ }
+ /*
+ * Check if this thread has detached or if it is a signal
+ * handler thread:
+ */
+ else if (((pthread->attr.flags & PTHREAD_DETACHED) != 0) || pthread->parent_thread != NULL) {
+ /* Check if there is no previous dead thread: */
+ if (pthread_prv == NULL) {
+ /*
+ * The dead thread is at the head of the
+ * list:
+ */
+ _thread_dead = pthread_nxt;
+ } else {
+ /*
+ * The dead thread is not at the head of the
+ * list:
+ */
+ pthread_prv->nxt = pthread->nxt;
+ }
+
+ /*
+ * Check if the stack was not specified by the caller
+ * to pthread_create and has not been destroyed yet:
+ */
+ if (pthread->attr.stackaddr_attr == NULL && pthread->stack != NULL) {
+ /* Free the stack of the dead thread: */
+ free(pthread->stack);
+ }
+ /* Free the memory allocated to the thread structure: */
+ free(pthread);
+ } else {
+ /*
+ * This thread has not detached, so do not destroy
+ * it:
+ */
+ pthread_prv = pthread;
+
+ /*
+ * Check if the stack was not specified by the caller
+ * to pthread_create and has not been destroyed yet:
+ */
+ if (pthread->attr.stackaddr_attr == NULL && pthread->stack != NULL) {
+ /* Free the stack of the dead thread: */
+ free(pthread->stack);
+
+ /*
+ * NULL the stack pointer now that the memory
+ * has been freed:
+ */
+ pthread->stack = NULL;
+ }
+ }
+
+ /* Point to the next thread: */
+ pthread = pthread_nxt;
+ }
+
+ /*
+ * Enter a the scheduling loop that finds the next thread that is
+ * ready to run. This loop completes when there are no more threads
+ * in the global list or when a thread has its state restored by
+ * either a sigreturn (if the state was saved as a sigcontext) or a
+ * longjmp (if the state was saved by a setjmp).
+ */
+ while (_thread_link_list != NULL) {
+ /* Get the current time of day: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+
+ /*
+ * Poll file descriptors to update the state of threads
+ * waiting on file I/O where data may be available:
+ */
+ _thread_kern_select(0);
+
+ /*
+ * Enter a loop to look for sleeping threads that are ready
+ * or threads with pending signals that are no longer
+ * blocked:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Enter a loop to process the sending signals: */
+ for (i = 1; i < NSIG; i++) {
+ /*
+ * Check if there are no pending signals of
+ * this type:
+ */
+ if (pthread->sigpend[i] == 0) {
+ }
+ /* Check if this signal type is not masked: */
+ else if (sigismember(&pthread->sigmask, i) == 0) {
+ /*
+ * Delete the signal from the set of
+ * pending signals for this thread:
+ */
+ pthread->sigpend[i] -= 1;
+
+ /*
+ * Act on the signal for the current
+ * thread:
+ */
+ _thread_signal(pthread, i);
+ } else {
+ /*
+ * This signal is masked, so make
+ * sure the count does not exceed 1:
+ */
+ pthread->sigpend[i] = 1;
+ }
+ }
+
+ /* Check if this thread is to timeout: */
+ if (pthread->state == PS_COND_WAIT ||
+ pthread->state == PS_SLEEP_WAIT ||
+ pthread->state == PS_FDR_WAIT ||
+ pthread->state == PS_FDW_WAIT ||
+ pthread->state == PS_SELECT_WAIT) {
+ /* Check if this thread is to wait forever: */
+ if (pthread->wakeup_time.tv_sec == -1) {
+ }
+ /*
+ * Check if this thread is to wakeup
+ * immediately or if it is past its wakeup
+ * time:
+ */
+ else if ((pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) ||
+ (ts.tv_sec > pthread->wakeup_time.tv_sec) ||
+ ((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
+ (ts.tv_nsec >= pthread->wakeup_time.tv_nsec))) {
+ /*
+ * Check if this thread is waiting on
+ * select:
+ */
+ if (pthread->state == PS_SELECT_WAIT) {
+ /*
+ * The select has timed out,
+ * so zero the file
+ * descriptor sets:
+ */
+ FD_ZERO(&pthread->data.select_data->readfds);
+ FD_ZERO(&pthread->data.select_data->writefds);
+ FD_ZERO(&pthread->data.select_data->exceptfds);
+ pthread->data.select_data->nfds = 0;
+ }
+ /*
+ * Return an error as an interrupted
+ * wait:
+ */
+ _thread_seterrno(pthread, EINTR);
+
+ /*
+ * Flag the timeout in the thread
+ * structure:
+ */
+ pthread->timeout = 1;
+
+ /*
+ * Change the threads state to allow
+ * it to be restarted:
+ */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ }
+ }
+
+ /* Check if there is a current thread: */
+ if (_thread_run != &_thread_kern_thread) {
+ /*
+ * Save the current time as the time that the thread
+ * became inactive:
+ */
+ _thread_run->last_inactive.tv_sec = tv.tv_sec;
+ _thread_run->last_inactive.tv_usec = tv.tv_usec;
+
+ /*
+ * Accumulate the number of microseconds that this
+ * thread has run for:
+ */
+ _thread_run->slice_usec += (_thread_run->last_inactive.tv_sec -
+ _thread_run->last_active.tv_sec) * 1000000 +
+ _thread_run->last_inactive.tv_usec -
+ _thread_run->last_active.tv_usec;
+
+ /*
+ * Check if this thread has reached its allocated
+ * time slice period:
+ */
+ if (_thread_run->slice_usec > TIMESLICE_USEC) {
+ /*
+ * Flag the allocated time slice period as
+ * up:
+ */
+ _thread_run->slice_usec = -1;
+ }
+ }
+ /* Check if an incremental priority update is required: */
+ if (((tv.tv_sec - kern_inc_prio_time.tv_sec) * 1000000 +
+ tv.tv_usec - kern_inc_prio_time.tv_usec) > INC_PRIO_USEC) {
+ /*
+ * Enter a loop to look for run-enabled threads that
+ * have not run since the last time that an
+ * incremental priority update was performed:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if this thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ }
+ /*
+ * Check if the last time that this thread
+ * was run (as indicated by the last time it
+ * became inactive) is before the time that
+ * the last incremental priority check was
+ * made:
+ */
+ else if (timercmp(&_thread_run->last_inactive, &kern_inc_prio_time, >)) {
+ /*
+ * Increment the incremental priority
+ * for this thread in the hope that
+ * it will eventually get a chance to
+ * run:
+ */
+ (pthread->inc_prio)++;
+ }
+ }
+
+ /* Save the new incremental priority update time: */
+ kern_inc_prio_time.tv_sec = tv.tv_sec;
+ kern_inc_prio_time.tv_usec = tv.tv_usec;
+ }
+ /*
+ * Enter a loop to look for the first thread of the highest
+ * priority that is ready to run:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
+ /* Check if the current thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ }
+ /*
+ * Check if no run-enabled thread has been seen or if
+ * the current thread has a priority higher than the
+ * highest seen so far:
+ */
+ else if (pthread_h == NULL || (pthread->pthread_priority + pthread->inc_prio) > prio) {
+ /*
+ * Save this thread as the highest priority
+ * thread seen so far:
+ */
+ pthread_h = pthread;
+ prio = pthread->pthread_priority + pthread->inc_prio;
+ }
+ }
+
+ /*
+ * Enter a loop to look for a thread that: 1. Is run-enabled.
+ * 2. Has the required agregate priority. 3. Has not been
+ * allocated its allocated time slice. 4. Became inactive
+ * least recently.
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
+ /* Check if the current thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ /* Ignore threads that are not ready to run. */
+ }
+ /*
+ * Check if the current thread as an agregate
+ * priority not equal to the highest priority found
+ * above:
+ */
+ else if ((pthread->pthread_priority + pthread->inc_prio) != prio) {
+ /*
+ * Ignore threads which have lower agregate
+ * priority.
+ */
+ }
+ /*
+ * Check if the current thread reached its time slice
+ * allocation last time it ran (or if it has not run
+ * yet):
+ */
+ else if (pthread->slice_usec == -1) {
+ }
+ /*
+ * Check if an eligible thread has not been found
+ * yet, or if the current thread has an inactive time
+ * earlier than the last one seen:
+ */
+ else if (pthread_s == NULL || timercmp(&pthread->last_inactive, &tv1, <)) {
+ /*
+ * Save the pointer to the current thread as
+ * the most eligible thread seen so far:
+ */
+ pthread_s = pthread;
+
+ /*
+ * Save the time that the selected thread
+ * became inactive:
+ */
+ tv1.tv_sec = pthread->last_inactive.tv_sec;
+ tv1.tv_usec = pthread->last_inactive.tv_usec;
+ }
+ }
+
+ /*
+ * Check if no thread was selected according to incomplete
+ * time slice allocation:
+ */
+ if (pthread_s == NULL) {
+ /*
+ * Enter a loop to look for any other thread that: 1.
+ * Is run-enabled. 2. Has the required agregate
+ * priority. 3. Became inactive least recently.
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
+ /*
+ * Check if the current thread is unable to
+ * run:
+ */
+ if (pthread->state != PS_RUNNING) {
+ /*
+ * Ignore threads that are not ready
+ * to run.
+ */
+ }
+ /*
+ * Check if the current thread as an agregate
+ * priority not equal to the highest priority
+ * found above:
+ */
+ else if ((pthread->pthread_priority + pthread->inc_prio) != prio) {
+ /*
+ * Ignore threads which have lower
+ * agregate priority.
+ */
+ }
+ /*
+ * Check if an eligible thread has not been
+ * found yet, or if the current thread has an
+ * inactive time earlier than the last one
+ * seen:
+ */
+ else if (pthread_s == NULL || timercmp(&pthread->last_inactive, &tv1, <)) {
+ /*
+ * Save the pointer to the current
+ * thread as the most eligible thread
+ * seen so far:
+ */
+ pthread_s = pthread;
+
+ /*
+ * Save the time that the selected
+ * thread became inactive:
+ */
+ tv1.tv_sec = pthread->last_inactive.tv_sec;
+ tv1.tv_usec = pthread->last_inactive.tv_usec;
+ }
+ }
+ }
+ /* Check if there are no threads ready to run: */
+ if (pthread_s == NULL) {
+ /*
+ * Lock the pthread kernel by changing the pointer to
+ * the running thread to point to the global kernel
+ * thread structure:
+ */
+ _thread_run = &_thread_kern_thread;
+
+ /*
+ * There are no threads ready to run, so wait until
+ * something happens that changes this condition:
+ */
+ _thread_kern_select(1);
+ } else {
+ /* Make the selected thread the current thread: */
+ _thread_run = pthread_s;
+
+ /*
+ * Save the current time as the time that the thread
+ * became active:
+ */
+ _thread_run->last_active.tv_sec = tv.tv_sec;
+ _thread_run->last_active.tv_usec = tv.tv_usec;
+
+ /*
+ * Check if this thread is running for the first time
+ * or running again after using its full time slice
+ * allocation:
+ */
+ if (_thread_run->slice_usec == -1) {
+ /* Reset the accumulated time slice period: */
+ _thread_run->slice_usec = 0;
+ }
+ /*
+ * Reset the incremental priority now that this
+ * thread has been given the chance to run:
+ */
+ _thread_run->inc_prio = 0;
+
+ /* Check if there is more than one thread: */
+ if (_thread_run != _thread_link_list || _thread_run->nxt != NULL) {
+ /*
+ * Define the maximum time before a SIGVTALRM
+ * is required:
+ */
+ itimer.it_value.tv_sec = 0;
+ itimer.it_value.tv_usec = TIMESLICE_USEC;
+
+ /*
+ * The interval timer is not reloaded when it
+ * times out. The interval time needs to be
+ * calculated every time.
+ */
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+
+ /*
+ * Enter a loop to look for threads waiting
+ * for a time:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /*
+ * Check if this thread is to
+ * timeout:
+ */
+ if (pthread->state == PS_COND_WAIT ||
+ pthread->state == PS_SLEEP_WAIT ||
+ pthread->state == PS_FDR_WAIT ||
+ pthread->state == PS_FDW_WAIT ||
+ pthread->state == PS_SELECT_WAIT) {
+ /*
+ * Check if this thread is to
+ * wait forever:
+ */
+ if (pthread->wakeup_time.tv_sec == -1) {
+ }
+ /*
+ * Check if this thread is to
+ * wakeup immediately:
+ */
+ else if (pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) {
+ }
+ /*
+ * Check if the current time
+ * is after the wakeup time:
+ */
+ else if ((ts.tv_sec > pthread->wakeup_time.tv_sec) ||
+ ((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
+ (ts.tv_nsec > pthread->wakeup_time.tv_nsec))) {
+ } else {
+ /*
+ * Calculate the time
+ * until this thread
+ * is ready, allowing
+ * for the clock
+ * resolution:
+ */
+ ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
+ ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
+ CLOCK_RES_NSEC;
+
+ /*
+ * Check for
+ * underflow of the
+ * nanosecond field:
+ */
+ if (ts1.tv_nsec < 0) {
+ /*
+ * Allow for
+ * the
+ * underflow
+ * of the
+ * nanosecond
+ * field:
+ */
+ ts1.tv_sec--;
+ ts1.tv_nsec += 1000000000;
+ }
+ /*
+ * Check for overflow
+ * of the nanosecond
+ * field:
+ */
+ if (ts1.tv_nsec >= 1000000000) {
+ /*
+ * Allow for
+ * the
+ * overflow
+ * of the
+ * nanosecond
+ * field:
+ */
+ ts1.tv_sec++;
+ ts1.tv_nsec -= 1000000000;
+ }
+ /*
+ * Convert the
+ * timespec structure
+ * to a timeval
+ * structure:
+ */
+ TIMESPEC_TO_TIMEVAL(&tv, &ts1);
+
+ /*
+ * Check if the
+ * thread will be
+ * ready sooner than
+ * the earliest one
+ * found so far:
+ */
+ if (timercmp(&tv, &itimer.it_value, <)) {
+ /*
+ * Update the
+ * time
+ * value:
+ */
+ itimer.it_value.tv_sec = tv.tv_sec;
+ itimer.it_value.tv_usec = tv.tv_usec;
+ }
+ }
+ }
+ }
+
+ /*
+ * Start the interval timer for the
+ * calculated time interval:
+ */
+ if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) != 0) {
+ /*
+ * Cannot initialise the timer, so
+ * abort this process:
+ */
+ PANIC("Cannot set virtual timer");
+ }
+ }
+ /* Check if a signal context was saved: */
+ if (_thread_run->sig_saved == 1) {
+#ifndef __alpha
+ /*
+ * Point to the floating point data in the
+ * running thread:
+ */
+ fdata = _thread_run->saved_fp;
+
+ /* Restore the floating point state: */
+ __asm__("frstor %0": :"m"(*fdata));
+#endif
+
+ /*
+ * Do a sigreturn to restart the thread that
+ * was interrupted by a signal:
+ */
+ _thread_sys_sigreturn(&_thread_run->saved_sigcontext);
+ } else {
+ /*
+ * Do a longjmp to restart the thread that
+ * was context switched out (by a longjmp to
+ * a different thread):
+ */
+ _thread_sys_longjmp(_thread_run->saved_jmp_buf, 1);
+ }
+
+ /* This point should not be reached. */
+ PANIC("Thread has returned from sigreturn or longjmp");
+ }
+ }
+
+ /* There are no more threads, so exit this process: */
+ exit(0);
+}
+
+static void
+_thread_signal(pthread_t pthread, int sig)
+{
+ int done;
+ long l;
+ pthread_t new_pthread;
+ struct sigaction act;
+ void *arg;
+
+ /*
+ * Assume that the signal will not be dealt with according
+ * to the thread state:
+ */
+ done = 0;
+
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /* States which do not change when a signal is trapped: */
+ case PS_COND_WAIT:
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_RUNNING:
+ case PS_STATE_MAX:
+ case PS_SIGTHREAD:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* Wait for child: */
+ case PS_WAIT_WAIT:
+ /* Check if the signal is from a child exiting: */
+ if (sig == SIGCHLD) {
+ /* Reset the error: */
+ _thread_seterrno(pthread, 0);
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ } else {
+ /* Return the 'interrupted' error: */
+ _thread_seterrno(pthread, EINTR);
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ pthread->interrupted = 1;
+ break;
+
+ /* Waiting on I/O for zero or more file descriptors: */
+ case PS_SELECT_WAIT:
+ pthread->data.select_data->nfds = -1;
+
+ /* Return the 'interrupted' error: */
+ _thread_seterrno(pthread, EINTR);
+ pthread->interrupted = 1;
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ break;
+
+ /*
+ * States that are interrupted by the occurrence of a signal
+ * other than the scheduling alarm:
+ */
+ case PS_FDR_WAIT:
+ case PS_FDW_WAIT:
+ case PS_SLEEP_WAIT:
+ /* Return the 'interrupted' error: */
+ _thread_seterrno(pthread, EINTR);
+ pthread->interrupted = 1;
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+
+ /* Return the signal number: */
+ pthread->signo = sig;
+ break;
+
+ /* Waiting on a signal: */
+ case PS_SIGWAIT:
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+
+ /* Return the signal number: */
+ pthread->signo = sig;
+
+ /* Flag the signal as dealt with: */
+ done = 1;
+ break;
+ }
+
+ /*
+ * Check if this signal has been dealt with, or is being
+ * ignored:
+ */
+ if (done || pthread->act[sig - 1].sa_handler == SIG_IGN) {
+ /* Ignore the signal for this thread. */
+ }
+ /* Check if this signal is to use the default handler: */
+ else if (pthread->act[sig - 1].sa_handler == SIG_DFL) {
+ /* Process according to signal type: */
+ switch (sig) {
+ /* Signals which cause core dumps: */
+ case SIGQUIT:
+ case SIGILL:
+ case SIGTRAP:
+ case SIGABRT:
+ case SIGEMT:
+ case SIGFPE:
+ case SIGBUS:
+ case SIGSEGV:
+ case SIGSYS:
+ /* Clear the signal action: */
+ sigfillset(&act.sa_mask);
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = SA_RESTART;
+ _thread_sys_sigaction(sig, &act, NULL);
+
+ /*
+ * Do a sigreturn back to where the signal was
+ * detected and a core dump should occur:
+ */
+ _thread_sys_sigreturn(&pthread->saved_sigcontext);
+ break;
+
+ /* Default processing for other signals: */
+ default:
+ /*
+ * ### Default processing is a problem to resolve!
+ * ###
+ */
+ break;
+ }
+ } else {
+ /*
+ * Cast the signal number as a long and then to a void
+ * pointer. Sigh. This is POSIX.
+ */
+ l = (long) sig;
+ arg = (void *) l;
+
+ /* Create a signal handler thread, but don't run it yet: */
+ if (_thread_create(&new_pthread, NULL, (void *) pthread->act[sig - 1].sa_handler, arg, pthread) != 0) {
+ /*
+ * Error creating signal handler thread, so abort
+ * this process:
+ */
+ PANIC("Cannot create signal handler thread");
+ }
+ }
+
+ /* Nothing to return. */
+ return;
+}
+
+void
+_thread_kern_sig_block(int *status)
+{
+ sigset_t oset;
+
+ /*
+ * Block all signals so that the process will not be interrupted by
+ * signals:
+ */
+ _thread_sys_sigprocmask(SIG_SETMASK, &sig_to_block, &oset);
+
+ /* Check if the caller wants the current block status returned: */
+ if (status != NULL) {
+ /* Return the previous signal block status: */
+ *status = (oset != 0);
+ }
+ return;
+}
+
+void
+_thread_kern_sig_unblock(int status)
+{
+ sigset_t oset;
+
+ /*
+ * Check if the caller thinks that signals weren't blocked when it
+ * called _thread_kern_sig_block:
+ */
+ if (status == 0) {
+ /*
+ * Unblock all signals so that the process will be
+ * interrupted when a signal occurs:
+ */
+ _thread_sys_sigprocmask(SIG_SETMASK, &sig_to_unblock, &oset);
+ }
+ return;
+}
+
+void
+_thread_kern_sched_state(enum pthread_state state, char *fname, int lineno)
+{
+ /* Change the state of the current thread: */
+ _thread_run->state = state;
+ _thread_run->fname = fname;
+ _thread_run->lineno = lineno;
+
+ /* Schedule the next thread that is ready: */
+ _thread_kern_sched(NULL);
+ return;
+}
+
+static void
+_thread_kern_select(int wait_reqd)
+{
+ char bufr[128];
+ fd_set fd_set_except;
+ fd_set fd_set_read;
+ fd_set fd_set_write;
+ int count = 0;
+ int count_dec;
+ int found_one;
+ int i;
+ int nfds = -1;
+ int settimeout;
+ pthread_t pthread;
+ ssize_t num;
+ struct timespec ts;
+ struct timespec ts1;
+ struct timeval *p_tv;
+ struct timeval tv;
+ struct timeval tv1;
+
+ /* Zero the file descriptor sets: */
+ FD_ZERO(&fd_set_read);
+ FD_ZERO(&fd_set_write);
+ FD_ZERO(&fd_set_except);
+
+ /* Check if the caller wants to wait: */
+ if (wait_reqd) {
+ /*
+ * Add the pthread kernel pipe file descriptor to the read
+ * set:
+ */
+ FD_SET(_thread_kern_pipe[0], &fd_set_read);
+ nfds = _thread_kern_pipe[0];
+
+ /* Get the current time of day: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+ }
+ /* Initialise the time value structure: */
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ /*
+ * Enter a loop to process threads waiting on either file descriptors
+ * or times:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Assume that this state does not time out: */
+ settimeout = 0;
+
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /*
+ * States which do not depend on file descriptor I/O
+ * operations or timeouts:
+ */
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_RUNNING:
+ case PS_SIGTHREAD:
+ case PS_SIGWAIT:
+ case PS_STATE_MAX:
+ case PS_WAIT_WAIT:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* File descriptor read wait: */
+ case PS_FDR_WAIT:
+ /* Add the file descriptor to the read set: */
+ FD_SET(pthread->data.fd.fd, &fd_set_read);
+
+ /*
+ * Check if this file descriptor is greater than any
+ * of those seen so far:
+ */
+ if (pthread->data.fd.fd > nfds) {
+ /* Remember this file descriptor: */
+ nfds = pthread->data.fd.fd;
+ }
+ /* Increment the file descriptor count: */
+ count++;
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+
+ /* File descriptor write wait: */
+ case PS_FDW_WAIT:
+ /* Add the file descriptor to the write set: */
+ FD_SET(pthread->data.fd.fd, &fd_set_write);
+
+ /*
+ * Check if this file descriptor is greater than any
+ * of those seen so far:
+ */
+ if (pthread->data.fd.fd > nfds) {
+ /* Remember this file descriptor: */
+ nfds = pthread->data.fd.fd;
+ }
+ /* Increment the file descriptor count: */
+ count++;
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+
+ /* States that time out: */
+ case PS_SLEEP_WAIT:
+ case PS_COND_WAIT:
+ /* Flag a timeout as required: */
+ settimeout = 1;
+ break;
+
+ /* Select wait: */
+ case PS_SELECT_WAIT:
+ /*
+ * Enter a loop to process each file descriptor in
+ * the thread-specific file descriptor sets:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ /*
+ * Check if this file descriptor is set for
+ * exceptions:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
+ /*
+ * Add the file descriptor to the
+ * exception set:
+ */
+ FD_SET(i, &fd_set_except);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ /*
+ * Check if this file descriptor is set for
+ * write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
+ /*
+ * Add the file descriptor to the
+ * write set:
+ */
+ FD_SET(i, &fd_set_write);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ /*
+ * Check if this file descriptor is set for
+ * read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
+ /*
+ * Add the file descriptor to the
+ * read set:
+ */
+ FD_SET(i, &fd_set_read);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ }
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+ }
+
+ /*
+ * Check if the caller wants to wait and if the thread state
+ * is one that times out:
+ */
+ if (wait_reqd && settimeout) {
+ /* Check if this thread wants to wait forever: */
+ if (pthread->wakeup_time.tv_sec == -1) {
+ }
+ /* Check if this thread doesn't want to wait at all: */
+ else if (pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) {
+ /* Override the caller's request to wait: */
+ wait_reqd = 0;
+ } else {
+ /*
+ * Calculate the time until this thread is
+ * ready, allowing for the clock resolution:
+ */
+ ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
+ ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
+ CLOCK_RES_NSEC;
+
+ /*
+ * Check for underflow of the nanosecond
+ * field:
+ */
+ if (ts1.tv_nsec < 0) {
+ /*
+ * Allow for the underflow of the
+ * nanosecond field:
+ */
+ ts1.tv_sec--;
+ ts1.tv_nsec += 1000000000;
+ }
+ /*
+ * Check for overflow of the nanosecond
+ * field:
+ */
+ if (ts1.tv_nsec >= 1000000000) {
+ /*
+ * Allow for the overflow of the
+ * nanosecond field:
+ */
+ ts1.tv_sec++;
+ ts1.tv_nsec -= 1000000000;
+ }
+ /*
+ * Convert the timespec structure to a
+ * timeval structure:
+ */
+ TIMESPEC_TO_TIMEVAL(&tv1, &ts1);
+
+ /*
+ * Check if no time value has been found yet,
+ * or if the thread will be ready sooner that
+ * the earliest one found so far:
+ */
+ if ((tv.tv_sec == 0 && tv.tv_usec == 0) || timercmp(&tv1, &tv, <)) {
+ /* Update the time value: */
+ tv.tv_sec = tv1.tv_sec;
+ tv.tv_usec = tv1.tv_usec;
+ }
+ }
+ }
+ }
+
+ /* Check if the caller wants to wait: */
+ if (wait_reqd) {
+ /* Check if no threads were found with timeouts: */
+ if (tv.tv_sec == 0 && tv.tv_usec == 0) {
+ /* Wait forever: */
+ p_tv = NULL;
+ } else {
+ /*
+ * Point to the time value structure which contains
+ * the earliest time that a thread will be ready:
+ */
+ p_tv = &tv;
+ }
+
+ /*
+ * Flag the pthread kernel as in a select. This is to avoid
+ * the window between the next statement that unblocks
+ * signals and the select statement which follows.
+ */
+ _thread_kern_in_select = 1;
+
+ /* Unblock all signals: */
+ _thread_kern_sig_unblock(0);
+
+ /*
+ * Wait for a file descriptor to be ready for read, write, or
+ * an exception, or a timeout to occur:
+ */
+ count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
+
+ /* Block all signals again: */
+ _thread_kern_sig_block(NULL);
+
+ /* Reset the kernel in select flag: */
+ _thread_kern_in_select = 0;
+
+ /*
+ * Check if it is possible that there are bytes in the kernel
+ * read pipe waiting to be read:
+ */
+ if (count < 0 || FD_ISSET(_thread_kern_pipe[0], &fd_set_read)) {
+ /*
+ * Check if the kernel read pipe was included in the
+ * count:
+ */
+ if (count > 0) {
+ /*
+ * Remove the kernel read pipe from the
+ * count:
+ */
+ FD_CLR(_thread_kern_pipe[0], &fd_set_read);
+
+ /* Decrement the count of file descriptors: */
+ count--;
+ }
+ /*
+ * Enter a loop to read (and trash) bytes from the
+ * pthread kernel pipe:
+ */
+ while ((num = _thread_sys_read(_thread_kern_pipe[0], bufr, sizeof(bufr))) > 0) {
+ /*
+ * The buffer read contains one byte per
+ * signal and each byte is the signal number.
+ * This data is not used, but the fact that
+ * the signal handler wrote to the pipe *is*
+ * used to cause the _thread_sys_select call
+ * to complete if the signal occurred between
+ * the time when signals were unblocked and
+ * the _thread_sys_select select call being
+ * made.
+ */
+ }
+ }
+ }
+ /* Check if there are file descriptors to poll: */
+ else if (count > 0) {
+ /*
+ * Point to the time value structure which has been zeroed so
+ * that the call to _thread_sys_select will not wait:
+ */
+ p_tv = &tv;
+
+ /* Poll file descrptors without wait: */
+ count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
+ }
+ /*
+ * Check if the select call was interrupted, or some other error
+ * occurred:
+ */
+ if (count < 0) {
+ /* Check if the select call was interrupted: */
+ if (errno == EINTR) {
+ /*
+ * Interrupted calls are expected. The interrupting
+ * signal will be in the sigpend array.
+ */
+ } else {
+ /* This should not occur: */
+ }
+ }
+ /* Check if no file descriptors are ready: */
+ else if (count == 0) {
+ /* Nothing to do here. */
+ } else {
+ /*
+ * Enter a loop to look for threads waiting on file
+ * descriptors that are flagged as available by the
+ * _thread_sys_select syscall:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /*
+ * States which do not depend on file
+ * descriptor I/O operations:
+ */
+ case PS_RUNNING:
+ case PS_COND_WAIT:
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_SIGWAIT:
+ case PS_SLEEP_WAIT:
+ case PS_WAIT_WAIT:
+ case PS_SIGTHREAD:
+ case PS_STATE_MAX:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* File descriptor read wait: */
+ case PS_FDR_WAIT:
+ /*
+ * Check if the file descriptor is available
+ * for read:
+ */
+ if (FD_ISSET(pthread->data.fd.fd, &fd_set_read)) {
+ /*
+ * Change the thread state to allow
+ * it to read from the file when it
+ * is scheduled next:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+
+ /* File descriptor write wait: */
+ case PS_FDW_WAIT:
+ /*
+ * Check if the file descriptor is available
+ * for write:
+ */
+ if (FD_ISSET(pthread->data.fd.fd, &fd_set_write)) {
+ /*
+ * Change the thread state to allow
+ * it to write to the file when it is
+ * scheduled next:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+
+ /* Select wait: */
+ case PS_SELECT_WAIT:
+ /*
+ * Reset the flag that indicates if a file
+ * descriptor is ready for some type of
+ * operation:
+ */
+ count_dec = 0;
+
+ /*
+ * Enter a loop to search though the
+ * thread-specific select file descriptors
+ * for the first descriptor that is ready:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds && count_dec == 0; i++) {
+ /*
+ * Check if this file descriptor does
+ * not have an exception:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds) && FD_ISSET(i, &fd_set_except)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ /*
+ * Check if this file descriptor is
+ * not ready for write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds) && FD_ISSET(i, &fd_set_write)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ /*
+ * Check if this file descriptor is
+ * not ready for read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds) && FD_ISSET(i, &fd_set_read)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ }
+
+ /*
+ * Check if any file descriptors are ready
+ * for the current thread:
+ */
+ if (count_dec) {
+ /*
+ * Reset the count of file
+ * descriptors that are ready for
+ * this thread:
+ */
+ found_one = 0;
+
+ /*
+ * Enter a loop to search though the
+ * thread-specific select file
+ * descriptors:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ /*
+ * Reset the count of
+ * operations for which the
+ * current file descriptor is
+ * ready:
+ */
+ count_dec = 0;
+
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * exceptions:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
+ /*
+ * Check if this file
+ * descriptor has an
+ * exception:
+ */
+ if (FD_ISSET(i, &fd_set_except)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->exceptfds);
+ }
+ }
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
+ /*
+ * Check if this file
+ * descriptor is
+ * ready for write:
+ */
+ if (FD_ISSET(i, &fd_set_write)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->writefds);
+ }
+ }
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
+ /*
+ * Check if this file
+ * descriptor is
+ * ready for read:
+ */
+ if (FD_ISSET(i, &fd_set_read)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->readfds);
+ }
+ }
+ /*
+ * Check if the current file
+ * descriptor is ready for
+ * any one of the operations:
+ */
+ if (count_dec > 0) {
+ /*
+ * Increment the
+ * count of file
+ * descriptors that
+ * are ready for the
+ * current thread:
+ */
+ found_one++;
+ }
+ }
+
+ /*
+ * Return the number of file
+ * descriptors that are ready:
+ */
+ pthread->data.select_data->nfds = found_one;
+
+ /*
+ * Change the state of the current
+ * thread to run:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+ }
+ }
+ }
+
+ /* Nothing to return. */
+ return;
+}
+
+void
+_thread_kern_set_timeout(struct timespec * timeout)
+{
+ struct timespec current_time;
+ struct timeval tv;
+
+ /* Reset the timeout flag for the running thread: */
+ _thread_run->timeout = 0;
+
+ /* Check if the thread is to wait forever: */
+ if (timeout == NULL) {
+ /*
+ * Set the wakeup time to something that can be recognised as
+ * different to an actual time of day:
+ */
+ _thread_run->wakeup_time.tv_sec = -1;
+ _thread_run->wakeup_time.tv_nsec = -1;
+ }
+ /* Check if no waiting is required: */
+ else if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
+ /* Set the wake up time to 'immediately': */
+ _thread_run->wakeup_time.tv_sec = 0;
+ _thread_run->wakeup_time.tv_nsec = 0;
+ } else {
+ /* Get the current time: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &current_time);
+
+ /* Calculate the time for the current thread to wake up: */
+ _thread_run->wakeup_time.tv_sec = current_time.tv_sec + timeout->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + timeout->tv_nsec;
+
+ /* Check if the nanosecond field needs to wrap: */
+ if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
+ /* Wrap the nanosecond field: */
+ _thread_run->wakeup_time.tv_sec += 1;
+ _thread_run->wakeup_time.tv_nsec -= 1000000000;
+ }
+ }
+ return;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_kill.c b/lib/libc_r/uthread/uthread_kill.c
new file mode 100644
index 0000000..eb2c6b7
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_kill.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_kill(pthread_t pthread, int sig)
+{
+ int rval = 0;
+ int status;
+ pthread_t p_pthread;
+
+ /* Check for invalid signal numbers: */
+ if (sig < 0 || sig >= NSIG)
+ /* Invalid signal: */
+ rval = EINVAL;
+ else {
+ /* Assume that the search will succeed: */
+ rval = 0;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Search for the thread: */
+ p_pthread = _thread_link_list;
+ while (p_pthread != NULL && p_pthread != pthread) {
+ p_pthread = p_pthread->nxt;
+ }
+
+ /* Check if the thread was not found: */
+ if (p_pthread == NULL)
+ /* Can't find the thread: */
+ rval = ESRCH;
+ else
+ /* Increment the pending signal count: */
+ p_pthread->sigpend[sig] += 1;
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_listen.c b/lib/libc_r/uthread/uthread_listen.c
new file mode 100644
index 0000000..453f25e
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_listen.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+listen(int fd, int backlog)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_listen(fd, backlog);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_longjmp.c b/lib/libc_r/uthread/uthread_longjmp.c
new file mode 100644
index 0000000..435f3cf
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_longjmp.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* ### This function needs to do something special with signals? ### */
+void
+longjmp(jmp_buf env, int val)
+{
+ _thread_sys_longjmp(env, val);
+ abort();
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_mattr_init.c b/lib/libc_r/uthread/uthread_mattr_init.c
new file mode 100644
index 0000000..323c982
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_mattr_init.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1996 Jeffrey Hsu <hsu@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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_mutexattr_init(pthread_mutexattr_t *attr)
+{
+ int ret;
+ pthread_mutexattr_t pattr;
+
+ if ((pattr = (pthread_mutexattr_t)
+ malloc(sizeof(struct pthread_mutex_attr))) == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ memcpy(pattr, &pthread_mutexattr_default,
+ sizeof(struct pthread_mutex_attr));
+ *attr = pattr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_mattr_kind_np.c b/lib/libc_r/uthread/uthread_mattr_kind_np.c
new file mode 100644
index 0000000..3eeabff
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_mattr_kind_np.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1996 Jeffrey Hsu <hsu@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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ (*attr)->m_type = kind;
+ ret = 0;
+ }
+ return(ret);
+}
+
+int
+pthread_mutexattr_getkind_np(pthread_mutexattr_t attr)
+{
+ int ret;
+ if (attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ ret = attr->m_type;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_multi_np.c b/lib/libc_r/uthread/uthread_multi_np.c
new file mode 100644
index 0000000..64f360f
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_multi_np.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_multi_np()
+{
+ /* Return to multi-threaded scheduling mode: */
+ _thread_single = NULL;
+ return(0);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_mutex.c b/lib/libc_r/uthread/uthread_mutex.c
new file mode 100644
index 0000000..82a26e8
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_mutex.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_mutex_init(pthread_mutex_t * mutex,
+ const pthread_mutexattr_t * mutex_attr)
+{
+ enum pthread_mutextype type;
+ pthread_mutex_t pmutex;
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Check if default mutex attributes: */
+ if (mutex_attr == NULL || *mutex_attr == NULL) {
+ /* Default to a fast mutex: */
+ type = MUTEX_TYPE_FAST;
+ } else if ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Use the requested mutex type: */
+ type = (*mutex_attr)->m_type;
+ }
+
+ /* Check no errors so far: */
+ if (ret == 0) {
+ if ((pmutex = (pthread_mutex_t) malloc(sizeof(struct pthread_mutex))) == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ /* Reset the mutex flags: */
+ pmutex->m_flags = 0;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch (type) {
+ /* Fast mutex: */
+ case MUTEX_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Reset the mutex count: */
+ pmutex->m_data.m_count = 0;
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+ if (ret == 0) {
+ /* Initialise the rest of the mutex: */
+ _thread_queue_init(&pmutex->m_queue);
+ pmutex->m_flags |= MUTEX_FLAGS_INITED;
+ pmutex->m_owner = NULL;
+ pmutex->m_type = type;
+ *mutex = pmutex;
+ } else {
+ free(pmutex);
+ *mutex = NULL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+ }
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_destroy(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutex: */
+ case MUTEX_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Reset the mutex count: */
+ (*mutex)->m_data.m_count = 0;
+ break;
+
+ /* Trap undefined mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Clean up the mutex in case that others want to use it: */
+ _thread_queue_init(&(*mutex)->m_queue);
+ (*mutex)->m_owner = NULL;
+ (*mutex)->m_flags = 0;
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_trylock(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutex: */
+ case MUTEX_TYPE_FAST:
+ /* Check if this mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for the running thread: */
+ (*mutex)->m_owner = _thread_run;
+ } else {
+ /* Return a busy error: */
+ errno = EBUSY;
+ ret = -1;
+ }
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Check if this mutex is locked: */
+ if ((*mutex)->m_owner != NULL) {
+ /*
+ * Check if the mutex is locked by the running
+ * thread:
+ */
+ if ((*mutex)->m_owner == _thread_run) {
+ /* Increment the lock count: */
+ (*mutex)->m_data.m_count++;
+ } else {
+ /* Return a busy error: */
+ errno = EBUSY;
+ ret = -1;
+ }
+ } else {
+ /* Lock the mutex for the running thread: */
+ (*mutex)->m_owner = _thread_run;
+ }
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_lock(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutexes do not check for any error conditions: */
+ case MUTEX_TYPE_FAST:
+ /*
+ * Enter a loop to wait for the mutex to be locked by the
+ * current thread:
+ */
+ while ((*mutex)->m_owner != _thread_run) {
+ /* Check if the mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for this thread: */
+ (*mutex)->m_owner = _thread_run;
+ } else {
+ /*
+ * Join the queue of threads waiting to lock
+ * the mutex:
+ */
+ _thread_queue_enq(&(*mutex)->m_queue, _thread_run);
+
+ /* Block signals: */
+ _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+ }
+ }
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /*
+ * Enter a loop to wait for the mutex to be locked by the
+ * current thread:
+ */
+ while ((*mutex)->m_owner != _thread_run) {
+ /* Check if the mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for this thread: */
+ (*mutex)->m_owner = _thread_run;
+
+ /* Reset the lock count for this mutex: */
+ (*mutex)->m_data.m_count = 0;
+ } else {
+ /*
+ * Join the queue of threads waiting to lock
+ * the mutex:
+ */
+ _thread_queue_enq(&(*mutex)->m_queue, _thread_run);
+
+ /* Block signals: */
+ _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+ }
+ }
+
+ /* Increment the lock count for this mutex: */
+ (*mutex)->m_data.m_count++;
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_unlock(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutexes do not check for any error conditions: */
+ case MUTEX_TYPE_FAST:
+ /* Check if the running thread is not the owner of the mutex: */
+ if ((*mutex)->m_owner != _thread_run) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ }
+ /*
+ * Get the next thread from the queue of threads waiting on
+ * the mutex:
+ */
+ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
+ /* Allow the new owner of the mutex to run: */
+ PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING);
+ }
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Check if the running thread is not the owner of the mutex: */
+ if ((*mutex)->m_owner != _thread_run) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ }
+ /* Check if there are still counts: */
+ else if ((*mutex)->m_data.m_count) {
+ /* Decrement the count: */
+ (*mutex)->m_data.m_count--;
+ }
+ /*
+ * Get the next thread from the queue of threads waiting on
+ * the mutex:
+ */
+ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
+ /* Allow the new owner of the mutex to run: */
+ PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING);
+ }
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_mutexattr_destroy.c b/lib/libc_r/uthread/uthread_mutexattr_destroy.c
new file mode 100644
index 0000000..cf2e09f
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_mutexattr_destroy.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ free(*attr);
+ *attr = NULL;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_nanosleep.c b/lib/libc_r/uthread/uthread_nanosleep.c
new file mode 100644
index 0000000..39c7dad
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_nanosleep.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdio.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+nanosleep(const struct timespec * time_to_sleep,
+ struct timespec * time_remaining)
+{
+ int ret = 0;
+ struct timespec current_time;
+ struct timespec current_time1;
+ struct timespec remaining_time;
+ struct timeval tv;
+
+ /* Check if the time to sleep is legal: */
+ if (time_to_sleep == NULL || time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec > 1000000000) {
+ /* Return an EINVAL error : */
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Get the current time: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &current_time);
+
+ /* Calculate the time for the current thread to wake up: */
+ _thread_run->wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec;
+
+ /* Check if the nanosecond field has overflowed: */
+ if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
+ /* Wrap the nanosecond field: */
+ _thread_run->wakeup_time.tv_sec += 1;
+ _thread_run->wakeup_time.tv_nsec -= 1000000000;
+ }
+
+ /* Reschedule the current thread to sleep: */
+ _thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__);
+
+ /* Get the current time: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &current_time1);
+
+ /* Calculate the remaining time to sleep: */
+ remaining_time.tv_sec = time_to_sleep->tv_sec + current_time.tv_sec - current_time1.tv_sec;
+ remaining_time.tv_nsec = time_to_sleep->tv_nsec + current_time.tv_nsec - current_time1.tv_nsec;
+
+ /* Check if the nanosecond field has underflowed: */
+ if (remaining_time.tv_nsec < 0) {
+ /* Handle the underflow: */
+ remaining_time.tv_sec -= 1;
+ remaining_time.tv_nsec += 1000000000;
+ }
+
+ /* Check if the nanosecond field has overflowed: */
+ if (remaining_time.tv_nsec >= 1000000000) {
+ /* Handle the overflow: */
+ remaining_time.tv_sec += 1;
+ remaining_time.tv_nsec -= 1000000000;
+ }
+
+ /* Check if the sleep was longer than the required time: */
+ if (remaining_time.tv_sec < 0) {
+ /* Reset the time left: */
+ remaining_time.tv_sec = 0;
+ remaining_time.tv_nsec = 0;
+ }
+
+ /* Check if the time remaining is to be returned: */
+ if (time_remaining != NULL) {
+ /* Return the actual time slept: */
+ time_remaining->tv_sec = remaining_time.tv_sec;
+ time_remaining->tv_nsec = remaining_time.tv_nsec;
+ }
+
+ /* Check if the entire sleep was not completed: */
+ if (remaining_time.tv_nsec != 0 || remaining_time.tv_sec != 0) {
+ /* Return an EINTR error : */
+ errno = EINTR;
+ ret = -1;
+ }
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_once.c b/lib/libc_r/uthread/uthread_once.c
new file mode 100644
index 0000000..c55ba9e
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_once.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_once(pthread_once_t * once_control, void (*init_routine) (void))
+{
+ if (once_control->state == PTHREAD_NEEDS_INIT) {
+ pthread_mutex_lock(&(once_control->mutex));
+ if (once_control->state == PTHREAD_NEEDS_INIT) {
+ init_routine();
+ once_control->state = PTHREAD_DONE_INIT;
+ }
+ pthread_mutex_unlock(&(once_control->mutex));
+ }
+ return (0);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_open.c b/lib/libc_r/uthread/uthread_open.c
new file mode 100644
index 0000000..ef7a504
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_open.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+open(const char *path, int flags,...)
+{
+ int fd;
+ int mode = 0;
+ int status;
+ va_list ap;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Check if the file is being created: */
+ if (flags & O_CREAT) {
+ /* Get the creation mode: */
+ va_start(ap, flags);
+ mode = va_arg(ap, int);
+ va_end(ap);
+ }
+ /* Open the file: */
+ if ((fd = _thread_sys_open(path, flags, mode)) < 0) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(fd) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(fd);
+
+ /* Reset the file descriptor: */
+ fd = -1;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the file descriptor or -1 on error: */
+ return (fd);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_pipe.c b/lib/libc_r/uthread/uthread_pipe.c
new file mode 100644
index 0000000..5bac6b3
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_pipe.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <unistd.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pipe(int fds[2])
+{
+ int ret;
+ if ((ret = _thread_sys_pipe(fds)) >= 0) {
+ if (_thread_fd_table_init(fds[0]) != 0 ||
+ _thread_fd_table_init(fds[1]) != 0) {
+ _thread_sys_close(fds[0]);
+ _thread_sys_close(fds[1]);
+ ret = -1;
+ }
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_queue.c b/lib/libc_r/uthread/uthread_queue.c
new file mode 100644
index 0000000..5225ab8
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_queue.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+_thread_queue_init(struct pthread_queue * queue)
+{
+ /* Initialise the pointers in the queue structure: */
+ queue->q_next = NULL;
+ queue->q_last = NULL;
+ queue->q_data = NULL;
+ return;
+}
+
+void
+_thread_queue_enq(struct pthread_queue * queue, struct pthread * thread)
+{
+ if (queue->q_last) {
+ queue->q_last->qnxt = thread;
+ } else {
+ queue->q_next = thread;
+ }
+ queue->q_last = thread;
+ thread->queue = queue;
+ thread->qnxt = NULL;
+ return;
+}
+
+struct pthread *
+_thread_queue_get(struct pthread_queue * queue)
+{
+ /* Return the pointer to the next thread in the queue: */
+ return (queue->q_next);
+}
+
+struct pthread *
+_thread_queue_deq(struct pthread_queue * queue)
+{
+ struct pthread *thread = NULL;
+
+ if (queue->q_next) {
+ thread = queue->q_next;
+ if (!(queue->q_next = queue->q_next->qnxt)) {
+ queue->q_last = NULL;
+ }
+ thread->queue = NULL;
+ thread->qnxt = NULL;
+ }
+ return (thread);
+}
+
+int
+_thread_queue_remove(struct pthread_queue * queue, struct pthread * thread)
+{
+ struct pthread **current = &(queue->q_next);
+ struct pthread *prev = NULL;
+ int ret = -1;
+
+ while (*current) {
+ if (*current == thread) {
+ if ((*current)->qnxt) {
+ *current = (*current)->qnxt;
+ } else {
+ queue->q_last = prev;
+ *current = NULL;
+ }
+ ret = 0;
+ break;
+ }
+ prev = *current;
+ current = &((*current)->qnxt);
+ }
+ thread->queue = NULL;
+ thread->qnxt = NULL;
+ return (ret);
+}
+
+int
+pthread_llist_remove(struct pthread ** llist, struct pthread * thread)
+{
+ while (*llist) {
+ if (*llist == thread) {
+ *llist = thread->qnxt;
+ return (0);
+ }
+ llist = &(*llist)->qnxt;
+ }
+ return (-1);
+}
+
+#endif
diff --git a/lib/libc_r/uthread/uthread_read.c b/lib/libc_r/uthread/uthread_read.c
new file mode 100644
index 0000000..242014e
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_read.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+read(int fd, void *buf, size_t nbytes)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read: */
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking read syscall: */
+ while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDR_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_readv.c b/lib/libc_r/uthread/uthread_readv.c
new file mode 100644
index 0000000..3ea065e
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_readv.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+readv(int fd, const struct iovec * iov, int iovcnt)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read: */
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking readv syscall: */
+ while ((ret = _thread_sys_readv(fd, iov, iovcnt)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDR_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_recvfrom.c b/lib/libc_r/uthread/uthread_recvfrom.c
new file mode 100644
index 0000000..a3d6a7d
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_recvfrom.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr * from, int *from_len)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ while ((ret = _thread_sys_recvfrom(fd, buf, len, flags, from, from_len)) < 0) {
+ if (!(_thread_fd_table[fd]->flags & O_NONBLOCK) && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ _thread_run->data.fd.fd = fd;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(NULL);
+ _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
+
+ /* Check if the wait was interrupted: */
+ if (errno == EINTR) {
+ /* Return an error status: */
+ ret = -1;
+ break;
+ }
+ } else {
+ ret = -1;
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_resume.c b/lib/libc_r/uthread/uthread_resume.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_resume.c
diff --git a/lib/libc_r/uthread/uthread_resume_np.c b/lib/libc_r/uthread/uthread_resume_np.c
new file mode 100644
index 0000000..934df58
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_resume_np.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_resume_np(pthread_t thread)
+{
+ int ret = -1;
+ pthread_t pthread;
+ /*
+ * Search for the thread in the linked list.
+ */
+ for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
+ /* Is this the thread? */
+ if (pthread == thread) {
+ /* Found the thread. Is it suspended? */
+ if (pthread->state == PS_SUSPENDED) {
+ /* Allow the thread to run. */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ ret = 0;
+ } else if (pthread->state == PS_RUNNING) {
+ /* Thread is already running. */
+ ret = 0;
+ } else {
+ /* Thread is in some other state. */
+ errno = EINVAL;
+ }
+ }
+ }
+ /* Check if thread was not found. */
+ if (ret == -1) {
+ /* No such thread */
+ errno = ESRCH;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_select.c b/lib/libc_r/uthread/uthread_select.c
new file mode 100644
index 0000000..7db3ed2
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_select.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+select(int numfds, fd_set * readfds, fd_set * writefds,
+ fd_set * exceptfds, struct timeval * timeout)
+{
+ fd_set read_locks, write_locks, rdwr_locks;
+ struct timespec ts;
+ struct timeval zero_timeout = {0, 0};
+ int i, ret = 0, got_all_locks = 1;
+ struct pthread_select_data data;
+
+ if (numfds > _thread_dtablesize) {
+ numfds = _thread_dtablesize;
+ }
+ /* Check if a timeout was specified: */
+ if (timeout) {
+ /* Convert the timeval to a timespec: */
+ TIMEVAL_TO_TIMESPEC(timeout, &ts);
+
+ /* Set the wake up time: */
+ _thread_kern_set_timeout(&ts);
+ } else {
+ /* Wait for ever: */
+ _thread_kern_set_timeout(NULL);
+ }
+
+ FD_ZERO(&read_locks);
+ FD_ZERO(&write_locks);
+ FD_ZERO(&rdwr_locks);
+
+ /* lock readfds */
+ if (readfds || writefds || exceptfds) {
+ for (i = 0; i < numfds; i++) {
+ if ((readfds && (FD_ISSET(i, readfds))) || (exceptfds && FD_ISSET(i, exceptfds))) {
+ if (writefds && FD_ISSET(i, writefds)) {
+ if ((ret = _thread_fd_lock(i, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &rdwr_locks);
+ } else {
+ if ((ret = _thread_fd_lock(i, FD_READ, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &read_locks);
+ }
+ } else {
+ if (writefds && FD_ISSET(i, writefds)) {
+ if ((ret = _thread_fd_lock(i, FD_WRITE, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &write_locks);
+ }
+ }
+ }
+ }
+ if (got_all_locks) {
+ data.nfds = numfds;
+ FD_ZERO(&data.readfds);
+ FD_ZERO(&data.writefds);
+ FD_ZERO(&data.exceptfds);
+ if (readfds != NULL) {
+ memcpy(&data.readfds, readfds, sizeof(data.readfds));
+ }
+ if (writefds != NULL) {
+ memcpy(&data.writefds, writefds, sizeof(data.writefds));
+ }
+ if (exceptfds != NULL) {
+ memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds));
+ }
+ if ((ret = _thread_sys_select(data.nfds, &data.readfds, &data.writefds, &data.exceptfds, &zero_timeout)) == 0) {
+ data.nfds = numfds;
+ FD_ZERO(&data.readfds);
+ FD_ZERO(&data.writefds);
+ FD_ZERO(&data.exceptfds);
+ if (readfds != NULL) {
+ memcpy(&data.readfds, readfds, sizeof(data.readfds));
+ }
+ if (writefds != NULL) {
+ memcpy(&data.writefds, writefds, sizeof(data.writefds));
+ }
+ if (exceptfds != NULL) {
+ memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds));
+ }
+ _thread_run->data.select_data = &data;
+ _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__);
+ ret = data.nfds;
+ }
+ }
+ /* clean up the locks */
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &read_locks))
+ _thread_fd_unlock(i, FD_READ);
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &rdwr_locks))
+ _thread_fd_unlock(i, FD_RDWR);
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &write_locks))
+ _thread_fd_unlock(i, FD_WRITE);
+
+ if (ret > 0) {
+ if (readfds != NULL) {
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, readfds) &&
+ !FD_ISSET(i, &data.readfds)) {
+ FD_CLR(i, readfds);
+ }
+ }
+ }
+ if (writefds != NULL) {
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, writefds) &&
+ !FD_ISSET(i, &data.writefds)) {
+ FD_CLR(i, writefds);
+ }
+ }
+ }
+ if (exceptfds != NULL) {
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, exceptfds) &&
+ !FD_ISSET(i, &data.exceptfds)) {
+ FD_CLR(i, exceptfds);
+ }
+ }
+ }
+ }
+
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_self.c b/lib/libc_r/uthread/uthread_self.c
new file mode 100644
index 0000000..a0a2d2a
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_self.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pthread_t
+pthread_self(void)
+{
+ /* Return the running thread pointer: */
+ return (_thread_run);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sendto.c b/lib/libc_r/uthread/uthread_sendto.c
new file mode 100644
index 0000000..c7155c8
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sendto.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+sendto(int fd, const void *msg, size_t len, int flags, const struct sockaddr * to, int to_len)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_WRITE, NULL, __FILE__, __LINE__)) == 0) {
+ while ((ret = _thread_sys_sendto(fd, msg, len, flags, to, to_len)) < 0) {
+ if (!(_thread_fd_table[fd]->flags & O_NONBLOCK) && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ _thread_run->data.fd.fd = fd;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(NULL);
+ _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__);
+ } else {
+ ret = -1;
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_WRITE);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_seterrno.c b/lib/libc_r/uthread/uthread_seterrno.c
new file mode 100644
index 0000000..c4fe08b6
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_seterrno.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/*
+ * This function needs to reference the global error variable which is
+ * normally hidden from the user.
+ */
+#ifdef errno
+#undef errno;
+#endif
+extern int errno;
+
+void
+_thread_seterrno(pthread_t thread, int error)
+{
+ /* Check for the initial thread: */
+ if (thread == _thread_initial) {
+ /* The initial thread always uses the global error variable: */
+ errno = error;
+ } else {
+ /*
+ * Threads other than the initial thread always use the error
+ * field in the thread structureL
+ */
+ thread->error = error;
+ }
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_setjmp.c b/lib/libc_r/uthread/uthread_setjmp.c
new file mode 100644
index 0000000..7820466
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_setjmp.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* ### This function needs to do something special with signals? ### */
+int
+setjmp(jmp_buf env)
+{
+ return (_thread_sys_setjmp(env));
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_setprio.c b/lib/libc_r/uthread/uthread_setprio.c
new file mode 100644
index 0000000..4b49ed0
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_setprio.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_setprio(pthread_t pthread, int prio)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread_p;
+
+ /* Check if the priority is invalid: */
+ if (prio < PTHREAD_MIN_PRIORITY || prio > PTHREAD_MAX_PRIORITY) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the first thread in the list: */
+ pthread_p = _thread_link_list;
+
+ /* Enter a loop to search for the thread: */
+ while (pthread_p != NULL && pthread_p != pthread) {
+ /* Point to the next thread: */
+ pthread_p = pthread_p->nxt;
+ }
+
+ /* Check if the thread pointer is NULL: */
+ if (pthread == NULL || pthread_p == NULL) {
+ /* Return a 'search' error: */
+ errno = ESRCH;
+ rval = -1;
+ } else {
+ /* Set the thread priority: */
+ pthread->pthread_priority = prio;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the error status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_setsockopt.c b/lib/libc_r/uthread/uthread_setsockopt.c
new file mode 100644
index 0000000..be004a3
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_setsockopt.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+setsockopt(int fd, int level, int optname, const void *optval, int optlen)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_setsockopt(fd, level, optname, optval, optlen);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return ret;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_shutdown.c b/lib/libc_r/uthread/uthread_shutdown.c
new file mode 100644
index 0000000..5e06910
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_shutdown.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+shutdown(int fd, int how)
+{
+ int ret;
+
+ switch (how) {
+ case 0:
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_shutdown(fd, how);
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ break;
+ case 1:
+ if ((ret = _thread_fd_lock(fd, FD_WRITE, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_shutdown(fd, how);
+ _thread_fd_unlock(fd, FD_WRITE);
+ }
+ break;
+ case 2:
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_shutdown(fd, how);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ break;
+ default:
+ errno = EBADF;
+ ret = -1;
+ break;
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sig.c b/lib/libc_r/uthread/uthread_sig.c
new file mode 100644
index 0000000..e73d5a2
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sig.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+_thread_sig_handler(int sig, int code, struct sigcontext * scp)
+{
+ char c;
+ int i;
+ pthread_t pthread;
+
+ /*
+ * Check if the pthread kernel has unblocked signals (or is about to)
+ * and was on its way into a _thread_sys_select when the current
+ * signal interrupted it:
+ */
+ if (_thread_kern_in_select) {
+ /* Cast the signal number to a character variable: */
+ c = sig;
+
+ /*
+ * Write the signal number to the kernel pipe so that it will
+ * be ready to read when this signal handler returns. This
+ * means that the _thread_sys_select call will complete
+ * immediately.
+ */
+ if (_thread_sys_write(_thread_kern_pipe[1], &c, 1) != 1) {
+ }
+ }
+ /* Check if the signal requires a dump of thread information: */
+ if (sig == SIGINFO) {
+ /* Dump thread information to file: */
+ _thread_dump_info();
+ } else {
+ /* Handle depending on signal type: */
+ switch (sig) {
+ /* Interval timer used for timeslicing: */
+ case SIGVTALRM:
+ /*
+ * Don't add the signal to any thread. Just want to
+ * call the scheduler:
+ */
+ break;
+
+ /* Child termination: */
+ case SIGCHLD:
+ /*
+ * Enter a loop to process each thread in the linked
+ * list:
+ */
+ for (pthread = _thread_link_list; pthread != NULL;
+ pthread = pthread->nxt) {
+ /*
+ * Add the signal to the set of pending
+ * signals:
+ */
+ pthread->sigpend[sig] += 1;
+ if (pthread->state == PS_WAIT_WAIT) {
+ /* Reset the error: */
+ /* There should be another flag so that this is not required! ### */
+ _thread_seterrno(pthread, 0);
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ }
+
+ /*
+ * Go through the file list and set all files
+ * to non-blocking again in case the child
+ * set some of them to block. Sigh.
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Check if this file is used: */
+ if (_thread_fd_table[i] != NULL) {
+ /* Set the file descriptor to non-blocking: */
+ _thread_sys_fcntl(i, F_SETFL, _thread_fd_table[i]->flags | O_NONBLOCK);
+ }
+ }
+ break;
+
+ /* Signals specific to the running thread: */
+ case SIGBUS:
+ case SIGEMT:
+ case SIGFPE:
+ case SIGILL:
+ case SIGPIPE:
+ case SIGSEGV:
+ case SIGSYS:
+ /* Add the signal to the set of pending signals: */
+ _thread_run->sigpend[sig] += 1;
+ break;
+
+ /* Signals to send to all threads: */
+ default:
+ /*
+ * Enter a loop to process each thread in the linked
+ * list:
+ */
+ for (pthread = _thread_link_list; pthread != NULL;
+ pthread = pthread->nxt) {
+ /*
+ * Add the signal to the set of pending
+ * signals:
+ */
+ pthread->sigpend[sig] += 1;
+ }
+ break;
+ }
+
+ /* Check if the kernel is not locked: */
+ if (_thread_run != &_thread_kern_thread) {
+ /*
+ * Schedule the next thread. This function is not
+ * expected to return because it will do a longjmp
+ * instead.
+ */
+ _thread_kern_sched(scp);
+
+ /*
+ * This point should not be reached, so abort the
+ * process:
+ */
+ PANIC("Returned to signal function from scheduler");
+ }
+ }
+
+ /* Returns nothing. */
+ return;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigaction.c b/lib/libc_r/uthread/uthread_sigaction.c
new file mode 100644
index 0000000..dd08405
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigaction.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
+{
+ int ret = 0;
+ int status;
+
+ /* Check if the signal number is out of range: */
+ if (sig < 1 || sig > NSIG) {
+ /* Return an invalid argument: */
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /*
+ * Check if the existing signal action structure contents are
+ * to be returned:
+ */
+ if (oact != NULL) {
+ /* Return the existing signal action contents: */
+ oact->sa_handler = _thread_run->act[sig - 1].sa_handler;
+ oact->sa_mask = _thread_run->act[sig - 1].sa_mask;
+ oact->sa_flags = _thread_run->act[sig - 1].sa_flags;
+ }
+ /* Check if a signal action was supplied: */
+ if (act != NULL) {
+ /* Block signals while the signal handler is changed: */
+ _thread_kern_sig_block(&status);
+
+ /* Set the new signal handler: */
+ _thread_run->act[sig - 1].sa_handler = act->sa_handler;
+ _thread_run->act[sig - 1].sa_mask = act->sa_mask;
+ _thread_run->act[sig - 1].sa_flags = act->sa_flags;
+
+ /*
+ * Unblock signals to allow the new signal handler to
+ * take effect:
+ */
+ _thread_kern_sig_unblock(status);
+ }
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigblock.c b/lib/libc_r/uthread/uthread_sigblock.c
new file mode 100644
index 0000000..bca32e1
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigblock.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+_thread_sys_sigblock(int mask)
+{
+ int omask, n;
+
+ n = _thread_sys_sigprocmask(SIG_BLOCK, (sigset_t *) & mask, (sigset_t *) & omask);
+ if (n)
+ return (n);
+ return (omask);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigmask.c b/lib/libc_r/uthread/uthread_sigmask.c
new file mode 100644
index 0000000..94f64cb
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigmask.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
+{
+ int ret = 0;
+ int status;
+
+ /* Check if the existing signal process mask is to be returned: */
+ if (oset != NULL) {
+ /* Return the current mask: */
+ *oset = _thread_run->sigmask;
+ }
+ /* Check if a new signal set was provided by the caller: */
+ if (set != NULL) {
+ /* Block signals while the signal mask is changed: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to what to do: */
+ switch (how) {
+ /* Block signals: */
+ case SIG_BLOCK:
+ /* Add signals to the existing mask: */
+ _thread_run->sigmask |= *set;
+ break;
+
+ /* Unblock signals: */
+ case SIG_UNBLOCK:
+ /* Clear signals from the existing mask: */
+ _thread_run->sigmask &= ~(*set);
+ break;
+
+ /* Set the signal process mask: */
+ case SIG_SETMASK:
+ /* Set the new mask: */
+ _thread_run->sigmask = *set;
+ break;
+
+ /* Trap invalid actions: */
+ default:
+ /* Return an invalid argument: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /*
+ * Schedule the next thread in case there are signals that
+ * now need to be acted on:
+ */
+ _thread_kern_sched(NULL);
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_signal.c b/lib/libc_r/uthread/uthread_signal.c
new file mode 100644
index 0000000..cef725f
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_signal.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+sig_t
+_thread_sys_signal(int s, sig_t a)
+{
+ struct sigaction sa;
+ struct sigaction osa;
+
+ /* Initialise the signal action structure: */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = a;
+ sa.sa_flags = SA_RESTART;
+
+ /* Perform the sigaction syscall: */
+ if (_thread_sys_sigaction(s, &sa, &osa) < 0) {
+ /* Return an error: */
+ return (SIG_ERR);
+ }
+ /* Return a pointer to the old signal handler: */
+ return (osa.sa_handler);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigprocmask.c b/lib/libc_r/uthread/uthread_sigprocmask.c
new file mode 100644
index 0000000..b4a8d84
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigprocmask.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigprocmask(int how, const sigset_t * set, sigset_t * oset)
+{
+ int ret = 0;
+ int status;
+
+ /* Check if the existing signal process mask is to be returned: */
+ if (oset != NULL) {
+ /* Return the current mask: */
+ *oset = _thread_run->sigmask;
+ }
+ /* Check if a new signal set was provided by the caller: */
+ if (set != NULL) {
+ /* Block signals while the signal mask is changed: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to what to do: */
+ switch (how) {
+ /* Block signals: */
+ case SIG_BLOCK:
+ /* Add signals to the existing mask: */
+ _thread_run->sigmask |= *set;
+ break;
+
+ /* Unblock signals: */
+ case SIG_UNBLOCK:
+ /* Clear signals from the existing mask: */
+ _thread_run->sigmask &= ~(*set);
+ break;
+
+ /* Set the signal process mask: */
+ case SIG_SETMASK:
+ /* Set the new mask: */
+ _thread_run->sigmask = *set;
+ break;
+
+ /* Trap invalid actions: */
+ default:
+ /* Return an invalid argument: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /*
+ * Schedule the next thread in case there are signals that
+ * now need to be acted on:
+ */
+ _thread_kern_sched(NULL);
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigsetmask.c b/lib/libc_r/uthread/uthread_sigsetmask.c
new file mode 100644
index 0000000..2780670
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigsetmask.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+_thread_sys_sigsetmask(int mask)
+{
+ int omask, n;
+
+ n = _thread_sys_sigprocmask(SIG_SETMASK, (sigset_t *) & mask, (sigset_t *) & omask);
+ if (n)
+ return (n);
+ return (omask);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigsuspend.c b/lib/libc_r/uthread/uthread_sigsuspend.c
new file mode 100644
index 0000000..14cf74b
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigsuspend.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigsuspend(const sigset_t * set)
+{
+ int ret = -1;
+ sigset_t oset;
+
+ /* Check if a new signal set was provided by the caller: */
+ if (set != NULL) {
+ /* Save the current sigmal mask: */
+ oset = _thread_run->sigmask;
+
+ /* Combine the caller's mask with the current one: */
+ _thread_run->sigmask |= *set;
+
+ /* Wait for a signal: */
+ _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__);
+
+ /* Restore the signal mask: */
+ _thread_run->sigmask = oset;
+ } else {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigwait.c b/lib/libc_r/uthread/uthread_sigwait.c
new file mode 100644
index 0000000..4f95190
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigwait.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigwait(const sigset_t * set, int *sig)
+{
+ int ret;
+ int status;
+ sigset_t oset;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Save the current sigmal mask: */
+ oset = _thread_run->sigmask;
+
+ /* Combine the caller's mask with the current one: */
+ _thread_run->sigmask |= *set;
+
+ /* Wait for a signal: */
+ _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__);
+
+ /* Block signals again: */
+ _thread_kern_sig_block(NULL);
+
+ /* Return the signal number to the caller: */
+ *sig = _thread_run->signo;
+
+ /* Restore the signal mask: */
+ _thread_run->sigmask = oset;
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_single_np.c b/lib/libc_r/uthread/uthread_single_np.c
new file mode 100644
index 0000000..e36c856
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_single_np.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_single_np()
+{
+ /* Enter single-threaded (non-POSIX) scheduling mode: */
+ _thread_single = _thread_run;
+ return(0);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_socket.c b/lib/libc_r/uthread/uthread_socket.c
new file mode 100644
index 0000000..bfc657d
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_socket.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+socket(int af, int type, int protocol)
+{
+ int fd;
+
+ /* Create a socket: */
+ if ((fd = _thread_sys_socket(af, type, protocol)) < 0) {
+ /* Error creating socket. */
+
+ /* Initialise the entry in the file descriptor table: */
+ } else if (_thread_fd_table_init(fd) != 0) {
+ _thread_sys_close(fd);
+ fd = -1;
+ }
+ return (fd);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_socketpair.c b/lib/libc_r/uthread/uthread_socketpair.c
new file mode 100644
index 0000000..2c8761b
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_socketpair.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+socketpair(int af, int type, int protocol, int pair[2])
+{
+ int ret;
+ if (!((ret = _thread_sys_socketpair(af, type, protocol, pair)) < 0))
+ if (_thread_fd_table_init(pair[0]) != 0 ||
+ _thread_fd_table_init(pair[1]) != 0) {
+ _thread_sys_close(pair[0]);
+ _thread_sys_close(pair[1]);
+ ret = -1;
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_spec.c b/lib/libc_r/uthread/uthread_spec.c
new file mode 100644
index 0000000..8d06c52
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_spec.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* Static variables: */
+static struct pthread_key key_table[PTHREAD_KEYS_MAX];
+
+int
+pthread_key_create(pthread_key_t * key, void (*destructor) (void *))
+{
+ for ((*key) = 0; (*key) < PTHREAD_KEYS_MAX; (*key)++) {
+ if (key_table[(*key)].count == 0) {
+ key_table[(*key)].count++;
+ key_table[(*key)].destructor = destructor;
+ return (0);
+ }
+ }
+ return (EAGAIN);
+}
+
+int
+pthread_key_delete(pthread_key_t key)
+{
+ int ret;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ if (key < PTHREAD_KEYS_MAX) {
+ switch (key_table[key].count) {
+ case 1:
+ key_table[key].destructor = NULL;
+ key_table[key].count = 0;
+ case 0:
+ ret = 0;
+ break;
+ default:
+ ret = EBUSY;
+ }
+ } else {
+ ret = EINVAL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+
+void
+_thread_cleanupspecific(void)
+{
+ void *data;
+ int key;
+ int itr;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ for (itr = 0; itr < PTHREAD_DESTRUCTOR_ITERATIONS; itr++) {
+ for (key = 0; key < PTHREAD_KEYS_MAX; key++) {
+ if (_thread_run->specific_data_count) {
+ if (_thread_run->specific_data[key]) {
+ data = (void *) _thread_run->specific_data[key];
+ _thread_run->specific_data[key] = NULL;
+ _thread_run->specific_data_count--;
+ if (key_table[key].destructor) {
+ key_table[key].destructor(data);
+ }
+ key_table[key].count--;
+ }
+ } else {
+ free(_thread_run->specific_data);
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return;
+ }
+ }
+ }
+ free(_thread_run->specific_data);
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+}
+
+static inline const void **
+pthread_key_allocate_data(void)
+{
+ const void **new_data;
+ if ((new_data = (const void **) malloc(sizeof(void *) * PTHREAD_KEYS_MAX)) != NULL) {
+ memset((void *) new_data, 0, sizeof(void *) * PTHREAD_KEYS_MAX);
+ }
+ return (new_data);
+}
+
+int
+pthread_setspecific(pthread_key_t key, const void *value)
+{
+ pthread_t pthread;
+ int ret = 0;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the running thread: */
+ pthread = _thread_run;
+
+ /*
+ * Enter a loop for signal handler threads to find the parent thread
+ * which has the specific data associated with it:
+ */
+ while (pthread->parent_thread != NULL) {
+ /* Point to the parent thread: */
+ pthread = pthread->parent_thread;
+ }
+
+ if ((pthread->specific_data) || (pthread->specific_data = pthread_key_allocate_data())) {
+ if ((key < PTHREAD_KEYS_MAX) && (key_table)) {
+ if (key_table[key].count) {
+ if (pthread->specific_data[key] == NULL) {
+ if (value != NULL) {
+ pthread->specific_data_count++;
+ key_table[key].count++;
+ }
+ } else {
+ if (value == NULL) {
+ pthread->specific_data_count--;
+ key_table[key].count--;
+ }
+ }
+ pthread->specific_data[key] = value;
+ ret = 0;
+ } else {
+ ret = EINVAL;
+ }
+ } else {
+ ret = EINVAL;
+ }
+ } else {
+ ret = ENOMEM;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+
+void *
+pthread_getspecific(pthread_key_t key)
+{
+ pthread_t pthread;
+ int status;
+ void *data;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the running thread: */
+ pthread = _thread_run;
+
+ /*
+ * Enter a loop for signal handler threads to find the parent thread
+ * which has the specific data associated with it:
+ */
+ while (pthread->parent_thread != NULL) {
+ /* Point to the parent thread: */
+ pthread = pthread->parent_thread;
+ }
+
+ /* Check for errors: */
+ if (pthread == NULL) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ data = NULL;
+ }
+ /* Check if there is specific data: */
+ else if (pthread->specific_data != NULL && (key < PTHREAD_KEYS_MAX) && (key_table)) {
+ /* Check if this key has been used before: */
+ if (key_table[key].count) {
+ /* Return the value: */
+ data = (void *) pthread->specific_data[key];
+ } else {
+ /*
+ * This key has not been used before, so return NULL
+ * instead:
+ */
+ data = NULL;
+ }
+ } else {
+ /* No specific data has been created, so just return NULL: */
+ data = NULL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (data);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_suspend.c b/lib/libc_r/uthread/uthread_suspend.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_suspend.c
diff --git a/lib/libc_r/uthread/uthread_suspend_np.c b/lib/libc_r/uthread/uthread_suspend_np.c
new file mode 100644
index 0000000..d065b73
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_suspend_np.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_suspend_np(pthread_t thread)
+{
+ int ret = -1;
+ pthread_t pthread;
+ /*
+ * Search for the thread in the linked list.
+ */
+ for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
+ /* Is this the thread? */
+ if (pthread == thread) {
+ /* Found the thread. Is it running? */
+ if (pthread->state != PS_RUNNING &&
+ pthread->state != PS_SUSPENDED) {
+ /* The thread operation has been interrupted */
+ _thread_seterrno(pthread,EINTR);
+ }
+ /* Suspend the thread. */
+ PTHREAD_NEW_STATE(pthread,PS_SUSPENDED);
+ ret = 0;
+ }
+ }
+ /* Check if thread was not found. */
+ if (ret == -1) {
+ /* No such thread */
+ errno = ESRCH;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_wait4.c b/lib/libc_r/uthread/uthread_wait4.c
new file mode 100644
index 0000000..0a721af4f
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_wait4.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <sys/wait.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pid_t
+wait4(pid_t pid, int *istat, int options, struct rusage * rusage)
+{
+ int status;
+ pid_t ret;
+ _thread_kern_sig_block(&status);
+
+ /* Perform a non-blocking wait4 syscall: */
+ while ((ret = _thread_sys_wait4(pid, istat, options | WNOHANG, rusage)) == 0 && (options & WNOHANG) == 0) {
+ /* Schedule the next thread while this one waits: */
+ _thread_kern_sched_state(PS_WAIT_WAIT, __FILE__, __LINE__);
+
+ /* Check if this call was interrupted by a signal: */
+ if (errno == EINTR) {
+ ret = -1;
+ break;
+ }
+ _thread_kern_sig_block(NULL);
+ }
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_write.c b/lib/libc_r/uthread/uthread_write.c
new file mode 100644
index 0000000..eab105d
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_write.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+write(int fd, const void *buf, size_t nbytes)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read and write: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking write syscall: */
+ while ((ret = _thread_sys_write(fd, buf, nbytes)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDW_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_writev.c b/lib/libc_r/uthread/uthread_writev.c
new file mode 100644
index 0000000..5ad1ce9
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_writev.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+writev(int fd, const struct iovec * iov, int iovcnt)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read and write: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking writev syscall: */
+ while ((ret = _thread_sys_writev(fd, iov, iovcnt)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDW_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_yield.c b/lib/libc_r/uthread/uthread_yield.c
new file mode 100644
index 0000000..a88a948
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_yield.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+pthread_yield(void)
+{
+ /* Reset the accumulated time slice value for the current thread: */
+ _thread_run->slice_usec = -1;
+
+ /* Schedule the next thread: */
+ _thread_kern_sched(NULL);
+
+ /* Nothing to return. */
+ return;
+}
+#endif
diff --git a/lib/libcom_err/Makefile b/lib/libcom_err/Makefile
new file mode 100644
index 0000000..3112832
--- /dev/null
+++ b/lib/libcom_err/Makefile
@@ -0,0 +1,14 @@
+# $Id$
+
+LIB= com_err
+SRCS= com_err.c error_message.c et_name.c init_et.c
+MAN3= com_err.3
+
+SUBDIR= doc
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/com_err.h \
+ ${DESTDIR}/usr/include
+
+.include <bsd.lib.mk>
+
diff --git a/lib/libcom_err/com_err.3 b/lib/libcom_err/com_err.3
new file mode 100644
index 0000000..ee4375b
--- /dev/null
+++ b/lib/libcom_err/com_err.3
@@ -0,0 +1,96 @@
+.\" Copyright (c) 1988 Massachusetts Institute of Technology,
+.\" Student Information Processing Board. All rights reserved.
+.\"
+.\" $Header$
+.\"
+.TH COM_ERR 3 "22 Nov 1988" SIPB
+.SH NAME
+com_err \- common error display routine
+.SH SYNOPSIS
+.nf
+ #include <com_err.h>
+.PP
+void com_err (whoami, code, format, ...);
+ const char *whoami;
+ long code;
+ const char *format;
+.PP
+proc = set_com_err_hook (proc);
+.fi
+void (*
+.I proc
+) (const char *, long, const char *, va_list);
+.nf
+.PP
+proc = reset_com_err_hook ();
+.PP
+void initialize_XXXX_error_table ();
+.fi
+.SH DESCRIPTION
+.I Com_err
+displays an error message on the standard error stream
+.I stderr
+(see
+.IR stdio (3S))
+composed of the
+.I whoami
+string, which should specify the program name or some subportion of
+a program, followed by an error message generated from the
+.I code
+value (derived from
+.IR compile_et (1)),
+and a string produced using the
+.I format
+string and any following arguments, in the same style as
+.IR fprintf (3).
+
+The behavior of
+.I com_err
+can be modified using
+.I set_com_err_hook;
+this defines a procedure which is called with the arguments passed to
+.I com_err,
+instead of the default internal procedure which sends the formatted
+text to error output. Thus the error messages from a program can all
+easily be diverted to another form of diagnostic logging, such as
+.IR syslog (3).
+.I Reset_com_err_hook
+may be used to restore the behavior of
+.I com_err
+to its default form. Both procedures return the previous ``hook''
+value. These ``hook'' procedures must have the declaration given for
+.I proc
+above in the synopsis.
+
+The
+.I initialize_XXXX_error_table
+routine is generated mechanically by
+.IR compile_et (1)
+from a source file containing names and associated strings. Each
+table has a name of up to four characters, which is used in place of
+the
+.B XXXX
+in the name of the routine. These routines should be called before
+any of the corresponding error codes are used, so that the
+.I com_err
+library will recognize error codes from these tables when they are
+used.
+
+The
+.B com_err.h
+header file should be included in any source file that uses routines
+from the
+.I com_err
+library; executable files must be linked using
+.I ``-lcom_err''
+in order to cause the
+.I com_err
+library to be included.
+
+.\" .IR for manual entries
+.\" .PP for paragraph breaks
+
+.SH "SEE ALSO"
+compile_et (1), syslog (3).
+
+Ken Raeburn, "A Common Error Description Library for UNIX".
diff --git a/lib/libcom_err/com_err.c b/lib/libcom_err/com_err.c
new file mode 100644
index 0000000..9da3f9a
--- /dev/null
+++ b/lib/libcom_err/com_err.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board.
+ *
+ * For copyright info, see mit-sipb-copyright.h.
+ */
+
+#include <stdio.h>
+#include "mit-sipb-copyright.h"
+
+#include <stdarg.h>
+
+#include "error_table.h"
+#include "internal.h"
+#include "com_err.h"
+
+#if ! lint
+static const char rcsid[] =
+ "$Id$";
+#endif /* ! lint */
+
+static void
+#ifdef __STDC__
+ default_com_err_proc (const char *whoami, long code, const char *fmt, va_list args)
+#else
+ default_com_err_proc (whoami, code, fmt, args)
+ const char *whoami;
+ long code;
+ const char *fmt;
+ va_list args;
+#endif
+{
+ if (whoami) {
+ fputs(whoami, stderr);
+ fputs(": ", stderr);
+ }
+ if (code) {
+ fputs(error_message(code), stderr);
+ fputs(" ", stderr);
+ }
+ if (fmt) {
+ vfprintf (stderr, fmt, args);
+ }
+ putc('\n', stderr);
+ /* should do this only on a tty in raw mode */
+ putc('\r', stderr);
+ fflush(stderr);
+}
+
+#ifdef __STDC__
+typedef void (*errf) (const char *, long, const char *, va_list);
+#else
+typedef void (*errf) ();
+#endif
+
+errf com_err_hook = default_com_err_proc;
+
+void com_err_va (whoami, code, fmt, args)
+ const char *whoami;
+ long code;
+ const char *fmt;
+ va_list args;
+{
+ (*com_err_hook) (whoami, code, fmt, args);
+}
+
+#if ! VARARGS
+void com_err (const char *whoami,
+ long code,
+ const char *fmt, ...)
+{
+#else
+void com_err (va_alist)
+ va_dcl
+{
+ const char *whoami, *fmt;
+ long code;
+#endif
+ va_list pvar;
+
+ if (!com_err_hook)
+ com_err_hook = default_com_err_proc;
+#if VARARGS
+ va_start (pvar);
+ whoami = va_arg (pvar, const char *);
+ code = va_arg (pvar, long);
+ fmt = va_arg (pvar, const char *);
+#else
+ va_start(pvar, fmt);
+#endif
+ com_err_va (whoami, code, fmt, pvar);
+ va_end(pvar);
+}
+
+errf set_com_err_hook (new_proc)
+ errf new_proc;
+{
+ errf x = com_err_hook;
+
+ if (new_proc)
+ com_err_hook = new_proc;
+ else
+ com_err_hook = default_com_err_proc;
+
+ return x;
+}
+
+errf reset_com_err_hook () {
+ errf x = com_err_hook;
+ com_err_hook = default_com_err_proc;
+ return x;
+}
diff --git a/lib/libcom_err/com_err.h b/lib/libcom_err/com_err.h
new file mode 100644
index 0000000..7bea010
--- /dev/null
+++ b/lib/libcom_err/com_err.h
@@ -0,0 +1,36 @@
+/*
+ * Header file for common error description library.
+ *
+ * Copyright 1988, Student Information Processing Board of the
+ * Massachusetts Institute of Technology.
+ *
+ * For copyright and distribution info, see the documentation supplied
+ * with this package.
+ */
+
+#ifndef __COM_ERR_H
+
+#ifdef __STDC__
+#ifndef __HIGHC__ /* gives us STDC but not stdarg */
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+/* ANSI C -- use prototypes etc */
+void com_err (const char *, long, const char *, ...);
+char const *error_message (long);
+void (*com_err_hook) (const char *, long, const char *, va_list);
+void (*set_com_err_hook (void (*) (const char *, long, const char *, va_list)))
+ (const char *, long, const char *, va_list);
+void (*reset_com_err_hook ()) (const char *, long, const char *, va_list);
+#else
+/* no prototypes */
+void com_err ();
+char *error_message ();
+void (*com_err_hook) ();
+void (*set_com_err_hook ()) ();
+void (*reset_com_err_hook ()) ();
+#endif
+
+#define __COM_ERR_H
+#endif /* ! defined(__COM_ERR_H) */
diff --git a/lib/libcom_err/doc/Makefile b/lib/libcom_err/doc/Makefile
new file mode 100644
index 0000000..e94d862
--- /dev/null
+++ b/lib/libcom_err/doc/Makefile
@@ -0,0 +1,7 @@
+# $Id$
+
+INFO= com_err
+INFOSECTION= "Programming & development tools."
+INFOENTRY_com_err= "* libcom_err: (com_err). A Common Error Description Library for UNIX."
+
+.include <bsd.info.mk>
diff --git a/lib/libcom_err/doc/com_err.texinfo b/lib/libcom_err/doc/com_err.texinfo
new file mode 100644
index 0000000..77f62c7
--- /dev/null
+++ b/lib/libcom_err/doc/com_err.texinfo
@@ -0,0 +1,616 @@
+\input texinfo @c -*-texinfo-*-
+
+@c $Header: /home/ncvs/src/lib/libcom_err/doc/com_err.texinfo,v 1.1.1.1 1995/01/14 22:23:41 wollman Exp $
+@c $Source: /home/ncvs/src/lib/libcom_err/doc/com_err.texinfo,v $
+
+@c Note that although this source file is in texinfo format (more
+@c or less), it is not yet suitable for turning into an ``info''
+@c file. Sorry, maybe next time.
+@c
+@c In order to produce hardcopy documentation from a texinfo file,
+@c run ``tex com_err.texinfo'' which will load in texinfo.tex,
+@c provided in this distribution. (texinfo.tex is from the Free
+@c Software Foundation, and is under different copyright restrictions
+@c from the rest of this package.)
+
+@ifinfo
+@barfo
+@end ifinfo
+
+@iftex
+@tolerance 10000
+
+@c Mutate section headers...
+@begingroup
+ @catcode#=6
+ @gdef@secheading#1#2#3{@secheadingi {#3@enspace #1}}
+@endgroup
+@end iftex
+
+@c %**start of header (This is for running Texinfo on a region.)
+@setfilename com_err
+@settitle A Common Error Description Library for UNIX
+@c %**end of header (This is for running Texinfo on a region.)
+
+@ifinfo
+This file documents the use of the Common Error Description library.
+
+Copyright (C) 1987, 1988 Student Information Processing Board of 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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
+make no representations about the suitability of this software for any
+purpose. It is provided "as is" without express or implied warranty.
+
+Note that the file texinfo.tex, provided with this distribution, is from
+the Free Software Foundation, and is under different copyright restrictions
+from the remainder of this package.
+
+@end ifinfo
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+
+@setchapternewpage odd
+
+@titlepage
+@center @titlefont{A Common Error Description}
+@center @titlefont{Library for UNIX}
+@sp 2
+@center Ken Raeburn
+@center Bill Sommerfeld
+@sp 1
+@center MIT Student Information Processing Board
+@sp 3
+@center last updated 1 January 1989
+@center for version 1.2
+@center ***DRAFT COPY ONLY***
+
+@vskip 2in
+
+@center @b{Abstract}
+
+UNIX has always had a clean and simple system call interface, with a
+standard set of error codes passed between the kernel and user
+programs. Unfortunately, the same cannot be said of many of the
+libraries layered on top of the primitives provided by the kernel.
+Typically, each one has used a different style of indicating errors to
+their callers, leading to a total hodgepodge of error handling, and
+considerable amounts of work for the programmer. This paper describes
+a library and associated utilities which allows a more uniform way for
+libraries to return errors to their callers, and for programs to
+describe errors and exceptional conditions to their users.
+
+@page
+@vskip 0pt plus 1filll
+
+Copyright @copyright{} 1987, 1988 by the Student Information Processing
+Board of 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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
+make no representations about the suitability of this software for any
+purpose. It is provided "as is" without express or implied warranty.
+
+Note that the file texinfo.tex, provided with this distribution, is from
+the Free Software Foundation, and is under different copyright restrictions
+from the remainder of this package.
+
+@end titlepage
+
+@ifinfo
+@node Top, Why com_err?, (dir), (dir)
+@comment node-name, next, previous, up
+@top General Introduction
+
+@menu
+* Why com_err?:: What is all this for?
+* Error codes:: What's an error code, anyway?
+* Error table source file:: How to describe an error table.
+* The error-table compiler:: How to compile the table.
+* Run-time support routines:: How to use from within your program.
+* Coding Conventions:: Stylistic issues.
+* Building and Installation:: How to build and install.
+* Bug Reports:: You have found a bug? Report it.
+* Acknowledgements:: Whom to thank...
+
+@end menu
+
+@end ifinfo
+
+@page
+
+@ifinfo
+@node Why com_err?, Error codes, Top, (dir)
+@comment node-name, next, previous, up
+@end ifinfo
+
+@section Why com_err?
+
+In building application software packages, a programmer often has to
+deal with a number of libraries, each of which can use a different
+error-reporting mechanism. Sometimes one of two values is returned,
+indicating simply SUCCESS or FAILURE, with no description of errors
+encountered. Sometimes it is an index into a table of text strings,
+where the name of the table used is dependent on the library being
+used when the error is generated; since each table starts numbering at
+0 or 1, additional information as to the source of the error code is
+needed to determine which table to look at. Sometimes no text messages are
+supplied at all, and the programmer must supply them at any point at which
+he may wish to report error conditions.
+Often, a global variable is assigned some value describing the error, but
+the programmer has to know in each case whether to look at @code{errno},
+@code{h_errno}, the return value from @code{hes_err()}, or whatever other
+variables or routines are specified.
+And what happens if something
+in the procedure of
+examining or reporting the error changes the same variable?
+
+The package we have developed is an attempt to present a common
+error-handling mechanism to manipulate the most common form of error code
+in a fashion that does not have the problems listed above.
+
+A list of up to 256 text messages is supplied to a translator we have
+written, along with the three- to four-character ``name'' of the error
+table. The library using this error table need only call a routine
+generated from this error-table source to make the table ``known'' to the
+com_err library, and any error code the library generates can be converted
+to the corresponding error message. There is also a default format for
+error codes accidentally returned before making the table known, which is
+of the form @samp{unknown code foo 32}, where @samp{foo} would be the name
+of the table.
+
+@ifinfo
+@node Error codes, Error table source file, Why com_err?, (dir)
+@comment node-name, next, previous, up
+@end ifinfo
+
+@section Error codes
+
+Error codes themselves are 32 bit (signed) integers, of which the high
+order 24 bits are an identifier of which error table the error code is
+from, and the low order 8 bits are a sequential error number within
+the table. An error code may thus be easily decomposed into its component
+parts. Only the lowest 32 bits of an error code are considered significant
+on systems which support wider values.
+
+Error table 0 is defined to match the UNIX system call error table
+(@code{sys_errlist}); this allows @code{errno} values to be used directly
+in the library (assuming that @code{errno} is of a type with the same width
+as @t{long}). Other error table numbers are formed by compacting together
+the first four characters of the error table name. The mapping between
+characters in the name and numeric values in the error code are defined in
+a system-independent fashion, so that two systems that can pass integral
+values between them can reliably pass error codes without loss of meaning;
+this should work even if the character sets used are not the same.
+(However, if this is to be done, error table 0 should be avoided, since the
+local system call error tables may differ.)
+
+Any variable which is to contain an error code should be declared @t{long}.
+The draft proposed American National Standard for C (as of May, 1988)
+requires that @t{long} variables be at least 32 bits; any system which does
+not support 32-bit @t{long} values cannot make use of this package (nor
+much other software that assumes an ANSI-C environment base) without
+significant effort.
+
+@ifinfo
+@node Error table source file, The error-table compiler, Error codes, (dir)
+@comment node-name, next, previous, up
+@end ifinfo
+
+@section Error table source file
+
+The error table source file begins with the declaration of the table name,
+as
+
+@example
+error_table @var{tablename}
+@end example
+
+Individual error codes are
+specified with
+
+@example
+error_code @var{ERROR_NAME}, @var{"text message"}
+@end example
+
+where @samp{ec} can also be used as a short form of @samp{error_code}. To
+indicate the end of the table, use @samp{end}. Thus, a (short) sample
+error table might be:
+
+@example
+
+ error_table dsc
+
+ error_code DSC_DUP_MTG_NAME,
+ "Meeting already exists"
+
+ ec DSC_BAD_PATH,
+ "A bad meeting pathname was given"
+
+ ec DSC_BAD_MODES,
+ "Invalid mode for this access control list"
+
+ end
+
+@end example
+
+@ifinfo
+@node The error-table compiler, Run-time support routines, Error table source file, (dir)
+@comment node-name, next, previous, up
+@end ifinfo
+
+@section The error-table compiler
+
+The error table compiler is named @code{compile_et}. It takes one
+argument, the pathname of a file (ending in @samp{.et}, e.g.,
+@samp{dsc_err.et}) containing an error table source file. It parses the
+error table, and generates two output files -- a C header file
+(@samp{discuss_err.h}) which contains definitions of the numerical values
+of the error codes defined in the error table, and a C source file which
+should be compiled and linked with the executable. The header file must be
+included in the source of a module which wishes to reference the error
+codes defined; the object module generated from the C code may be linked in
+to a program which wishes to use the printed forms of the error codes.
+
+This translator accepts a @kbd{-language @var{lang}} argument, which
+determines for which language (or language variant) the output should be
+written. At the moment, @var{lang} is currently limited to @kbd{ANSI-C}
+and @kbd{K&R-C}, and some abbreviated forms of each. Eventually, this will
+be extended to include some support for C++. The default is currently
+@kbd{K&R-C}, though the generated sources will have ANSI-C code
+conditionalized on the symbol @t{__STDC__}.
+
+@ifinfo
+@node Run-time support routines, Coding Conventions, The error-table compiler, (dir)
+@comment node-name, next, previous, up
+@end ifinfo
+
+@section Run-time support routines
+
+Any source file which uses the routines supplied with or produced by the
+com_err package should include the header file @file{<com_err.h>}. It
+contains declarations and definitions which may be needed on some systems.
+(Some functions cannot be referenced properly without the return type
+declarations in this file. Some functions may work properly on most
+architectures even without the header file, but relying on this is not
+recommended.)
+
+The run-time support routines and variables provided via this package
+include the following:
+
+@example
+void initialize_@var{xxxx}_error_table (void);
+@end example
+
+One of these routines is built by the error compiler for each error table.
+It makes the @var{xxxx} error table ``known'' to the error reporting
+system. By convention, this routine should be called in the initialization
+routine of the @var{xxxx} library. If the library has no initialization
+routine, some combination of routines which form the core of the library
+should ensure that this routine is called. It is not advised to leave it
+the caller to make this call.
+
+There is no harm in calling this routine more than once.
+
+@example
+#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L
+@end example
+
+This symbol contains the value of the first error code entry in the
+specified table.
+This rarely needs be used by the
+programmer.
+
+@example
+const char *error_message (long code);
+@end example
+
+This routine returns the character string error message associated
+with @code{code}; if this is associated with an unknown error table, or
+if the code is associated with a known error table but the code is not
+in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is
+returned, where @var{xxxx} is the error table name produced by
+reversing the compaction performed on the error table number implied
+by that error code, and @var{nn} is the offset from that base value.
+
+Although this routine is available for use when needed, its use should be
+left to circumstances which render @code{com_err} (below) unusable.
+
+@example
+void com_err (const char *whoami, /* module reporting error */
+ long code, /* error code */
+ const char *format, /* format for additional detail */
+ ...); /* (extra parameters) */
+@end example
+
+This routine provides an alternate way to print error messages to
+standard error; it allows the error message to be passed in as a
+parameter, rather than in an external variable. @emph{Provide grammatical
+context for ``message.''}
+
+If @var{format} is @code{(char *)NULL}, the formatted message will not be
+printed. @var{format} may not be omitted.
+
+@example
+#include <stdarg.h>
+
+void com_err_va (const char *whoami,
+ long code,
+ const char *format,
+ va_list args);
+@end example
+
+This routine provides an interface, equivalent to @code{com_err} above,
+which may be used by higher-level variadic functions (functions which
+accept variable numbers of arguments).
+
+@example
+#include <stdarg.h>
+
+void (*set_com_err_hook (void (*proc) ())) ();
+
+void (*@var{proc}) (const char *whoami, long code, va_list args);
+
+void reset_com_err_hook ();
+@end example
+
+These two routines allow a routine to be dynamically substituted for
+@samp{com_err}. After @samp{set_com_err_hook} has been called,
+calls to @samp{com_err} will turn into calls to the new hook routine.
+@samp{reset_com_err_hook} turns off this hook. This may intended to
+be used in daemons (to use a routine which calls @var{syslog(3)}), or
+in a window system application (which could pop up a dialogue box).
+
+If a program is to be used in an environment in which simply printing
+messages to the @code{stderr} stream would be inappropriate (such as in a
+daemon program which runs without a terminal attached),
+@code{set_com_err_hook} may be used to redirect output from @code{com_err}.
+The following is an example of an error handler which uses @var{syslog(3)}
+as supplied in BSD 4.3:
+
+@example
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+
+/* extern openlog (const char * name, int logopt, int facility); */
+/* extern syslog (int priority, char * message, ...); */
+
+void hook (const char * whoami, long code,
+ const char * format, va_list args)
+@{
+ char buffer[BUFSIZ];
+ static int initialized = 0;
+ if (!initialized) @{
+ openlog (whoami,
+ LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY,
+ LOG_DAEMON);
+ initialized = 1;
+ @}
+ vsprintf (buffer, format, args);
+ syslog (LOG_ERR, "%s %s", error_message (code), buffer);
+@}
+@end example
+
+After making the call
+@code{set_com_err_hook (hook);},
+any calls to @code{com_err} will result in messages being sent to the
+@var{syslogd} daemon for logging.
+The name of the program, @samp{whoami}, is supplied to the
+@samp{openlog()} call, and the message is formatted into a buffer and
+passed to @code{syslog}.
+
+Note that since the extra arguments to @code{com_err} are passed by
+reference via the @code{va_list} value @code{args}, the hook routine may
+place any form of interpretation on them, including ignoring them. For
+consistency, @code{printf}-style interpretation is suggested, via
+@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for
+the ANSI C library).
+
+@ifinfo
+@node Coding Conventions, Building and Installation, Run-time support routines, (dir)
+@comment node-name, next, previous, up
+@end ifinfo
+
+@section Coding Conventions
+
+The following conventions are just some general stylistic conventions
+to follow when writing robust libraries and programs. Conventions
+similar to this are generally followed inside the UNIX kernel and most
+routines in the Multics operating system. In general, a routine
+either succeeds (returning a zero error code, and doing some side
+effects in the process), or it fails, doing minimal side effects; in
+any event, any invariant which the library assumes must be maintained.
+
+In general, it is not in the domain of non user-interface library
+routines to write error messages to the user's terminal, or halt the
+process. Such forms of ``error handling'' should be reserved for
+failures of internal invariants and consistancy checks only, as it
+provides the user of the library no way to clean up for himself in the
+event of total failure.
+
+Library routines which can fail should be set up to return an error
+code. This should usually be done as the return value of the
+function; if this is not acceptable, the routine should return a
+``null'' value, and put the error code into a parameter passed by
+reference.
+
+Routines which use the first style of interface can be used from
+user-interface levels of a program as follows:
+
+@example
+@{
+ if ((code = initialize_world(getuid(), random())) != 0) @{
+ com_err("demo", code,
+ "when trying to initialize world");
+ exit(1);
+ @}
+ if ((database = open_database("my_secrets", &code))==NULL) @{
+ com_err("demo", code,
+ "while opening my_secrets");
+ exit(1);
+ @}
+@}
+@end example
+
+A caller which fails to check the return status is in error. It is
+possible to look for code which ignores error returns by using lint;
+look for error messages of the form ``foobar returns value which is
+sometimes ignored'' or ``foobar returns value which is always
+ignored.''
+
+Since libraries may be built out of other libraries, it is often necessary
+for the success of one routine to depend on another. When a lower level
+routine returns an error code, the middle level routine has a few possible
+options. It can simply return the error code to its caller after doing
+some form of cleanup, it can substitute one of its own, or it can take
+corrective action of its own and continue normally. For instance, a
+library routine which makes a ``connect'' system call to make a network
+connection may reflect the system error code @code{ECONNREFUSED}
+(Connection refused) to its caller, or it may return a ``server not
+available, try again later,'' or it may try a different server.
+
+Cleanup which is typically necessary may include, but not be limited
+to, freeing allocated memory which will not be needed any more,
+unlocking concurrancy locks, dropping reference counts, closing file
+descriptors, or otherwise undoing anything which the procedure did up
+to this point. When there are a lot of things which can go wrong, it
+is generally good to write one block of error-handling code which is
+branched to, using a goto, in the event of failure. A common source
+of errors in UNIX programs is failing to close file descriptors on
+error returns; this leaves a number of ``zombied'' file descriptors
+open, which eventually causes the process to run out of file
+descriptors and fall over.
+
+@example
+@{
+ FILE *f1=NULL, *f2=NULL, *f3=NULL;
+ int status = 0;
+
+ if ( (f1 = fopen(FILE1, "r")) == NULL) @{
+ status = errno;
+ goto error;
+ @}
+
+ /*
+ * Crunch for a while
+ */
+
+ if ( (f2 = fopen(FILE2, "w")) == NULL) @{
+ status = errno;
+ goto error;
+ @}
+
+ if ( (f3 = fopen(FILE3, "a+")) == NULL) @{
+ status = errno;
+ goto error;
+ @}
+
+ /*
+ * Do more processing.
+ */
+ fclose(f1);
+ fclose(f2);
+ fclose(f3);
+ return 0;
+
+error:
+ if (f1) fclose(f1);
+ if (f2) fclose(f2);
+ if (f3) fclose(f3);
+ return status;
+@}
+@end example
+
+@ifinfo
+@node Building and Installation, Bug Reports, Coding Conventions, (dir)
+@comment node-name, next, previous, up
+@end ifinfo
+
+@section Building and Installation
+
+The distribution of this package will probably be done as a compressed
+``tar''-format file available via anonymous FTP from SIPB.MIT.EDU.
+Retrieve @samp{pub/com_err.tar.Z} and extract the contents. A subdirectory
+@t{profiled} should be created to hold objects compiled for profiling.
+Running ``make all'' should then be sufficient to build the library and
+error-table compiler. The files @samp{libcom_err.a},
+@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be
+installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be
+installed as manual pages.
+
+Potential problems:
+
+@itemize @bullet
+
+@item Use of @code{strcasecmp}, a routine provided in BSD for
+case-insensitive string comparisons. If an equivalent routine is
+available, you can modify @code{CFLAGS} in the makefile to define
+@code{strcasecmp} to the name of that routine.
+
+@item Compilers that defined @code{__STDC__} without providing the header
+file @code{<stdarg.h>}. One such example is Metaware's High ``C''
+compiler, as provided at Project Athena on the IBM RT/PC workstation; if
+@code{__HIGHC__} is defined, it is assumed that @code{<stdarg.h>} is not
+available, and therefore @code{<varargs.h>} must be used. If the symbol
+@code{VARARGS} is defined (e.g., in the makefile), @code{<varargs.h>} will
+be used.
+
+@item If your linker rejects symbols that are simultaneously defined in two
+library files, edit @samp{Makefile} to remove @samp{perror.c} from the
+library. This file contains a version of @var{perror(3)} which calls
+@code{com_err} instead of calling @code{write} directly.
+
+@end itemize
+
+As I do not have access to non-BSD systems, there are probably
+bugs present that may interfere with building or using this package on
+other systems. If they are reported to me, they can probably be fixed for
+the next version.
+
+@ifinfo
+@node Bug Reports, Acknowledgements, Building and Installation, (dir)
+@comment node-name, next, previous, up
+@end ifinfo
+
+@section Bug Reports
+
+Please send any comments or bug reports to the principal author: Ken
+Raeburn, @t{Raeburn@@Athena.MIT.EDU}.
+
+@ifinfo
+@node Acknowledgements, , Bug Reports, (dir)
+@comment node-name, next, previous, up
+@end ifinfo
+
+@section Acknowledgements
+
+I would like to thank: Bill Sommerfeld, for his help with some of this
+documentation, and catching some of the bugs the first time around;
+Honeywell Information Systems, for not killing off the @emph{Multics}
+operating system before I had an opportunity to use it; Honeywell's
+customers, who persuaded them not to do so, for a while; Ted Anderson of
+CMU, for catching some problems before version 1.2 left the nest; Stan
+Zanarotti and several others of MIT's Student Information Processing Board,
+for getting us started with ``discuss,'' for which this package was
+originally written; and everyone I've talked into --- I mean, asked to read
+this document and the ``man'' pages.
+
+@bye
diff --git a/lib/libcom_err/error_message.c b/lib/libcom_err/error_message.c
new file mode 100644
index 0000000..51ac568
--- /dev/null
+++ b/lib/libcom_err/error_message.c
@@ -0,0 +1,72 @@
+/*
+ * $Header: /home/ncvs/src/lib/libcom_err/error_message.c,v 1.1.1.1 1995/01/14 22:23:41 wollman Exp $
+ * $Source: /home/ncvs/src/lib/libcom_err/error_message.c,v $
+ * $Locker: $
+ *
+ * Copyright 1987 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * For copyright info, see "mit-sipb-copyright.h".
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "error_table.h"
+#include "mit-sipb-copyright.h"
+#include "internal.h"
+
+static const char rcsid[] =
+ "$Header: /home/ncvs/src/lib/libcom_err/error_message.c,v 1.1.1.1 1995/01/14 22:23:41 wollman Exp $";
+static const char copyright[] =
+ "Copyright 1986, 1987, 1988 by the Student Information Processing Board\nand the department of Information Systems\nof the Massachusetts Institute of Technology";
+
+static char buffer[25];
+
+struct et_list * _et_list = (struct et_list *) NULL;
+
+const char * error_message (code)
+long code;
+{
+ int offset;
+ struct et_list *et;
+ int table_num;
+ int started = 0;
+ char *cp;
+
+ offset = code & ((1<<ERRCODE_RANGE)-1);
+ table_num = code - offset;
+ if (!table_num) {
+ if (offset < sys_nerr)
+ return(sys_errlist[offset]);
+ else
+ goto oops;
+ }
+ for (et = _et_list; et; et = et->next) {
+ if (et->table->base == table_num) {
+ /* This is the right table */
+ if (et->table->n_msgs <= offset)
+ goto oops;
+ return(et->table->msgs[offset]);
+ }
+ }
+oops:
+ strcpy (buffer, "Unknown code ");
+ if (table_num) {
+ strcat (buffer, error_table_name (table_num));
+ strcat (buffer, " ");
+ }
+ for (cp = buffer; *cp; cp++)
+ ;
+ if (offset >= 100) {
+ *cp++ = '0' + offset / 100;
+ offset %= 100;
+ started++;
+ }
+ if (started || offset >= 10) {
+ *cp++ = '0' + offset / 10;
+ offset %= 10;
+ }
+ *cp++ = '0' + offset;
+ *cp = '\0';
+ return(buffer);
+}
diff --git a/lib/libcom_err/error_table.h b/lib/libcom_err/error_table.h
new file mode 100644
index 0000000..78f7db2
--- /dev/null
+++ b/lib/libcom_err/error_table.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 1988 by the Student Information Processing Board of the
+ * Massachusetts Institute of Technology.
+ *
+ * For copyright info, see mit-sipb-copyright.h.
+ */
+
+#ifndef _ET_H
+/* Are we using ANSI C? */
+#ifndef __STDC__
+#define const
+#endif
+extern int errno;
+struct error_table {
+ char const * const * msgs;
+ long base;
+ int n_msgs;
+};
+struct et_list {
+ struct et_list *next;
+ const struct error_table *table;
+};
+extern struct et_list * _et_list;
+
+#define ERRCODE_RANGE 8 /* # of bits to shift table number */
+#define BITS_PER_CHAR 6 /* # bits to shift per character in name */
+
+extern const char *error_table_name();
+#define _ET_H
+#endif
diff --git a/lib/libcom_err/et_name.c b/lib/libcom_err/et_name.c
new file mode 100644
index 0000000..a896bab
--- /dev/null
+++ b/lib/libcom_err/et_name.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright 1987 by MIT Student Information Processing Board
+ *
+ * For copyright info, see mit-sipb-copyright.h.
+ */
+
+#include "error_table.h"
+#include "mit-sipb-copyright.h"
+#include "internal.h"
+
+#ifndef lint
+static const char copyright[] =
+ "Copyright 1987,1988 by Student Information Processing Board, Massachusetts Institute of Technology";
+static const char rcsid_et_name_c[] =
+ "$Header: et_name.c,v 1.7 89/01/01 06:14:56 raeburn Exp $";
+#endif
+
+static const char char_set[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+
+static char buf[6];
+
+const char * error_table_name(num)
+ int num;
+{
+ int ch;
+ int i;
+ char *p;
+
+ /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
+ p = buf;
+ num >>= ERRCODE_RANGE;
+ /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
+ num &= 077777777;
+ /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
+ for (i = 4; i >= 0; i--) {
+ ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
+ if (ch != 0)
+ *p++ = char_set[ch-1];
+ }
+ *p = '\0';
+ return(buf);
+}
diff --git a/lib/libcom_err/init_et.c b/lib/libcom_err/init_et.c
new file mode 100644
index 0000000..630c2ac
--- /dev/null
+++ b/lib/libcom_err/init_et.c
@@ -0,0 +1,55 @@
+/*
+ * $Header: init_et.c,v 1.5 88/10/27 08:34:54 raeburn Exp $
+ * $Source: /mit/raeburn/Work/et/src/RCS/init_et.c,v $
+ * $Locker: $
+ *
+ * Copyright 1986, 1987, 1988 by MIT Information Systems and
+ * the MIT Student Information Processing Board.
+ *
+ * For copyright info, see mit-sipb-copyright.h.
+ */
+
+#include <stdio.h>
+#include "error_table.h"
+#include "mit-sipb-copyright.h"
+
+#ifndef __STDC__
+#define const
+#endif
+
+#ifndef lint
+static const char rcsid_init_et_c[] =
+ "$Header: init_et.c,v 1.5 88/10/27 08:34:54 raeburn Exp $";
+#endif
+
+extern char *malloc(), *realloc();
+
+struct foobar {
+ struct et_list etl;
+ struct error_table et;
+};
+
+extern struct et_list * _et_list;
+
+int init_error_table(msgs, base, count)
+ const char * const * msgs;
+ int base;
+ int count;
+{
+ struct foobar * new_et;
+
+ if (!base || !count || !msgs)
+ return 0;
+
+ new_et = (struct foobar *) malloc(sizeof(struct foobar));
+ if (!new_et)
+ return errno; /* oops */
+ new_et->etl.table = &new_et->et;
+ new_et->et.msgs = msgs;
+ new_et->et.base = base;
+ new_et->et.n_msgs= count;
+
+ new_et->etl.next = _et_list;
+ _et_list = &new_et->etl;
+ return 0;
+}
diff --git a/lib/libcom_err/internal.h b/lib/libcom_err/internal.h
new file mode 100644
index 0000000..880fe76
--- /dev/null
+++ b/lib/libcom_err/internal.h
@@ -0,0 +1,18 @@
+/*
+ * internal include file for com_err package
+ */
+#include "mit-sipb-copyright.h"
+#ifndef __STDC__
+#undef const
+#define const
+#endif
+
+extern int errno;
+extern char const * const sys_errlist[];
+extern /* const */ int sys_nerr;
+
+#ifdef __STDC__
+void perror (const char *);
+#else
+int perror ();
+#endif
diff --git a/lib/libcom_err/mit-sipb-copyright.h b/lib/libcom_err/mit-sipb-copyright.h
new file mode 100644
index 0000000..2f7eb29
--- /dev/null
+++ b/lib/libcom_err/mit-sipb-copyright.h
@@ -0,0 +1,19 @@
+/*
+
+Copyright 1987, 1988 by the Student Information Processing Board
+ of 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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+M.I.T. and the M.I.T. S.I.P.B. make no representations about
+the suitability of this software for any purpose. It is
+provided "as is" without express or implied warranty.
+
+*/
+
diff --git a/lib/libcom_err/test/test.c b/lib/libcom_err/test/test.c
new file mode 100644
index 0000000..955cb96
--- /dev/null
+++ b/lib/libcom_err/test/test.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <errno.h>
+#include "com_err.h"
+#include "test1.h"
+#include "test2.h"
+
+extern int sys_nerr, errno;
+
+main()
+{
+ printf("Before initiating error table:\n\n");
+ printf("Table name '%s'\n", error_table_name(KRB_MK_AP_TGTEXP));
+ printf("UNIX name '%s'\n", error_table_name(EPERM));
+ printf("Msg TGT-expired is '%s'\n", error_message(KRB_MK_AP_TGTEXP));
+ printf("Msg EPERM is '%s'\n", error_message(EPERM));
+ printf("Msg FOO_ERR is '%s'\n", error_message(FOO_ERR));
+ printf("Msg {sys_nerr-1} is '%s'\n", error_message(sys_nerr-1));
+ printf("Msg {sys_nerr} is '%s'\n", error_message(sys_nerr));
+
+ printf("With 0: tgt-expired -> %s\n", error_message(KRB_MK_AP_TGTEXP));
+
+ initialize_krb_error_table();
+ printf("KRB error table initialized: base %d (%s), name %s\n",
+ ERROR_TABLE_BASE_krb, error_message(ERROR_TABLE_BASE_krb),
+ error_table_name(ERROR_TABLE_BASE_krb));
+ initialize_krb_error_table();
+ printf("With krb: tgt-expired -> %s\n",
+ error_message(KRB_MK_AP_TGTEXP));
+
+ initialize_quux_error_table();
+ printf("QUUX error table initialized: base %d (%s), name %s\n",
+ ERROR_TABLE_BASE_quux, error_message(ERROR_TABLE_BASE_quux),
+ error_table_name(ERROR_TABLE_BASE_quux));
+
+ printf("Msg for TGT-expired is '%s'\n",
+ error_message(KRB_MK_AP_TGTEXP));
+ printf("Msg {sys_nerr-1} is '%s'\n", error_message(sys_nerr-1));
+ printf("Msg FOO_ERR is '%s'\n", error_message(FOO_ERR));
+ printf("Msg KRB_SKDC_CANT is '%s'\n",
+ error_message(KRB_SKDC_CANT));
+ printf("Msg 1e6 (8B 64) is '%s'\n", error_message(1000000));
+ printf("\n\nCOM_ERR tests:\n");
+ com_err("whoami", FOO_ERR, (char *)NULL);
+ com_err("whoami", FOO_ERR, " -- message goes %s", "here");
+ com_err("whoami", 0, (char *)0);
+ com_err("whoami", 0, "error number %d\n", 0);
+}
diff --git a/lib/libcom_err/test/test1.et b/lib/libcom_err/test/test1.et
new file mode 100644
index 0000000..4c7b77f
--- /dev/null
+++ b/lib/libcom_err/test/test1.et
@@ -0,0 +1,69 @@
+ error_table krb
+
+ error_code KRB_MK_AP_TKFIL,
+ "Can't read ticket file"
+
+ ec KRB_MK_AP_NOTKT,
+ "Can't find ticket or TGT"
+
+ ec KRB_MK_AP_TGTEXP,
+ "TGT expired"
+
+ ec KRB_RD_AP_UNDEC,
+ "Can't decode authenticator"
+
+ ec KRB_RD_AP_EXP,
+ "Ticket expired"
+
+ ec KRB_RD_AP_REPEAT,
+ "Repeated request"
+
+ ec KRB_RD_AP_NOT_US,
+ "The ticket isn't for us"
+
+ ec KRB_RD_AP_INCON,
+ "Request is inconsistent"
+
+ ec KRB_RD_AP_TIME,
+ "Delta-T too big"
+
+ ec KRB_RD_AP_BADD,
+ "Incorrect net address"
+
+ ec KRB_RD_AP_VERSION,
+ "Protocol version mismatch"
+
+ ec KRB_RD_AP_MSG_TYPE,
+ "Invalid message type"
+
+ ec KRB_RD_AP_MODIFIED,
+ "Message stream modified"
+
+ ec KRB_RD_AP_ORDER,
+ "Message out of order"
+
+ ec KRB_RD_AP_UNAUTHOR,
+ "Unauthorized request"
+
+ ec KRB_GT_PW_NULL,
+ "Current password is null"
+
+ ec KRB_GT_PW_BADPW,
+ "Incorrect current password"
+
+ ec KRB_GT_PW_PROT,
+ "Protocol error"
+
+ ec KRB_GT_PW_KDCERR,
+ "Error returned by KDC"
+
+ ec KRB_GT_PW_NULLTKT,
+ "Null ticket returned by KDC"
+
+ ec KRB_SKDC_RETRY,
+ "Retry count exceeded"
+
+ ec KRB_SKDC_CANT,
+ "Can't send request"
+
+ end
diff --git a/lib/libcom_err/test/test2.et b/lib/libcom_err/test/test2.et
new file mode 100644
index 0000000..55ad74e
--- /dev/null
+++ b/lib/libcom_err/test/test2.et
@@ -0,0 +1,9 @@
+ error_table quux
+
+ ec FOO_ERR, "foo"
+
+ ec BAR_ERR, "bar"
+
+ ec BAZ_ERR, "meow"
+
+ end
diff --git a/lib/libcompat/4.1/ascftime.c b/lib/libcompat/4.1/ascftime.c
new file mode 100644
index 0000000..e842b6e
--- /dev/null
+++ b/lib/libcompat/4.1/ascftime.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1994 Joerg Wunsch
+ *
+ * All rights reserved.
+ *
+ * This program is free software.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 Joerg Wunsch
+ * 4. The name of the developer may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <time.h>
+
+#define MAXLEN 1000 /* just a guess, only the user knows... */
+
+int
+#if __STDC__
+ascftime(char *s, const char *format, const struct tm *tmptr)
+#else
+ascftime(s, format, tmptr)
+ char *s;
+ char *format;
+ struct tm *tmptr;
+#endif
+{
+ return strftime(s, MAXLEN, format? format: "%C", tmptr);
+}
diff --git a/lib/libcompat/4.1/cftime.3 b/lib/libcompat/4.1/cftime.3
new file mode 100644
index 0000000..058f85c
--- /dev/null
+++ b/lib/libcompat/4.1/cftime.3
@@ -0,0 +1,99 @@
+.\"
+.\" Copyright (c) 1994, 1995 Joerg Wunsch
+.\"
+.\" All rights reserved.
+.\"
+.\" This program is free software.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 Joerg Wunsch
+.\" 4. The name of the developer may not be used to endorse or promote
+.\" products derived from this software without specific prior written
+.\" permission.
+.\"
+.\" 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.
+.\"
+.\"
+.\" $Id: cftime.3,v 1.3 1997/02/22 15:05:51 peter Exp $
+.\"
+.Dd June 15, 1993
+.Os
+.Dt CFTIME 3
+.Sh NAME
+.Nm cftime
+.Nm ascftime
+.Nd convert date and time to string
+.Sh SYNOPSIS
+.Fd #include <time.h>
+.Ft int
+.Fn cftime "char *s" "char *format" "const time_t *clock"
+.Ft int
+.Fn ascftime "char *s" "const char *format" "const struct tm *tmptr"
+.Sh DESCRIPTION
+.Bf -symbolic
+The cftime and ascftime functions are made obsolete by strftime(3).
+.br
+They are available from the compatibility library, libcompat.
+.Ef
+.Pp
+Use of the functions
+.Nm cftime
+and
+.Nm ascftime
+is strongly deprecated, since there is no way to check for a buffer
+overflow condition. Use
+.Xr strftime 3
+instead.
+
+.Nm Ascftime
+is almost identical with
+.Xr strftime 3 ,
+with the only exception there's no parameter to tell about the
+maximal buffer length, and the
+.Fa format
+parameter defaults to
+.Dq %C
+if a
+.Em NULL
+pointer is given.
+
+.Nm Cftime
+does the same job, but it first invokes
+.Xr localtime 3
+in order to convert the given
+.Fa clock ,
+then also performs the conversions as requested by the
+.Fa format
+argument.
+
+.Sh RETURN VALUES
+The
+.Nm cftime
+and
+.Nm ascftime
+functions return the number of characters written to the output
+buffer
+.Fa s ,
+not counting the trailing null character.
+
+.Sh SEE ALSO
+.Xr localtime 3 ,
+.Xr strftime 3 .
diff --git a/lib/libcompat/4.1/cftime.c b/lib/libcompat/4.1/cftime.c
new file mode 100644
index 0000000..2e3a34b
--- /dev/null
+++ b/lib/libcompat/4.1/cftime.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1994 Joerg Wunsch
+ *
+ * All rights reserved.
+ *
+ * This program is free software.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 Joerg Wunsch
+ * 4. The name of the developer may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <time.h>
+
+#define MAXLEN 1000 /* just a guess, only the user knows... */
+
+int
+#if __STDC__
+cftime(char *s, char *format, const time_t *clock)
+#else
+cftime(s, format, clock)
+ char *s;
+ char *format;
+ time_t *clock;
+#endif
+{
+ return strftime(s, MAXLEN, format? format: "%C", localtime(clock));
+}
+
diff --git a/lib/libcompat/4.1/ftime.3 b/lib/libcompat/4.1/ftime.3
index a9491af..097eaa6 100644
--- a/lib/libcompat/4.1/ftime.3
+++ b/lib/libcompat/4.1/ftime.3
@@ -40,7 +40,7 @@
.Sh SYNOPSIS
.Fd #include <sys/types.h>
.Fd #include <sys/timeb.h>
-.Ft struct timeb *
+.Ft int
.Fn ftime "struct timeb *tp"
.Sh DESCRIPTION
.Bf -symbolic
@@ -75,8 +75,8 @@ Daylight Saving time applies locally during the appropriate part of the year.
.Sh SEE ALSO
.Xr gettimeofday 2 ,
.Xr settimeofday 2 ,
-.Xr time 2 ,
-.Xr ctime 3
+.Xr ctime 3 ,
+.Xr time 3
.Sh HISTORY
The
.Nm
diff --git a/lib/libcompat/4.1/ftime.c b/lib/libcompat/4.1/ftime.c
new file mode 100644
index 0000000..7da7e85
--- /dev/null
+++ b/lib/libcompat/4.1/ftime.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1994 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.
+ * 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.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+
+int
+ftime(tbp)
+ struct timeb *tbp;
+{
+ struct timezone tz;
+ struct timeval t;
+
+ if (gettimeofday(&t, &tz) < 0)
+ return (-1);
+ tbp->millitm = t.tv_usec / 1000;
+ tbp->time = t.tv_sec;
+ tbp->timezone = tz.tz_minuteswest;
+ tbp->dstflag = tz.tz_dsttime;
+
+ return (0);
+}
diff --git a/lib/libcompat/4.1/getpw.3 b/lib/libcompat/4.1/getpw.3
index 1568e74..b64e588 100644
--- a/lib/libcompat/4.1/getpw.3
+++ b/lib/libcompat/4.1/getpw.3
@@ -38,7 +38,9 @@
.Nm getpw
.Nd get name from uid
.Sh SYNOPSIS
-.Fn getpw uid "char *buf"
+.Fd #include <sys/types.h>
+.Ft int
+.Fn getpw "uid_t uid" "char *buf"
.Sh DESCRIPTION
.Bf -symbolic
The getpw function is made obsolete by getpwuid(3).
@@ -76,3 +78,11 @@ A
.Fn getpw
function appeared in
.At v6 .
+.Sh BUGS
+The area pointed to by
+.Fa buf
+must be large enough to hold the user name.
+
+All of the bugs from
+.Xr getpwent 3
+hold valid as well.
diff --git a/lib/libcompat/4.1/getpw.c b/lib/libcompat/4.1/getpw.c
new file mode 100644
index 0000000..82f7025
--- /dev/null
+++ b/lib/libcompat/4.1/getpw.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1995 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Joerg Wunsch
+ * 4. The name of the developer may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <string.h>
+#include <stdio.h>
+
+int
+#if __STDC__
+getpw(uid_t uid, char *buf)
+#else
+getpw(uid, buf)
+ uid_t uid;
+ char *buf;
+#endif
+{
+ struct passwd *pw;
+
+ pw = getpwuid(uid);
+ endpwent();
+
+ if(pw == 0) return -1;
+
+ strncpy(buf, pw->pw_name, L_cuserid);
+ return 0;
+}
diff --git a/lib/libcompat/4.1/gtty.c b/lib/libcompat/4.1/gtty.c
new file mode 100644
index 0000000..5517ae9
--- /dev/null
+++ b/lib/libcompat/4.1/gtty.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1994 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.
+ * 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.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif /* not lint */
+
+#include <sgtty.h>
+
+/*
+ * Get tty modes.
+ * This was defined in ioctl_compat.h as:
+ * #define gtty(fd, tty) ioctl(fd, TIOCGETP, tty)
+ */
+
+#undef gtty
+
+int
+gtty(fd, tty)
+ int fd;
+ struct sgttyb *tty;
+{
+
+ return (ioctl(fd, TIOCGETP, tty));
+}
diff --git a/lib/libcompat/4.1/stty.3 b/lib/libcompat/4.1/stty.3
index eb3a5c8..32bb114 100644
--- a/lib/libcompat/4.1/stty.3
+++ b/lib/libcompat/4.1/stty.3
@@ -40,7 +40,9 @@
.Nd set and get terminal state (defunct)
.Sh SYNOPSIS
.Fd #include <sgtty.h>
+.Ft int
.Fn stty "int fd" "struct sgttyb *buf"
+.Ft int
.Fn gtty "int fd" "struct sgttyb *buf"
.Sh DESCRIPTION
.Bf -symbolic
diff --git a/lib/libcompat/4.1/stty.c b/lib/libcompat/4.1/stty.c
new file mode 100644
index 0000000..3a73c93
--- /dev/null
+++ b/lib/libcompat/4.1/stty.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1994 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.
+ * 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.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif /* not lint */
+
+#include <sgtty.h>
+
+/*
+ * Set tty modes.
+ * This was defined in ioctl_compat.h as:
+ * #define stty(fd, tty) ioctl(fd, TIOCSETP, tty)
+ */
+
+#undef stty
+
+int
+stty(fd, tty)
+ int fd;
+ struct sgttyb *tty;
+{
+
+ return (ioctl(fd, TIOCSETP, tty));
+}
diff --git a/lib/libcompat/4.1/vlimit.3 b/lib/libcompat/4.1/vlimit.3
index 062f557..4736800 100644
--- a/lib/libcompat/4.1/vlimit.3
+++ b/lib/libcompat/4.1/vlimit.3
@@ -92,7 +92,7 @@ is thus a built-in command to
.Pp
The system refuses to extend the data or stack space when the limits
would be exceeded in the normal way; a
-.Xr break 2
+.Xr brk 2
call fails if the data space limit is reached, or the process is
killed when the stack limit is reached (since the stack cannot be
extended, there is no way to send a signal!).
@@ -121,3 +121,5 @@ function appeared in
.Sh BUGS
.Dv LIM_NORAISE
no longer exists.
+
+This function has not yet been reimplemented.
diff --git a/lib/libcompat/4.1/vtimes.3 b/lib/libcompat/4.1/vtimes.3
index dc4ff4a..6eeee64 100644
--- a/lib/libcompat/4.1/vtimes.3
+++ b/lib/libcompat/4.1/vtimes.3
@@ -131,11 +131,13 @@ These numbers account only for real
data supplied by the caching mechanism is charged only
to the first process to read or write the data.
.Sh SEE ALSO
-.Xr time 2 ,
+.Xr getrusage 2 ,
.Xr wait3 2 ,
-.Xr getrusage 2
+.Xr time 3
.Sh HISTORY
The
.Fn vlimit
function appeared in
.Bx 4.2 .
+.Sh BUGS
+This function has not yet been re-implemented.
diff --git a/lib/libcompat/4.3/cfree.3 b/lib/libcompat/4.3/cfree.3
new file mode 100644
index 0000000..0f5afb2
--- /dev/null
+++ b/lib/libcompat/4.3/cfree.3
@@ -0,0 +1,49 @@
+.\"
+.\" Copyright (c) 1995 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.
+.\"
+.\" $Id$
+.\" " <- this is for hilit19 :)
+.Dd November 23, 1995
+.Dt CFREE 3
+.Os
+.Sh NAME
+.Nm cfree
+.Nd free up allocated memory
+.Sh SYNOPSIS
+.Ft void
+.Fn cfree "void *"
+.Sh DESCRIPTION
+.Bf -symbolic
+The cfree function considered obsolete.
+.br
+It is available from the compatibility library, libcompat.
+.Ef
+.Pp
+The
+.Nm
+function is a synonym for
+.Xr free 3 .
+.Sh SEE ALSO
+.Xr free 3 .
diff --git a/lib/libcompat/4.3/cfree.c b/lib/libcompat/4.3/cfree.c
index 8bade2e..7f029ff 100644
--- a/lib/libcompat/4.3/cfree.c
+++ b/lib/libcompat/4.3/cfree.c
@@ -35,6 +35,8 @@
static char sccsid[] = "@(#)cfree.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
+#include <stdlib.h>
+
void
cfree(p)
void *p;
diff --git a/lib/libcompat/4.3/insque.3 b/lib/libcompat/4.3/insque.3
index 2decaed..2c6ea06 100644
--- a/lib/libcompat/4.3/insque.3
+++ b/lib/libcompat/4.3/insque.3
@@ -47,9 +47,17 @@ struct qelem {
};
.Ed
-.Fn insque "(caddr_t) struct qelem *elem" "(caddr_t) struct qelem *pred"
-.Fn remque "(caddr_t) struct qelem *elem"
+.Ft void
+.Fn insque "struct qelem *elem" "struct qelem *pred"
+.Ft void
+.Fn remque "struct qelem *elem"
.Sh DESCRIPTION
+.Bf -symbolic
+The insque and remque functions are considered obsolete.
+.br
+They are available from the compatibility library, libcompat.
+.Ef
+.Pp
The
.Fn insque
and
diff --git a/lib/libcompat/4.3/insque.c b/lib/libcompat/4.3/insque.c
index 55818fd..3035976 100644
--- a/lib/libcompat/4.3/insque.c
+++ b/lib/libcompat/4.3/insque.c
@@ -46,6 +46,7 @@ struct vaxque { /* queue format expected by VAX queue instructions */
struct vaxque *vq_prev;
};
+void
insque(e, prev)
register struct vaxque *e, *prev;
{
diff --git a/lib/libcompat/4.3/lsearch.3 b/lib/libcompat/4.3/lsearch.3
index d6abfca..ac0e6d5 100644
--- a/lib/libcompat/4.3/lsearch.3
+++ b/lib/libcompat/4.3/lsearch.3
@@ -39,6 +39,7 @@
.Nm lfind,
.Nd linear searching routines
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
.Ft char *
.Fn lsearch "const void *key" "const void *base" "size_t *nelp" "size_t width" "int (*compar)(void *, void *)"
.Ft char *
diff --git a/lib/libcompat/4.3/lsearch.c b/lib/libcompat/4.3/lsearch.c
index baf90ed..be650b4 100644
--- a/lib/libcompat/4.3/lsearch.c
+++ b/lib/libcompat/4.3/lsearch.c
@@ -40,6 +40,7 @@ static char sccsid[] = "@(#)lsearch.c 8.1 (Berkeley) 6/4/93";
#include <sys/types.h>
#include <unistd.h>
+#include <string.h>
static char *linear_base();
diff --git a/lib/libcompat/4.3/re_comp.3 b/lib/libcompat/4.3/re_comp.3
index 498e639..1c6a91d 100644
--- a/lib/libcompat/4.3/re_comp.3
+++ b/lib/libcompat/4.3/re_comp.3
@@ -47,6 +47,7 @@
.Sh DESCRIPTION
This interface is made obsolete by
.Xr regex 3 .
+It is available from the compatibility library, libcompat.
.Pp
The
.Fn re_comp
@@ -109,8 +110,8 @@ unmatched \e).
.Ed
.Sh SEE ALSO
.Xr ed 1 ,
-.Xr ex 1 ,
.Xr egrep 1 ,
+.Xr ex 1 ,
.Xr fgrep 1 ,
.Xr grep 1 ,
.Xr regex 3
diff --git a/lib/libc/db/btree/bt_stack.c b/lib/libcompat/4.3/regex.c
index 5c7fab9..07566b5 100644
--- a/lib/libc/db/btree/bt_stack.c
+++ b/lib/libcompat/4.3/regex.c
@@ -1,9 +1,9 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992 The Regents of the University of California.
+ * All rights reserved.
*
* This code is derived from software contributed to Berkeley by
- * Mike Olson.
+ * James da Silva at the University of Maryland at College Park.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,59 +34,63 @@
* SUCH DAMAGE.
*/
+/*
+ * Compatibility routines that implement the old re_comp/re_exec interface in
+ * terms of the regcomp/regexec interface. It's possible that some programs
+ * rely on dark corners of re_comp/re_exec and won't work with this version,
+ * but most programs should be fine.
+ */
+
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_stack.c 8.3 (Berkeley) 2/21/94";
+static char sccsid[] = "@(#)regex.c 5.1 (Berkeley) 3/29/92";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
-
-#include <errno.h>
-#include <stdio.h>
+#include <stddef.h>
+#include <regexp.h>
+#include <string.h>
#include <stdlib.h>
+#include <string.h>
-#include <db.h>
-#include "btree.h"
+static regexp *re_regexp;
+static int re_goterr;
+static char *re_errstr;
-/*
- * When a page splits, a new record has to be inserted into its parent page.
- * This page may have to split as well, all the way up to the root. Since
- * parent pointers in each page would be expensive, we maintain a stack of
- * parent pages as we descend the tree.
- *
- * XXX
- * This is a concurrency problem -- if user a builds a stack, then user b
- * splits the tree, then user a tries to split the tree, there's a new level
- * in the tree that user a doesn't know about.
- */
+char *
+re_comp(s)
+ char *s;
+{
+ if (s == NULL || *s == '\0') {
+ if (re_regexp == NULL)
+ return "no previous regular expression";
+ return (NULL);
+ }
+ if (re_regexp)
+ free(re_regexp);
+ if (re_errstr)
+ free(re_errstr);
+ re_goterr = 0;
+ re_regexp = regcomp(s);
+ return (re_goterr ? re_errstr : NULL);
+}
-/*
- * __BT_PUSH -- Push parent page info onto the stack (LIFO).
- *
- * Parameters:
- * t: tree
- * pgno: page
- * index: page index
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
int
-__bt_push(t, pgno, index)
- BTREE *t;
- pgno_t pgno;
- indx_t index;
+re_exec(s)
+ char *s;
{
- if (t->bt_sp == t->bt_maxstack) {
- t->bt_maxstack += 50;
- if ((t->bt_stack = (EPGNO *)realloc(t->bt_stack,
- t->bt_maxstack * sizeof(EPGNO))) == NULL) {
- t->bt_maxstack -= 50;
- return (RET_ERROR);
- }
- }
+ int rc;
+
+ re_goterr = 0;
+ rc = regexec(re_regexp, s);
+ return (re_goterr ? -1 : rc);
+}
- t->bt_stack[t->bt_sp].pgno = pgno;
- t->bt_stack[t->bt_sp].index = index;
- ++t->bt_sp;
- return (RET_SUCCESS);
+void
+regerror(s)
+ const char *s;
+{
+ re_goterr = 1;
+ if (re_errstr)
+ free(re_errstr);
+ re_errstr = strdup(s);
}
diff --git a/lib/libcompat/4.3/remque.c b/lib/libcompat/4.3/remque.c
index 39ebfe0..e0f9aa3 100644
--- a/lib/libcompat/4.3/remque.c
+++ b/lib/libcompat/4.3/remque.c
@@ -46,6 +46,7 @@ struct vaxque { /* queue format expected by VAX queue instructions */
struct vaxque *vq_prev;
};
+void
remque(e)
register struct vaxque *e;
{
diff --git a/lib/libcompat/4.3/rexec.3 b/lib/libcompat/4.3/rexec.3
index 2bcb5be..f6d7478 100644
--- a/lib/libcompat/4.3/rexec.3
+++ b/lib/libcompat/4.3/rexec.3
@@ -39,7 +39,7 @@
.Nd return stream to a remote command
.Sh SYNOPSIS
.Ft int
-.Fn rexec ahost "int inport" "char *user" "char *passwd" "char *cmd" "int *fd2p"
+.Fn rexec "char **ahost" "int inport" "char *user" "char *passwd" "char *cmd" "int *fd2p"
.Sh DESCRIPTION
.Bf -symbolic
This interface is obsoleted by krcmd(3).
@@ -120,3 +120,12 @@ The
.Fn rexec
function appeared in
.Bx 4.2 .
+.Sh BUGS
+The
+.Fn rexec
+function sends the unencrypted password across the network.
+.Pp
+The underlying service is considered a big security hole and therefore
+not enabled on many sites, see
+.Xr rexecd 8
+for explanations.
diff --git a/lib/libcompat/4.3/rexec.c b/lib/libcompat/4.3/rexec.c
index 297e444..beb2108 100644
--- a/lib/libcompat/4.3/rexec.c
+++ b/lib/libcompat/4.3/rexec.c
@@ -36,19 +36,262 @@ static char sccsid[] = "@(#)rexec.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
+#include <sys/uio.h>
#include <sys/socket.h>
+#include <sys/param.h>
+#include <sys/stat.h>
#include <netinet/in.h>
#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
#include <netdb.h>
#include <errno.h>
+#include <ctype.h>
+#include <err.h>
+#include <stdlib.h>
+#include <unistd.h>
-extern errno;
-char *index();
int rexecoptions;
char *getpass(), *getlogin();
+/*
+ * Options and other state info.
+ */
+struct macel {
+ char mac_name[9]; /* macro name */
+ char *mac_start; /* start of macro in macbuf */
+ char *mac_end; /* end of macro in macbuf */
+};
+
+int macnum; /* number of defined macros */
+struct macel macros[16];
+char macbuf[4096];
+
+static FILE *cfile;
+
+#define DEFAULT 1
+#define LOGIN 2
+#define PASSWD 3
+#define ACCOUNT 4
+#define MACDEF 5
+#define ID 10
+#define MACH 11
+
+static char tokval[100];
+
+static struct toktab {
+ char *tokstr;
+ int tval;
+} toktab[]= {
+ { "default", DEFAULT },
+ { "login", LOGIN },
+ { "password", PASSWD },
+ { "passwd", PASSWD },
+ { "account", ACCOUNT },
+ { "machine", MACH },
+ { "macdef", MACDEF },
+ { NULL, 0 }
+};
+
+static int
+token()
+{
+ char *cp;
+ int c;
+ struct toktab *t;
+
+ if (feof(cfile) || ferror(cfile))
+ return (0);
+ while ((c = getc(cfile)) != EOF &&
+ (c == '\n' || c == '\t' || c == ' ' || c == ','))
+ continue;
+ if (c == EOF)
+ return (0);
+ cp = tokval;
+ if (c == '"') {
+ while ((c = getc(cfile)) != EOF && c != '"') {
+ if (c == '\\')
+ c = getc(cfile);
+ *cp++ = c;
+ }
+ } else {
+ *cp++ = c;
+ while ((c = getc(cfile)) != EOF
+ && c != '\n' && c != '\t' && c != ' ' && c != ',') {
+ if (c == '\\')
+ c = getc(cfile);
+ *cp++ = c;
+ }
+ }
+ *cp = 0;
+ if (tokval[0] == 0)
+ return (0);
+ for (t = toktab; t->tokstr; t++)
+ if (!strcmp(t->tokstr, tokval))
+ return (t->tval);
+ return (ID);
+}
+
+static int
+ruserpass(host, aname, apass, aacct)
+ char *host, **aname, **apass, **aacct;
+{
+ char *hdir, buf[BUFSIZ], *tmp;
+ char myname[MAXHOSTNAMELEN], *mydomain;
+ int t, i, c, usedefault = 0;
+ struct stat stb;
+
+ hdir = getenv("HOME");
+ if (hdir == NULL)
+ hdir = ".";
+ (void) sprintf(buf, "%s/.netrc", hdir);
+ cfile = fopen(buf, "r");
+ if (cfile == NULL) {
+ if (errno != ENOENT)
+ warn("%s", buf);
+ return (0);
+ }
+ if (gethostname(myname, sizeof(myname)) < 0)
+ myname[0] = '\0';
+ if ((mydomain = strchr(myname, '.')) == NULL)
+ mydomain = "";
+next:
+ while ((t = token())) switch(t) {
+
+ case DEFAULT:
+ usedefault = 1;
+ /* FALL THROUGH */
+
+ case MACH:
+ if (!usedefault) {
+ if (token() != ID)
+ continue;
+ /*
+ * Allow match either for user's input host name
+ * or official hostname. Also allow match of
+ * incompletely-specified host in local domain.
+ */
+ if (strcasecmp(host, tokval) == 0)
+ goto match;
+ if ((tmp = strchr(host, '.')) != NULL &&
+ strcasecmp(tmp, mydomain) == 0 &&
+ strncasecmp(host, tokval, tmp - host) == 0 &&
+ tokval[tmp - host] == '\0')
+ goto match;
+ continue;
+ }
+ match:
+ while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
+
+ case LOGIN:
+ if (token())
+ if (*aname == 0) {
+ *aname = malloc((unsigned) strlen(tokval) + 1);
+ (void) strcpy(*aname, tokval);
+ } else {
+ if (strcmp(*aname, tokval))
+ goto next;
+ }
+ break;
+ case PASSWD:
+ if ((*aname == 0 || strcmp(*aname, "anonymous")) &&
+ fstat(fileno(cfile), &stb) >= 0 &&
+ (stb.st_mode & 077) != 0) {
+ warnx("Error: .netrc file is readable by others.");
+ warnx("Remove password or make file unreadable by others.");
+ goto bad;
+ }
+ if (token() && *apass == 0) {
+ *apass = malloc((unsigned) strlen(tokval) + 1);
+ (void) strcpy(*apass, tokval);
+ }
+ break;
+ case ACCOUNT:
+ if (fstat(fileno(cfile), &stb) >= 0
+ && (stb.st_mode & 077) != 0) {
+ warnx("Error: .netrc file is readable by others.");
+ warnx("Remove account or make file unreadable by others.");
+ goto bad;
+ }
+ if (token() && *aacct == 0) {
+ *aacct = malloc((unsigned) strlen(tokval) + 1);
+ (void) strcpy(*aacct, tokval);
+ }
+ break;
+ case MACDEF:
+ while ((c=getc(cfile)) != EOF &&
+ (c == ' ' || c == '\t'))
+ ;
+ if (c == EOF || c == '\n') {
+ printf("Missing macdef name argument.\n");
+ goto bad;
+ }
+ if (macnum == 16) {
+ printf("Limit of 16 macros have already been defined\n");
+ goto bad;
+ }
+ tmp = macros[macnum].mac_name;
+ *tmp++ = c;
+ for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
+ !isspace(c); ++i) {
+ *tmp++ = c;
+ }
+ if (c == EOF) {
+ printf("Macro definition missing null line terminator.\n");
+ goto bad;
+ }
+ *tmp = '\0';
+ if (c != '\n') {
+ while ((c=getc(cfile)) != EOF && c != '\n');
+ }
+ if (c == EOF) {
+ printf("Macro definition missing null line terminator.\n");
+ goto bad;
+ }
+ if (macnum == 0) {
+ macros[macnum].mac_start = macbuf;
+ }
+ else {
+ macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
+ }
+ tmp = macros[macnum].mac_start;
+ while (tmp != macbuf + 4096) {
+ if ((c=getc(cfile)) == EOF) {
+ printf("Macro definition missing null line terminator.\n");
+ goto bad;
+ }
+ *tmp = c;
+ if (*tmp == '\n') {
+ if (*(tmp-1) == '\0') {
+ macros[macnum++].mac_end = tmp - 1;
+ break;
+ }
+ *tmp = '\0';
+ }
+ tmp++;
+ }
+ if (tmp == macbuf + 4096) {
+ printf("4K macro buffer exceeded\n");
+ goto bad;
+ }
+ break;
+ default:
+ warnx("Unknown .netrc keyword %s", tokval);
+ break;
+ }
+ goto done;
+ }
+done:
+ (void) fclose(cfile);
+ return (0);
+bad:
+ (void) fclose(cfile);
+ return (-1);
+}
+
+int
rexec(ahost, rport, name, pass, cmd, fd2p)
char **ahost;
int rport;
@@ -93,7 +336,7 @@ retry:
} else {
char num[8];
int s2, sin2len;
-
+
s2 = socket(AF_INET, SOCK_STREAM, 0);
if (s2 < 0) {
(void) close(s);
diff --git a/lib/libcompat/4.4/cuserid.3 b/lib/libcompat/4.4/cuserid.3
new file mode 100644
index 0000000..6d25fba
--- /dev/null
+++ b/lib/libcompat/4.4/cuserid.3
@@ -0,0 +1,82 @@
+.\"
+.\" Copyright (c) 1995 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Joerg Wunsch
+.\" 4. The name of the developer may not be used to endorse or promote
+.\" products derived from this software without specific prior written
+.\" permission.
+.\"
+.\" 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.
+.\"
+.\" $Id$
+.\"
+.Dd April 10, 1995
+.Os
+.Dt CUSERID 3
+.Sh NAME
+.Nm cuserid
+.Nd get user name associated with effective UID
+.Sh SYNOPSIS
+.Fd #include <stdio.h>
+.Ft char *
+.Fn cuserid "char *s"
+.Sh DESCRIPTION
+.Bf -symbolic
+The cuserid function is made obsolete by getpwuid.
+.br
+It is available from the compatibility library, libcompat.
+.Ef
+.Pp
+The function
+.Nm cuserid
+gets the user name associated with the effective UID of the current
+process. If the argument
+.Fa s
+is non-zero, the name is copied to the buffer it is pointing to,
+and that address is being returned. This buffer must provide space
+for at least
+.Em L_cuserid
+characters, this constant is defined in
+.Pa Aq stdio.h .
+
+If
+.Fa s
+is zero, an internal array is used an its address will be returned.
+.Sh RETURN VALUES
+.Nm cuserid
+returns the address of an array where the name has been stored to.
+
+If the name associated with the effective UID of the current process
+could not be found, either a null pointer will be returned, or
+.Po
+if
+.Fa s
+is non-zero
+.Pc
+the buffer
+.Fa s
+will be filled with a null string.
+.Sh SEE ALSO
+.Xr geteuid 2 ,
+.Xr getpwuid 3
diff --git a/lib/libcompat/Makefile b/lib/libcompat/Makefile
index bd2aaf9..5bf8c33 100644
--- a/lib/libcompat/Makefile
+++ b/lib/libcompat/Makefile
@@ -1,28 +1,33 @@
# @(#)Makefile 8.1 (Berkeley) 6/4/93
LIB=compat
-CFLAGS+=-DLIBC_SCCS -DSYSLIBC_SCCS
+CFLAGS+=-DLIBC_SCCS -DSYSLIBC_SCCS -I${.CURDIR}/../libc/locale
AINC= -I${.CURDIR}/../libc/${MACHINE}
+NOPIC=
.PATH: ${.CURDIR}/4.1/${MACHINE} ${.CURDIR}/4.1 \
${.CURDIR}/4.3/${MACHINE} ${.CURDIR}/4.3 \
${.CURDIR}/4.4/${MACHINE} ${.CURDIR}/4.4 \
- ${.CURDIR}/regexp
+ ${.CURDIR}/regexp \
+ ${.CURDIR}/SysV
# compat 4.1 sources
-SRCS= ftime.c getpw.c gtty.c stty.c tell.c vlimit.c vtimes.c
+# XXX MISSING: tell.c vlimit.c vtimes.c
+SRCS+= ascftime.c cftime.c ftime.c getpw.c gtty.c stty.c
.if (${MACHINE} == "vax")
SRCS+= reset.s
.endif
-MAN3+= ftime.0 getpw.0 stty.0 vlimit.0 vtimes.0
+MAN3+= 4.1/ftime.3 4.1/getpw.3 4.1/stty.3 4.1/vlimit.3 4.1/vtimes.3
+MAN3+= 4.1/cftime.3
MLINKS+=stty.3 gtty.3
+MLINKS+=cftime.3 ascftime.3
# compat 4.3 sources
-SRCS+= cfree.c ecvt.c gcvt.c lsearch.c regex.c rexec.c sibuf.c sobuf.c \
- strout.c
+# XXX MISSING: ecvt.c gcvt.c sibuf.c sobuf.c strout.c
+SRCS+= cfree.c lsearch.c regex.c rexec.c
.if (${MACHINE} == "hp300" || ${MACHINE} == "luna68k")
SRCS+= insque.s remque.s
@@ -38,21 +43,32 @@ SRCS+= nargs.s insque.s remque.s
SRCS+= nargs.s insque.s remque.s
.endif
-MAN3+= ecvt.0 insque.0 lsearch.0 re_comp.0 rexec.0
+# XXX MISSING: ecvt.0
+MAN3+= 4.3/cfree.3 4.3/insque.3 4.3/lsearch.3 4.3/re_comp.3 4.3/rexec.3
-MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
+# XXX MISSING: ecvt.3, so can't MLINK
+#MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
MLINKS+=insque.3 remque.3
MLINKS+=re_comp.3 re_exec.3
+MLINKS+=lsearch.3 lfind.3
# compat 4.4 sources
SRCS+= cuserid.c
+MAN3+= 4.4/cuserid.3
# regexp sources
SRCS+= regerror.c regexp.c regsub.c
-MAN3+= regexp.0
+MAN3+= regexp/regexp.3
+
+# XXX name clash with libc
+# MLINKS+=regexp.3 regcomp.3 regexp.3 regexec.3 regexp.3 regerror.3
+MLINKS+=regexp.3 regsub.3
+
+# SysV compat sources
+SRCS+= ftok.c
+
+MAN3+= SysV/ftok.3
-MLINKS+=regexp.3 regcomp.3 regexp.3 regexec.3 regexp.3 regsub.3 \
- regexp.3 regerror.3
.include <bsd.lib.mk>
diff --git a/lib/libcompat/SysV/ftok.3 b/lib/libcompat/SysV/ftok.3
new file mode 100644
index 0000000..03b586d
--- /dev/null
+++ b/lib/libcompat/SysV/ftok.3
@@ -0,0 +1,85 @@
+.\" 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.
+.\"
+.\" $Id: ftok.3,v 1.7 1997/02/22 15:06:08 peter Exp $
+.Dd June 24, 1994
+.Os
+.Dt ftok 3
+.Sh NAME
+.Nm ftok
+.Nd create IPC identifier from path name
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ipc.h>
+.Ft key_t
+.Fn ftok "const char *path" "int id"
+.Sh DESCRIPTION
+.Bf -symbolic
+This function is available from the compatibility library, libcompat.
+.Ef
+The
+.Fn ftok
+function attempts to create a unique key suitable for use with the
+.Xr msgget 3 ,
+.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 3
+.Sh HISTORY
+The
+.Fn ftok
+function originates with System V and is typically used by programs
+that use the System V IPC routines.
+.Sh AUTHOR
+.Bl -tag
+Thorsten Lockert <tholo@sigmasoft.com>
+.El
+.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/libcompat/SysV/ftok.c b/lib/libcompat/SysV/ftok.c
new file mode 100644
index 0000000..4f59725
--- /dev/null
+++ b/lib/libcompat/SysV/ftok.c
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ipc.h>
+
+key_t
+ftok(path, id)
+ const char *path;
+ char 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/libcompat/regexp/regexp.3 b/lib/libcompat/regexp/regexp.3
index 0986d4e..f99202e 100644
--- a/lib/libcompat/regexp/regexp.3
+++ b/lib/libcompat/regexp/regexp.3
@@ -51,6 +51,8 @@
.Sh DESCRIPTION
This interface is made obsolete by
.Xr regex 3 .
+.br
+It is available from the compatibility library, libcompat.
.Pp
The
.Fn regcomp ,
@@ -279,9 +281,9 @@ where failures are syntax errors, exceeding implementation limits,
or applying `+' or `*' to a possibly-null operand.
.Sh SEE ALSO
.Xr ed 1 ,
+.Xr egrep 1 ,
.Xr ex 1 ,
.Xr expr 1 ,
-.Xr egrep 1 ,
.Xr fgrep 1 ,
.Xr grep 1 ,
.Xr regex 3
diff --git a/lib/libcompat/regexp/regexp.c b/lib/libcompat/regexp/regexp.c
index 0084295..fc97378 100644
--- a/lib/libcompat/regexp/regexp.c
+++ b/lib/libcompat/regexp/regexp.c
@@ -32,11 +32,13 @@
* precedence is structured in regular expressions. Serious changes in
* regular-expression syntax might require a total rethink.
*/
+#include <limits.h>
#include <regexp.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
+#include "collate.h"
#include "regmagic.h"
/*
@@ -335,7 +337,7 @@ int *flagp;
}
/* Make a closing node, and hook it on the end. */
- ender = regnode((paren) ? CLOSE+parno : END);
+ ender = regnode((paren) ? CLOSE+parno : END);
regtail(ret, ender);
/* Hook the tails of the branches to the closing node. */
@@ -489,6 +491,7 @@ int *flagp;
case '[': {
register int class;
register int classend;
+ int i;
if (*regparse == '^') { /* Complement of range. */
ret = regnode(ANYBUT);
@@ -503,12 +506,23 @@ int *flagp;
if (*regparse == ']' || *regparse == '\0')
regc('-');
else {
- class = UCHARAT(regparse-2)+1;
+ class = UCHARAT(regparse-2);
classend = UCHARAT(regparse);
- if (class > classend+1)
- FAIL("invalid [] range");
- for (; class <= classend; class++)
- regc(class);
+ if (__collate_load_error) {
+ if (class > classend)
+ FAIL("invalid [] range");
+ for (class++; class <= classend; class++)
+ regc(class);
+ } else {
+ if (__collate_range_cmp(class, classend) > 0)
+ FAIL("invalid [] range");
+ for (i = 0; i <= UCHAR_MAX; i++)
+ if ( i != class
+ && __collate_range_cmp(class, i) <= 0
+ && __collate_range_cmp(i, classend) <= 0
+ )
+ regc(i);
+ }
regparse++;
}
} else
@@ -567,7 +581,7 @@ int *flagp;
* On entry, the char at regparse[-1] is going to go
* into the string, no matter what it is. (It could be
* following a \ if we are entered from the '\' case.)
- *
+ *
* Basic idea is to pick up a good char in ch and
* examine the next char. If it's *+? then we twiddle.
* If it's \ then we frozzle. If it's other magic char
@@ -622,7 +636,7 @@ int *flagp;
default:
/* Backup point is \, scan * point is after it. */
regprev = regparse;
- regparse++;
+ regparse++;
continue; /* NOT break; */
}
}
@@ -888,7 +902,6 @@ char *prog;
{
register char *scan; /* Current node. */
char *next; /* Next node. */
- extern char *strchr();
scan = prog;
#ifdef DEBUG
@@ -913,16 +926,16 @@ char *prog;
break;
case WORDA:
/* Must be looking at a letter, digit, or _ */
- if ((!isalnum(*reginput)) && *reginput != '_')
+ if ((!isalnum((unsigned char)*reginput)) && *reginput != '_')
return(0);
/* Prev must be BOL or nonword */
if (reginput > regbol &&
- (isalnum(reginput[-1]) || reginput[-1] == '_'))
+ (isalnum((unsigned char)reginput[-1]) || reginput[-1] == '_'))
return(0);
break;
case WORDZ:
/* Must be looking at non letter, digit, or _ */
- if (isalnum(*reginput) || *reginput == '_')
+ if (isalnum((unsigned char)*reginput) || *reginput == '_')
return(0);
/* We don't care what the previous char was */
break;
@@ -1174,7 +1187,7 @@ regexp *r;
next = regnext(s);
if (next == NULL) /* Next ptr. */
printf("(0)");
- else
+ else
printf("(%d)", (s-r->program)+(next-s));
s += 3;
if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
diff --git a/lib/libcrypt/Makefile b/lib/libcrypt/Makefile
new file mode 100644
index 0000000..6fd0c73
--- /dev/null
+++ b/lib/libcrypt/Makefile
@@ -0,0 +1,41 @@
+#
+# $Id$
+#
+
+LCRYPTBASE= libcrypt
+LCRYPTSO= ${LCRYPTBASE}.so.${SHLIB_MAJOR}.${SHLIB_MINOR}
+
+LSCRYPTBASE= libscrypt
+LSCRYPTSO= ${LSCRYPTBASE}.so.${SHLIB_MAJOR}.${SHLIB_MINOR}
+
+# called libscrypt - for scramble crypt!
+.PATH: ${.CURDIR}/../libmd
+LIB= scrypt
+SRCS= crypt.c md5c.c
+CFLAGS+= -I${.CURDIR}/../libmd
+
+# We only install the links if they do not already exist.
+# This may have to be revised
+
+afterinstall:
+.if !defined(NOPIC)
+ @cd ${DESTDIR}${SHLIBDIR}; \
+ if [ ! -e ${LCRYPTSO} ]; then \
+ rm -f ${LCRYPTSO}; \
+ ln -s ${LSCRYPTSO} ${LCRYPTSO}; \
+ fi
+.endif
+ @cd ${DESTDIR}${LIBDIR}; \
+ if [ ! -e ${LCRYPTBASE}.a ]; then \
+ rm -f ${LCRYPTBASE}.a; \
+ ln -s ${LSCRYPTBASE}.a libcrypt.a; \
+ fi
+.if !defined(NOPROFILE)
+ @cd ${DESTDIR}${LIBDIR}; \
+ if [ ! -e ${LCRYPTBASE}_p.a ]; then \
+ rm -f ${LCRYPTBASE}_p.a; \
+ ln -s ${LSCRYPTBASE}_p.a libcrypt_p.a; \
+ fi
+.endif
+
+.include <bsd.lib.mk>
diff --git a/lib/libcrypt/crypt.c b/lib/libcrypt/crypt.c
new file mode 100644
index 0000000..c0a8dc9
--- /dev/null
+++ b/lib/libcrypt/crypt.c
@@ -0,0 +1,157 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Header: /home/ncvs/src/lib/libcrypt/crypt.c,v 1.6 1997/01/14 06:09:00 jkh Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <md5.h>
+#include <string.h>
+
+static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static void to64 __P((char *, unsigned long, int));
+
+static void
+to64(s, v, n)
+ char *s;
+ unsigned long v;
+ int n;
+{
+static void to64 __P((char *, unsigned long, int));
+
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+
+/*
+ * UNIX password
+ *
+ * Use MD5 for what it is best at...
+ */
+
+char *
+crypt(pw, salt)
+ register const char *pw;
+ register const char *salt;
+{
+ static char *magic = "$1$"; /*
+ * This string is magic for
+ * this algorithm. Having
+ * it this way, we can get
+ * get better later on
+ */
+ static char passwd[120], *p;
+ static const char *sp,*ep;
+ unsigned char final[16];
+ int sl,pl,i,j;
+ MD5_CTX ctx,ctx1;
+ unsigned long l;
+
+ /* Refine the Salt first */
+ sp = salt;
+
+ /* If it starts with the magic string, then skip that */
+ if(!strncmp(sp,magic,strlen(magic)))
+ sp += strlen(magic);
+
+ /* It stops at the first '$', max 8 chars */
+ for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
+ continue;
+
+ /* get the length of the true salt */
+ sl = ep - sp;
+
+ MD5Init(&ctx);
+
+ /* The password first, since that is what is most unknown */
+ MD5Update(&ctx,pw,strlen(pw));
+
+ /* Then our magic string */
+ MD5Update(&ctx,magic,strlen(magic));
+
+ /* Then the raw salt */
+ MD5Update(&ctx,sp,sl);
+
+ /* Then just as many characters of the MD5(pw,salt,pw) */
+ MD5Init(&ctx1);
+ MD5Update(&ctx1,pw,strlen(pw));
+ MD5Update(&ctx1,sp,sl);
+ MD5Update(&ctx1,pw,strlen(pw));
+ MD5Final(final,&ctx1);
+ for(pl = strlen(pw); pl > 0; pl -= 16)
+ MD5Update(&ctx,final,pl>16 ? 16 : pl);
+
+ /* Don't leave anything around in vm they could use. */
+ memset(final,0,sizeof final);
+
+ /* Then something really weird... */
+ for (i = strlen(pw); i ; i >>= 1)
+ if(i&1)
+ MD5Update(&ctx, final, 1);
+ else
+ MD5Update(&ctx, pw, 1);
+
+ /* Now make the output string */
+ strcpy(passwd,magic);
+ strncat(passwd,sp,sl);
+ strcat(passwd,"$");
+
+ MD5Final(final,&ctx);
+
+ /*
+ * and now, just to make sure things don't run too fast
+ * On a 60 Mhz Pentium this takes 34 msec, so you would
+ * need 30 seconds to build a 1000 entry dictionary...
+ */
+ for(i=0;i<1000;i++) {
+ MD5Init(&ctx1);
+ if(i & 1)
+ MD5Update(&ctx1,pw,strlen(pw));
+ else
+ MD5Update(&ctx1,final,16);
+
+ if(i % 3)
+ MD5Update(&ctx1,sp,sl);
+
+ if(i % 7)
+ MD5Update(&ctx1,pw,strlen(pw));
+
+ if(i & 1)
+ MD5Update(&ctx1,final,16);
+ else
+ MD5Update(&ctx1,pw,strlen(pw));
+ MD5Final(final,&ctx1);
+ }
+
+ p = passwd + strlen(passwd);
+
+ l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
+ l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
+ l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
+ l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
+ l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
+ l = final[11] ; to64(p,l,2); p += 2;
+ *p = '\0';
+
+ /* Don't leave anything around in vm they could use. */
+ memset(final,0,sizeof final);
+
+ return passwd;
+}
+
diff --git a/lib/libcurses/EXAMPLES/ex1.c b/lib/libcurses/EXAMPLES/ex1.c
index 76da41b..e8a4e0f 100644
--- a/lib/libcurses/EXAMPLES/ex1.c
+++ b/lib/libcurses/EXAMPLES/ex1.c
@@ -47,7 +47,7 @@ static char sccsid[] = "@(#)ex1.c 8.1 (Berkeley) 6/4/93";
#include <signal.h>
-#define YSIZE 10
+#define YSIZE 10
#define XSIZE 20
int quit();
@@ -65,7 +65,7 @@ main()
crmode(); /* We want cbreak mode */
noecho(); /* We want to have control of chars */
delwin(stdscr); /* Create our own stdscr */
- stdscr = newwin(YSIZE, XSIZE, 10, 35);
+ stdscr = newwin(YSIZE, XSIZE, 10, 35);
flushok(stdscr, TRUE); /* Enable flushing of stdout */
scrollok(stdscr, TRUE); /* Enable scrolling */
erase(); /* Initially, clear the screen */
@@ -107,6 +107,6 @@ quit()
exit(0);
}
-
-
-
+
+
+
diff --git a/lib/libcurses/Makefile b/lib/libcurses/Makefile
index 06de56b..5046265 100644
--- a/lib/libcurses/Makefile
+++ b/lib/libcurses/Makefile
@@ -1,20 +1,22 @@
-# @(#)Makefile 8.2 (Berkeley) 1/2/94
+# From: @(#)Makefile 8.2 (Berkeley) 1/2/94
+# $Id$
CFLAGS+=#-DTFILE=\"/dev/ttyp0\"
CFLAGS+=-D_CURSES_PRIVATE -I${.CURDIR}
+DPADD= ${LIBTERMCAP}
+LDADD= -ltermcap
LIB= curses
SRCS= addbytes.c addch.c addnstr.c box.c clear.c clrtobot.c clrtoeol.c \
cr_put.c ctrace.c cur_hash.c curses.c delch.c deleteln.c delwin.c \
erase.c fullname.c getch.c getstr.c id_subwins.c idlok.c initscr.c \
insch.c insertln.c longname.c move.c mvwin.c newwin.c overlay.c \
- overwrite.c printw.c putchar.c refresh.c scanw.c scroll.c setterm.c \
- standout.c toucholap.c touchwin.c tscroll.c tstp.c tty.c unctrl.c
-MAN3= curses.0
+ overwrite.c printw.c _putchar.c putchar.c refresh.c scanw.c scroll.c \
+ setterm.c standout.c toucholap.c touchwin.c tscroll.c tstp.c tty.c \
+ unctrl.c
+MAN3= curses.3
beforeinstall:
- -cd ${.CURDIR}; cmp -s curses.h ${DESTDIR}/usr/include/curses.h > \
- /dev/null 2>&1 || \
- install -c -o ${BINOWN} -g ${BINGRP} -m 444 curses.h \
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/curses.h \
${DESTDIR}/usr/include
.include <bsd.lib.mk>
diff --git a/lib/libcurses/PSD.doc/appenA b/lib/libcurses/PSD.doc/appenA
new file mode 100644
index 0000000..a40c95d
--- /dev/null
+++ b/lib/libcurses/PSD.doc/appenA
@@ -0,0 +1,77 @@
+.\" 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.
+.\" 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.
+.\"
+.\" @(#)appen.A 8.1 (Berkeley) 6/8/93
+.\"
+.ie t .oh '\*(Ln Appendix A''PS1:19-%'
+.eh 'PS1:19-%''\*(Ln Appendix A'
+.el .he ''\fIAppendix A\fR''
+.bp
+.(x
+.ti 0
+.b "Appendix A"
+.)x
+.sh 1 "Examples" 1
+.pp
+Here we present a few examples
+of how to use the package.
+They attempt to be representative,
+though not comprehensive. Further examples can be found in the games section
+of the source tree and in various utilities that use the screen such as
+.i systat(1) .
+.pp
+The following examples are intended to demonstrate
+the basic structure of a program
+using the package. An additional, more comprehensive, program can be found in
+the source code in the
+\fIexamples\fP subdirectory.
+.sh 2 "Simple Character Output"
+.pp
+This program demonstrates how to set up a window and output characters to it.
+Also, it demonstrates how one might control the output to the window. If
+you run this program, you will get a demonstration of the character output
+chracteristics discussed in the above Character Output section.
+.(l I
+.so ex1.gr
+.)l
+.sh 2 "Twinkle"
+.pp
+This is a moderately simple program which prints
+patterns on the screen.
+It switches between patterns of asterisks,
+putting them on one by one in random order,
+and then taking them off in the same fashion.
+It is more efficient to write this
+using only the motion optimization,
+as is demonstrated below.
+.(l I
+.so twinkle1.gr
+.)l
diff --git a/lib/libcurses/PSD.doc/ex1.c b/lib/libcurses/PSD.doc/ex1.c
index 02ed9b9..97d8432 100644
--- a/lib/libcurses/PSD.doc/ex1.c
+++ b/lib/libcurses/PSD.doc/ex1.c
@@ -37,7 +37,7 @@
#include <signal.h>
-#define YSIZE 10
+#define YSIZE 10
#define XSIZE 20
int quit();
@@ -55,7 +55,7 @@ main()
crmode(); /* We want cbreak mode */
noecho(); /* We want to have control of chars */
delwin(stdscr); /* Create our own stdscr */
- stdscr = newwin(YSIZE, XSIZE, 10, 35);
+ stdscr = newwin(YSIZE, XSIZE, 10, 35);
flushok(stdscr, TRUE); /* Enable flushing of stdout */
scrollok(stdscr, TRUE); /* Enable scrolling */
erase(); /* Initially, clear the screen */
@@ -97,6 +97,6 @@ quit()
exit(0);
}
-
-
-
+
+
+
diff --git a/lib/libcurses/PSD.doc/ex2.c b/lib/libcurses/PSD.doc/ex2.c
index 13e8f29..7b23b61 100644
--- a/lib/libcurses/PSD.doc/ex2.c
+++ b/lib/libcurses/PSD.doc/ex2.c
@@ -52,7 +52,7 @@ main()
char id[100];
int hh = 0;
int curx, cury, base, arg;
-
+
initscr();
signal(SIGINT, quit);
crmode();
@@ -181,7 +181,7 @@ main()
insertln();
sprintf(id, "%d: ", base);
addstr(id);
- for (j = 0; j < XSIZE - strlen(id) - 2; j++)
+ for (j = 0; j < XSIZE - strlen(id) - 2; j++)
addch('0' + (base % 10));
cury++;
} else if (cury >= YSIZE) {
diff --git a/lib/libcurses/PSD.doc/life.c b/lib/libcurses/PSD.doc/life.c
index 72febba..5ecd07f 100644
--- a/lib/libcurses/PSD.doc/life.c
+++ b/lib/libcurses/PSD.doc/life.c
@@ -128,7 +128,7 @@ getstart()
if (Head != NULL) /* start new list */
dellist(Head);
- Head = malloc(sizeof (LIST));
+ Head = malloc(sizeof (LIST));
/*
* loop through the screen looking for 'x's, and add a list
diff --git a/lib/libcurses/_putchar.c b/lib/libcurses/_putchar.c
new file mode 100644
index 0000000..ff90d2c
--- /dev/null
+++ b/lib/libcurses/_putchar.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1981, 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.
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)_putchar.c 8.2 (Berkeley) 5/4/94";
+#endif /* not lint */
+
+#include "curses.h"
+
+int
+_putchar(ch)
+ int ch;
+{
+ __cputchar(ch);
+ return 0;
+}
+
diff --git a/lib/libcurses/addbytes.c b/lib/libcurses/addbytes.c
index 6dd8bf9..39124a0 100644
--- a/lib/libcurses/addbytes.c
+++ b/lib/libcurses/addbytes.c
@@ -75,7 +75,7 @@ __waddbytes(win, bytes, count, so)
#ifdef DEBUG
__CTRACE("ADDBYTES(%0.2o, %d, %d)\n", win, y, x);
#endif
-
+
lp = win->lines[y];
if (lp->flags & __ISPASTEOL) {
lp->flags &= ~__ISPASTEOL;
@@ -96,7 +96,7 @@ newline: if (y == win->maxy - 1) {
if (c == '\n')
break;
}
-
+
stand = '\0';
if (win->flags & __WSTANDOUT || so)
stand |= __STANDOUT;
@@ -104,7 +104,7 @@ newline: if (y == win->maxy - 1) {
__CTRACE("ADDBYTES: 1: y = %d, x = %d, firstch = %d, lastch = %d\n",
y, x, *win->lines[y]->firstchp, *win->lines[y]->lastchp);
#endif
- if (lp->line[x].ch != c ||
+ if (lp->line[x].ch != c ||
!(lp->line[x].attr & stand)) {
newx = x + win->ch_off;
if (!(lp->flags & __ISDIRTY)) {
diff --git a/lib/libcurses/clrtoeol.c b/lib/libcurses/clrtoeol.c
index 44fc190..1f10c41 100644
--- a/lib/libcurses/clrtoeol.c
+++ b/lib/libcurses/clrtoeol.c
@@ -70,7 +70,7 @@ wclrtoeol(win)
}
#ifdef DEBUG
__CTRACE("CLRTOEOL: minx = %d, maxx = %d, firstch = %d, lastch = %d\n",
- minx, maxx - win->lines[y]->line, *win->lines[y]->firstchp,
+ minx, maxx - win->lines[y]->line, *win->lines[y]->firstchp,
*win->lines[y]->lastchp);
#endif
/* Update firstch and lastch for the line. */
diff --git a/lib/libcurses/cr_put.c b/lib/libcurses/cr_put.c
index ada2df5..f17bb2a 100644
--- a/lib/libcurses/cr_put.c
+++ b/lib/libcurses/cr_put.c
@@ -79,10 +79,11 @@ __mvcur(ly, lx, y, x, in_refresh)
destline = y;
outcol = lx;
outline = ly;
- fgoto(in_refresh);
+ if (destline != outline || destcol != outcol)
+ fgoto(in_refresh);
return (OK);
-}
-
+}
+
static void
fgoto(in_refresh)
int in_refresh;
@@ -102,11 +103,11 @@ fgoto(in_refresh)
while (l > 0) {
if (__pfast)
if (CR)
- tputs(CR, 0, __cputchar);
+ tputs(CR, 1, __cputchar);
else
putchar('\r');
if (NL)
- tputs(NL, 0, __cputchar);
+ tputs(NL, 1, __cputchar);
else
putchar('\n');
l--;
@@ -136,7 +137,7 @@ fgoto(in_refresh)
* list this won't work. We should probably have an
* sc capability but sf will generally take the place
* if it works.
- *
+ *
* Superbee glitch: in the middle of the screen have
* to use esc B (down) because linefeed screws up in
* "Efficient Paging" (what a joke) mode (which is
@@ -147,7 +148,7 @@ fgoto(in_refresh)
* Eggert's Superbee description which wins better.
*/
if (NL /* && !XB */ && __pfast)
- tputs(NL, 0, __cputchar);
+ tputs(NL, 1, __cputchar);
else
putchar('\n');
l--;
@@ -166,8 +167,8 @@ fgoto(in_refresh)
*/
if (outcol != COLS - 1 && plod(strlen(cgp), in_refresh) > 0)
plod(0, in_refresh);
- else
- tputs(cgp, 0, __cputchar);
+ else
+ tputs(cgp, 1, __cputchar);
} else
plod(0, in_refresh);
outline = destline;
@@ -244,7 +245,7 @@ plod(cnt, in_refresh)
* Cheaper to home. Do it now and pretend it's a
* regular local motion.
*/
- tputs(HO, 0, plodput);
+ tputs(HO, 1, plodput);
outcol = outline = 0;
} else if (LL) {
/*
@@ -253,7 +254,7 @@ plod(cnt, in_refresh)
*/
k = (LINES - 1) - destline;
if (i + k + 2 < j && (k <= 0 || UP)) {
- tputs(LL, 0, plodput);
+ tputs(LL, 1, plodput);
outcol = 0;
outline = LINES - 1;
}
@@ -297,18 +298,18 @@ plod(cnt, in_refresh)
* If it will be cheaper, or if we can't back up, then send a return
* preliminarily.
*/
- if (j > i + 1 || outcol > destcol && !BS && !BC) {
+ if ((j > i + 1) || (outcol > destcol && !BS && !BC)) {
/*
* BUG: this doesn't take the (possibly long) length of CR
* into account.
*/
if (CR)
- tputs(CR, 0, plodput);
+ tputs(CR, 1, plodput);
else
plodput('\r');
if (NC) {
if (NL)
- tputs(NL, 0, plodput);
+ tputs(NL, 1, plodput);
else
plodput('\n');
outline++;
@@ -319,7 +320,7 @@ plod(cnt, in_refresh)
dontcr: while (outline < destline) {
outline++;
if (NL)
- tputs(NL, 0, plodput);
+ tputs(NL, 1, plodput);
else
plodput('\n');
if (plodcnt < 0)
@@ -348,7 +349,7 @@ dontcr: while (outline < destline) {
}
while (outline > destline) {
outline--;
- tputs(UP, 0, plodput);
+ tputs(UP, 1, plodput);
if (plodcnt < 0)
goto out;
}
diff --git a/lib/libcurses/cur_hash.c b/lib/libcurses/cur_hash.c
index ed47fe3..b358184 100644
--- a/lib/libcurses/cur_hash.c
+++ b/lib/libcurses/cur_hash.c
@@ -43,7 +43,7 @@ static char sccsid[] = "@(#)cur_hash.c 8.1 (Berkeley) 6/4/93";
*/
u_int
__hash(s, len)
- char *s;
+ unsigned char *s;
int len;
{
register u_int h, g, i;
@@ -51,8 +51,8 @@ __hash(s, len)
h = 0;
i = 0;
while (i < len) {
- h = (h << 4) + s[i];
- if (g = h & 0xf0000000) {
+ h = (h << 4) + s[i];
+ if ( (g = h & 0xf0000000) ) {
h = h ^ (g >> 24);
h = h ^ g;
}
diff --git a/lib/libcurses/curses.3 b/lib/libcurses/curses.3
index cd3a18f..a081540 100644
--- a/lib/libcurses/curses.3
+++ b/lib/libcurses/curses.3
@@ -85,7 +85,7 @@ should be called before exiting.
.It delch() delete a character
.It deleteln() delete a line
.It delwin(win) delete
-.Em stdscr
+.Em win
.It echo() set echo mode
.It endwin() end window modes
.It erase() erase
@@ -99,13 +99,14 @@ should be called before exiting.
.It getstr(str) get a string through
.Em stdscr
.It gettmode() get tty modes
-.It getyx(win,y,x) get (y,x) co-ordinates
+.It getyx(win,y,x) get (y,x) co-ordinates for
+.Em win
.It inch() get char at current (y,x) co-ordinates
.It initscr() initialize screens
.It insch(c) insert a char
.It insertln() insert a line
.It leaveok(win,boolf) set leave flag for
-.Em stdscr
+.Em win
.It longname(termbuf,name) get long name from
.Em termbuf
.It move(y,x) move to (y,x) on
@@ -117,8 +118,14 @@ should be called before exiting.
.It noecho() unset echo mode
.It nonl() unset newline mapping
.It noraw() unset raw mode
-.It overlay(win1,win2) overlay win1 on win2
-.It overwrite(win1,win2) overwrite win1 on top of win2
+.It overlay(win1,win2) overlay
+.Em win1
+on
+.Em win2
+.It overwrite(win1,win2) overwrite
+.Em win1
+on top of
+.Em win2
.It printw(fmt,arg1,arg2,...) printf on
.Em stdscr
.It raw() set raw mode
@@ -131,17 +138,20 @@ should be called before exiting.
.It scroll(win) scroll
.Em win
one line
-.It scrollok(win,boolf) set scroll flag
+.It scrollok(win,boolf) set scroll flag for
+.Em win
.It setterm(name) set term variables for name
.It standend() end standout mode
.It standout() start standout mode
-.It subwin(win,lines,cols,begin_y,begin_x)\ create a subwindow
+.It subwin(win,lines,cols,begin_y,begin_x)\ create a subwindow of
+.Em win
.It touchline(win,y,sx,ex) mark line
.Em y
.Em sx
through
.Em sy
-as changed
+as changed on
+.Em win
.It touchoverlap(win1,win2) mark overlap of
.Em win1
on
diff --git a/lib/libcurses/curses.c b/lib/libcurses/curses.c
index 07cbb5b..d78d284 100644
--- a/lib/libcurses/curses.c
+++ b/lib/libcurses/curses.c
@@ -41,12 +41,18 @@ static char sccsid[] = "@(#)curses.c 8.3 (Berkeley) 5/4/94";
int __echoit = 1; /* If stty indicates ECHO. */
int __pfast;
int __rawmode = 0; /* If stty indicates RAW mode. */
-int __noqch = 0; /*
- * If terminal doesn't have
- * insert/delete line capabilities
+int __noqch = 0; /*
+ * If terminal doesn't have
+ * insert/delete line capabilities
+ * or change scroll capabilities
* for quick change on refresh.
*/
-char AM, BS, CA, DA, EO, HC, IN, MI, MS, NC, NS, OS, PC,
+int __usecs = 0; /*
+ * If terminal able to change scroll
+ * region (used only if insert/delete
+ * line capabilities absent)
+ */
+char AM, BS, CA, DA, DB, EO, HC, IN, MI, MS, NC, NS, OS, PC,
UL, XB, XN, XT, XS, XX;
char *AL, *BC, *BT, *CD, *CE, *CL, *CM, *CR, *CS, *DC, *DL,
*DM, *DO, *ED, *EI, *K0, *K1, *K2, *K3, *K4, *K5, *K6,
diff --git a/lib/libcurses/curses.h b/lib/libcurses/curses.h
index d6f9d65..49982c4 100644
--- a/lib/libcurses/curses.h
+++ b/lib/libcurses/curses.h
@@ -30,14 +30,21 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)curses.h 8.5 (Berkeley) 4/29/95
+ * @(#)curses.h 8.3 (Berkeley) 7/27/94
*/
#ifndef _CURSES_H_
#define _CURSES_H_
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
#include <stdio.h>
+#ifndef _BSD_VA_LIST_
+#define _BSD_VA_LIST_ char *
+#endif
+
/*
* The following #defines and #includes are present for backward
* compatibility only. They should not be used in future code.
@@ -45,9 +52,35 @@
* START BACKWARD COMPATIBILITY ONLY.
*/
#ifndef _CURSES_PRIVATE
-#ifndef __cplusplus
+
+/* This stuff needed for those pgms which include <sgtty.h> */
+/* Undef things manually to avoid redefinition */
+
+#undef USE_OLD_TTY
+#undef B0
+#undef B50
+#undef B75
+#undef B110
+#undef B134
+#undef B150
+#undef B200
+#undef B300
+#undef B600
+#undef B1200
+#undef B1800
+#undef B2400
+#undef B4800
+#undef B9600
+#undef EXTA
+#undef EXTB
+#undef B57600
+#undef B115200
+
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/ioctl_compat.h> /* For sgttyb and related */
+
#define bool char
-#endif
#define reg register
#ifndef TRUE
@@ -58,7 +91,6 @@
#endif
#define _puts(s) tputs(s, 0, __cputchar)
-#define _putchar(c) __cputchar(c)
/* Old-style terminal modes access. */
#define baudrate() (cfgetospeed(&__baset))
@@ -66,7 +98,17 @@
#define erasechar() (__baset.c_cc[VERASE])
#define killchar() (__baset.c_cc[VKILL])
#define nocrmode() nocbreak()
-#define ospeed (cfgetospeed(&__baset))
+
+/* WINDOW structure members name compatibility */
+#define _curx curx
+#define _cury cury
+#define _begx begx
+#define _begy begy
+#define _maxx maxx
+#define _maxy maxy
+
+#define _tty __baset
+
#endif /* _CURSES_PRIVATE */
extern char GT; /* Gtty indicates tabs. */
@@ -77,7 +119,7 @@ extern int My_term; /* Use Def_term regardless. */
extern char *Def_term; /* Default terminal type. */
/* Termcap capabilities. */
-extern char AM, BS, CA, DA, EO, HC, IN, MI, MS, NC, NS, OS,
+extern char AM, BS, CA, DA, EO, HC, IN, MI, MS, NC, NS, OS,
PC, UL, XB, XN, XT, XS, XX;
extern char *AL, *BC, *BT, *CD, *CE, *CL, *CM, *CR, *CS, *DC, *DL,
*DM, *DO, *ED, *EI, *K0, *K1, *K2, *K3, *K4, *K5, *K6,
@@ -102,7 +144,7 @@ extern char __unctrllen[256]; /* Control strings length. */
* A line is an array of __LDATA structures pointed to by the 'line' pointer.
*
* IMPORTANT: the __LDATA structure must NOT induce any padding, so if new
- * fields are added -- padding fields with *constant values* should ensure
+ * fields are added -- padding fields with *constant values* should ensure
* that the compiler will not generate any padding when storing an array of
* __LDATA structures. This is to enable consistent use of memcmp, and memcpy
* for comparing and copying arrays.
@@ -145,7 +187,8 @@ typedef struct __window { /* Window structure. */
#define __SCROLLOK 0x020 /* Scrolling ok. */
#define __CLEAROK 0x040 /* Clear on next refresh. */
#define __WSTANDOUT 0x080 /* Standout window */
-#define __LEAVEOK 0x100 /* If curser left */
+#define __LEAVEOK 0x100 /* If curser left */
+#define __FULLLINE 0x200 /* Line width = terminal width. */
u_int flags;
} WINDOW;
@@ -153,9 +196,12 @@ typedef struct __window { /* Window structure. */
extern WINDOW *curscr; /* Current screen. */
extern WINDOW *stdscr; /* Standard screen. */
-extern struct termios __orig_termios; /* Terminal state before curses */
-extern struct termios __baset; /* Our base terminal state */
+typedef struct termios SGTTY;
+
+extern SGTTY __orig_termios; /* Terminal state before curses */
+extern SGTTY __baset; /* Our base terminal state */
extern int __tcaction; /* If terminal hardware set. */
+extern int __tty_fileno; /* Terminal file descriptor */
extern int COLS; /* Columns on the screen. */
extern int LINES; /* Lines on the screen. */
@@ -229,7 +275,7 @@ extern char *ttytype; /* Full name of current terminal. */
#define scrollok(w, bf) \
((bf) ? ((w)->flags |= __SCROLLOK) : ((w)->flags &= ~__SCROLLOK))
#define winch(w) \
- ((w)->lines[(w)->cury]->line[(w)->curx].ch & 0177)
+ ((w)->lines[(w)->cury]->line[(w)->curx].ch & 0377)
/* Public function prototypes. */
int box __P((WINDOW *, int, int));
@@ -288,12 +334,13 @@ int wmove __P((WINDOW *, int, int));
int wprintw __P((WINDOW *, const char *, ...));
int wrefresh __P((WINDOW *));
int wscanw __P((WINDOW *, const char *, ...));
-int wstandend __P((WINDOW *));
-int wstandout __P((WINDOW *));
+int wstandend __P((WINDOW *));
+int wstandout __P((WINDOW *));
int vwprintw __P((WINDOW *, const char *, _BSD_VA_LIST_));
/* Private functions that are needed for user programs prototypes. */
void __cputchar __P((int));
+int _putchar __P((int));
int __waddbytes __P((WINDOW *, const char *, int, int));
/* Private functions. */
@@ -305,6 +352,7 @@ int __mvcur __P((int, int, int, int, int));
void __restore_stophandler __P((void));
void __set_stophandler __P((void));
void __set_subwin __P((WINDOW *, WINDOW *));
+void __set_scroll_region __P((int, int, int, int));
void __startwin __P((void));
void __stop_signal_handler __P((int));
void __swflags __P((WINDOW *));
@@ -318,19 +366,27 @@ int __waddch __P((WINDOW *, __LDATA *));
#define max(a,b) (a > b ? a : b)
/* Private externs. */
+extern char DB;
extern int __echoit;
extern int __endwin;
extern int __pfast;
extern int __rawmode;
extern int __noqch;
+extern int __usecs;
+
+int tputs __P((const char *, int, void (*)(int)));
+
+#else
+
+int tputs __P((const char *, int, int (*)(int)));
+
#endif
/* Termcap functions. */
-int tgetent __P((char *, char *));
-int tgetnum __P((char *));
-int tgetflag __P((char *));
-char *tgetstr __P((char *, char **));
-char *tgoto __P((char *, int, int));
-int tputs __P((char *, int, void (*)(int)));
+int tgetent __P((char *, const char *));
+int tgetnum __P((const char *));
+int tgetflag __P((const char *));
+char *tgetstr __P((const char *, char **));
+char *tgoto __P((const char *, int, int));
#endif /* !_CURSES_H_ */
diff --git a/lib/libcurses/deleteln.c b/lib/libcurses/deleteln.c
index 4cb08ea..afe6b93 100644
--- a/lib/libcurses/deleteln.c
+++ b/lib/libcurses/deleteln.c
@@ -60,8 +60,8 @@ wdeleteln(win)
if (win->orig == NULL)
win->lines[y] = win->lines[y + 1];
else
- (void) memcpy(win->lines[y]->line,
- win->lines[y + 1]->line,
+ (void) memcpy(win->lines[y]->line,
+ win->lines[y + 1]->line,
win->maxx * __LDATASIZE);
__touchline(win, y, 0, win->maxx - 1, 0);
}
diff --git a/lib/libcurses/erase.c b/lib/libcurses/erase.c
index 42ca68a..c2e3e48 100644
--- a/lib/libcurses/erase.c
+++ b/lib/libcurses/erase.c
@@ -58,7 +58,7 @@ werase(win)
end = &start[win->maxx];
for (sp = start; sp < end; sp++)
if (sp->ch != ' ' || sp->attr != 0) {
- maxx = sp;
+ maxx = sp;
if (minx == -1)
minx = sp - start;
sp->ch = ' ';
diff --git a/lib/libcurses/getch.c b/lib/libcurses/getch.c
index 6108229..31dd2b6 100644
--- a/lib/libcurses/getch.c
+++ b/lib/libcurses/getch.c
@@ -61,13 +61,15 @@ wgetch(win)
weset = 0;
inp = getchar();
+ if (inp != EOF) {
#ifdef DEBUG
- __CTRACE("wgetch got '%s'\n", unctrl(inp));
+ __CTRACE("wgetch got '%s'\n", unctrl(inp));
#endif
- if (__echoit) {
- mvwaddch(curscr,
- win->cury + win->begy, win->curx + win->begx, inp);
- waddch(win, inp);
+ if (__echoit) {
+ mvwaddch(curscr,
+ win->cury + win->begy, win->curx + win->begx, inp);
+ waddch(win, inp);
+ }
}
if (weset)
nocbreak();
diff --git a/lib/libcurses/getstr.c b/lib/libcurses/getstr.c
index daf8e61..2536999 100644
--- a/lib/libcurses/getstr.c
+++ b/lib/libcurses/getstr.c
@@ -46,12 +46,12 @@ wgetstr(win, str)
register WINDOW *win;
register char *str;
{
- while ((*str = wgetch(win)) != ERR && *str != '\n')
- str++;
- if (*str == ERR) {
- *str = '\0';
- return (ERR);
- }
- *str = '\0';
+ int c;
+
+ while ((c = wgetch(win)) != ERR && c != EOF && c != '\n')
+ *str++ = c;
+ *str = '\0';
+ if (c == ERR)
+ return (ERR);
return (OK);
}
diff --git a/lib/libcurses/id_subwins.c b/lib/libcurses/id_subwins.c
index 3528348..0ceef2d 100644
--- a/lib/libcurses/id_subwins.c
+++ b/lib/libcurses/id_subwins.c
@@ -59,7 +59,7 @@ __id_subwins(orig)
oy = orig->cury;
for (y = realy - win->begy; y < win->maxy; y++, oy++)
- win->lines[y]->line =
+ win->lines[y]->line =
&orig->lines[oy]->line[win->ch_off];
}
}
diff --git a/lib/libcurses/initscr.c b/lib/libcurses/initscr.c
index 1af8b6f..ac39669 100644
--- a/lib/libcurses/initscr.c
+++ b/lib/libcurses/initscr.c
@@ -68,7 +68,7 @@ initscr()
return (NULL);
/* Need either homing or cursor motion for refreshes */
- if (!HO && !CM)
+ if (!HO && !CM)
return (NULL);
if (curscr != NULL)
diff --git a/lib/libcurses/insch.c b/lib/libcurses/insch.c
index 36cc0de..aa48bcb 100644
--- a/lib/libcurses/insch.c
+++ b/lib/libcurses/insch.c
@@ -61,7 +61,7 @@ winsch(win, ch)
temp1->ch = ch;
temp1->attr &= ~__STANDOUT;
__touchline(win, win->cury, win->curx, win->maxx - 1, 0);
- if (win->cury == LINES - 1 &&
+ if (win->cury == LINES - 1 &&
(win->lines[LINES - 1]->line[COLS - 1].ch != ' ' ||
win->lines[LINES -1]->line[COLS - 1].attr != 0))
if (win->flags & __SCROLLOK) {
diff --git a/lib/libcurses/insertln.c b/lib/libcurses/insertln.c
index c2179f0..ce713ca 100644
--- a/lib/libcurses/insertln.c
+++ b/lib/libcurses/insertln.c
@@ -56,14 +56,14 @@ winsertln(win)
#endif
if (win->orig == NULL)
temp = win->lines[win->maxy - 1];
- for (y = win->maxy - 1; y > win->cury; --y) {
+ for (y = win->maxy - 1; y > (int) win->cury; --y) {
win->lines[y]->flags &= ~__ISPASTEOL;
win->lines[y - 1]->flags &= ~__ISPASTEOL;
if (win->orig == NULL)
win->lines[y] = win->lines[y - 1];
else
- (void)memcpy(win->lines[y]->line,
- win->lines[y - 1]->line,
+ (void)memcpy(win->lines[y]->line,
+ win->lines[y - 1]->line,
win->maxx * __LDATASIZE);
__touchline(win, y, 0, win->maxx - 1, 0);
}
diff --git a/lib/libcurses/newwin.c b/lib/libcurses/newwin.c
index 8f09cbf..3273817 100644
--- a/lib/libcurses/newwin.c
+++ b/lib/libcurses/newwin.c
@@ -134,8 +134,8 @@ __set_subwin(orig, win)
/* Point line pointers to line space. */
for (lp = win->lspace, i = 0; i < win->maxy; i++, lp++) {
win->lines[i] = lp;
- olp = orig->lines[i + win->begy];
- lp->line = &olp->line[win->begx];
+ olp = orig->lines[i + win->begy - orig->begy];
+ lp->line = &olp->line[win->ch_off];
lp->firstchp = &olp->firstch;
lp->lastchp = &olp->lastch;
lp->hash = __hash((char *) lp->line, win->maxx * __LDATASIZE);
@@ -158,7 +158,7 @@ __makenew(nl, nc, by, bx, sub)
register WINDOW *win;
register __LINE *lp;
int i;
-
+
#ifdef DEBUG
__CTRACE("makenew: (%d, %d, %d, %d)\n", nl, nc, by, bx);
@@ -169,7 +169,7 @@ __makenew(nl, nc, by, bx, sub)
__CTRACE("makenew: nl = %d\n", nl);
#endif
- /*
+ /*
* Set up line pointer array and line space.
*/
if ((win->lines = malloc (nl * sizeof(__LINE *))) == NULL) {
@@ -187,14 +187,14 @@ __makenew(nl, nc, by, bx, sub)
/*
* Allocate window space in one chunk.
*/
- if ((win->wspace =
+ if ((win->wspace =
malloc(nc * nl * sizeof(__LDATA))) == NULL) {
free(win->lines);
free(win->lspace);
free(win);
return NULL;
}
-
+
/*
* Point line pointers to line space, and lines themselves into
* window space.
@@ -233,11 +233,16 @@ void
__swflags(win)
register WINDOW *win;
{
- win->flags &= ~(__ENDLINE | __FULLWIN | __SCROLLWIN | __LEAVEOK);
+ win->flags &=
+ ~(__ENDLINE | __FULLLINE | __FULLWIN | __SCROLLWIN | __LEAVEOK);
if (win->begx + win->maxx == COLS) {
win->flags |= __ENDLINE;
- if (win->begx == 0 && win->maxy == LINES && win->begy == 0)
- win->flags |= __FULLWIN;
+ if (win->begx == 0) {
+ if (!__noqch)
+ win->flags |= __FULLLINE;
+ if (win->maxy == LINES && win->begy == 0)
+ win->flags |= __FULLWIN;
+ }
if (win->begy + win->maxy == LINES)
win->flags |= __SCROLLWIN;
}
diff --git a/lib/libcurses/overlay.c b/lib/libcurses/overlay.c
index 9f35c79..22c3433 100644
--- a/lib/libcurses/overlay.c
+++ b/lib/libcurses/overlay.c
@@ -69,7 +69,7 @@ overlay(win1, win2)
for (y = starty; y < endy; y++, y1++, y2++) {
end = &win1->lines[y1]->line[endx - win1->begx];
x = startx - win2->begx;
- for (sp = &win1->lines[y1]->line[startx - win1->begx];
+ for (sp = &win1->lines[y1]->line[startx - win1->begx];
sp < end; sp++) {
if (!isspace(sp->ch)) {
wmove(win2, y2, x);
diff --git a/lib/libcurses/overwrite.c b/lib/libcurses/overwrite.c
index e2d91bd..162c731 100644
--- a/lib/libcurses/overwrite.c
+++ b/lib/libcurses/overwrite.c
@@ -66,7 +66,7 @@ overwrite(win1, win2)
x = endx - startx;
for (y = starty; y < endy; y++) {
(void)memcpy(
- &win2->lines[y - win2->begy]->line[startx - win2->begx],
+ &win2->lines[y - win2->begy]->line[startx - win2->begx],
&win1->lines[y - win1->begy]->line[startx - win1->begx],
x * __LDATASIZE);
__touchline(win2, y, startx - win2->begx, endx - win2->begx,
diff --git a/lib/libcurses/refresh.c b/lib/libcurses/refresh.c
index 3271bd9..1719454 100644
--- a/lib/libcurses/refresh.c
+++ b/lib/libcurses/refresh.c
@@ -32,7 +32,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)refresh.c 8.7 (Berkeley) 8/13/94";
+static char sccsid[] = "@(#)refresh.c 8.4 (Berkeley) 8/4/94";
#endif /* not lint */
#include <string.h>
@@ -45,7 +45,7 @@ static short ly, lx;
static void domvcur __P((int, int, int, int));
static int makech __P((WINDOW *, int));
static void quickch __P((WINDOW *));
-static void scrolln __P((WINDOW *, int, int, int, int, int));
+static void scrolln __P((int, int, int, int, int));
/*
* wrefresh --
@@ -71,13 +71,17 @@ wrefresh(win)
for (wy = 0; wy < win->maxy; wy++) {
wlp = win->lines[wy];
if (wlp->flags & __ISDIRTY)
- wlp->hash = __hash((char *)wlp->line,
- win->maxx * __LDATASIZE);
+ wlp->hash =
+ __hash((char *) wlp->line, win->maxx * __LDATASIZE);
}
if (win->flags & __CLEAROK || curscr->flags & __CLEAROK || curwin) {
if ((win->flags & __FULLWIN) || curscr->flags & __CLEAROK) {
- tputs(CL, 0, __cputchar);
+ if (curscr->flags & __WSTANDOUT) {
+ tputs(SE, 0, __cputchar);
+ curscr->flags &= ~__WSTANDOUT;
+ }
+ tputs(CL, win->maxy, __cputchar);
ly = 0;
lx = 0;
if (!curwin) {
@@ -102,7 +106,7 @@ wrefresh(win)
#endif
#ifndef NOQCH
- if ((win->flags & __FULLWIN) && !curwin) {
+ if ((win->flags & __FULLLINE) && !curwin) {
/*
* Invoke quickch() only if more than a quarter of the lines
* in the window are dirty.
@@ -110,7 +114,8 @@ wrefresh(win)
for (wy = 0, dnum = 0; wy < win->maxy; wy++)
if (win->lines[wy]->flags & (__ISDIRTY | __FORCEPAINT))
dnum++;
- if (!__noqch && dnum > (int) win->maxy / 4)
+ /* __noqch already == 0 when __FULLLINE */
+ if (dnum > (int) win->maxy / 4)
quickch(win);
}
#endif
@@ -129,16 +134,18 @@ wrefresh(win)
__CTRACE("%x",
curscr->lines[i]->line[j].attr);
__CTRACE("\n");
- __CTRACE("W: %d:", i);
- __CTRACE(" 0x%x \n", win->lines[i]->hash);
- __CTRACE(" 0x%x ", win->lines[i]->flags);
+ if (i < win->begy || i > win->begy + win->maxy - 1)
+ continue;
+ __CTRACE("W: %d:", i - win->begy);
+ __CTRACE(" 0x%x \n", win->lines[i - win->begy]->hash);
+ __CTRACE(" 0x%x ", win->lines[i - win->begy]->flags);
for (j = 0; j < win->maxx; j++)
__CTRACE("%c",
- win->lines[i]->line[j].ch);
+ win->lines[i - win->begy]->line[j].ch);
__CTRACE("\n");
for (j = 0; j < win->maxx; j++)
__CTRACE("%x",
- win->lines[i]->line[j].attr);
+ win->lines[i - win->begy]->line[j].attr);
__CTRACE("\n");
}
}
@@ -150,7 +157,7 @@ wrefresh(win)
wy, *win->lines[wy]->firstchp, *win->lines[wy]->lastchp);
#endif
if (!curwin)
- curscr->lines[wy]->hash = win->lines[wy]->hash;
+ curscr->lines[win->begy + wy]->hash = win->lines[wy]->hash;
if (win->lines[wy]->flags & (__ISDIRTY | __FORCEPAINT)) {
if (makech(win, wy) == ERR)
return (ERR);
@@ -218,10 +225,10 @@ makech(win, wy)
int wy;
{
static __LDATA blank = {' ', 0};
- __LDATA *nsp, *csp, *cp, *cep;
+ register int nlsp, clsp; /* Last space in lines. */
+ register int wx, lch, y;
+ register __LDATA *nsp, *csp, *cp, *cep;
u_int force;
- int clsp, nlsp; /* Last space in lines. */
- int lch, wx, y;
char *ce;
/* Is the cursor still on the end of the last line? */
@@ -264,23 +271,22 @@ makech(win, wy)
if (force) {
if (CM)
- tputs(tgoto(CM, lx, ly), 0, __cputchar);
+ tputs(tgoto(CM, lx, ly), 1, __cputchar);
else {
- tputs(HO, 0, __cputchar);
+ tputs(HO, 1, __cputchar);
__mvcur(0, 0, ly, lx, 1);
}
}
-
while (wx <= lch) {
if (!force && memcmp(nsp, csp, sizeof(__LDATA)) == 0) {
if (wx <= lch) {
while (wx <= lch &&
- memcmp(nsp, csp, sizeof(__LDATA)) == 0) {
- nsp++;
- if (!curwin)
- ++csp;
- ++wx;
- }
+ memcmp(nsp, csp, sizeof(__LDATA)) == 0) {
+ nsp++;
+ if (!curwin)
+ csp++;
+ ++wx;
+ }
continue;
}
break;
@@ -296,27 +302,29 @@ makech(win, wy)
while ((force || memcmp(nsp, csp, sizeof(__LDATA)) != 0)
&& wx <= lch) {
- if (ce != NULL &&
- win->maxx + win->begx == curscr->maxx &&
- wx >= nlsp && nsp->ch == ' ' && nsp->attr == 0) {
+ if (ce != NULL && win->maxx + win->begx ==
+ curscr->maxx && wx >= nlsp && nsp->ch == ' ' && nsp->attr == 0) {
/* Check for clear to end-of-line. */
- cep = &curscr->lines[wy]->line[win->maxx - 1];
+ cep = &curscr->lines[win->begy + wy]->line[win->begx + win->maxx - 1];
while (cep->ch == ' ' && cep->attr == 0)
if (cep-- <= csp)
break;
- clsp = cep - curscr->lines[wy]->line -
- win->begx * __LDATASIZE;
+ clsp = cep - curscr->lines[win->begy + wy]->line -
+ win->begx;
#ifdef DEBUG
__CTRACE("makech: clsp = %d, nlsp = %d\n", clsp, nlsp);
#endif
if ((clsp - nlsp >= strlen(CE)
- && clsp < win->maxx * __LDATASIZE) ||
+ && clsp < win->maxx) ||
wy == win->maxy - 1) {
+#ifdef DEBUG
+ __CTRACE("makech: using CE\n");
+#endif
if (curscr->flags & __WSTANDOUT) {
tputs(SE, 0, __cputchar);
curscr->flags &= ~__WSTANDOUT;
}
- tputs(CE, 0, __cputchar);
+ tputs(CE, 1, __cputchar);
lx = wx + win->begx;
while (wx++ <= clsp) {
csp->ch = ' ';
@@ -328,23 +336,19 @@ makech(win, wy)
ce = NULL;
}
- /*
- * Enter/exit standout mode as appropriate.
- * XXX
- * Should use UC if SO/SE not available.
- */
- if (nsp->attr & __STANDOUT) {
- if (!(curscr->flags & __WSTANDOUT) &&
- SO != NULL && SE != NULL) {
+ /* Enter/exit standout mode as appropriate. */
+ /* don't use simple ! here due to gcc -O bug */
+ if (SO && !!(nsp->attr & __STANDOUT) !=
+ !!(curscr->flags & __WSTANDOUT)
+ ) {
+ if (nsp->attr & __STANDOUT) {
tputs(SO, 0, __cputchar);
curscr->flags |= __WSTANDOUT;
- }
- } else
- if (curscr->flags & __WSTANDOUT &&
- SE != NULL) {
+ } else {
tputs(SE, 0, __cputchar);
curscr->flags &= ~__WSTANDOUT;
}
+ }
wx++;
if (wx >= win->maxx && wy == win->maxy - 1 && !curwin)
@@ -408,12 +412,6 @@ makech(win, wy)
__CTRACE("makech: 3: wx = %d, lx = %d\n", wx, lx);
#endif
}
-
- /* Don't leave the screen in standout mode. */
- if (curscr->flags & __WSTANDOUT) {
- tputs(SE, 0, __cputchar);
- curscr->flags &= ~__WSTANDOUT;
- }
return (OK);
}
@@ -454,27 +452,27 @@ quickch(win)
/*
* Find how many lines from the top of the screen are unchanged.
*/
- for (top = 0; top < win->maxy; top++)
- if (win->lines[top]->flags & __FORCEPAINT ||
- win->lines[top]->hash != curscr->lines[top]->hash
- || memcmp(win->lines[top]->line,
+ for (top = win->begy; top < win->begy + win->maxy; top++)
+ if (win->lines[top - win->begy]->flags & __FORCEPAINT ||
+ win->lines[top - win->begy]->hash != curscr->lines[top]->hash
+ || memcmp(win->lines[top - win->begy]->line,
curscr->lines[top]->line,
win->maxx * __LDATASIZE) != 0)
break;
else
- win->lines[top]->flags &= ~__ISDIRTY;
+ win->lines[top - win->begy]->flags &= ~__ISDIRTY;
/*
* Find how many lines from bottom of screen are unchanged.
*/
- for (bot = win->maxy - 1; bot >= 0; bot--)
- if (win->lines[bot]->flags & __FORCEPAINT ||
- win->lines[bot]->hash != curscr->lines[bot]->hash
- || memcmp(win->lines[bot]->line,
+ for (bot = win->begy + win->maxy - 1; bot >= (int) win->begy; bot--)
+ if (win->lines[bot - win->begy]->flags & __FORCEPAINT ||
+ win->lines[bot - win->begy]->hash != curscr->lines[bot]->hash
+ || memcmp(win->lines[bot - win->begy]->line,
curscr->lines[bot]->line,
win->maxx * __LDATASIZE) != 0)
break;
else
- win->lines[bot]->flags &= ~__ISDIRTY;
+ win->lines[bot - win->begy]->flags &= ~__ISDIRTY;
#ifdef NO_JERKINESS
/*
@@ -483,7 +481,7 @@ quickch(win)
* This will increase the number of characters sent to the screen
* but it looks better.
*/
- if (bot < win->maxy - 1)
+ if (bot < (int) win->begy + win->maxy - 1)
return;
#endif /* NO_JERKINESS */
@@ -493,8 +491,8 @@ quickch(win)
* - Startw is the index of the beginning of the examined block in win.
* - Starts is the index of the beginning of the examined block in
* curscr.
- * - Curs is the index of one past the end of the exmined block in win.
- * - Curw is the index of one past the end of the exmined block in
+ * - Curw is the index of one past the end of the exmined block in win.
+ * - Curs is the index of one past the end of the exmined block in
* curscr.
* - bsize is the current size of the examined block.
*/
@@ -504,11 +502,11 @@ quickch(win)
starts++) {
for (curw = startw, curs = starts;
curs < starts + bsize; curw++, curs++)
- if (win->lines[curw]->flags &
+ if (win->lines[curw - win->begy]->flags &
__FORCEPAINT ||
- (win->lines[curw]->hash !=
+ (win->lines[curw - win->begy]->hash !=
curscr->lines[curs]->hash ||
- memcmp(win->lines[curw]->line,
+ memcmp(win->lines[curw - win->begy]->line,
curscr->lines[curs]->line,
win->maxx * __LDATASIZE) != 0))
break;
@@ -550,16 +548,18 @@ quickch(win)
__CTRACE("%x",
curscr->lines[i]->line[j].attr);
__CTRACE("\n");
- __CTRACE("W: %d:", i);
- __CTRACE(" 0x%x \n", win->lines[i]->hash);
- __CTRACE(" 0x%x ", win->lines[i]->flags);
+ if (i < win->begy || i > win->begy + win->maxy - 1)
+ continue;
+ __CTRACE("W: %d:", i - win->begy);
+ __CTRACE(" 0x%x \n", win->lines[i - win->begy]->hash);
+ __CTRACE(" 0x%x ", win->lines[i - win->begy]->flags);
for (j = 0; j < win->maxx; j++)
__CTRACE("%c",
- win->lines[i]->line[j].ch);
+ win->lines[i - win->begy]->line[j].ch);
__CTRACE("\n");
for (j = 0; j < win->maxx; j++)
__CTRACE("%x",
- win->lines[i]->line[j].attr);
+ win->lines[i - win->begy]->line[j].attr);
__CTRACE("\n");
}
#endif
@@ -622,7 +622,7 @@ quickch(win)
#ifdef DEBUG
__CTRACE("-- notdirty");
#endif
- win->lines[target]->flags &= ~__ISDIRTY;
+ win->lines[target - win->begy]->flags &= ~__ISDIRTY;
} else if ((n > 0 && target >= top && target < top + n) ||
(n < 0 && target <= bot && target > bot + n)) {
if (clp->hash != blank_hash || memcmp(clp->line,
@@ -633,9 +633,9 @@ quickch(win)
__CTRACE("-- blanked out: dirty");
#endif
clp->hash = blank_hash;
- __touchline(win, target, 0, win->maxx - 1, 0);
+ __touchline(win, target - win->begy, 0, win->maxx - 1, 0);
} else {
- __touchline(win, target, 0, win->maxx - 1, 0);
+ __touchline(win, target - win->begy, 0, win->maxx - 1, 0);
#ifdef DEBUG
__CTRACE(" -- blank line already: dirty");
#endif
@@ -644,7 +644,7 @@ quickch(win)
#ifdef DEBUG
__CTRACE(" -- dirty");
#endif
- __touchline(win, target, 0, win->maxx - 1, 0);
+ __touchline(win, target - win->begy, 0, win->maxx - 1, 0);
}
#ifdef DEBUG
__CTRACE("\n");
@@ -666,15 +666,18 @@ quickch(win)
__CTRACE("%c",
curscr->lines[i]->line[j].ch);
__CTRACE("\n");
- __CTRACE("W: %d:", i);
+ if (i < win->begy || i > win->begy + win->maxy - 1)
+ continue;
+ __CTRACE("W: %d:", i - win->begy);
for (j = 0; j < win->maxx; j++)
- __CTRACE("%c", win->lines[i]->line[j].ch);
+ __CTRACE("%c",
+ win->lines[i - win->begy]->line[j].ch);
__CTRACE("\n");
}
#endif
if (n != 0) {
WINDOW *wp;
- scrolln(win, starts, startw, curs, bot, top);
+ scrolln(starts, startw, curs, bot, top);
/*
* Need to repoint any subwindow lines to the rotated
* line structured.
@@ -689,8 +692,7 @@ quickch(win)
* Scroll n lines, where n is starts - startw.
*/
static void
-scrolln(win, starts, startw, curs, bot, top)
- WINDOW *win;
+scrolln(starts, startw, curs, bot, top)
int starts, startw, curs, bot, top;
{
int i, oy, ox, n;
@@ -700,19 +702,6 @@ scrolln(win, starts, startw, curs, bot, top)
n = starts - startw;
/*
- * XXX
- * The initial tests that set __noqch don't let us reach here unless
- * we have either CS + HO + SF/sf/SR/sr, or AL + DL. SF/sf and SR/sr
- * scrolling can only shift the entire scrolling region, not just a
- * part of it, which means that the quickch() routine is going to be
- * sadly disappointed in us if we don't have CS as well.
- *
- * If CS, HO and SF/sf are set, can use the scrolling region. Because
- * the cursor position after CS is undefined, we need HO which gives us
- * the ability to move to somewhere without knowledge of the current
- * location of the cursor. Still call __mvcur() anyway, to update its
- * idea of where the cursor is.
- *
* When the scrolling region has been set, the cursor has to be at the
* last line of the region to make the scroll happen.
*
@@ -722,51 +711,91 @@ scrolln(win, starts, startw, curs, bot, top)
* AL/DL, otherwise use the scrolling region. The "almost all" is a
* shameless hack for vi.
*/
- if (n > 0) {
- if (CS != NULL && HO != NULL && (SF != NULL ||
- (AL == NULL || DL == NULL ||
- top > 3 || bot + 3 < win->maxy) && sf != NULL)) {
- tputs(__tscroll(CS, top, bot + 1), 0, __cputchar);
- __mvcur(oy, ox, 0, 0, 1);
- tputs(HO, 0, __cputchar);
- __mvcur(0, 0, bot, 0, 1);
- if (SF != NULL)
- tputs(__tscroll(SF, n, 0), 0, __cputchar);
+
+ if (__usecs) { /* Use change scroll region */
+ if (bot != curscr->maxy - 1 || top != 0)
+ __set_scroll_region(top, bot, ox, oy);
+ if (n > 0) {
+ __mvcur(oy, ox, bot, 0, 1);
+ /* Scroll up the block */
+ if (SF != NULL && n > 1)
+ tputs(__tscroll(SF, n, 0), n, __cputchar);
else
- for (i = 0; i < n; i++)
- tputs(sf, 0, __cputchar);
- tputs(__tscroll(CS, 0, win->maxy), 0, __cputchar);
- __mvcur(bot, 0, 0, 0, 1);
- tputs(HO, 0, __cputchar);
- __mvcur(0, 0, oy, ox, 1);
- return;
+ /* newline seems faster than sf */
+ for(i = 0; i < n; i++)
+ if (NL && __pfast)
+ tputs(NL, 1, __cputchar);
+ else
+ putchar('\n');
+ __mvcur(bot, 0, oy, ox, 1);
+ } else {
+ __mvcur(oy, ox, top, 0, 1);
+ /* Scroll the block down */
+ if (SR != NULL && (sr == NULL || -n > 1))
+ tputs(__tscroll(SR, -n, 0), -n, __cputchar);
+ else
+ for(i = n; i < 0; i++)
+ tputs(sr, 1, __cputchar);
+ __mvcur(top, 0, oy, ox, 1);
}
+ if (bot != curscr->maxy - 1 || top != 0)
+ __set_scroll_region(0, curscr->maxy - 1, ox, oy);
+ return;
+ }
- /* Scroll up the block. */
- if (SF != NULL && top == 0) {
- __mvcur(oy, ox, bot, 0, 1);
- tputs(__tscroll(SF, n, 0), 0, __cputchar);
- } else if (DL != NULL) {
+ if (n > 0) {
+ /* Scroll up the screen. */
+ if (((!DB && SF != NULL) || n == 1) && (bot == curscr->maxy - 1) && top == 0) {
+ __mvcur(oy, ox, curscr->maxy - 1, 0, 1);
+ if (n == 1)
+ goto f_nl1;
+ tputs(__tscroll(SF, n, 0), n, __cputchar);
+ __mvcur(curscr->maxy - 1, 0, oy, ox, 1);
+ return;
+ }
+ else if (DL != NULL && top != 0) {
__mvcur(oy, ox, top, 0, 1);
- tputs(__tscroll(DL, n, 0), 0, __cputchar);
- } else if (dl != NULL) {
+ if (dl != NULL && n == 1)
+ goto f_dl1;
+ tputs(__tscroll(DL, n, 0), n, __cputchar);
+ __mvcur(top, 0, bot - n + 1, 0, 1);
+ }
+ else if (dl != NULL && top != 0) {
__mvcur(oy, ox, top, 0, 1);
+ f_dl1:
for (i = 0; i < n; i++)
- tputs(dl, 0, __cputchar);
- } else if (sf != NULL && top == 0) {
- __mvcur(oy, ox, bot, 0, 1);
- for (i = 0; i < n; i++)
- tputs(sf, 0, __cputchar);
- } else
+ tputs(dl, 1, __cputchar);
+ __mvcur(top, 0, bot - n + 1, 0, 1);
+ }
+ else if (top == 0) {
+ __mvcur(oy, ox, curscr->maxy - 1, 0, 1);
+ f_nl1:
+ /* newline seems faster than sf */
+ for(i = 0; i < n; i++)
+ if (NL && __pfast)
+ tputs(NL, 1, __cputchar);
+ else
+ putchar('\n');
+ if (bot == curscr->maxy - 1) {
+ __mvcur(curscr->maxy - 1, 0, oy, ox, 1);
+ return;
+ }
+ __mvcur(curscr->maxy - 1, 0, bot - n + 1, 0, 1);
+ }
+ else
abort();
/* Push down the bottom region. */
- __mvcur(top, 0, bot - n + 1, 0, 1);
- if (AL != NULL)
- tputs(__tscroll(AL, n, 0), 0, __cputchar);
- else if (al != NULL)
+ if (AL != NULL) {
+ if (al != NULL && n == 1)
+ goto f_al1;
+ tputs(__tscroll(AL, n, 0), n, __cputchar);
+ }
+ else if (al != NULL) {
+ f_al1:
for (i = 0; i < n; i++)
- tputs(al, 0, __cputchar);
+ tputs(al, 1, __cputchar);
+ }
else
abort();
__mvcur(bot - n + 1, 0, oy, ox, 1);
@@ -774,52 +803,46 @@ scrolln(win, starts, startw, curs, bot, top)
/*
* !!!
* n < 0
- *
- * If CS, HO and SR/sr are set, can use the scrolling region.
- * See the above comments for details.
*/
- if (CS != NULL && HO != NULL && (SR != NULL ||
- (AL == NULL || DL == NULL ||
- top > 3 || bot + 3 < win->maxy) && sr != NULL)) {
- tputs(__tscroll(CS, top, bot + 1), 0, __cputchar);
+ /* Scroll down the screen. */
+ if (!DA && (SR != NULL || sr != NULL) && bot == curscr->maxy - 1 && top == 0) {
__mvcur(oy, ox, 0, 0, 1);
- tputs(HO, 0, __cputchar);
- __mvcur(0, 0, top, 0, 1);
-
- if (SR != NULL)
- tputs(__tscroll(SR, -n, 0), 0, __cputchar);
- else
+ if (SR == NULL || (sr != NULL && -n == 1)) {
for (i = n; i < 0; i++)
- tputs(sr, 0, __cputchar);
- tputs(__tscroll(CS, 0, win->maxy), 0, __cputchar);
- __mvcur(top, 0, 0, 0, 1);
- tputs(HO, 0, __cputchar);
+ tputs(sr, 1, __cputchar);
+ } else
+ tputs(__tscroll(SR, -n, 0), -n, __cputchar);
__mvcur(0, 0, oy, ox, 1);
return;
}
-
- /* Preserve the bottom lines. */
- __mvcur(oy, ox, bot + n + 1, 0, 1);
- if (SR != NULL && bot == win->maxy)
- tputs(__tscroll(SR, -n, 0), 0, __cputchar);
- else if (DL != NULL)
- tputs(__tscroll(DL, -n, 0), 0, __cputchar);
- else if (dl != NULL)
- for (i = n; i < 0; i++)
- tputs(dl, 0, __cputchar);
- else if (sr != NULL && bot == win->maxy)
+ else if (DL != NULL) {
+ __mvcur(oy, ox, bot + n + 1, 0, 1);
+ if (dl != NULL && -n == 1)
+ goto b_dl1;
+ tputs(__tscroll(DL, -n, 0), -n, __cputchar);
+ __mvcur(bot + n + 1, 0, top, 0, 1);
+ }
+ else if (dl != NULL) {
+ __mvcur(oy, ox, bot + n + 1, 0, 1);
+ b_dl1:
for (i = n; i < 0; i++)
- tputs(sr, 0, __cputchar);
+ tputs(dl, 1, __cputchar);
+ __mvcur(bot + n + 1, 0, top, 0, 1);
+ }
else
abort();
/* Scroll the block down. */
- __mvcur(bot + n + 1, 0, top, 0, 1);
- if (AL != NULL)
- tputs(__tscroll(AL, -n, 0), 0, __cputchar);
- else if (al != NULL)
+ if (AL != NULL) {
+ if (al != NULL && -n == 1)
+ goto b_al1;
+ tputs(__tscroll(AL, -n, 0), -n, __cputchar);
+ }
+ else if (al != NULL) {
+ b_al1:
for (i = n; i < 0; i++)
- tputs(al, 0, __cputchar);
+ tputs(al, 1, __cputchar);
+ }
else
abort();
__mvcur(top, 0, oy, ox, 1);
diff --git a/lib/libcurses/scanw.c b/lib/libcurses/scanw.c
index d8d79fd..221384f 100644
--- a/lib/libcurses/scanw.c
+++ b/lib/libcurses/scanw.c
@@ -101,7 +101,7 @@ wscanw(win, fmt, va_alist)
}
/*
- * mvscanw, mvwscanw --
+ * mvscanw, mvwscanw --
* Implement the mvscanw commands. Due to the variable number of
* arguments, they cannot be macros. Another sigh....
*/
diff --git a/lib/libcurses/setterm.c b/lib/libcurses/setterm.c
index 887bcb1..252c599 100644
--- a/lib/libcurses/setterm.c
+++ b/lib/libcurses/setterm.c
@@ -32,7 +32,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)setterm.c 8.8 (Berkeley) 10/25/94";
+static char sccsid[] = "@(#)setterm.c 8.7 (Berkeley) 7/27/94";
#endif /* not lint */
#include <sys/ioctl.h> /* TIOCGWINSZ on old systems. */
@@ -47,8 +47,8 @@ static char sccsid[] = "@(#)setterm.c 8.8 (Berkeley) 10/25/94";
static void zap __P((void));
static char *sflags[] = {
- /* am bs da eo hc in mi ms */
- &AM, &BS, &DA, &EO, &HC, &IN, &MI, &MS,
+ /* am bs da db eo hc in mi ms */
+ &AM, &BS, &DA, &DB, &EO, &HC, &IN, &MI, &MS,
/* nc ns os ul xb xn xt xs xx */
&NC, &NS, &OS, &UL, &XB, &XN, &XT, &XS, &XX
};
@@ -68,9 +68,9 @@ static char *_PC,
/* so SR ta te ti uc ue up us */
&SO, &SR, &TA, &TE, &TI, &UC, &UE, &UP, &US,
/* vb vs ve al dl sf sr AL */
- &VB, &VS, &VE, &al, &dl, &sf, &sr, &AL_PARM,
+ &VB, &VS, &VE, &al, &dl, &sf, &sr, &AL_PARM,
/* DL UP DO LE */
- &DL_PARM, &UP_PARM, &DOWN_PARM, &LEFT_PARM,
+ &DL_PARM, &UP_PARM, &DOWN_PARM, &LEFT_PARM,
/* RI */
&RIGHT_PARM,
};
@@ -106,7 +106,7 @@ setterm(type)
#endif
/* Try TIOCGWINSZ, and, if it fails, the termcap entry. */
- if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) != -1 &&
+ if (ioctl(__tty_fileno, TIOCGWINSZ, &win) != -1 &&
win.ws_row != 0 && win.ws_col != 0) {
LINES = win.ws_row;
COLS = win.ws_col;
@@ -141,25 +141,28 @@ setterm(type)
* Test for cursor motion capbility.
*
* XXX
- * This is truly stupid -- historically, tgoto returns "OOPS" if it
- * can't do cursor motions. Some systems have been fixed to return
- * a NULL pointer.
+ * This is truly stupid -- tgoto returns "OOPS" if it can't
+ * do cursor motions.
*/
- if ((p = tgoto(CM, 0, 0)) == NULL || *p == 'O') {
+ if (tgoto(CM, 0, 0)[0] == 'O') {
CA = 0;
CM = 0;
} else
CA = 1;
PC = _PC ? _PC[0] : 0;
+
aoftspace = tspace;
ttytype = longname(genbuf, __ttytype);
+ __usecs =
+ ((AL == NULL && al == NULL) || (DL == NULL && dl == NULL)) &&
+ !NS && ((SC != NULL && RC != NULL) || HO != NULL) &&
+ CS != NULL && (SR != NULL || sr != NULL);
+
/* If no scrolling commands, no quick change. */
- __noqch =
- (CS == NULL || HO == NULL ||
- SF == NULL && sf == NULL || SR == NULL && sr == NULL) &&
- (AL == NULL && al == NULL || DL == NULL && dl == NULL);
+ __noqch = !__usecs &&
+ ((AL == NULL && al == NULL) || (DL == NULL && dl == NULL));
return (unknown ? ERR : OK);
}
@@ -179,7 +182,7 @@ zap()
#endif
tmp[2] = '\0';
- namp = "ambsdaeohcinmimsncnsosulxbxnxtxsxx";
+ namp = "ambsdadbeohcinmimsncnsosulxbxnxtxsxx";
fp = sflags;
do {
*tmp = *namp;
@@ -189,7 +192,7 @@ zap()
__CTRACE("2.2s = %s\n", namp, *fp[-1] ? "TRUE" : "FALSE");
#endif
namp += 2;
-
+
} while (*namp);
namp = "ALbcbtcdceclcmcrcsdcDLdmdoedeik0k1k2k3k4k5k6k7k8k9hoicimipkdkekhklkrkskullmandnlpcrcscseSFsoSRtatetiucueupusvbvsvealdlsfsrALDLUPDOLERI";
sp = sstrs;
diff --git a/lib/libcurses/standout.c b/lib/libcurses/standout.c
index 8851d63..903400a 100644
--- a/lib/libcurses/standout.c
+++ b/lib/libcurses/standout.c
@@ -32,7 +32,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)standout.c 8.3 (Berkeley) 8/10/94";
+static char sccsid[] = "@(#)standout.c 8.2 (Berkeley) 5/4/94";
#endif /* not lint */
#include "curses.h"
@@ -43,15 +43,13 @@ static char sccsid[] = "@(#)standout.c 8.3 (Berkeley) 8/10/94";
*/
int
wstandout(win)
- WINDOW *win;
+ register WINDOW *win;
{
- /*
- * If standout/standend strings, or can underline, set the
- * screen standout bit.
- */
- if (SO != NULL && SE != NULL || UC != NULL)
- win->flags |= __WSTANDOUT;
- return (1);
+ if (!SO && !UC)
+ return (ERR);
+
+ win->flags |= __WSTANDOUT;
+ return (OK);
}
/*
@@ -60,8 +58,11 @@ wstandout(win)
*/
int
wstandend(win)
- WINDOW *win;
+ register WINDOW *win;
{
+ if (!SO && !UC)
+ return (ERR);
+
win->flags &= ~__WSTANDOUT;
- return (1);
+ return (OK);
}
diff --git a/lib/libcurses/tscroll.c b/lib/libcurses/tscroll.c
index 359b396..a3326a9 100644
--- a/lib/libcurses/tscroll.c
+++ b/lib/libcurses/tscroll.c
@@ -66,7 +66,7 @@ __tscroll(cap, n1, n2)
int n1, n2;
{
static char result[MAXRETURNSIZE];
- int c, n;
+ int c, n, increment = 0;
char *dp;
if (cap == NULL)
@@ -94,6 +94,8 @@ __tscroll(cap, n1, n2)
two: *dp++ = n / 10 | '0';
one: *dp++ = n % 10 | '0';
n = n2;
+ if (increment)
+ n++;
continue;
case '>':
if (n > *cap++)
@@ -108,6 +110,7 @@ one: *dp++ = n % 10 | '0';
*dp++ = n;
continue;
case 'i':
+ increment = 1;
n++;
continue;
case '%':
diff --git a/lib/libcurses/tstp.c b/lib/libcurses/tstp.c
index 07debf4..069dbd8 100644
--- a/lib/libcurses/tstp.c
+++ b/lib/libcurses/tstp.c
@@ -54,7 +54,7 @@ __stop_signal_handler(signo)
sigset_t oset, set;
/* Get the current terminal state (which the user may have changed). */
- if (tcgetattr(STDIN_FILENO, &save))
+ if (tcgetattr(__tty_fileno, &save))
return;
/*
@@ -65,7 +65,7 @@ __stop_signal_handler(signo)
(void)sigaddset(&set, SIGALRM);
(void)sigaddset(&set, SIGWINCH);
(void)sigprocmask(SIG_BLOCK, &set, &oset);
-
+
/*
* End the window, which also resets the terminal state to the
* original modes.
@@ -87,10 +87,10 @@ __stop_signal_handler(signo)
__set_stophandler();
/* save the new "default" terminal state */
- (void)tcgetattr(STDIN_FILENO, &__orig_termios);
+ (void)tcgetattr(__tty_fileno, &__orig_termios);
/* Reset the terminal state to the mode just before we stopped. */
- (void)tcsetattr(STDIN_FILENO, __tcaction ?
+ (void)tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, &save);
/* Restart the screen. */
@@ -122,3 +122,7 @@ __restore_stophandler()
{
(void)signal(SIGTSTP, otstpfn);
}
+
+/* For compatibility */
+
+void tstp() { __stop_signal_handler(SIGTSTP); }
diff --git a/lib/libcurses/tty.c b/lib/libcurses/tty.c
index db031d5..8265881 100644
--- a/lib/libcurses/tty.c
+++ b/lib/libcurses/tty.c
@@ -32,12 +32,12 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)tty.c 8.6 (Berkeley) 1/10/95";
+static char sccsid[] = "@(#)tty.c 8.4 (Berkeley) 5/18/94";
#endif /* not lint */
-#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
+#include <fcntl.h>
#include "curses.h"
@@ -54,6 +54,7 @@ int __tcaction = 1; /* Ignore hardware settings. */
int __tcaction = 0;
#endif
+int __tty_fileno, __noterm = 0;
struct termios __orig_termios, __baset;
static struct termios cbreakt, rawt, *curt;
static int useraw;
@@ -74,9 +75,10 @@ int
gettmode()
{
useraw = 0;
-
- if (tcgetattr(STDIN_FILENO, &__orig_termios))
- return (ERR);
+
+ if (tcgetattr(__tty_fileno = STDIN_FILENO, &__orig_termios))
+ if (tcgetattr(__tty_fileno = STDOUT_FILENO, &__orig_termios))
+ __noterm = 1;
__baset = __orig_termios;
__baset.c_oflag &= ~OXTABS;
@@ -116,8 +118,9 @@ gettmode()
}
curt = &__baset;
- return (tcsetattr(STDIN_FILENO, __tcaction ?
+ return (!__noterm && tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
+ return OK;
}
int
@@ -125,7 +128,7 @@ raw()
{
useraw = __pfast = __rawmode = 1;
curt = &rawt;
- return (tcsetattr(STDIN_FILENO, __tcaction ?
+ return (!__noterm && tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
}
@@ -134,7 +137,7 @@ noraw()
{
useraw = __pfast = __rawmode = 0;
curt = &__baset;
- return (tcsetattr(STDIN_FILENO, __tcaction ?
+ return (!__noterm && tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
}
@@ -144,7 +147,7 @@ cbreak()
__rawmode = 1;
curt = useraw ? &rawt : &cbreakt;
- return (tcsetattr(STDIN_FILENO, __tcaction ?
+ return (!__noterm && tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
}
@@ -154,19 +157,19 @@ nocbreak()
__rawmode = 0;
curt = useraw ? &rawt : &__baset;
- return (tcsetattr(STDIN_FILENO, __tcaction ?
+ return (!__noterm && tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
}
-
+
int
echo()
{
rawt.c_lflag |= ECHO;
cbreakt.c_lflag |= ECHO;
__baset.c_lflag |= ECHO;
-
+
__echoit = 1;
- return (tcsetattr(STDIN_FILENO, __tcaction ?
+ return (!__noterm && tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
}
@@ -176,9 +179,9 @@ noecho()
rawt.c_lflag &= ~ECHO;
cbreakt.c_lflag &= ~ECHO;
__baset.c_lflag &= ~ECHO;
-
+
__echoit = 0;
- return (tcsetattr(STDIN_FILENO, __tcaction ?
+ return (!__noterm && tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
}
@@ -193,7 +196,7 @@ nl()
__baset.c_oflag |= ONLCR;
__pfast = __rawmode;
- return (tcsetattr(STDIN_FILENO, __tcaction ?
+ return (!__noterm && tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
}
@@ -208,35 +211,35 @@ nonl()
__baset.c_oflag &= ~ONLCR;
__pfast = 1;
- return (tcsetattr(STDIN_FILENO, __tcaction ?
+ return (!__noterm && tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
}
void
__startwin()
{
- static char *stdbuf;
- static size_t len;
-
(void)fflush(stdout);
-
- /*
- * Some C libraries default to a 1K buffer when talking to a tty.
- * With a larger screen, especially across a network, we'd like
- * to get it to all flush in a single write. Make it twice as big
- * as just the characters (so that we have room for cursor motions
- * and standout information) but no more than 8K.
- */
- if (stdbuf == NULL) {
- if ((len = LINES * COLS * 2) > 8192)
- len = 8192;
- if ((stdbuf = malloc(len)) == NULL)
- len = 0;
- }
- (void)setvbuf(stdout, stdbuf, _IOFBF, len);
+ (void)setvbuf(stdout, NULL, _IOFBF, 0);
tputs(TI, 0, __cputchar);
tputs(VS, 0, __cputchar);
+ if (curscr != NULL && __usecs)
+ __set_scroll_region(0, curscr->maxy - 1, 0, 0);
+}
+
+void
+__set_scroll_region(top, bot, ox, oy)
+int top, bot, ox, oy;
+{
+ if (SC != NULL && RC != NULL)
+ tputs(SC, 0, __cputchar);
+ tputs(__tscroll(CS, top, bot), 1, __cputchar);
+ if (SC != NULL && RC != NULL)
+ tputs(RC, 0, __cputchar);
+ else {
+ tputs(HO, 1, __cputchar);
+ __mvcur(0, 0, oy, ox, 1);
+ }
}
int
@@ -249,7 +252,9 @@ endwin()
tputs(SE, 0, __cputchar);
curscr->flags &= ~__WSTANDOUT;
}
- __mvcur(curscr->cury, curscr->curx, curscr->maxy - 1, 0, 0);
+ if (__usecs)
+ __set_scroll_region(0, curscr->maxy - 1, 0, 0);
+ __mvcur(curscr->curx, curscr->cury, curscr->maxy - 1, 0, 0);
}
(void)tputs(VE, 0, __cputchar);
@@ -257,7 +262,7 @@ endwin()
(void)fflush(stdout);
(void)setvbuf(stdout, NULL, _IOLBF, 0);
- return (tcsetattr(STDIN_FILENO, __tcaction ?
+ return (!__noterm && tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, &__orig_termios) ? ERR : OK);
}
@@ -270,12 +275,12 @@ static struct termios savedtty;
int
savetty()
{
- return (tcgetattr(STDIN_FILENO, &savedtty) ? ERR : OK);
+ return (!__noterm && tcgetattr(__tty_fileno, &savedtty) ? ERR : OK);
}
int
resetty()
{
- return (tcsetattr(STDIN_FILENO, __tcaction ?
+ return (!__noterm && tcsetattr(__tty_fileno, __tcaction ?
TCSASOFT | TCSADRAIN : TCSADRAIN, &savedtty) ? ERR : OK);
}
diff --git a/lib/libcurses/unctrl.c b/lib/libcurses/unctrl.c
index ff52230..530dcc2 100644
--- a/lib/libcurses/unctrl.c
+++ b/lib/libcurses/unctrl.c
@@ -87,7 +87,7 @@ char __unctrllen[256] = {
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, 2,
+ 1, 1, 1, 1, 1, 1, 1, 2,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
diff --git a/lib/libdisk/Makefile b/lib/libdisk/Makefile
new file mode 100644
index 0000000..05919d5
--- /dev/null
+++ b/lib/libdisk/Makefile
@@ -0,0 +1,60 @@
+# $Id$
+
+LIB= disk
+SRCS= blocks.c disklabel.c dkcksum.c chunk.c disk.c change.c \
+ create_chunk.c rules.c write_disk.c data.c
+
+CFLAGS+= -Wall
+CLEANFILES+= tmp.c tst01 tst01.o data.c
+VPATH= ${.CURDIR}/../../sbin/disklabel
+NOPROFILE= yes
+NOSHARED= yes
+NOPIC= yes
+
+MAN3= libdisk.3
+MLINKS+= libdisk.3 Open_Disk.3 \
+ libdisk.3 Clone_Disk.3 \
+ libdisk.3 Free_Disk.3 \
+ libdisk.3 Debug_Disk.3 \
+ libdisk.3 Set_Bios_Geom.3 \
+ libdisk.3 Delete_Chunk.3 \
+ libdisk.3 Collapse_Disk.3 \
+ libdisk.3 Collapse_Chunk.3 \
+ libdisk.3 Create_Chunk.3 \
+ libdisk.3 All_FreeBSD.3 \
+ libdisk.3 CheckRules.3 \
+ libdisk.3 Disk_Names.3 \
+ libdisk.3 Set_Boot_Mgr.3 \
+ libdisk.3 Set_Boot_Blocks.3 \
+ libdisk.3 Write_Disk.3 \
+ libdisk.3 Cyl_Aligned.3 \
+ libdisk.3 Next_Cyl_Aligned.3 \
+ libdisk.3 Prev_Cyl_Aligned.3 \
+ libdisk.3 Track_Aligned.3 \
+ libdisk.3 Next_Track_Aligned.3 \
+ libdisk.3 Prev_Track_Aligned.3 \
+ libdisk.3 Create_Chunk_DWIM.3 \
+ libdisk.3 MakeDev.3 \
+ libdisk.3 MakeDevDisk.3 \
+ libdisk.3 ShowChunkFlags.3 \
+ libdisk.3 ChunkCanBeRoot.3 \
+ libdisk.3 slice_type_name.3
+
+.include <bsd.lib.mk>
+
+BOOTS=/usr/mdec
+
+data.c: ${.CURDIR}/libdisk.h ${BOOTS}/boot1 ${BOOTS}/boot2
+ file2c 'const unsigned char boot1[] = {' '};' \
+ < ${BOOTS}/boot1 > tmp.c
+ file2c 'const unsigned char boot2[] = {' '};' \
+ < ${BOOTS}/boot2 >> tmp.c
+ mv -f tmp.c data.c
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/libdisk.h \
+ ${DESTDIR}/usr/include/libdisk.h
+
+
+tst01: tst01.o libdisk.a
+ cc ${CFLAGS} -static tst01.o -o tst01 libdisk.a
diff --git a/lib/libdisk/blocks.c b/lib/libdisk/blocks.c
new file mode 100644
index 0000000..3864ec2
--- /dev/null
+++ b/lib/libdisk/blocks.c
@@ -0,0 +1,41 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include "libdisk.h"
+
+void *
+read_block(int fd, daddr_t block)
+{
+ void *foo;
+
+ foo = malloc(512);
+ if (!foo)
+ err(1,"malloc");
+ if (-1 == lseek(fd, (off_t)block * 512, SEEK_SET))
+ err(1, "lseek");
+ if (512 != read(fd,foo, 512))
+ err(1,"read");
+ return foo;
+}
+
+void
+write_block(int fd, daddr_t block, void *foo)
+{
+ if (-1 == lseek(fd, (off_t)block * 512, SEEK_SET))
+ err(1, "lseek");
+ if (512 != write(fd,foo, 512))
+ err(1,"write");
+}
diff --git a/lib/libdisk/change.c b/lib/libdisk/change.c
new file mode 100644
index 0000000..a144aa5
--- /dev/null
+++ b/lib/libdisk/change.c
@@ -0,0 +1,82 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <err.h>
+#include <sys/types.h>
+#include "libdisk.h"
+
+void
+Set_Bios_Geom(struct disk *disk, u_long cyl, u_long hd, u_long sect)
+{
+ disk->bios_cyl = cyl;
+ disk->bios_hd = hd;
+ disk->bios_sect = sect;
+ Bios_Limit_Chunk(disk->chunks,1024*hd*sect);
+}
+
+void
+Sanitize_Bios_Geom(struct disk *disk)
+{
+ int sane = 1;
+
+ if (disk->bios_cyl > 1024)
+ sane = 0;
+ if (disk->bios_hd > 16)
+ sane = 0;
+ if (disk->bios_sect > 63)
+ sane = 0;
+ if (disk->bios_cyl*disk->bios_hd*disk->bios_sect !=
+ disk->chunks->size)
+ sane = 0;
+ if (sane)
+ return;
+
+ /* First try something that IDE can handle */
+ disk->bios_sect = 63;
+ disk->bios_hd = 16;
+ disk->bios_cyl = disk->chunks->size/(disk->bios_sect*disk->bios_hd);
+
+ if (disk->bios_cyl < 1024)
+ return;
+
+ /* Hmm, try harder... */
+ disk->bios_hd = 255;
+ disk->bios_cyl = disk->chunks->size/(disk->bios_sect*disk->bios_hd);
+
+ return;
+}
+
+void
+All_FreeBSD(struct disk *d, int force_all)
+{
+ struct chunk *c;
+
+ again:
+ for (c=d->chunks->part;c;c=c->next)
+ if (c->type != unused) {
+ Delete_Chunk(d,c);
+ goto again;
+ }
+ c=d->chunks;
+ if (force_all) {
+ Sanitize_Bios_Geom(d);
+ Create_Chunk(d,c->offset,c->size,freebsd,0xa5,
+ CHUNK_FORCE_ALL);
+ } else {
+ Create_Chunk(d,c->offset,c->size,freebsd,0xa5, 0);
+ }
+}
diff --git a/lib/libdisk/chunk.c b/lib/libdisk/chunk.c
new file mode 100644
index 0000000..a0ea6aa
--- /dev/null
+++ b/lib/libdisk/chunk.c
@@ -0,0 +1,434 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <err.h>
+#include "libdisk.h"
+
+#define new_chunk() memset(malloc(sizeof(struct chunk)), 0, sizeof(struct chunk))
+
+/* Is c2 completely inside c1 ? */
+
+static int
+Chunk_Inside(struct chunk *c1, struct chunk *c2)
+{
+ /* if c1 ends before c2 do */
+ if (c1->end < c2->end)
+ return 0;
+ /* if c1 starts after c2 do */
+ if (c1->offset > c2->offset)
+ return 0;
+ return 1;
+}
+
+struct chunk *
+Find_Mother_Chunk(struct chunk *chunks, u_long offset, u_long end, chunk_e type)
+{
+ struct chunk *c1,*c2,ct;
+ ct.offset = offset;
+ ct.end = end;
+ switch (type) {
+ case whole:
+ if (Chunk_Inside(chunks,&ct))
+ return chunks;
+ case extended:
+ for(c1=chunks->part;c1;c1=c1->next) {
+ if (c1->type != type)
+ continue;
+ if (Chunk_Inside(c1,&ct))
+ return c1;
+ }
+ return 0;
+ case freebsd:
+ for(c1=chunks->part;c1;c1=c1->next) {
+ if (c1->type == type)
+ if (Chunk_Inside(c1,&ct))
+ return c1;
+ if (c1->type != extended)
+ continue;
+ for(c2=c1->part;c2;c2=c2->next)
+ if (c2->type == type
+ && Chunk_Inside(c2,&ct))
+ return c2;
+ }
+ return 0;
+ default:
+ warn("Unsupported mother (0x%x) in Find_Mother_Chunk");
+ return 0;
+ }
+}
+
+void
+Free_Chunk(struct chunk *c1)
+{
+ if(!c1) return;
+ if(c1->private_data && c1->private_free)
+ (*c1->private_free)(c1->private_data);
+ if(c1->part)
+ Free_Chunk(c1->part);
+ if(c1->next)
+ Free_Chunk(c1->next);
+ free(c1->name);
+ free(c1);
+}
+
+struct chunk *
+Clone_Chunk(struct chunk *c1)
+{
+ struct chunk *c2;
+ if(!c1)
+ return 0;
+ c2 = new_chunk();
+ if (!c2) err(1,"malloc failed");
+ *c2 = *c1;
+ if (c1->private_data && c1->private_clone)
+ c2->private_data = c2->private_clone(c2->private_data);
+ c2->name = strdup(c2->name);
+ c2->next = Clone_Chunk(c2->next);
+ c2->part = Clone_Chunk(c2->part);
+ return c2;
+}
+
+int
+Insert_Chunk(struct chunk *c2, u_long offset, u_long size, const char *name,
+ chunk_e type, int subtype, u_long flags)
+{
+ struct chunk *ct,*cs;
+
+ /* We will only insert into empty spaces */
+ if (c2->type != unused)
+ return __LINE__;
+
+ ct = new_chunk();
+ if (!ct) err(1,"malloc failed");
+ memset(ct,0,sizeof *ct);
+ ct->disk = c2->disk;
+ ct->offset = offset;
+ ct->size = size;
+ ct->end = offset + size - 1;
+ ct->type = type;
+ ct->name = strdup(name);
+ ct->subtype = subtype;
+ ct->flags = flags;
+
+ if (!Chunk_Inside(c2,ct)) {
+ Free_Chunk(ct);
+ return __LINE__;
+ }
+
+ if(type==freebsd || type==extended) {
+ cs = new_chunk();
+ if (!cs) err(1,"malloc failed");
+ memset(cs,0,sizeof *cs);
+ cs->disk = c2->disk;
+ cs->offset = offset;
+ cs->size = size;
+ cs->end = offset + size - 1;
+ cs->type = unused;
+ cs->name = strdup("-");
+ ct->part = cs;
+ }
+
+ /* Make a new chunk for any trailing unused space */
+ if (c2->end > ct->end) {
+ cs = new_chunk();
+ if (!cs) err(1,"malloc failed");
+ *cs = *c2;
+ cs->disk = c2->disk;
+ cs->offset = ct->end + 1;
+ cs->size = c2->end - ct->end;
+ if(c2->name)
+ cs->name = strdup(c2->name);
+ c2->next = cs;
+ c2->size -= c2->end - ct->end;
+ c2->end = ct->end;
+ }
+ /* If no leading unused space just occupy the old chunk */
+ if (c2->offset == ct->offset) {
+ c2->name = ct->name;
+ c2->type = ct->type;
+ c2->part = ct->part;
+ c2->subtype = ct->subtype;
+ c2->flags = ct->flags;
+ ct->name = 0;
+ ct->part = 0;
+ Free_Chunk(ct);
+ return 0;
+ }
+ /* else insert new chunk and adjust old one */
+ c2->end = ct->offset - 1;
+ c2->size -= ct->size;
+ ct->next = c2->next;
+ c2->next = ct;
+ return 0;
+}
+
+int
+Add_Chunk(struct disk *d, long offset, u_long size, const char *name,
+ chunk_e type, int subtype, u_long flags)
+{
+ struct chunk *c1,*c2,ct;
+ u_long end = offset + size - 1;
+ ct.offset = offset;
+ ct.end = end;
+ ct.size = size;
+
+ if (type == whole) {
+ d->chunks = c1 = new_chunk();
+ if (!c1) err(1,"malloc failed");
+ memset(c1,0,sizeof *c1);
+ c2 = c1->part = new_chunk();
+ if (!c2) err(1,"malloc failed");
+ memset(c2,0,sizeof *c2);
+ c2->disk = c1->disk = d;
+ c2->offset = c1->offset = offset;
+ c2->size = c1->size = size;
+ c2->end = c1->end = end;
+ c1->name = strdup(name);
+ c2->name = strdup("-");
+ c1->type = type;
+ c2->type = unused;
+ c1->flags = flags;
+ c1->subtype = subtype;
+ return 0;
+ }
+ if (type == freebsd)
+ subtype = 0xa5;
+ c1 = 0;
+ if(!c1 && (type == freebsd || type == fat || type == unknown))
+ c1 = Find_Mother_Chunk(d->chunks,offset,end,extended);
+ if(!c1 && (type == freebsd || type == fat || type == unknown))
+ c1 = Find_Mother_Chunk(d->chunks,offset,end,whole);
+ if(!c1 && type == extended)
+ c1 = Find_Mother_Chunk(d->chunks,offset,end,whole);
+ if(!c1 && type == part)
+ c1 = Find_Mother_Chunk(d->chunks,offset,end,freebsd);
+ if(!c1)
+ return __LINE__;
+ for(c2=c1->part;c2;c2=c2->next) {
+ if (c2->type != unused)
+ continue;
+ if(Chunk_Inside(c2,&ct)) {
+ if (type != freebsd)
+ goto doit;
+ if (!(flags & CHUNK_ALIGN))
+ goto doit;
+ if (offset == d->chunks->offset
+ && end == d->chunks->end)
+ goto doit;
+
+ /* Round down to prev cylinder */
+ offset = Prev_Cyl_Aligned(d,offset);
+ /* Stay inside the parent */
+ if (offset < c2->offset)
+ offset = c2->offset;
+ /* Round up to next cylinder */
+ offset = Next_Cyl_Aligned(d,offset);
+ /* Keep one track clear in front of parent */
+ if (offset == c1->offset)
+ offset = Next_Track_Aligned(d,offset+1);
+
+ /* Work on the (end+1) */
+ size += offset;
+ /* Round up to cylinder */
+ size = Next_Cyl_Aligned(d,size);
+ /* Stay inside parent */
+ if ((size-1) > c2->end)
+ size = c2->end+1;
+ /* Round down to cylinder */
+ size = Prev_Cyl_Aligned(d,size);
+
+ /* Convert back to size */
+ size -= offset;
+
+ doit:
+ return Insert_Chunk(c2,offset,size,name,
+ type,subtype,flags);
+ }
+ }
+ return __LINE__;
+}
+
+char *
+ShowChunkFlags(struct chunk *c)
+{
+ static char ret[10];
+
+ int i=0;
+ if (c->flags & CHUNK_BSD_COMPAT) ret[i++] = 'C';
+ if (c->flags & CHUNK_ACTIVE) ret[i++] = 'A';
+ if (c->flags & CHUNK_ALIGN) ret[i++] = '=';
+ if (c->flags & CHUNK_PAST_1024) ret[i++] = '>';
+ if (c->flags & CHUNK_IS_ROOT) ret[i++] = 'R';
+ if (c->flags & CHUNK_BAD144) ret[i++] = 'B';
+ ret[i++] = '\0';
+ return ret;
+}
+
+void
+Print_Chunk(struct chunk *c1,int offset)
+{
+ int i;
+ if(!c1) return;
+ for(i=0;i<offset-2;i++) putchar(' ');
+ for(;i<offset;i++) putchar('-');
+ putchar('>');
+ for(;i<10;i++) putchar(' ');
+ printf("%p %8ld %8lu %8lu %-8s %-8s 0x%02x %s",
+ c1, c1->offset, c1->size, c1->end, c1->name,
+ chunk_n[c1->type],c1->subtype,
+ ShowChunkFlags(c1));
+ putchar('\n');
+ Print_Chunk(c1->part,offset + 2);
+ Print_Chunk(c1->next,offset);
+}
+
+void
+Debug_Chunk(struct chunk *c1)
+{
+ Print_Chunk(c1,2);
+}
+
+void
+Bios_Limit_Chunk(struct chunk *c1, u_long limit)
+{
+ if (c1->part)
+ Bios_Limit_Chunk(c1->part,limit);
+ if (c1->next)
+ Bios_Limit_Chunk(c1->next,limit);
+ if (c1->end >= limit) {
+ c1->flags |= CHUNK_PAST_1024;
+ } else {
+ c1->flags &= ~CHUNK_PAST_1024;
+ }
+}
+
+int
+Delete_Chunk(struct disk *d, struct chunk *c)
+{
+ struct chunk *c1=0,*c2,*c3;
+ chunk_e type = c->type;
+
+ if(type == whole)
+ return 1;
+ if(!c1 && (type == freebsd || type == fat || type == unknown))
+ c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,extended);
+ if(!c1 && (type == freebsd || type == fat || type == unknown))
+ c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,whole);
+ if(!c1 && type == extended)
+ c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,whole);
+ if(!c1 && type == part)
+ c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,freebsd);
+ if(!c1)
+ return 1;
+ for(c2=c1->part;c2;c2=c2->next) {
+ if (c2 == c) {
+ c2->type = unused;
+ c2->subtype = 0;
+ c2->flags = 0;
+ free(c2->name);
+ c2->name = strdup("-");
+ Free_Chunk(c2->part);
+ c2->part =0;
+ goto scan;
+ }
+ }
+ return 1;
+ scan:
+ for(c2=c1->part;c2;c2=c2->next) {
+ if (c2->type != unused)
+ continue;
+ if (!c2->next)
+ continue;
+ if (c2->next->type != unused)
+ continue;
+ c3 = c2->next;
+ c2->size += c3->size;
+ c2->end = c3->end;
+ c2->next = c3->next;
+ c3->next = 0;
+ Free_Chunk(c3);
+ goto scan;
+ }
+ Fixup_Names(d);
+ return 0;
+}
+
+#if 0
+int
+Collapse_Chunk(struct disk *d, struct chunk *c1)
+{
+ struct chunk *c2, *c3;
+
+ if(c1->next && Collapse_Chunk(d,c1->next))
+ return 1;
+
+ if(c1->type == unused && c1->next && c1->next->type == unused) {
+ c3 = c1->next;
+ c1->size += c3->size;
+ c1->end = c3->end;
+ c1->next = c3->next;
+ c3->next = 0;
+ Free_Chunk(c3);
+ return 1;
+ }
+ c3 = c1->part;
+ if(!c3)
+ return 0;
+ if (Collapse_Chunk(d,c1->part))
+ return 1;
+
+ if (c1->type == whole)
+ return 0;
+
+ if(c3->type == unused && c3->size == c1->size) {
+ Delete_Chunk(d,c1);
+ return 1;
+ }
+ if(c3->type == unused) {
+ c2 = new_chunk();
+ if (!c2) err(1,"malloc failed");
+ *c2 = *c1;
+ c1->next = c2;
+ c1->disk = d;
+ c1->name = strdup("-");
+ c1->part = 0;
+ c1->type = unused;
+ c1->flags = 0;
+ c1->subtype = 0;
+ c1->size = c3->size;
+ c1->end = c3->end;
+ c2->offset += c1->size;
+ c2->size -= c1->size;
+ c2->part = c3->next;
+ c3->next = 0;
+ Free_Chunk(c3);
+ return 1;
+ }
+ for(c2=c3;c2->next;c2 = c2->next)
+ c3 = c2;
+ if (c2 && c2->type == unused) {
+ c3->next = 0;
+ c2->next = c1->next;
+ c1->next = c2;
+ c1->size -= c2->size;
+ c1->end -= c2->size;
+ return 1;
+ }
+
+ return 0;
+}
+#endif
diff --git a/lib/libdisk/create_chunk.c b/lib/libdisk/create_chunk.c
new file mode 100644
index 0000000..83fa345
--- /dev/null
+++ b/lib/libdisk/create_chunk.c
@@ -0,0 +1,358 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/disklabel.h>
+#include <sys/diskslice.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <err.h>
+#include "libdisk.h"
+
+/* Clone these two from sysinstall because we need our own copies
+ * due to link order problems with `crunch'. Feh!
+ */
+static int
+isDebug()
+{
+ static int debug = 0; /* Allow debugger to tweak it */
+
+ return debug;
+}
+
+/* Write something to the debugging port */
+static void
+msgDebug(char *fmt, ...)
+{
+ va_list args;
+ char *dbg;
+ static int DebugFD = -1;
+
+ if (DebugFD == -1)
+ DebugFD = open("/dev/ttyv1", O_RDWR);
+ dbg = (char *)alloca(FILENAME_MAX);
+ strcpy(dbg, "DEBUG: ");
+ va_start(args, fmt);
+ vsnprintf((char *)(dbg + strlen(dbg)), FILENAME_MAX, fmt, args);
+ va_end(args);
+ write(DebugFD, dbg, strlen(dbg));
+}
+
+void
+Fixup_FreeBSD_Names(struct disk *d, struct chunk *c)
+{
+ struct chunk *c1, *c3;
+ int j;
+
+ if (!strcmp(c->name, "X")) return;
+
+ /* reset all names to "X" */
+ for (c1 = c->part; c1 ; c1 = c1->next) {
+ c1->oname = c1->name;
+ c1->name = malloc(12);
+ if(!c1->name) err(1,"Malloc failed");
+ strcpy(c1->name,"X");
+ }
+
+ /* Allocate the first swap-partition we find */
+ for (c1 = c->part; c1 ; c1 = c1->next) {
+ if (c1->type == unused) continue;
+ if (c1->subtype != FS_SWAP) continue;
+ sprintf(c1->name,"%s%c",c->name,SWAP_PART+'a');
+ break;
+ }
+
+ /* Allocate the first root-partition we find */
+ for (c1 = c->part; c1 ; c1 = c1->next) {
+ if (c1->type == unused) continue;
+ if (!(c1->flags & CHUNK_IS_ROOT)) continue;
+ sprintf(c1->name,"%s%c",c->name,0+'a');
+ break;
+ }
+
+ /* Try to give them the same as they had before */
+ for (c1 = c->part; c1 ; c1 = c1->next) {
+ if (strcmp(c1->name,"X")) continue;
+ for(c3 = c->part; c3 ; c3 = c3->next)
+ if (c1 != c3 && !strcmp(c3->name, c1->oname)) {
+ goto newname;
+ }
+ strcpy(c1->name,c1->oname);
+ newname:
+ }
+
+
+ /* Allocate the rest sequentially */
+ for (c1 = c->part; c1 ; c1 = c1->next) {
+ const char order[] = "efghabd";
+ if (c1->type == unused) continue;
+ if (strcmp("X",c1->name)) continue;
+
+ for(j=0;j<strlen(order);j++) {
+ sprintf(c1->name,"%s%c",c->name,order[j]);
+ for(c3 = c->part; c3 ; c3 = c3->next)
+ if (c1 != c3 && !strcmp(c3->name, c1->name))
+ goto match;
+ break;
+ match:
+ strcpy(c1->name,"X");
+ continue;
+ }
+ }
+ for (c1 = c->part; c1 ; c1 = c1->next) {
+ free(c1->oname);
+ c1->oname = 0;
+ }
+}
+
+void
+Fixup_Extended_Names(struct disk *d, struct chunk *c)
+{
+ struct chunk *c1;
+ int j=5;
+
+ for (c1 = c->part; c1 ; c1 = c1->next) {
+ if (c1->type == unused) continue;
+ free(c1->name);
+ c1->name = malloc(12);
+ if(!c1->name) err(1,"malloc failed");
+ sprintf(c1->name,"%ss%d",d->chunks->name,j++);
+ if (c1->type == freebsd)
+ Fixup_FreeBSD_Names(d,c1);
+ }
+}
+
+void
+Fixup_Names(struct disk *d)
+{
+ struct chunk *c1, *c2, *c3;
+ int i,j;
+
+ c1 = d->chunks;
+ for(i=1,c2 = c1->part; c2 ; c2 = c2->next) {
+ c2->flags &= ~CHUNK_BSD_COMPAT;
+ if (c2->type == unused)
+ continue;
+ if (strcmp(c2->name,"X"))
+ continue;
+ c2->oname = malloc(12);
+ if(!c2->oname) err(1,"malloc failed");
+ for(j=1;j<=NDOSPART;j++) {
+ sprintf(c2->oname,"%ss%d",c1->name,j);
+ for(c3 = c1->part; c3 ; c3 = c3->next)
+ if (c3 != c2 && !strcmp(c3->name, c2->oname))
+ goto match;
+ free(c2->name);
+ c2->name = c2->oname;
+ c2->oname = 0;
+ break;
+ match:
+ continue;
+ }
+ if (c2->oname)
+ free(c2->oname);
+ }
+ for(c2 = c1->part; c2 ; c2 = c2->next) {
+ if (c2->type == freebsd) {
+ c2->flags |= CHUNK_BSD_COMPAT;
+ break;
+ }
+ }
+ for(c2 = c1->part; c2 ; c2 = c2->next) {
+ if (c2->type == freebsd)
+ Fixup_FreeBSD_Names(d,c2);
+ if (c2->type == extended)
+ Fixup_Extended_Names(d,c2);
+ }
+}
+
+int
+Create_Chunk(struct disk *d, u_long offset, u_long size, chunk_e type, int subtype, u_long flags)
+{
+ int i;
+ u_long l;
+
+ if(!(flags & CHUNK_FORCE_ALL))
+ {
+ /* Never use the first track */
+ if (!offset) {
+ offset += d->bios_sect;
+ size -= d->bios_sect;
+ }
+
+ /* Always end on cylinder boundary */
+ l = (offset+size) % (d->bios_sect * d->bios_hd);
+ size -= l;
+ }
+
+ i = Add_Chunk(d,offset,size,"X",type,subtype,flags);
+ Fixup_Names(d);
+ return i;
+}
+
+struct chunk *
+Create_Chunk_DWIM(struct disk *d, struct chunk *parent , u_long size, chunk_e type, int subtype, u_long flags)
+{
+ int i;
+ struct chunk *c1;
+ u_long offset,edge;
+
+ if (!parent)
+ parent = d->chunks;
+ for (c1=parent->part; c1 ; c1 = c1->next) {
+ if (c1->type != unused) continue;
+ if (c1->size < size) continue;
+ offset = c1->offset;
+ goto found;
+ }
+ return 0;
+ found:
+ if (parent->flags & CHUNK_BAD144) {
+ edge = c1->end - d->bios_sect - 127;
+ if (offset > edge)
+ return 0;
+ if (offset + size > edge)
+ size = edge - offset + 1;
+ }
+ i = Add_Chunk(d,offset,size,"X",type,subtype,flags);
+ if (i)
+ return 0;
+ Fixup_Names(d);
+ for (c1=parent->part; c1 ; c1 = c1->next)
+ if (c1->offset == offset)
+ return c1;
+ err(1,"Serious internal trouble");
+}
+
+int
+MakeDev(struct chunk *c1, const char *path)
+{
+ char *p = c1->name;
+ u_long cmaj, bmaj, min, unit, part, slice;
+ char buf[BUFSIZ], buf2[BUFSIZ];
+
+ *buf2 = '\0';
+ if (isDebug())
+ msgDebug("MakeDev: Called with %s on path %s\n", p, path);
+ if (!strcmp(p, "X"))
+ return 0;
+
+ if (!strncmp(p, "wd", 2))
+ bmaj = 0, cmaj = 3;
+ else if (!strncmp(p, "sd", 2))
+ bmaj = 4, cmaj = 13;
+ else if (!strncmp(p, "od", 2))
+ bmaj = 20, cmaj = 70;
+ else {
+ return 0;
+ }
+ p += 2;
+ if (!isdigit(*p)) {
+ msgDebug("MakeDev: Invalid disk unit passed: %s\n", p);
+ return 0;
+ }
+ unit = *p - '0';
+ p++;
+ if (!*p) {
+ slice = 1;
+ part = 2;
+ goto done;
+ }
+ else if (isdigit(*p)) {
+ unit *= 10;
+ unit += (*p - '0');
+ p++;
+ }
+ if (*p != 's') {
+ msgDebug("MakeDev: `%s' is not a valid slice delimiter\n", p);
+ return 0;
+ }
+ p++;
+ if (!isdigit(*p)) {
+ msgDebug("MakeDev: `%s' is an invalid slice number\n", p);
+ return 0;
+ }
+ slice = *p - '0';
+ p++;
+ if (isdigit(*p)) {
+ slice *= 10;
+ slice += (*p - '0');
+ p++;
+ }
+ slice = slice + 1;
+ if (!*p) {
+ part = 2;
+ if(c1->type == freebsd)
+ sprintf(buf2, "%sc", c1->name);
+ goto done;
+ }
+ if (*p < 'a' || *p > 'h') {
+ msgDebug("MakeDev: `%s' is not a valid partition name.\n", p);
+ return 0;
+ }
+ part = *p - 'a';
+ done:
+ if (isDebug())
+ msgDebug("MakeDev: Unit %d, Slice %d, Part %d\n", unit, slice, part);
+ if (unit > 32)
+ return 0;
+ if (slice > 32)
+ return 0;
+ min = unit * 8 + 65536 * slice + part;
+ sprintf(buf, "%s/r%s", path, c1->name);
+ unlink(buf);
+ if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
+ msgDebug("mknod of %s returned failure status!\n", buf);
+ return 0;
+ }
+ if (*buf2) {
+ sprintf(buf, "%s/r%s", path, buf2);
+ unlink(buf);
+ if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
+ msgDebug("mknod of %s returned failure status!\n", buf);
+ return 0;
+ }
+ }
+ sprintf(buf, "%s/%s", path, c1->name);
+ unlink(buf);
+ if (mknod(buf, S_IFBLK|0640, makedev(bmaj,min)) == -1) {
+ msgDebug("mknod of %s returned failure status!\n", buf);
+ return 0;
+ }
+ return 1;
+}
+
+int
+MakeDevChunk(struct chunk *c1, const char *path)
+{
+ int i;
+
+ i = MakeDev(c1, path);
+ if (c1->next)
+ MakeDevChunk(c1->next, path);
+ if (c1->part)
+ MakeDevChunk(c1->part, path);
+ return i;
+}
+
+int
+MakeDevDisk(struct disk *d, const char *path)
+{
+ return MakeDevChunk(d->chunks, path);
+}
diff --git a/lib/libdisk/disk.c b/lib/libdisk/disk.c
new file mode 100644
index 0000000..583073d
--- /dev/null
+++ b/lib/libdisk/disk.c
@@ -0,0 +1,386 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/disklabel.h>
+#include <sys/diskslice.h>
+#include "libdisk.h"
+
+#define DOSPTYP_EXTENDED 5
+#define DOSPTYP_ONTRACK 84
+
+const char *chunk_n[] = {
+ "whole",
+ "unknown",
+ "fat",
+ "freebsd",
+ "extended",
+ "part",
+ "unused",
+ NULL
+};
+
+struct disk *
+Open_Disk(const char *name)
+{
+ return Int_Open_Disk(name,0);
+}
+
+struct disk *
+Int_Open_Disk(const char *name, u_long size)
+{
+ int i,fd;
+ struct diskslices ds;
+ struct disklabel dl;
+ char device[64];
+ struct disk *d;
+ struct dos_partition *dp;
+ void *p;
+ u_long offset = 0;
+
+ strcpy(device,"/dev/r");
+ strcat(device,name);
+
+ d = (struct disk *)malloc(sizeof *d);
+ if(!d) err(1,"malloc failed");
+ memset(d,0,sizeof *d);
+
+ fd = open(device,O_RDONLY);
+ if (fd < 0) {
+#ifdef DEBUG
+ warn("open(%s) failed",device);
+#endif
+ return 0;
+ }
+
+ memset(&dl,0,sizeof dl);
+ ioctl(fd,DIOCGDINFO,&dl);
+ i = ioctl(fd,DIOCGSLICEINFO,&ds);
+ if (i < 0) {
+#ifdef DEBUG
+ warn("DIOCGSLICEINFO(%s) failed",device);
+#endif
+ close(fd);
+ return 0;
+ }
+
+#ifdef DEBUG
+ for(i=0;i<ds.dss_nslices;i++)
+ if(ds.dss_slices[i].ds_openmask)
+ printf(" open(%d)=0x%2x",
+ i,ds.dss_slices[i].ds_openmask);
+ printf("\n");
+#endif
+
+ if (!size)
+ size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size;
+
+ p = read_block(fd,0);
+ dp = (struct dos_partition*)(p+DOSPARTOFF);
+ for(i=0;i<NDOSPART;i++) {
+ if (dp->dp_start >= size) continue;
+ if (dp->dp_start+dp->dp_size >= size) continue;
+ if (!dp->dp_size) continue;
+
+ if (dp->dp_typ == DOSPTYP_ONTRACK) {
+ d->flags |= DISK_ON_TRACK;
+ offset = 63;
+ }
+
+ }
+ free(p);
+
+ d->bios_sect = dl.d_nsectors;
+ d->bios_hd = dl.d_ntracks;
+
+ d->name = strdup(name);
+
+
+ if (dl.d_ntracks && dl.d_nsectors)
+ d->bios_cyl = size/(dl.d_ntracks*dl.d_nsectors);
+
+ if (Add_Chunk(d, -offset, size, name, whole, 0, 0))
+#ifdef DEBUG
+ warn("Failed to add 'whole' chunk");
+#else
+ {}
+#endif
+
+ for(i=BASE_SLICE;i<ds.dss_nslices;i++) {
+ char sname[20];
+ chunk_e ce;
+ u_long flags=0;
+ int subtype=0;
+ if (! ds.dss_slices[i].ds_size)
+ continue;
+ ds.dss_slices[i].ds_offset -= offset;
+ sprintf(sname,"%ss%d",name,i-1);
+ subtype = ds.dss_slices[i].ds_type;
+ switch (ds.dss_slices[i].ds_type) {
+ case 0xa5:
+ ce = freebsd;
+ break;
+ case 0x1:
+ case 0x6:
+ case 0x4:
+ ce = fat;
+ break;
+ case DOSPTYP_EXTENDED:
+ ce = extended;
+ break;
+ default:
+ ce = unknown;
+ break;
+ }
+ if (Add_Chunk(d, ds.dss_slices[i].ds_offset,
+ ds.dss_slices[i].ds_size, sname, ce, subtype, flags))
+#ifdef DEBUG
+ warn("failed to add chunk for slice %d", i - 1);
+#else
+ {}
+#endif
+
+ if (ds.dss_slices[i].ds_type != 0xa5)
+ continue;
+ {
+ struct disklabel dl;
+ char pname[20];
+ int j,k;
+
+ strcpy(pname,"/dev/r");
+ strcat(pname,sname);
+ j = open(pname,O_RDONLY);
+ if (j < 0) {
+#ifdef DEBUG
+ warn("open(%s)",pname);
+#endif
+ continue;
+ }
+ k = ioctl(j,DIOCGDINFO,&dl);
+ if (k < 0) {
+#ifdef DEBUG
+ warn("ioctl(%s,DIOCGDINFO)",pname);
+#endif
+ close(j);
+ continue;
+ }
+ close(j);
+
+ for(j=0; j <= dl.d_npartitions; j++) {
+ if (j == RAW_PART)
+ continue;
+ if (j == 3)
+ continue;
+ if (j == dl.d_npartitions) {
+ j = 3;
+ dl.d_npartitions=0;
+ }
+ if (!dl.d_partitions[j].p_size)
+ continue;
+ if (dl.d_partitions[j].p_size +
+ dl.d_partitions[j].p_offset >
+ ds.dss_slices[i].ds_size)
+ continue;
+ sprintf(pname,"%s%c",sname,j+'a');
+ if (Add_Chunk(d,
+ dl.d_partitions[j].p_offset +
+ ds.dss_slices[i].ds_offset,
+ dl.d_partitions[j].p_size,
+ pname,part,
+ dl.d_partitions[j].p_fstype,
+ 0) && j != 3)
+#ifdef DEBUG
+ warn(
+ "Failed to add chunk for partition %c [%lu,%lu]",
+ j + 'a',dl.d_partitions[j].p_offset,
+ dl.d_partitions[j].p_size);
+#else
+ {}
+#endif
+ }
+ }
+ }
+ close(fd);
+ Fixup_Names(d);
+ Bios_Limit_Chunk(d->chunks,1024*d->bios_hd*d->bios_sect);
+ return d;
+}
+
+void
+Debug_Disk(struct disk *d)
+{
+ printf("Debug_Disk(%s)",d->name);
+ printf(" flags=%lx",d->flags);
+#if 0
+ printf(" real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect);
+#endif
+ printf(" bios_geom=%lu/%lu/%lu = %lu\n",
+ d->bios_cyl,d->bios_hd,d->bios_sect,
+ d->bios_cyl*d->bios_hd*d->bios_sect);
+ printf(" boot1=%p, boot2=%p, bootmgr=%p\n",
+ d->boot1,d->boot2,d->bootmgr);
+ Debug_Chunk(d->chunks);
+}
+
+void
+Free_Disk(struct disk *d)
+{
+ if(d->chunks) Free_Chunk(d->chunks);
+ if(d->name) free(d->name);
+ if(d->bootmgr) free(d->bootmgr);
+ if(d->boot1) free(d->boot1);
+ if(d->boot2) free(d->boot2);
+ free(d);
+}
+
+struct disk *
+Clone_Disk(struct disk *d)
+{
+ struct disk *d2;
+
+ d2 = (struct disk*) malloc(sizeof *d2);
+ if(!d2) err(1,"malloc failed");
+ *d2 = *d;
+ d2->name = strdup(d2->name);
+ d2->chunks = Clone_Chunk(d2->chunks);
+ if(d2->bootmgr) {
+ d2->bootmgr = malloc(DOSPARTOFF);
+ memcpy(d2->bootmgr,d->bootmgr,DOSPARTOFF);
+ }
+ if(d2->boot1) {
+ d2->boot1 = malloc(512);
+ memcpy(d2->boot1,d->boot1,512);
+ }
+ if(d2->boot2) {
+ d2->boot2 = malloc(512*15);
+ memcpy(d2->boot2,d->boot2,512*15);
+ }
+ return d2;
+}
+
+#if 0
+void
+Collapse_Disk(struct disk *d)
+{
+
+ while(Collapse_Chunk(d,d->chunks))
+ ;
+}
+#endif
+
+static char * device_list[] = {"wd","sd","od",0};
+
+char **
+Disk_Names()
+{
+ int i,j,k;
+ char disk[25];
+ char diskname[25];
+ struct stat st;
+ struct diskslices ds;
+ int fd;
+ static char **disks;
+
+ disks = malloc(sizeof *disks * (1 + MAX_NO_DISKS));
+ memset(disks,0,sizeof *disks * (1 + MAX_NO_DISKS));
+ k = 0;
+ for (j = 0; device_list[j]; j++) {
+ for (i = 0; i < 10; i++) {
+ sprintf(diskname, "%s%d", device_list[j], i);
+ sprintf(disk, "/dev/r%s", diskname);
+ if (stat(disk, &st) || !(st.st_mode & S_IFCHR))
+ continue;
+ if ((fd = open(disk, O_RDWR)) == -1)
+ continue;
+ if (ioctl(fd, DIOCGSLICEINFO, &ds) == -1) {
+ close(fd);
+ continue;
+ }
+ disks[k++] = strdup(diskname);
+ if(k == MAX_NO_DISKS)
+ return disks;
+ }
+ }
+ return disks;
+}
+
+void
+Set_Boot_Mgr(struct disk *d, const u_char *b)
+{
+ if (d->bootmgr)
+ free(d->bootmgr);
+ if (!b) {
+ d->bootmgr = 0;
+ } else {
+ d->bootmgr = malloc(DOSPARTOFF);
+ if(!d->bootmgr) err(1,"malloc failed");
+ memcpy(d->bootmgr,b,DOSPARTOFF);
+ }
+}
+
+void
+Set_Boot_Blocks(struct disk *d, const u_char *b1, const u_char *b2)
+{
+ if (d->boot1) free(d->boot1);
+ d->boot1 = malloc(512);
+ if(!d->boot1) err(1,"malloc failed");
+ memcpy(d->boot1,b1,512);
+ if (d->boot2) free(d->boot2);
+ d->boot2 = malloc(15*512);
+ if(!d->boot2) err(1,"malloc failed");
+ memcpy(d->boot2,b2,15*512);
+}
+
+const char *
+slice_type_name( int type, int subtype )
+{
+ switch (type) {
+ case 0: return "whole";
+ case 1: switch (subtype) {
+ case 1: return "fat (12-bit)";
+ case 2: return "XENIX /";
+ case 3: return "XENIX /usr";
+ case 4: return "fat (16-bit)";
+ case 5: return "extended DOS";
+ case 6: return "fat (>32Mb)";
+ case 7: return "NTFS/HPFS";
+ case 10: return "OS/2 bootmgr";
+ case 84: return "OnTrack diskmgr";
+ case 100: return "Netware 2.x";
+ case 101: return "Netware 3.x";
+ case 128: return "Minix 1.1";
+ case 129: return "Minix 1.5";
+ case 130: return "linux_swap";
+ case 131: return "ext2fs";
+ case 183: return "bsd/os";
+ case 184: return "bsd/os swap";
+ default: return "unknown";
+ }
+ case 2: return "fat";
+ case 3: switch (subtype) {
+ case 165: return "freebsd";
+ default: return "unknown";
+ }
+ case 4: return "extended";
+ case 5: return "part";
+ case 6: return "unused";
+ default: return "unknown";
+ }
+}
diff --git a/lib/libdisk/disklabel.c b/lib/libdisk/disklabel.c
new file mode 100644
index 0000000..9714e6c
--- /dev/null
+++ b/lib/libdisk/disklabel.c
@@ -0,0 +1,33 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <sys/disklabel.h>
+#include "libdisk.h"
+
+struct disklabel *
+read_disklabel(int fd, daddr_t block)
+{
+ struct disklabel *dp;
+
+ dp = (struct disklabel *) read_block(fd,block);
+ if (dp->d_magic != DISKMAGIC)
+ return 0;
+ if (dp->d_magic2 != DISKMAGIC)
+ return 0;
+ if (dkcksum(dp) != 0)
+ return 0;
+ return dp;
+}
diff --git a/lib/libdisk/libdisk.3 b/lib/libdisk/libdisk.3
new file mode 100644
index 0000000..1cc9388
--- /dev/null
+++ b/lib/libdisk/libdisk.3
@@ -0,0 +1,339 @@
+.\"
+.\" Copyright (c) 1996 Joerg Wunsch
+.\"
+.\" All rights reserved.
+.\"
+.\" This program is free software.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this 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.
+.\"
+.\" $Id$
+.\" "
+.Dd March 15, 1996
+.Dt LIBDISK 3
+.Os
+.Sh NAME
+.Nm Open_Disk ,
+.Nm Clone_Disk ,
+.Nm Free_Disk ,
+.Nm Debug_Disk ,
+.Nm Set_Bios_Geom ,
+.Nm Delete_Chunk ,
+.Nm Collapse_Disk ,
+.Nm Collapse_Chunk ,
+.Nm Create_Chunk ,
+.Nm All_FreeBSD ,
+.Nm CheckRules ,
+.Nm Disk_Names ,
+.Nm Set_Boot_Mgr ,
+.Nm Set_Boot_Blocks ,
+.Nm Write_Disk ,
+.Nm Cyl_Aligned ,
+.Nm Next_Cyl_Aligned ,
+.Nm Prev_Cyl_Aligned ,
+.Nm Track_Aligned ,
+.Nm Next_Track_Aligned ,
+.Nm Prev_Track_Aligned ,
+.Nm Create_Chunk_DWIM ,
+.Nm MakeDev ,
+.Nm MakeDevDisk ,
+.Nm ShowChunkFlags ,
+.Nm ChunkCanBeRoot ,
+.Nm chunk_n ,
+.Nm slice_type_name
+.Nd library interface to slice and partition labels
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <libdisk.h>
+.Dv extern const u_char *boot1, boot2;
+.\" What is the correct way to cause a single line break ???
+.Bd -literal
+.Dv extern const char *chunk_n[];
+.Ed
+.Ft const char *
+.Fn slice_type_name "int type" "int subtype"
+.Ft struct disk *
+.Fn Open_Disk "const char *devname"
+.Ft struct disk *
+.Fn Clone_Disk "struct disk *disk"
+.Ft void
+.Fn Free_Disk "struct disk *disk"
+.Ft void
+.Fn Debug_Disk "struct disk *disk"
+.Ft void
+.Fn Set_Bios_Geom "struct disk *disk" "u_long cyl" "u_long heads" "u_long sects"
+.Ft int
+.Fn Delete_Chunk "struct disk *disk" "struct chunk *"
+.Ft void
+.Fn Collapse_Disk "struct disk *disk"
+.Ft int
+.Fn Collapse_Chunk "struct disk *disk" "struct chunk *chunk"
+.Ft int
+.Fn Create_Chunk "struct disk *disk" "u_long offset" "u_long size" "chunk_e type" "int subtype" "u_long flags"
+.Ft void
+.Fn All_FreeBSD "struct disk *d" "int force_all"
+.Ft char *
+.Fn CheckRules "struct disk *"
+.Ft char **
+.Fn Disk_Names "void"
+.Ft void
+.Fn Set_Boot_Mgr "struct disk *d" "const u_char *bootmgr"
+.Ft void
+.Fn Set_Boot_Blocks "struct disk *d" "const u_char *boot1" "const u_char *boot2"
+.Ft int
+.Fn Write_Disk "struct disk *d"
+.Ft int
+.Fn Cyl_Aligned "struct disk *d" "u_long offset"
+.Ft u_long
+.Fn Next_Cyl_Aligned "struct disk *d" "u_long offset"
+.Ft u_long
+.Fn Prev_Cyl_Aligned "struct disk *d" "u_long offset"
+.Ft int
+.Fn Track_Aligned "struct disk *d" "u_long offset"
+.Ft u_long
+.Fn Next_Track_Aligned "struct disk *d" "u_long offset"
+.Ft u_long
+.Fn Prev_Track_Aligned "struct disk *d" "u_long offset"
+.Ft struct chunk *
+.Fn Create_Chunk_DWIM "struct disk *d" "struct chunk *parent" "u_long size" "chunk_e type" "int subtype" "u_long flags"
+.Ft int
+.Fn MakeDev "struct chunk *c" "const char *path"
+.Ft int
+.Fn MakeDevDisk "struct disk *d" "const char *path"
+.Ft char *
+.Fn ShowChunkFlags "struct chunk *c"
+.Ft char *
+.Fn ChunkCanBeRoot "struct chunk *c"
+.Sh DESCRIPTION
+.Nm Libdisk
+provides an interface to the low-level disk slice and partition labels.
+Most functions operate with arguments of the types
+.Ql struct disk ,
+or
+.Ql struct chunk .
+.Pp
+While both types are mostly opaque to the programmer, the internal
+structure is mentioned below for the sake of completeness.
+.Bd -literal -offset indent
+struct disk {
+ char *name;
+ u_long flags;
+ u_long bios_cyl;
+ u_long bios_hd;
+ u_long bios_sect;
+ u_char *bootmgr;
+ u_char *boot1;
+ u_char *boot2;
+ struct chunk *chunks;
+};
+.Ed
+The only flag value by now is
+.Ql DISK_ON_TRACK ,
+meaning that this disk is handled by the On-Track Disk Manager.
+.Pp
+.Bd -literal -offset indent
+struct chunk {
+ struct chunk *next;
+ struct chunk *part;
+ struct disk *disk;
+ long offset;
+ u_long size;
+ u_long end;
+ char *name;
+ char *oname;
+ chunk_e type;
+ int subtype;
+ u_long flags;
+ void (*private_free)(void*);
+ void *(*private_clone)(void*);
+ void *private_data;
+};
+.Ed
+The
+.Ql type
+field can be one of the following values:
+.Ql whole, unknown, fat, freebsd, extended, part, unused .
+.Pp
+These are the valid
+.Ql flag
+values for a
+.Ql struct chunk .
+.Bl -tag -offset indent -width CHUNK_BSD_COMPATXX
+.It CHUNK_PAST_1024
+This chunk cannot be booted from because it extends past cylinder 1024.
+.It CHUNK_BSD_COMPAT
+This chunk is in the BSD-compatibility, and has a short name too, i.e.
+.Ql wd0s4f -> wd0f .
+.It CHUNK_BAD144
+This chunk has bad144 mapping.
+.It CHUNK_ALIGN
+This chunk should be aligned.
+.It CHUNK_IS_ROOT
+This
+.Ql part
+is a rootfs, allocate partition
+.Sq a .
+.It CHUNK_ACTIVE
+This is the active slice in the MBR.
+.It CHUNK_FORCE_ALL
+Force a dedicated disk for FreeBSD, bypassing all BIOS geometry
+considerations.
+.El
+.Pp
+The
+.Ql private_data ,
+.Ql private_free ,
+and
+.Ql private_clone
+fields are for data private to the application, and the management
+thereof. If the functions are not provided, no storage management is
+done, cloning will just copy the pointer and freeing will just forget
+it.
+.Pp
+.Fn Open_Disk
+will open the named disk, and return populated tree.
+.Pp
+.Fn Clone_Disk
+clones a copy of a tree. Useful for
+.Dq Undo
+functionality.
+.Pp
+.Fn Free_Disk
+frees a tree made with
+.Fn Open_Disk
+or
+.Fn Clone_Disk .
+.Pp
+.Fn Debug_Disk
+prints the content of the tree to stdout.
+.Pp
+.Fn Set_Bios_Geom
+sets the geometry the bios uses.
+.Pp
+.Fn Delete_Chunk
+frees a chunk of disk_space.
+.Pp
+.Fn Collapse_Disk,
+and
+.Fn Collapse_Chunk
+are experimental, do not use.
+.Pp
+.Fn Create_Chunk
+creates a chunk with the specified paramters.
+.Pp
+.Fn All_FreeBSD
+makes one FreeBSD chunk covering the entire disk; if
+.Ql force_all
+is set, bypass all BIOS geometry considerations.
+.Pp
+.Fn CheckRules
+returns
+.Ql char*
+to warnings about broken design rules in this disklayout.
+.Pp
+.Fn Disk_Names
+returns
+.Ql char**
+with all disk's names (wd0, wd1 ...). You must free each pointer, as
+well as the array by hand.
+.Pp
+.Fn Set_Boot_Mgr
+sets this boot-manager for use on this disk. Gets written when
+.Fn Write_Disk
+is called.
+.Pp
+.Fn Set_Boot_Blocks
+sets the boot-blocks for use on this disk. Gets written when
+.Fn Write_Disk
+is called. The external variables
+.Dv boot1
+and
+.Dv boot2
+contain suitable data to be passed to this function.
+.Pp
+.Fn Write_Disk
+writes all the MBRs, disklabels, bootblocks and boot managers.
+.Pp
+.Fn Cyl_Aligned
+checks if
+.Ql offset
+is aligned on a cylinder according to the BIOS.
+geometry.
+.Pp
+.Fn Next_Cyl_Aligned
+rounds
+.Ql offset
+up to next cylinder according to the BIOS geometry.
+.Pp
+.Fn Prev_Cyl_Aligned
+rounds
+.Ql offset
+down to previous cylinder according to the BIOS geometry.
+.Pp
+.Fn Track_Aligned
+checks if
+.Ql offset
+is aligned on a track according to the BIOS geometry.
+.Pp
+.Fn Next_Track_Aligned
+rounds
+.Ql offset
+up to next track according to the BIOS geometry.
+.Pp
+.Fn Prev_Track_Aligned
+checks if
+.Ql offset
+is aligned on a track according to the BIOS geometry.
+.Pp
+.Fn Create_Chunk_DWIM
+creates a partition inside the given parent of the given size, and
+returns a pointer to it. The first unused chunk big enough is used.
+.Pp
+.Fn MakeDev
+makes the device nodes for this chunk.
+.Pp
+.Fn MakeDevDisk
+makes the device nodes for all chunks on this disk.
+.Pp
+.Fn ShowChunkFlags
+returns a string to show flags.
+.Pp
+.Fn ChunkCanBeRoot
+returns NULL if chunk can be
+.Pp
+Chunk name strings can be accessed directly using the external array
+.Va chunk_n .
+.Pp
+.Fn slice_type_name
+returns the name strings associated with the specified
+.Ql type .
+.Ql subtype .
+If
+.Fn slice_type_name
+returns "unknown" for slices it isn't familar with.
+.Ql / .
+.Sh AUTHOR
+.Nm Libdisk
+has been written by Poul-Henning Kamp.
+.Pp
+This man page by
+.ie t J\(:org Wunsch.
+.el Joerg Wunsch.
diff --git a/lib/libdisk/libdisk.h b/lib/libdisk/libdisk.h
new file mode 100644
index 0000000..b8c724e
--- /dev/null
+++ b/lib/libdisk/libdisk.h
@@ -0,0 +1,326 @@
+/*
+* ----------------------------------------------------------------------------
+* "THE BEER-WARE LICENSE" (Revision 42):
+* <phk@login.dknet.dk> 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
+* ----------------------------------------------------------------------------
+*
+* $Id: libdisk.h,v 1.26 1997/02/22 15:06:35 peter Exp $
+*
+*/
+
+#define MAX_NO_DISKS 20
+/* Max # of disks Disk_Names() will return */
+
+typedef enum {
+ whole,
+ unknown,
+ fat,
+ freebsd,
+ extended,
+ part,
+ unused
+} chunk_e;
+
+__BEGIN_DECLS
+struct disk {
+ char *name;
+ u_long flags;
+# define DISK_ON_TRACK 1
+ u_long bios_cyl;
+ u_long bios_hd;
+ u_long bios_sect;
+ u_char *bootmgr;
+ u_char *boot1;
+ u_char *boot2;
+ struct chunk *chunks;
+};
+
+struct chunk {
+ struct chunk *next;
+ struct chunk *part;
+ struct disk *disk;
+ long offset;
+ u_long size;
+ u_long end;
+ char *name;
+ char *oname;
+ /* Used during Fixup_Names() to avoid renaming more than
+ * absolutely needed.
+ */
+ chunk_e type;
+ int subtype;
+ u_long flags;
+# define CHUNK_PAST_1024 1
+ /* this chunk cannot be booted from because it
+ * extends past cylinder 1024
+ */
+# define CHUNK_BSD_COMPAT 2
+ /* this chunk is in the BSD-compatibility, and has a
+ * short name too, ie wd0s4f -> wd0f
+ */
+# define CHUNK_BAD144 4
+ /* this chunk has bad144 mapping */
+# define CHUNK_ALIGN 8
+ /* This chunk should be aligned */
+# define CHUNK_IS_ROOT 16
+ /* This 'part' is a rootfs, allocate 'a' */
+# define CHUNK_ACTIVE 32
+ /* This is the active slice in the MBR */
+# define CHUNK_FORCE_ALL 64
+ /* Force a dedicated disk for FreeBSD, bypassing
+ * all BIOS geometry considerations
+ */
+
+ void (*private_free)(void*);
+ void *(*private_clone)(void*);
+ void *private_data;
+ /* For data private to the application, and the management
+ * thereof. If the functions are not provided, no storage
+ * management is done, Cloning will just copy the pointer
+ * and freeing will just forget it.
+ */
+};
+
+extern const char *chunk_n[];
+extern const u_char boot1[], boot2[];
+
+const char *
+slice_type_name( int type, int subtype );
+/* "chunk_n" for subtypes too
+ */
+
+struct disk *
+Open_Disk(const char *devname);
+/* Will open the named disk, and return populated tree.
+ */
+
+struct disk *
+Clone_Disk(struct disk *disk);
+/* Clone a copy of a tree. Useful for "Undo" functionality
+ */
+
+void
+Free_Disk(struct disk *disk);
+/* Free a tree made with Open_Disk() or Clone_Disk()
+ */
+
+void
+Debug_Disk(struct disk *disk);
+/* Print the content of the tree to stdout
+ */
+
+void
+Set_Bios_Geom(struct disk *disk, u_long cyl, u_long heads, u_long sects);
+/* Set the geometry the bios uses.
+ */
+
+void
+Sanitize_Bios_Geom(struct disk *disk);
+/* Set the bios geometry to something sane
+ */
+
+int
+Delete_Chunk(struct disk *disk, struct chunk *);
+/* Free a chunk of disk_space
+ */
+
+void
+Collapse_Disk(struct disk *disk);
+/* Experimental, do not use.
+ */
+int
+Collapse_Chunk(struct disk *disk, struct chunk *chunk);
+/* Experimental, do not use.
+ */
+
+int
+Create_Chunk(struct disk *disk, u_long offset, u_long size, chunk_e type,
+ int subtype, u_long flags);
+/* Create a chunk with the specified paramters
+ */
+
+void
+All_FreeBSD(struct disk *d, int force_all);
+/* Make one FreeBSD chunk covering the entire disk;
+ * if force_all is set, bypass all BIOS geometry
+ * considerations.
+ */
+
+char *
+CheckRules(struct disk *);
+/* Return char* to warnings about broken design rules in this disklayout
+ */
+
+char **
+Disk_Names();
+/* Return char** with all disk's names (wd0, wd1 ...). You must free
+ * each pointer, as well as the array by hand
+ */
+
+void
+Set_Boot_Mgr(struct disk *d, const u_char *bootmgr);
+/* Use this boot-manager on this disk. Gets written when Write_Disk()
+ * is called
+ */
+
+void
+Set_Boot_Blocks(struct disk *d, const u_char *boot1, const u_char *boot2);
+/* Use these boot-blocks on this disk. Gets written when Write_Disk()
+ * is called
+ */
+
+int
+Write_Disk(struct disk *d);
+/* Write all the MBRs, disklabels, bootblocks and boot managers
+ */
+
+int
+Cyl_Aligned(struct disk *d, u_long offset);
+/* Check if offset is aligned on a cylinder according to the
+ * bios geometry
+ */
+
+u_long
+Next_Cyl_Aligned(struct disk *d, u_long offset);
+/* Round offset up to next cylinder according to the bios-geometry
+ */
+
+u_long
+Prev_Cyl_Aligned(struct disk *d, u_long offset);
+/* Round offset down to previous cylinder according to the bios-
+ * geometry
+ */
+
+int
+Track_Aligned(struct disk *d, u_long offset);
+/* Check if offset is aligned on a track according to the
+ * bios geometry
+ */
+
+u_long
+Next_Track_Aligned(struct disk *d, u_long offset);
+/* Round offset up to next track according to the bios-geometry
+ */
+
+u_long
+Prev_Track_Aligned(struct disk *d, u_long offset);
+/* Check if offset is aligned on a track according to the
+ * bios geometry
+ */
+
+struct chunk *
+Create_Chunk_DWIM(struct disk *d, struct chunk *parent , u_long size,
+ chunk_e type, int subtype, u_long flags);
+/* This one creates a partition inside the given parent of the given
+ * size, and returns a pointer to it. The first unused chunk big
+ * enough is used.
+ */
+
+int
+MakeDev(struct chunk *c, const char *path);
+
+int
+MakeDevDisk(struct disk *d, const char *path);
+/* Make device nodes for all chunks on this disk */
+
+char *
+ShowChunkFlags(struct chunk *c);
+/* Return string to show flags. */
+
+char *
+ChunkCanBeRoot(struct chunk *c);
+/* Return NULL if chunk can be /, explanation otherwise */
+
+/*
+ * Implementation details >>> DO NOT USE <<<
+ */
+
+void Debug_Chunk(struct chunk *);
+void Free_Chunk(struct chunk *);
+struct chunk * Clone_Chunk(struct chunk *);
+int Add_Chunk(struct disk *, long, u_long, const char *, chunk_e, int, u_long);
+void Bios_Limit_Chunk(struct chunk *, u_long);
+void * read_block(int, daddr_t);
+void write_block(int fd, daddr_t block, void *foo);
+struct disklabel * read_disklabel(int, daddr_t);
+u_short dkcksum(struct disklabel *);
+struct chunk * Find_Mother_Chunk(struct chunk *, u_long, u_long, chunk_e);
+struct disk * Int_Open_Disk(const char *name, u_long size);
+void Fixup_Names(struct disk *);
+__END_DECLS
+
+#define dprintf printf
+
+/* TODO
+ *
+ * Need a error string mechanism from the functions instead of warn()
+ *
+ * Make sure only FreeBSD start at offset==0
+ *
+ * Collapse must align.
+ *
+ * Make Write_Disk(struct disk*)
+ *
+ * Consider booting from OnTrack'ed disks.
+ *
+ * Get Bios-geom, ST506 & OnTrack from driver (or otherwise)
+ *
+ * Make Create_DWIM().
+ *
+ * Make Is_Unchanged(struct disk *d1, struct chunk *c1)
+ *
+ * don't rename slices unless we have to
+ *
+ *Sample output from tst01:
+ *
+ * Debug_Disk(wd0) flags=0 bios_geom=0/0/0
+ * >> 0x3d040 0 1411200 1411199 wd0 0 whole 0 0
+ * >>>> 0x3d080 0 960120 960119 wd0s1 3 freebsd 0 8
+ * >>>>>> 0x3d100 0 40960 40959 wd0s1a 5 part 0 0
+ * >>>>>> 0x3d180 40960 131072 172031 wd0s1b 5 part 0 0
+ * >>>>>> 0x3d1c0 172032 409600 581631 wd0s1e 5 part 0 0
+ * >>>>>> 0x3d200 581632 378488 960119 wd0s1f 5 part 0 0
+ * >>>> 0x3d140 960120 5670 965789 wd0s2 4 extended 0 8
+ * >>>>>> 0x3d2c0 960120 63 960182 - 6 unused 0 0
+ * >>>>>> 0x3d0c0 960183 5607 965789 wd0s5 2 fat 0 8
+ * >>>> 0x3d280 965790 1890 967679 wd0s3 1 foo -2 8
+ * >>>> 0x3d300 967680 443520 1411199 wd0s4 3 freebsd 0 8
+ * >>>>>> 0x3d340 967680 443520 1411199 wd0s4a 5 part 0 0
+ *
+ * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
+ * level chunkptr start size end name type subtype flags
+ *
+ * Underlying data structure:
+ *
+ * Legend:
+ * <struct chunk> --> part
+ * |
+ * v next
+ *
+ * <wd0> --> <wd0s1> --> <wd0s1a>
+ * | |
+ * | v
+ * | <wd0s1b>
+ * | |
+ * | v
+ * | <wd0s1e>
+ * | |
+ * | v
+ * | <wd0s1f>
+ * |
+ * v
+ * <wd0s2> --> <unused>
+ * | |
+ * | v
+ * | <wd0s5>
+ * |
+ * v
+ * <wd0s3>
+ * |
+ * v
+ * <wd0s4> --> <wd0s4a>
+ *
+ *
+ */
diff --git a/lib/libdisk/rules.c b/lib/libdisk/rules.c
new file mode 100644
index 0000000..5bf75ec
--- /dev/null
+++ b/lib/libdisk/rules.c
@@ -0,0 +1,316 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/diskslice.h>
+#include <sys/disklabel.h>
+#include <err.h>
+#include "libdisk.h"
+
+int
+Track_Aligned(struct disk *d, u_long offset)
+{
+ if (!d->bios_sect)
+ return 1;
+ if (offset % d->bios_sect)
+ return 0;
+ return 1;
+}
+
+u_long
+Prev_Track_Aligned(struct disk *d, u_long offset)
+{
+ if (!d->bios_sect)
+ return offset;
+ return (offset / d->bios_sect) * d->bios_sect;
+}
+
+u_long
+Next_Track_Aligned(struct disk *d, u_long offset)
+{
+ if (!d->bios_sect)
+ return offset;
+ return Prev_Track_Aligned(d,offset + d->bios_sect-1);
+}
+
+int
+Cyl_Aligned(struct disk *d, u_long offset)
+{
+ if (!d->bios_sect || !d->bios_hd)
+ return 1;
+ if (offset % (d->bios_sect * d->bios_hd))
+ return 0;
+ return 1;
+}
+
+u_long
+Prev_Cyl_Aligned(struct disk *d, u_long offset)
+{
+ if (!d->bios_sect || !d->bios_hd)
+ return offset;
+ return (offset / (d->bios_sect*d->bios_hd)) * d->bios_sect * d->bios_hd;
+}
+
+u_long
+Next_Cyl_Aligned(struct disk *d, u_long offset)
+{
+ if (!d->bios_sect || !d->bios_hd)
+ return offset;
+ return Prev_Cyl_Aligned(d,offset + (d->bios_sect * d->bios_hd)-1);
+}
+
+/*
+ * Rule#0:
+ * Chunks of type 'whole' can have max NDOSPART children.
+ * Only one of them can have the "active" flag
+ */
+void
+Rule_000(struct disk *d, struct chunk *c, char *msg)
+{
+ int i=0,j=0;
+ struct chunk *c1;
+
+ if (c->type != whole)
+ return;
+ for (c1=c->part; c1; c1=c1->next) {
+ if (c1->type != unused) continue;
+ if (c1->flags & CHUNK_ACTIVE)
+ j++;
+ i++;
+ }
+ if (i > NDOSPART)
+ sprintf(msg+strlen(msg),
+ "%d is too many children of the 'whole' chunk. Max is %d\n",
+ i, NDOSPART);
+ if (j > 1)
+ sprintf(msg+strlen(msg),
+ "Too many active children of 'whole'");
+}
+
+/*
+ * Rule#1:
+ * All children of 'whole' and 'extended' must be track-aligned.
+ * Exception: the end can be unaligned if it matches the end of 'whole'
+ */
+void
+Rule_001(struct disk *d, struct chunk *c, char *msg)
+{
+ int i;
+ struct chunk *c1;
+
+ if (c->type != whole && c->type != extended)
+ return;
+ for (i=0, c1=c->part; c1; c1=c1->next) {
+ if (c1->type == unused) continue;
+ c1->flags |= CHUNK_ALIGN;
+ if (!Track_Aligned(d,c1->offset))
+ sprintf(msg+strlen(msg),
+ "chunk '%s' [%ld..%ld] does not start on a track boundary\n",
+ c1->name,c1->offset,c1->end);
+ if ((c->type == whole || c->end == c1->end)
+ || Cyl_Aligned(d,c1->end+1))
+ ;
+ else
+ sprintf(msg+strlen(msg),
+ "chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n",
+ c1->name,c1->offset,c1->end);
+ }
+}
+
+/*
+ * Rule#2:
+ * Max one 'fat' as child of 'whole'
+ */
+void
+Rule_002(struct disk *d, struct chunk *c, char *msg)
+{
+ int i;
+ struct chunk *c1;
+
+ if (c->type != whole)
+ return;
+ for (i=0, c1=c->part; c1; c1=c1->next) {
+ if (c1->type != fat)
+ continue;
+ i++;
+ }
+ if (i > 1) {
+ sprintf(msg+strlen(msg),
+ "Max one 'fat' allowed as child of 'whole'\n");
+ }
+}
+
+/*
+ * Rule#3:
+ * Max one extended as child of 'whole'
+ */
+void
+Rule_003(struct disk *d, struct chunk *c, char *msg)
+{
+ int i;
+ struct chunk *c1;
+
+ if (c->type != whole)
+ return;
+ for (i=0, c1=c->part; c1; c1=c1->next) {
+ if (c1->type != extended)
+ continue;
+ i++;
+ }
+ if (i > 1) {
+ sprintf(msg+strlen(msg),
+ "Max one 'extended' allowed as child of 'whole'\n");
+ }
+}
+
+/*
+ * Rule#4:
+ * Max seven 'part' as children of 'freebsd'
+ * Max one CHUNK_IS_ROOT child per 'freebsd'
+ * If Bad144, space for table must exist.
+ * If Bad144 & root, bad144 table must be inside 1024
+ */
+void
+Rule_004(struct disk *d, struct chunk *c, char *msg)
+{
+ int i=0,k=0;
+ struct chunk *c1;
+ u_long l;
+
+ if (c->type != freebsd)
+ return;
+
+ if (c->flags & CHUNK_BAD144) {
+ l = c->end - 127 - d->bios_sect + 1;
+ for (c1=c->part; c1; c1=c1->next) {
+ if (c1->end < l || c1->type == unused)
+ continue;
+ sprintf(msg+strlen(msg),
+ "Blocks %lu to %lu are needed for bad144 information, but isn't unused.\n",
+ l, c->end);
+ break;
+ }
+ if (c->flags & CHUNK_PAST_1024) {
+ for (c1=c->part; c1; c1=c1->next) {
+ if (c1->flags & CHUNK_IS_ROOT) {
+ sprintf(msg+strlen(msg),
+ "You have assigned root to a slice which uses bad144, and\n extends past the first 1023 cylinders, and thus cannot be booted from.\n");
+ break;
+ }
+ }
+ }
+ }
+
+ for (c1=c->part; c1; c1=c1->next) {
+ if (c1->type != part)
+ continue;
+ if (c1->flags & CHUNK_IS_ROOT) {
+ k++;
+ if (c1->flags & CHUNK_PAST_1024)
+ sprintf(msg+strlen(msg),
+ "Root filesystem extends past cylinder 1024, and cannot be booted from\n");
+ }
+ i++;
+ }
+ if (i > 7) {
+ sprintf(msg+strlen(msg),
+ "Max seven partitions per freebsd slice\n");
+ }
+ if (k > 1) {
+ sprintf(msg+strlen(msg),
+ "Max one root partition child per freebsd slice\n");
+ }
+}
+
+void
+Check_Chunk(struct disk *d, struct chunk *c, char *msg)
+{
+ Rule_000(d,c,msg);
+ Rule_001(d,c,msg);
+ Rule_002(d,c,msg);
+ Rule_003(d,c,msg);
+ Rule_004(d,c,msg);
+ if (c->part)
+ Check_Chunk(d,c->part,msg);
+ if (c->next)
+ Check_Chunk(d,c->next,msg);
+
+ if (c->end >= 1024*d->bios_hd*d->bios_sect)
+ c->flags |= CHUNK_PAST_1024;
+ else
+ c->flags &= ~CHUNK_PAST_1024;
+}
+
+char *
+CheckRules(struct disk *d)
+{
+ char msg[BUFSIZ];
+
+ *msg = '\0';
+ Check_Chunk(d,d->chunks,msg);
+ if (*msg)
+ return strdup(msg);
+ return 0;
+}
+
+char *
+ChunkCanBeRoot(struct chunk *c)
+{
+ struct chunk *c1;
+ struct disk *d = c->disk;
+ char msg[BUFSIZ];
+
+ *msg = '\0';
+ if (c->flags & CHUNK_PAST_1024) {
+ strcat(msg,
+"The root partition must end before cylinder 1024 seen from\n");
+ strcat(msg,
+"the BIOS' point of view, or it cannot be booted from.\n");
+ return strdup(msg);
+ }
+ for (c1=d->chunks->part;;) {
+ for (; c1; c1=c1->next)
+ if (c1->offset <= c->offset && c1->end >= c->end)
+ break;
+ if (!c1) {
+ strcat(msg,
+"Internal trouble, cannot find this chunk in the chunk-tree\n");
+ return strdup(msg);
+ }
+ if (c1->type == freebsd)
+ break;
+ c1 = c1->part;
+ }
+
+ if (c1->type != freebsd) {
+ strcat(msg,
+"The root partition must be in a FreeBSD slice, otherwise\n");
+ strcat(msg,
+"the kernel cannot be booted from it\n");
+ return strdup(msg);
+ }
+
+ if ((c1->flags & CHUNK_BAD144) && (c1->flags & CHUNK_PAST_1024)) {
+ strcat(msg,
+"This partition is unsuitable for root, because the FreeBSD slice\n");
+ strcat(msg,
+"it is inside has bad144 enabled, but the badblock data lives past\n");
+ strcat(msg,
+"the 1024th cylinder, and the bootblocks cannot get to it there.\n");
+ return strdup(msg);
+ }
+ return NULL;
+}
diff --git a/lib/libdisk/tst01.c b/lib/libdisk/tst01.c
new file mode 100644
index 0000000..f1fb5eb
--- /dev/null
+++ b/lib/libdisk/tst01.c
@@ -0,0 +1,296 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <err.h>
+#ifdef READLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+#include <sys/types.h>
+#include "libdisk.h"
+
+u_char mbr[] = {
+250,51,192,142,208,188,0,124,139,244,80,7,80,31,251,252,191,0,6,185,0,1,
+242,165,234,29,6,0,0,190,190,7,179,4,128,60,128,116,14,128,60,0,117,28,
+131,198,16,254,203,117,239,205,24,139,20,139,76,2,139,238,131,198,16,254,
+203,116,26,128,60,0,116,244,190,139,6,172,60,0,116,11,86,187,7,0,180,14,
+205,16,94,235,240,235,254,191,5,0,187,0,124,184,1,2,87,205,19,95,115,12,
+51,192,205,19,79,117,237,190,163,6,235,211,190,194,6,191,254,125,129,61,
+85,170,117,199,139,245,234,0,124,0,0,73,110,118,97,108,105,100,32,112,97,
+114,116,105,116,105,111,110,32,116,97,98,108,101,0,69,114,114,111,114,32,
+108,111,97,100,105,110,103,32,111,112,101,114,97,116,105,110,103,32,115,
+121,115,116,101,109,0,77,105,115,115,105,110,103,32,111,112,101,114,97,
+116,105,110,103,32,115,121,115,116,101,109,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,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,128,
+1,1,0,4,15,63,60,63,0,0,0,241,239,0,0,0,0,1,61,5,15,63,243,48,240,0,0,144,
+208,2,0,0,0,1,244,165,15,63,170,192,192,3,0,144,208,2,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,85,170
+};
+
+u_char bteasy17[] = {
+51,192,142,192,142,216,142,208,188,0,124,252,139,244,191,0,6,185,0,1,242,
+165,234,96,6,0,0,139,213,88,162,72,7,60,53,116,28,180,16,246,228,5,174,
+4,150,246,68,4,255,116,62,198,4,128,232,218,0,138,116,1,139,76,2,235,8,
+232,207,0,185,1,0,50,209,187,0,124,184,1,2,205,19,114,30,129,191,254,1,
+85,170,117,22,234,0,124,0,0,128,250,129,116,2,178,128,139,234,66,128,242,
+179,136,22,58,7,191,190,7,185,4,0,198,6,45,7,49,50,246,136,45,138,69,4,
+60,0,116,35,60,5,116,31,254,198,190,42,7,232,113,0,190,72,7,70,70,139,28,
+10,255,116,5,50,125,4,117,243,141,183,114,7,232,90,0,131,199,16,254,6,45,
+7,226,203,128,62,117,4,2,116,11,190,59,7,10,246,117,10,205,24,235,172,190,
+42,7,232,57,0,232,54,0,50,228,205,26,139,218,131,195,96,180,1,205,22,180,
+0,117,11,205,26,59,211,114,242,160,72,7,235,10,205,22,138,196,60,28,116,
+243,4,246,60,49,114,214,60,53,119,210,80,190,40,7,187,27,6,83,252,172,80,
+36,127,180,14,205,16,88,168,128,116,242,195,86,184,1,3,187,0,6,185,1,0,
+50,246,205,19,94,198,6,72,7,63,195,13,138,13,10,70,48,32,46,32,46,32,46,
+160,100,105,115,107,32,49,13,10,10,68,101,102,97,117,108,116,58,32,70,63,
+160,0,1,0,4,0,6,3,7,7,10,10,99,14,100,14,101,20,128,20,129,25,130,30,147,
+36,165,39,159,43,117,47,82,47,219,50,64,55,242,61,0,100,111,243,72,80,70,
+211,79,115,178,85,110,105,248,78,111,118,101,108,236,77,105,110,105,248,
+76,105,110,117,248,65,109,111,101,98,225,66,83,196,66,83,68,233,80,67,73,
+216,67,80,205,86,101,110,105,248,68,111,115,115,101,227,63,191,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,85,170
+};
+
+int
+scan_block(int fd, daddr_t block)
+{
+ u_char foo[512];
+
+ if (-1 == lseek(fd, (off_t)block * 512, SEEK_SET))
+ err(1, "lseek");
+ if (512 != read(fd,foo, 512))
+ return 1;
+ return 0;
+}
+
+void
+Scan_Disk(struct disk *d)
+{
+ char device[64];
+ u_long l;
+ int i,j,fd;
+
+ strcpy(device,"/dev/r");
+ strcat(device,d->name);
+
+ fd = open(device,O_RDWR);
+ if (fd < 0) {
+ warn("open(%s) failed",device);
+ return;
+ }
+ for(i=-1,l=0;;l++) {
+ j = scan_block(fd,l);
+ if (j != i) {
+ if (i == -1) {
+ printf("%c: %lu.",j ? 'B' : 'G', l);
+ fflush(stdout);
+ } else if (i == 0) {
+ printf(".%lu\nB: %lu.",l-1,l);
+ fflush(stdout);
+ } else {
+ printf(".%lu\nG: %lu.",l-1,l);
+ fflush(stdout);
+ }
+ i = j;
+ }
+ }
+ close(fd);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct disk *d,*db;
+ char myprompt[BUFSIZ];
+#ifndef READLINE
+ char input[BUFSIZ];
+#endif
+ char *p,*q=0;
+ char **cp,*cmds[200];
+ int ncmd,i;
+
+ if (argc < 2) {
+ fprintf(stderr,"Usage:\n\t%s diskname\n",argv[0]);
+ exit(1);
+ }
+ d = Open_Disk(argv[1]);
+ if (!d)
+ err(1,"Couldn't open disk %s",argv[1]);
+
+ sprintf(myprompt,"%s %s> ",argv[0],argv[1]);
+ while(1) {
+ printf("--==##==--\n");
+ p = CheckRules(d);
+ Debug_Disk(d);
+ if (p) {
+ printf("%s",p);
+ free(p);
+ }
+#ifdef READLINE
+ if (q)
+ free(q);
+ q = p = readline(myprompt);
+#else
+ printf(myprompt);
+ fflush(stdout);
+ q = p = fgets(input,sizeof(input),stdin);
+#endif
+ if(!p)
+ break;
+ for(cp = cmds; (*cp = strsep(&p, " \t\n")) != NULL;)
+ if (**cp != '\0')
+ cp++;
+ ncmd = cp - cmds;
+ if(!ncmd)
+ continue;
+ if (!strcasecmp(*cmds,"quit")) { break; }
+ if (!strcasecmp(*cmds,"exit")) { break; }
+ if (!strcasecmp(*cmds,"q")) { break; }
+ if (!strcasecmp(*cmds,"x")) { break; }
+ if (!strcasecmp(*cmds,"dwim") && ncmd == 6) {
+ printf("dwim = %p\n",
+ Create_Chunk_DWIM(d,
+ (struct chunk *)strtol(cmds[1],0,0),
+ strtol(cmds[2],0,0),
+ strtol(cmds[3],0,0),
+ strtol(cmds[4],0,0),
+ strtol(cmds[5],0,0)));
+ continue;
+ }
+ if (!strcasecmp(*cmds,"mknod")) {
+ MakeDevDisk(d,"/tmp");
+ continue;
+ }
+ if (!strcasecmp(*cmds,"delete") && ncmd == 2) {
+ printf("delete = %d\n",
+ Delete_Chunk(d,
+ (struct chunk *)strtol(cmds[1],0,0)));
+ continue;
+ }
+ if (!strcasecmp(*cmds,"allfreebsd")) {
+ All_FreeBSD(d, 0);
+ continue;
+ }
+ if (!strcasecmp(*cmds,"dedicate")) {
+ All_FreeBSD(d, 1);
+ continue;
+ }
+ if (!strcasecmp(*cmds,"sanitize")) {
+ Sanitize_Bios_Geom(d);
+ continue;
+ }
+ if (!strcasecmp(*cmds,"bios") && ncmd == 4) {
+ Set_Bios_Geom(d,
+ strtol(cmds[1],0,0),
+ strtol(cmds[2],0,0),
+ strtol(cmds[3],0,0));
+ continue;
+ }
+ if (!strcasecmp(*cmds,"list")) {
+ cp = Disk_Names();
+ printf("Disks:");
+ for(i=0;cp[i];i++) {
+ printf(" %s",cp[i]);
+ free(cp[i]);
+ }
+ free(cp);
+ continue;
+ }
+ if (!strcasecmp(*cmds,"create") && ncmd == 6) {
+
+ printf("Create=%d\n",
+ Create_Chunk(d,
+ strtol(cmds[1],0,0),
+ strtol(cmds[2],0,0),
+ strtol(cmds[3],0,0),
+ strtol(cmds[4],0,0),
+ strtol(cmds[5],0,0)));
+ continue;
+ }
+ if (!strcasecmp(*cmds,"read")) {
+ db = d;
+ if (ncmd > 1)
+ d = Open_Disk(cmds[1]);
+ else
+ d = Open_Disk(argv[1]);
+ if (d)
+ Free_Disk(db);
+ else
+ d = db;
+ continue;
+ }
+ if (!strcasecmp(*cmds,"scan")) {
+ Scan_Disk(d);
+ continue;
+ }
+ if (!strcasecmp(*cmds,"bteasy")) {
+ Set_Boot_Mgr(d,bteasy17);
+ continue;
+ }
+ if (!strcasecmp(*cmds,"mbr")) {
+ Set_Boot_Mgr(d,mbr);
+ continue;
+ }
+ if (!strcasecmp(*cmds,"boot")) {
+ Set_Boot_Blocks(d,boot1,boot2);
+ continue;
+ }
+ if (!strcasecmp(*cmds,"write")) {
+ printf("Write=%d\n",
+ Write_Disk(d));
+ Free_Disk(d);
+ d = Open_Disk(d->name);
+ continue;
+ }
+ if (strcasecmp(*cmds,"help"))
+ printf("\007ERROR\n");
+ printf("CMDS:\n");
+ printf("\tallfreebsd\n");
+ printf("\tdedicate\n");
+ printf("\tbios cyl hd sect\n");
+ printf("\tboot\n");
+ printf("\tbteasy17\n");
+#if 0
+ printf("\tcollapse [pointer]\n");
+#endif
+ printf("\tcreate offset size enum subtype flags\n");
+ printf("\t\tsubtype(part): swap=1, ffs=7\n");
+ printf("\tdelete pointer\n");
+ printf("\tlist\n");
+ printf("\tmbr\n");
+#if 0
+ printf("\tphys cyl hd sect\n");
+#endif
+ printf("\tquit\n");
+ printf("\tread [disk]\n");
+ printf("\tscan\n");
+ printf("\twrite\n");
+ printf("\nENUM:\n\t");
+ for(i=0;chunk_n[i];i++)
+ printf("%d = %s%s",i,chunk_n[i],i == 4 ? "\n\t" : " ");
+ printf("\n");
+
+ }
+ exit (0);
+}
diff --git a/lib/libdisk/write_disk.c b/lib/libdisk/write_disk.c
new file mode 100644
index 0000000..b810cf3
--- /dev/null
+++ b/lib/libdisk/write_disk.c
@@ -0,0 +1,233 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/disklabel.h>
+#include <sys/diskslice.h>
+#include "libdisk.h"
+
+#define DOSPTYP_EXTENDED 5
+#define BBSIZE 8192
+#define SBSIZE 8192
+#define DEF_RPM 3600
+#define DEF_INTERLEAVE 1
+
+#define WHERE(offset,disk) (disk->flags & DISK_ON_TRACK ? offset + 63 : offset)
+int
+Write_FreeBSD(int fd, struct disk *new, struct disk *old, struct chunk *c1)
+{
+ struct disklabel *dl;
+ struct chunk *c2;
+ int i,j;
+ void *p;
+ u_char buf[BBSIZE];
+
+ for(i=0;i<BBSIZE/512;i++) {
+ p = read_block(fd,WHERE(i + c1->offset,new));
+ memcpy(buf+512*i,p,512);
+ free(p);
+ }
+ if(new->boot1)
+ memcpy(buf,new->boot1,512);
+
+ if(new->boot2)
+ memcpy(buf+512,new->boot2,BBSIZE-512);
+
+ dl = (struct disklabel *) (buf+512*LABELSECTOR+LABELOFFSET);
+ memset(dl,0,sizeof *dl);
+
+ for(c2=c1->part;c2;c2=c2->next) {
+ if (c2->type == unused) continue;
+ if (!strcmp(c2->name,"X")) continue;
+ j = c2->name[5] - 'a';
+ if (j < 0 || j >= MAXPARTITIONS || j == RAW_PART) {
+#ifdef DEBUG
+ warn("Weird parititon letter %c",c2->name[5]);
+#endif
+ continue;
+ }
+ dl->d_partitions[j].p_size = c2->size;
+ dl->d_partitions[j].p_offset = c2->offset;
+ dl->d_partitions[j].p_fstype = c2->subtype;
+ }
+
+ dl->d_bbsize = BBSIZE;
+ /*
+ * Add in defaults for superblock size, interleave, and rpms
+ */
+ dl->d_sbsize = SBSIZE;
+ dl->d_interleave = DEF_INTERLEAVE;
+ dl->d_rpm = DEF_RPM;
+
+ strcpy(dl->d_typename,c1->name);
+
+ dl->d_secsize = 512;
+ dl->d_secperunit = new->chunks->size;
+ dl->d_ncylinders = new->bios_cyl;
+ dl->d_ntracks = new->bios_hd;
+ dl->d_nsectors = new->bios_sect;
+ dl->d_secpercyl = dl->d_ntracks * dl->d_nsectors;
+
+ dl->d_npartitions = MAXPARTITIONS;
+
+ dl->d_type = new->name[0] == 's' ? DTYPE_SCSI : DTYPE_ESDI;
+ dl->d_partitions[RAW_PART].p_size = c1->size;
+ dl->d_partitions[RAW_PART].p_offset = c1->offset;
+
+ if(new->flags & DISK_ON_TRACK)
+ for(i=0;i<MAXPARTITIONS;i++)
+ if (dl->d_partitions[i].p_size)
+ dl->d_partitions[i].p_offset += 63;
+ dl->d_magic = DISKMAGIC;
+ dl->d_magic2 = DISKMAGIC;
+ dl->d_checksum = dkcksum(dl);
+
+ for(i=0;i<BBSIZE/512;i++) {
+ write_block(fd,WHERE(i + c1->offset,new),buf+512*i);
+ }
+
+ return 0;
+}
+
+int
+Write_Extended(int fd, struct disk *new, struct disk *old, struct chunk *c1)
+{
+ return 0;
+}
+
+int
+Write_Disk(struct disk *d1)
+{
+ int fd,i,j;
+ struct disk *old = 0;
+ struct chunk *c1;
+ int ret = 0;
+ char device[64];
+ u_char *mbr;
+ struct dos_partition *dp,work[NDOSPART];
+ int s[4];
+
+ strcpy(device,"/dev/r");
+ strcat(device,d1->name);
+
+ fd = open(device,O_RDWR);
+ if (fd < 0) {
+#ifdef DEBUG
+ warn("open(%s) failed",device);
+#endif
+ return 1;
+ }
+
+ memset(s,0,sizeof s);
+ mbr = read_block(fd,WHERE(0,d1));
+ dp = (struct dos_partition*) (mbr + DOSPARTOFF);
+ memcpy(work,dp,sizeof work);
+ dp = work;
+ free(mbr);
+ for (c1=d1->chunks->part; c1 ; c1 = c1->next) {
+ if (c1->type == unused) continue;
+ if (!strcmp(c1->name,"X")) continue;
+ j = c1->name[4] - '1';
+ if (j < 0 || j > 3)
+ continue;
+ s[j]++;
+ if (c1->type == extended)
+ ret += Write_Extended(fd, d1,old,c1);
+ if (c1->type == freebsd)
+ ret += Write_FreeBSD(fd, d1,old,c1);
+
+ dp[j].dp_start = c1->offset;
+ dp[j].dp_size = c1->size;
+
+ i = c1->offset;
+ if (i >= 1024*d1->bios_sect*d1->bios_hd) {
+ dp[j].dp_ssect = 0xff;
+ dp[j].dp_shd = 0xff;
+ dp[j].dp_scyl = 0xff;
+ } else {
+ dp[j].dp_ssect = i % d1->bios_sect;
+ i -= dp[j].dp_ssect++;
+ i /= d1->bios_sect;
+ dp[j].dp_shd = i % d1->bios_hd;
+ i -= dp[j].dp_shd;
+ i /= d1->bios_hd;
+ dp[j].dp_scyl = i;
+ i -= dp[j].dp_scyl;
+ dp[j].dp_ssect |= i >> 2;
+ }
+
+#ifdef DEBUG
+ printf("S:%lu = (%x/%x/%x)",
+ c1->offset,dp[j].dp_scyl,dp[j].dp_shd,dp[j].dp_ssect);
+#endif
+
+ i = c1->end;
+ dp[j].dp_esect = i % d1->bios_sect;
+ i -= dp[j].dp_esect++;
+ i /= d1->bios_sect;
+ dp[j].dp_ehd = i % d1->bios_hd;
+ i -= dp[j].dp_ehd;
+ i /= d1->bios_hd;
+ if (i>1023) i = 1023;
+ dp[j].dp_ecyl = i;
+ i -= dp[j].dp_ecyl;
+ dp[j].dp_esect |= i >> 2;
+
+#ifdef DEBUG
+ printf(" E:%lu = (%x/%x/%x)\n",
+ c1->end,dp[j].dp_ecyl,dp[j].dp_ehd,dp[j].dp_esect);
+#endif
+
+ dp[j].dp_typ = c1->subtype;
+ if (c1->flags & CHUNK_ACTIVE)
+ dp[j].dp_flag = 0x80;
+ else
+ dp[j].dp_flag = 0;
+ }
+ j = 0;
+ for(i=0;i<NDOSPART;i++) {
+ if (!s[i])
+ memset(dp+i,0,sizeof *dp);
+ if (dp[i].dp_flag)
+ j++;
+ }
+ if (!j)
+ for(i=0;i<NDOSPART;i++)
+ if (dp[i].dp_typ == 0xa5)
+ dp[i].dp_flag = 0x80;
+
+ mbr = read_block(fd,WHERE(0,d1));
+ if (d1->bootmgr)
+ memcpy(mbr,d1->bootmgr,DOSPARTOFF);
+ memcpy(mbr+DOSPARTOFF,dp,sizeof *dp * NDOSPART);
+ mbr[512-2] = 0x55;
+ mbr[512-1] = 0xaa;
+ write_block(fd,WHERE(0,d1),mbr);
+
+ i = 1;
+ i = ioctl(fd,DIOCSYNCSLICEINFO,&i);
+#ifdef DEBUG
+ if (i != 0)
+ warn("ioctl(DIOCSYNCSLICEINFO)");
+#endif
+ close(fd);
+ return 0;
+}
+
diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile
index 9dc0471..2f4feda 100644
--- a/lib/libedit/Makefile
+++ b/lib/libedit/Makefile
@@ -2,21 +2,36 @@
LIB= edit
-OSRCS= chared.c common.c el.c emacs.c hist.c key.c map.c parse.c \
- prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c \
- help.c fcns.c
+OSRCS= chared.c common.c el.c emacs.c fcns.c help.c hist.c key.c map.c \
+ parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c
+
+LDADD+= -ltermcap
+DPADD+= ${LIBTERMCAP}
+
+MAN3= editline.3
+MAN5= editrc.5
+
+MLINKS= editline.3 el_init.3 editline.3 el_end.3 editline.3 el_reset.3 \
+ editline.3 el_gets.3 editline.3 el_getc.3 editline.3 el_push.3 \
+ editline.3 el_parse.3 editline.3 el_set.3 editline.3 el_source.3 \
+ editline.3 el_resize.3 editline.3 el_line.3 \
+ editline.3 el_insertstr.3 editline.3 el_deletestr.3 \
+ editline.3 history_init.3 editline.3 history_end.3 editline.3 history.3
+
# For speed and debugging
#SRCS= ${OSRCS} tokenizer.c history.c
# For protection
SRCS= editline.c tokenizer.c history.c
-CLEANFILES+=common.h emacs.h fcns.h help.h vi.h help.c fcns.c editline.c
-CFLAGS+=-I. -I${.CURDIR}
+SRCS+= common.h emacs.h fcns.h help.h vi.h
+
+CLEANFILES+=common.h editline.c emacs.h fcns.c fcns.h help.c help.h vi.h
+CFLAGS+=-I. -I${.CURDIR}
CFLAGS+=#-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH
CFLAGS+=#-DDEBUG_PASTE
-AHDR=vi.h emacs.h common.h
+AHDR=vi.h emacs.h common.h
ASRC=${.CURDIR}/vi.c ${.CURDIR}/emacs.c ${.CURDIR}/common.c
vi.h: vi.c makelist
@@ -34,7 +49,7 @@ fcns.h: ${AHDR} makelist
fcns.c: ${AHDR} fcns.h makelist
sh ${.CURDIR}/makelist -fc ${AHDR} > ${.TARGET}
-help.c: ${ASRC} makelist
+help.c: ${ASRC} makelist
sh ${.CURDIR}/makelist -bc ${ASRC} > ${.TARGET}
help.h: ${ASRC} makelist
@@ -45,14 +60,7 @@ editline.c: ${OSRCS}
.depend: vi.h emacs.h common.h fcns.h help.h help.c
-
-test: libedit.a test.o
- ${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermcap
-
-beforeinstall:
- -cd ${.CURDIR}; cmp -s histedit.h ${DESTDIR}/usr/include/histedit.h > \
- /dev/null 2>&1 || \
- install -c -o ${BINOWN} -g ${BINGRP} -m 444 histedit.h \
- ${DESTDIR}/usr/include
+test: test.o libedit.a ${DPADD} ${LIBTERMCAP}
+ ${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD}
.include <bsd.lib.mk>
diff --git a/lib/libedit/TEST/test.c b/lib/libedit/TEST/test.c
index f456f51..097055a 100644
--- a/lib/libedit/TEST/test.c
+++ b/lib/libedit/TEST/test.c
@@ -87,7 +87,7 @@ complete(el, ch)
EditLine *el;
int ch;
{
- DIR *dd = opendir(".");
+ DIR *dd = opendir(".");
struct dirent *dp;
const char* ptr;
const LineInfo *lf = el_line(el);
@@ -179,28 +179,56 @@ main(argc, argv)
history(hist, continuation ? H_ADD : H_ENTER, buf);
continuation = 0;
- if (el_parse(el, ac, av) != -1) {
- tok_reset(tok);
- continue;
- }
- switch (fork()) {
- case 0:
- execvp(av[0], av);
- perror(av[0]);
- _exit(1);
- /*NOTREACHED*/
- break;
-
- case -1:
- perror("fork");
- break;
-
- default:
- if (wait(&num) == -1)
- perror("wait");
- (void) fprintf(stderr, "Exit %x\n", num);
- break;
+ if (strcmp(av[0], "history") == 0) {
+ const struct HistEvent *he;
+
+ switch (ac) {
+ case 1:
+ for (he = history(hist, H_LAST); he;
+ he = history(hist, H_PREV))
+ (void) fprintf(stdout, "%4d %s", he->num, he->str);
+ break;
+
+ case 2:
+ if (strcmp(av[1], "clear") == 0)
+ history(hist, H_CLEAR);
+ else
+ goto badhist;
+ break;
+
+ case 3:
+ if (strcmp(av[1], "load") == 0)
+ history(hist, H_LOAD, av[2]);
+ else if (strcmp(av[1], "save") == 0)
+ history(hist, H_SAVE, av[2]);
+ break;
+
+ badhist:
+ default:
+ (void) fprintf(stderr, "Bad history arguments\n");
+ break;
+ }
+ }
+ else if (el_parse(el, ac, av) == -1) {
+ switch (fork()) {
+ case 0:
+ execvp(av[0], av);
+ perror(av[0]);
+ _exit(1);
+ /*NOTREACHED*/
+ break;
+
+ case -1:
+ perror("fork");
+ break;
+
+ default:
+ if (wait(&num) == -1)
+ perror("wait");
+ (void) fprintf(stderr, "Exit %x\n", num);
+ break;
+ }
}
tok_reset(tok);
}
diff --git a/lib/libedit/chared.c b/lib/libedit/chared.c
index 5a393a7..dcd189c 100644
--- a/lib/libedit/chared.c
+++ b/lib/libedit/chared.c
@@ -38,7 +38,7 @@
static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
-/*
+/*
* chared.c: Character editor utilities
*/
#include "sys.h"
@@ -67,7 +67,7 @@ cv_undo(el, action, size, ptr)
}
-/* c_insert():
+/* c_insert():
* Insert num characters
*/
protected void
@@ -80,7 +80,7 @@ c_insert(el, num)
if (el->el_line.lastchar + num >= el->el_line.limit)
return; /* can't go past end of buffer */
- if (el->el_line.cursor < el->el_line.lastchar) {
+ if (el->el_line.cursor < el->el_line.lastchar) {
/* if I must move chars */
for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
cp[num] = *cp;
@@ -93,7 +93,7 @@ c_insert(el, num)
* Delete num characters after the cursor
*/
protected void
-c_delafter(el, num)
+c_delafter(el, num)
EditLine *el;
int num;
{
@@ -101,10 +101,10 @@ c_delafter(el, num)
if (el->el_line.cursor + num > el->el_line.lastchar)
num = el->el_line.lastchar - el->el_line.cursor;
- if (num > 0) {
+ if (num > 0) {
char *cp;
- if (el->el_map.current != el->el_map.emacs)
+ if (el->el_map.current != el->el_map.emacs)
cv_undo(el, INSERT, num, el->el_line.cursor);
for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
@@ -125,12 +125,12 @@ c_delbefore(el, num)
{
if (el->el_line.cursor - num < el->el_line.buffer)
- num = el->el_line.cursor - el->el_line.buffer;
+ num = el->el_line.cursor - el->el_line.buffer;
- if (num > 0) {
+ if (num > 0) {
char *cp;
- if (el->el_map.current != el->el_map.emacs)
+ if (el->el_map.current != el->el_map.emacs)
cv_undo(el, INSERT, num, el->el_line.cursor - num);
for (cp = el->el_line.cursor - num; cp <= el->el_line.lastchar; cp++)
@@ -145,10 +145,10 @@ c_delbefore(el, num)
* Return if p is part of a word according to emacs
*/
protected int
-ce__isword(p)
+ce__isword(p)
int p;
{
- return isalpha(p) || isdigit(p) || strchr("*?_-.[]~=", p) != NULL;
+ return isalpha((unsigned char) p) || isdigit((unsigned char) p) || strchr("*?_-.[]~=", p) != NULL;
}
@@ -156,10 +156,10 @@ ce__isword(p)
* Return if p is part of a word according to vi
*/
protected int
-cv__isword(p)
+cv__isword(p)
int p;
{
- return !isspace(p);
+ return !isspace((unsigned char) p);
}
@@ -167,7 +167,7 @@ cv__isword(p)
* Find the previous word
*/
protected char *
-c__prev_word(p, low, n, wtest)
+c__prev_word(p, low, n, wtest)
register char *p, *low;
register int n;
int (*wtest) __P((int));
@@ -175,9 +175,9 @@ c__prev_word(p, low, n, wtest)
p--;
while (n--) {
- while ((p >= low) && !(*wtest)((unsigned char) *p))
+ while ((p >= low) && !(*wtest)((unsigned char) *p))
p--;
- while ((p >= low) && (*wtest)((unsigned char) *p))
+ while ((p >= low) && (*wtest)((unsigned char) *p))
p--;
}
@@ -200,9 +200,9 @@ c__next_word(p, high, n, wtest)
int (*wtest) __P((int));
{
while (n--) {
- while ((p < high) && !(*wtest)((unsigned char) *p))
+ while ((p < high) && !(*wtest)((unsigned char) *p))
p++;
- while ((p < high) && (*wtest)((unsigned char) *p))
+ while ((p < high) && (*wtest)((unsigned char) *p))
p++;
}
if (p > high)
@@ -225,14 +225,14 @@ cv_next_word(el, p, high, n, wtest)
while (n--) {
test = (*wtest)((unsigned char) *p);
- while ((p < high) && (*wtest)((unsigned char) *p) == test)
+ while ((p < high) && (*wtest)((unsigned char) *p) == test)
p++;
/*
* vi historically deletes with cw only the word preserving the
* trailing whitespace! This is not what 'w' does..
*/
- if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
- while ((p < high) && isspace((unsigned char) *p))
+ if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
+ while ((p < high) && isspace((unsigned char) *p))
p++;
}
@@ -262,14 +262,14 @@ cv_prev_word(el, p, low, n, wtest)
* vi historically deletes with cb only the word preserving the
* leading whitespace! This is not what 'b' does..
*/
- if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
- while ((p > low) && isspace((unsigned char) *p))
+ if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
+ while ((p > low) && isspace((unsigned char) *p))
p--;
test = (*wtest)((unsigned char) *p);
- while ((p >= low) && (*wtest)((unsigned char) *p) == test)
+ while ((p >= low) && (*wtest)((unsigned char) *p) == test)
p--;
p++;
- while (isspace((unsigned char) *p))
+ while (isspace((unsigned char) *p))
p++;
}
@@ -319,7 +319,7 @@ c__number(p, num, dval)
* Finish vi delete action
*/
protected void
-cv_delfini(el)
+cv_delfini(el)
EditLine *el;
{
register int size;
@@ -331,13 +331,13 @@ cv_delfini(el)
oaction = el->el_chared.c_vcmd.action;
el->el_chared.c_vcmd.action = NOP;
- if (el->el_chared.c_vcmd.pos == 0)
+ if (el->el_chared.c_vcmd.pos == 0)
return;
if (el->el_line.cursor > el->el_chared.c_vcmd.pos) {
size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos);
- c_delbefore(el, size);
+ c_delbefore(el, size);
el->el_line.cursor = el->el_chared.c_vcmd.pos;
re_refresh_cursor(el);
}
@@ -362,7 +362,7 @@ cv_delfini(el)
abort();
break;
}
-
+
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.dsize = size;
@@ -383,7 +383,7 @@ ce__endword(p, high, n)
while (n--) {
while ((p < high) && isspace((unsigned char) *p))
p++;
- while ((p < high) && !isspace((unsigned char) *p))
+ while ((p < high) && !isspace((unsigned char) *p))
p++;
}
@@ -404,14 +404,14 @@ cv__endword(p, high, n)
p++;
while (n--) {
- while ((p < high) && isspace((unsigned char) *p))
+ while ((p < high) && isspace((unsigned char) *p))
p++;
if (isalnum((unsigned char) *p))
- while ((p < high) && isalnum((unsigned char) *p))
+ while ((p < high) && isalnum((unsigned char) *p))
p++;
else
- while ((p < high) && !(isspace((unsigned char) *p) ||
+ while ((p < high) && !(isspace((unsigned char) *p) ||
isalnum((unsigned char) *p)))
p++;
}
@@ -458,7 +458,7 @@ ch_init(el)
el->el_chared.c_macro.nline = NULL;
el->el_chared.c_macro.level = -1;
- el->el_chared.c_macro.macro = (char **) el_malloc(EL_MAXMACRO *
+ el->el_chared.c_macro.macro = (char **) el_malloc(EL_MAXMACRO *
sizeof(char *));
return 0;
}
@@ -551,7 +551,7 @@ el_deletestr(el, n)
if (n <= 0)
return;
- if (el->el_line.cursor < &el->el_line.buffer[n])
+ if (el->el_line.cursor < &el->el_line.buffer[n])
return;
c_delbefore(el, n); /* delete before dot */
@@ -575,8 +575,8 @@ c_gets(el, buf)
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
switch (ch) {
- case 0010: /* Delete and backspace */
- case 0177:
+ case '\010': /* Delete and backspace */
+ case '\177':
if (len > 1) {
*el->el_line.cursor-- = '\0';
el->el_line.lastchar = el->el_line.cursor;
@@ -592,7 +592,7 @@ c_gets(el, buf)
ch = 0;
break;
- case 0033: /* ESC */
+ case '\033': /* ESC */
case '\r': /* Newline */
case '\n':
break;
@@ -630,7 +630,7 @@ c_hpos(el)
if (el->el_line.cursor == el->el_line.buffer)
return 0;
else {
- for (ptr = el->el_line.cursor - 1;
+ for (ptr = el->el_line.cursor - 1;
ptr >= el->el_line.buffer && *ptr != '\n';
ptr--)
continue;
diff --git a/lib/libedit/chared.h b/lib/libedit/chared.h
index 20da6c8..22d07f0 100644
--- a/lib/libedit/chared.h
+++ b/lib/libedit/chared.h
@@ -54,7 +54,7 @@
* like real vi: i.e. the transition from command<->insert modes moves
* the cursor.
*
- * On the other hand we really don't want to move the cursor, because
+ * On the other hand we really don't want to move the cursor, because
* all the editing commands don't include the character under the cursor.
* Probably the best fix is to make all the editing commands aware of
* this fact.
@@ -68,7 +68,7 @@ typedef struct c_macro_t {
char *nline;
} c_macro_t;
-/*
+/*
* Undo information for both vi and emacs
*/
typedef struct c_undo_t {
@@ -139,7 +139,7 @@ protected void cv_delfini __P((EditLine *));
protected char *cv__endword __P((char *, char *, int));
protected int ce__isword __P((int));
protected void cv_undo __P((EditLine *, int, int, char *));
-protected char *cv_next_word __P((EditLine*, char *, char *, int,
+protected char *cv_next_word __P((EditLine*, char *, char *, int,
int (*)(int)));
protected char *cv_prev_word __P((EditLine*, char *, char *, int,
int (*)(int)));
diff --git a/lib/libedit/common.c b/lib/libedit/common.c
index 696da52..6908819 100644
--- a/lib/libedit/common.c
+++ b/lib/libedit/common.c
@@ -44,7 +44,7 @@ static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
#include "sys.h"
#include "el.h"
-/* ed_end_of_file():
+/* ed_end_of_file():
* Indicate end of file
* [^D]
*/
@@ -60,7 +60,7 @@ ed_end_of_file(el, c)
}
-/* ed_insert():
+/* ed_insert():
* Add character to the line
* Insert a character [bound to all insert keys]
*/
@@ -74,16 +74,16 @@ ed_insert(el, c)
if (c == '\0')
return CC_ERROR;
- if (el->el_line.lastchar + el->el_state.argument >=
+ if (el->el_line.lastchar + el->el_state.argument >=
el->el_line.limit)
return CC_ERROR; /* end of buffer space */
if (el->el_state.argument == 1) {
if (el->el_state.inputmode != MODE_INSERT) {
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
*el->el_line.cursor;
el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
- c_delafter(el, 1);
+ c_delafter(el, 1);
}
c_insert(el, 1);
@@ -95,12 +95,12 @@ ed_insert(el, c)
else {
if (el->el_state.inputmode != MODE_INSERT) {
- for(i = 0;i < el->el_state.argument; i++)
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
+ for(i = 0;i < el->el_state.argument; i++)
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
el->el_line.cursor[i];
el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
- c_delafter(el, el->el_state.argument);
+ c_delafter(el, el->el_state.argument);
}
c_insert(el, el->el_state.argument);
@@ -117,7 +117,7 @@ ed_insert(el, c)
}
-/* ed_delete_prev_word():
+/* ed_delete_prev_word():
* Delete from beginning of current word to cursor
* [M-^?] [^W]
*/
@@ -132,7 +132,7 @@ ed_delete_prev_word(el, c)
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
- cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
+ cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
el->el_state.argument, ce__isword);
for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
@@ -147,7 +147,7 @@ ed_delete_prev_word(el, c)
}
-/* ed_delete_next_char():
+/* ed_delete_next_char():
* Delete character under cursor
* [^D] [x]
*/
@@ -159,12 +159,12 @@ ed_delete_next_char(el, c)
{
#ifdef notdef /* XXX */
#define EL el->el_line
-fprintf(stderr, "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
+fprintf(stderr, "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, EL.lastchar, EL.limit, EL.limit);
#endif
if (el->el_line.cursor == el->el_line.lastchar) {/* if I'm at the end */
if (el->el_map.type == MAP_VI) {
- if (el->el_line.cursor == el->el_line.buffer) {
+ if (el->el_line.cursor == el->el_line.buffer) {
/* if I'm also at the beginning */
#ifdef KSHVI
return CC_ERROR;
@@ -196,7 +196,7 @@ fprintf(stderr, "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
}
-/* ed_kill_line():
+/* ed_kill_line():
* Cut to the end of line
* [^K] [^K]
*/
@@ -218,7 +218,7 @@ ed_kill_line(el, c)
}
-/* ed_move_to_end():
+/* ed_move_to_end():
* Move cursor to the end of line
* [^E] [^E]
*/
@@ -242,7 +242,7 @@ ed_move_to_end(el, c)
}
-/* ed_move_to_beg():
+/* ed_move_to_beg():
* Move cursor to the beginning of line
* [^A] [^A]
*/
@@ -256,7 +256,7 @@ ed_move_to_beg(el, c)
if (el->el_map.type == MAP_VI) {
/* We want FIRST non space character */
- while (isspace(*el->el_line.cursor))
+ while (isspace((unsigned char) *el->el_line.cursor))
el->el_line.cursor++;
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
@@ -268,7 +268,7 @@ ed_move_to_beg(el, c)
}
-/* ed_transpose_chars():
+/* ed_transpose_chars():
* Exchange the character to the left of the cursor with the one under it
* [^T] [^T]
*/
@@ -280,7 +280,7 @@ ed_transpose_chars(el, c)
if (el->el_line.cursor < el->el_line.lastchar) {
if (el->el_line.lastchar <= &el->el_line.buffer[1])
return CC_ERROR;
- else
+ else
el->el_line.cursor++;
}
if (el->el_line.cursor > &el->el_line.buffer[1]) {
@@ -290,12 +290,12 @@ ed_transpose_chars(el, c)
el->el_line.cursor[-1] = c;
return CC_REFRESH;
}
- else
+ else
return CC_ERROR;
}
-/* ed_next_char():
+/* ed_next_char():
* Move to the right one character
* [^F] [^F]
*/
@@ -322,7 +322,7 @@ ed_next_char(el, c)
}
-/* ed_prev_word():
+/* ed_prev_word():
* Move to the beginning of the current word
* [M-b] [b]
*/
@@ -335,8 +335,8 @@ ed_prev_word(el, c)
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
- el->el_line.cursor = c__prev_word(el->el_line.cursor, el->el_line.buffer,
- el->el_state.argument,
+ el->el_line.cursor = c__prev_word(el->el_line.cursor, el->el_line.buffer,
+ el->el_state.argument,
ce__isword);
if (el->el_map.type == MAP_VI)
@@ -349,7 +349,7 @@ ed_prev_word(el, c)
}
-/* ed_prev_char():
+/* ed_prev_char():
* Move to the left one character
* [^B] [^B]
*/
@@ -372,12 +372,12 @@ ed_prev_char(el, c)
return CC_CURSOR;
}
- else
+ else
return CC_ERROR;
}
-/* ed_quoted_insert():
+/* ed_quoted_insert():
* Add the next character typed verbatim
* [^V] [^V]
*/
@@ -400,7 +400,7 @@ ed_quoted_insert(el, c)
}
-/* ed_digit():
+/* ed_digit():
* Adds to argument or enters a digit
*/
protected el_action_t
@@ -408,17 +408,17 @@ ed_digit(el, c)
EditLine *el;
int c;
{
- if (!isdigit(c))
+ if (!isdigit((unsigned char) c))
return CC_ERROR;
- if (el->el_state.doingarg) {
+ if (el->el_state.doingarg) {
/* if doing an arg, add this in... */
- if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
+ if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
el->el_state.argument = c - '0';
else {
if (el->el_state.argument > 1000000)
return CC_ERROR;
- el->el_state.argument =
+ el->el_state.argument =
(el->el_state.argument * 10) + (c - '0');
}
return CC_ARGHACK;
@@ -428,10 +428,10 @@ ed_digit(el, c)
return CC_ERROR;
if (el->el_state.inputmode != MODE_INSERT) {
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
*el->el_line.cursor;
el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
- c_delafter(el, 1);
+ c_delafter(el, 1);
}
c_insert(el, 1);
*el->el_line.cursor++ = c;
@@ -442,7 +442,7 @@ ed_digit(el, c)
}
-/* ed_argument_digit():
+/* ed_argument_digit():
* Digit that starts argument
* For ESC-n
*/
@@ -451,7 +451,7 @@ ed_argument_digit(el, c)
EditLine *el;
register int c;
{
- if (!isdigit(c))
+ if (!isdigit((unsigned char) c))
return CC_ERROR;
if (el->el_state.doingarg) {
@@ -467,7 +467,7 @@ ed_argument_digit(el, c)
}
-/* ed_unassigned():
+/* ed_unassigned():
* Indicates unbound character
* Bound to keys that are not assigned
*/
@@ -487,7 +487,7 @@ ed_unassigned(el, c)
** TTY key handling.
**/
-/* ed_tty_sigint():
+/* ed_tty_sigint():
* Tty interrupt character
* [^C]
*/
@@ -496,12 +496,12 @@ protected el_action_t
ed_tty_sigint(el, c)
EditLine *el;
int c;
-{
+{
return CC_NORM;
}
-/* ed_tty_dsusp():
+/* ed_tty_dsusp():
* Tty delayed suspend character
* [^Y]
*/
@@ -515,7 +515,7 @@ ed_tty_dsusp(el, c)
}
-/* ed_tty_flush_output():
+/* ed_tty_flush_output():
* Tty flush output characters
* [^O]
*/
@@ -529,7 +529,7 @@ ed_tty_flush_output(el, c)
}
-/* ed_tty_sigquit():
+/* ed_tty_sigquit():
* Tty quit character
* [^\]
*/
@@ -543,7 +543,7 @@ ed_tty_sigquit(el, c)
}
-/* ed_tty_sigtstp():
+/* ed_tty_sigtstp():
* Tty suspend character
* [^Z]
*/
@@ -557,7 +557,7 @@ ed_tty_sigtstp(el, c)
}
-/* ed_tty_stop_output():
+/* ed_tty_stop_output():
* Tty disallow output characters
* [^S]
*/
@@ -571,7 +571,7 @@ ed_tty_stop_output(el, c)
}
-/* ed_tty_start_output():
+/* ed_tty_start_output():
* Tty allow output characters
* [^Q]
*/
@@ -585,7 +585,7 @@ ed_tty_start_output(el, c)
}
-/* ed_newline():
+/* ed_newline():
* Execute command
* [^J]
*/
@@ -604,7 +604,7 @@ ed_newline(el, c)
}
-/* ed_delete_prev_char():
+/* ed_delete_prev_char():
* Delete the character to the left of the cursor
* [^?]
*/
@@ -614,10 +614,10 @@ ed_delete_prev_char(el, c)
EditLine *el;
int c;
{
- if (el->el_line.cursor <= el->el_line.buffer)
+ if (el->el_line.cursor <= el->el_line.buffer)
return CC_ERROR;
- c_delbefore(el, el->el_state.argument);
+ c_delbefore(el, el->el_state.argument);
el->el_line.cursor -= el->el_state.argument;
if (el->el_line.cursor < el->el_line.buffer)
el->el_line.cursor = el->el_line.buffer;
@@ -625,7 +625,7 @@ ed_delete_prev_char(el, c)
}
-/* ed_clear_screen():
+/* ed_clear_screen():
* Clear screen leaving current line at the top
* [^L]
*/
@@ -641,7 +641,7 @@ ed_clear_screen(el, c)
}
-/* ed_redisplay():
+/* ed_redisplay():
* Redisplay everything
* ^R
*/
@@ -651,13 +651,11 @@ ed_redisplay(el, c)
EditLine *el;
int c;
{
- re_clear_lines(el);
- re_clear_display(el);
- return CC_REFRESH;
+ return CC_REDISPLAY;
}
-/* ed_start_over():
+/* ed_start_over():
* Erase current line and start from scratch
* [^G]
*/
@@ -672,7 +670,7 @@ ed_start_over(el, c)
}
-/* ed_sequence_lead_in():
+/* ed_sequence_lead_in():
* First character in a bound sequence
* Placeholder for external keys
*/
@@ -686,7 +684,7 @@ ed_sequence_lead_in(el, c)
}
-/* ed_prev_history():
+/* ed_prev_history():
* Move to the previous history line
* [^P] [k]
*/
@@ -703,7 +701,7 @@ ed_prev_history(el, c)
if (el->el_history.eventno == 0) { /* save the current buffer away */
(void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
- el->el_history.last = el->el_history.buf +
+ el->el_history.last = el->el_history.buf +
(el->el_line.lastchar - el->el_line.buffer);
}
@@ -712,7 +710,7 @@ ed_prev_history(el, c)
if (hist_get(el) == CC_ERROR) {
beep = 1;
/* el->el_history.eventno was fixed by first call */
- (void) hist_get(el);
+ (void) hist_get(el);
}
re_refresh(el);
@@ -723,7 +721,7 @@ ed_prev_history(el, c)
}
-/* ed_next_history():
+/* ed_next_history():
* Move to the next history line
* [^N] [j]
*/
@@ -747,7 +745,7 @@ ed_next_history(el, c)
}
-/* ed_search_prev_history():
+/* ed_search_prev_history():
* Search previous in history for a line matching the current
* next search history [M-P] [K]
*/
@@ -774,7 +772,7 @@ ed_search_prev_history(el, c)
if (el->el_history.eventno == 0) {
(void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
- el->el_history.last = el->el_history.buf +
+ el->el_history.last = el->el_history.buf +
(el->el_line.lastchar - el->el_line.buffer);
}
@@ -795,9 +793,9 @@ ed_search_prev_history(el, c)
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
#endif
- if ((strncmp(hp, el->el_line.buffer,
- el->el_line.lastchar - el->el_line.buffer) ||
- hp[el->el_line.lastchar-el->el_line.buffer]) &&
+ if ((strncmp(hp, el->el_line.buffer,
+ el->el_line.lastchar - el->el_line.buffer) ||
+ hp[el->el_line.lastchar-el->el_line.buffer]) &&
c_hmatch(el, hp)) {
found++;
break;
@@ -808,7 +806,7 @@ ed_search_prev_history(el, c)
if (!found) {
#ifdef SDEBUG
- (void) fprintf(el->el_errfile, "not found\n");
+ (void) fprintf(el->el_errfile, "not found\n");
#endif
return CC_ERROR;
}
@@ -819,7 +817,7 @@ ed_search_prev_history(el, c)
}
-/* ed_search_next_history():
+/* ed_search_next_history():
* Search next in history for a line matching the current
* [M-N] [J]
*/
@@ -853,9 +851,9 @@ ed_search_next_history(el, c)
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
#endif
- if ((strncmp(hp, el->el_line.buffer,
- el->el_line.lastchar - el->el_line.buffer) ||
- hp[el->el_line.lastchar-el->el_line.buffer]) &&
+ if ((strncmp(hp, el->el_line.buffer,
+ el->el_line.lastchar - el->el_line.buffer) ||
+ hp[el->el_line.lastchar-el->el_line.buffer]) &&
c_hmatch(el, hp))
found = h;
hp = HIST_NEXT(el);
@@ -864,7 +862,7 @@ ed_search_next_history(el, c)
if (!found) { /* is it the current history number? */
if (!c_hmatch(el, el->el_history.buf)) {
#ifdef SDEBUG
- (void) fprintf(el->el_errfile, "not found\n");
+ (void) fprintf(el->el_errfile, "not found\n");
#endif
return CC_ERROR;
}
@@ -888,7 +886,7 @@ ed_prev_line(el, c)
{
char *ptr;
int nchars = c_hpos(el);
-
+
/*
* Move to the line requested
*/
@@ -907,15 +905,15 @@ ed_prev_line(el, c)
*/
for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
continue;
-
+
/*
* Move to the character requested
*/
- for (ptr++;
- nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
+ for (ptr++;
+ nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
ptr++)
continue;
-
+
el->el_line.cursor = ptr;
return CC_CURSOR;
}
@@ -948,16 +946,16 @@ ed_next_line(el, c)
* Move to the character requested
*/
for (ptr++;
- nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
+ nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
ptr++)
continue;
-
+
el->el_line.cursor = ptr;
return CC_CURSOR;
}
-/* ed_command():
+/* ed_command():
* Editline extended command
* [M-X] [:]
*/
diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3
new file mode 100644
index 0000000..b2858f6
--- /dev/null
+++ b/lib/libedit/editline.3
@@ -0,0 +1,532 @@
+.\" $NetBSD: editline.3,v 1.4 1997/01/14 04:17:23 lukem Exp $
+.\"
+.\" Copyright (c) 1997 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.
+.\" 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 REGENTS OR CONTRIBUTORS BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (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 January 11, 1997
+.Os BSD 4.4
+.Dt EDITLINE 3
+.Sh NAME
+.Nm editline ,
+.Nm el_init ,
+.Nm el_end ,
+.Nm el_reset ,
+.Nm el_gets ,
+.Nm el_getc ,
+.Nm el_push ,
+.Nm el_parse ,
+.Nm el_set ,
+.Nm el_source ,
+.Nm el_resize ,
+.Nm el_line ,
+.Nm el_insertstr ,
+.Nm el_deletestr ,
+.Nm history_init ,
+.Nm history_end ,
+.Nm history
+.Nd line editor and history functions
+.Sh SYNOPSIS
+.Fd #include <histedit.h>
+.Ft EditLine *
+.Fn el_init "const char *prog" "FILE *fin" "FILE *fout"
+.Ft void
+.Fn el_end "EditLine *e"
+.Ft void
+.Fn el_reset "EditLine *e"
+.Ft const char *
+.Fn el_gets "EditLine *e" "int *count"
+.Ft int
+.Fn el_getc "EditLine *e" "char *ch"
+.Ft void
+.Fn el_push "EditLine *e" "const char *str"
+.Ft int
+.Fn el_parse "EditLine *e" "int argc" "char *argv[]"
+.Ft int
+.Fn el_set "EditLine *e" "int op" "..."
+.Ft int
+.Fn el_source "EditLine *e" "const char *file"
+.Ft void
+.Fn el_resize "EditLine *e"
+.Ft const LineInfo *
+.Fn el_line "EditLine *e"
+.Ft int
+.Fn el_insertstr "EditLine *e" "char *str"
+.Ft void
+.Fn el_deletestr "EditLine *e" "int count"
+.Ft History *
+.Fn history_init
+.Ft void
+.Fn history_end "History *h"
+.Ft HistEvent *
+.Fn history "History h" "int op" "..."
+.Sh DESCRIPTION
+The
+.Nm
+library provides generic line editing and history functions,
+similar to those found in
+.Xr sh 1 .
+.Pp
+These functions are available in the
+.Nm libedit
+library (which needs the
+.Nm libtermcap
+library).
+Programs should be linked with
+.Fl ledit ltermcap .
+.Sh LINE EDITING FUNCTIONS
+The line editing functions use a common data structure,
+.Fa EditLine ,
+which is created by
+.Fn el_init
+and freed by
+.Fn el_end .
+.Pp
+The following functions are available:
+.Bl -tag -width 4n
+.It Fn el_init
+Initialise the line editor, and return a data structure
+to be used by all other line editing functions.
+.Fa prog
+is the name of the invoking program, used when reading the
+.Xr editrc 5
+file to determine which settings to use.
+.Fa fin
+and
+.Fa fout
+are the input and output streams (respectively) to use.
+In this documentation, references to
+.Dq the tty
+are actually to this input/output stream combination.
+.It Fn el_end
+Clean up and finish with
+.Fa e ,
+assumed to have been created with
+.Fn el_init .
+.It Fn el_reset
+Reset the tty and the parser.
+This should be called after an error which may have upset the tty's
+state.
+.It Fn el_gets
+Read a line from the tty.
+.Fa count
+is modified to contain the number of characters read.
+Returns the line read if successful, or
+.Dv NULL
+if no characters were read or if an error occurred.
+.It Fn el_getc
+Read a character from the tty.
+.Fa ch
+is modified to contain the character read.
+Returns the number of characters read if successful, -1 otherwise.
+.It Fn el_push
+Pushes
+.Fa str
+back onto the input stream.
+This is used by the macro expansion mechanism.
+Refer to the description of
+.Ic bind
+.Fl s
+in
+.Xr editrc 5
+for more information.
+.It Fn el_parse
+Parses the
+.Fa argv
+array (which is
+.Fa argc
+elements in size)
+to execute builtin
+.Nm
+commands.
+If the command is prefixed with
+.Dq prog:
+then
+.Fn el_parse
+will only execute the command if
+.Dq prog
+matches the
+.Fa prog
+argument supplied to
+.Fn el_init .
+The return value is
+-1 if the command is unknown,
+0 if there was no error or
+.Dq prog
+didn't match, or
+1 if the command returned an error.
+Refer to
+.Xr editrc 5
+for more information.
+.Pp
+.Em NOTE:
+.Va argv[0]
+may be modified by
+.Fn el_parse .
+The colon between
+.Dq prog
+and the command,
+.Ar command ,
+will be replaced with a NUL
+.Po
+.Dq \e0
+.Pc .
+.It Fn el_set
+Set
+.Nm
+parameters.
+.Fa op
+determines which parameter to set, and each operation has its
+own parameter list.
+.Pp
+The following values for
+.Fa op
+are supported, along with the required argument list:
+.Bl -tag -width 4n
+.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)"
+Define prompt printing function as
+.Fa f ,
+which is to return a string that contains the prompt.
+.It Dv EL_TERMINAL , Fa "const char *type"
+Define terminal type of the tty to be
+.Fa type ,
+or to
+.Ev TERM
+if
+.Fa type
+is
+.Dv NULL .
+.It Dv EL_EDITOR , Fa "const char *mode"
+Set editing mode to
+.Fa mode ,
+which must be one of
+.Dq emacs
+or
+.Dq vi .
+.It Dv EL_SIGNAL , Fa "int flag"
+If
+.Fa flag
+is non-zero,
+.Nm
+will install its own signal handler for the following signals when
+reading command input:
+.Dv SIGCONT ,
+.Dv SIGHUP ,
+.Dv SIGINT ,
+.Dv SIGQUIT ,
+.Dv SIGSTOP ,
+.Dv SIGTERM ,
+.Dv SIGTSTP ,
+and
+.Dv SIGWINCH .
+Otherwise, the current signal handlers will be used.
+.It Dv EL_BIND , Xo
+.Fa "const char *" ,
+.Fa "..." ,
+.Dv NULL
+.Xc
+Perform the
+.Ic bind
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_ECHOTC , Xo
+.Fa "const char *" ,
+.Fa "..." ,
+.Dv NULL
+.Xc
+Perform the
+.Ic echotc
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_SETTC , Xo
+.Fa "const char *" ,
+.Fa "..." ,
+.Dv NULL
+.Xc
+Perform the
+.Ic settc
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_SETTY , Xo
+.Fa "const char *" ,
+.Fa "..." ,
+.Dv NULL
+.Xc
+Perform the
+.Ic setty
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_TELLTC , Xo
+.Fa "const char *" ,
+.Fa "..." ,
+.Dv NULL
+.Xc
+Perform the
+.Ic telltc
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_ADDFN , Xo
+.Fa "const char *name" ,
+.Fa "const char *help" ,
+.Fa "unsigned char (*func)(EditLine *e, int ch)
+.Xc
+Add a user defined function,
+.Fn func ,
+referred to as
+.Fa name
+which is invoked when a key which is bound to
+.Fa name
+is entered.
+.Fa help
+is a description of
+.Fa name .
+At invocation time,
+.Fa ch
+is the key which caused the invocation.
+The return value of
+.Fn func
+should be one of:
+.Bl -tag -width "CC_REDISPLAY"
+.It Dv CC_NORM
+Add a normal character.
+.It Dv CC_NEWLINE
+End of line was entered.
+.It Dv CC_EOF
+EOF was entered.
+.It Dv CC_ARGHACK
+Expecting further command input as arguments, do nothing visually.
+.It Dv CC_REFRESH
+Refresh display.
+.It Dv CC_CURSOR
+Cursor moved, so update and perform
+.Dv CC_REFRESH.
+.It Dv CC_REDISPLAY
+Redisplay entire input line.
+This is useful if a key binding outputs extra information.
+.It Dv CC_ERROR
+An error occurred.
+Beep, and flush tty.
+.It Dv CC_FATAL
+Fatal error, reset tty to known state.
+.El
+.It Dv EL_HIST , Xo
+.Fa "History *(*func)(History *, int op, ...)" ,
+.Fa "const char *ptr"
+.Xc
+Defines which history function to use, which is usually
+.Fn history .
+.Fa ptr
+should be the value returned by
+.Fn history_init .
+.El
+.It Fn el_source
+Initialise
+.Nm
+by reading the contents of
+.Fa file .
+.Fn el_parse
+is called for each line in
+.Fa file .
+If
+.Fa file
+is
+.Dv NULL ,
+try
+.Pa $PWD/.editrc
+then
+.Pa $HOME/.editrc .
+Refer to
+.Xr editrc 5
+for details on the format of
+.Fa file .
+.It Fn el_resize
+Must be called if the terminal size changes.
+If
+.Dv EL_SIGNAL
+has been set with
+.Fn el_set ,
+then this is done automatically.
+Otherwise, it's the responsibility of the application to call
+.Fn el_resize
+on the appropriate occasions.
+.It Fn el_line
+Return the editing information for the current line in a
+.Fa LineInfo
+structure, which is defined as follows:
+.Bd -literal
+typedef struct lineinfo {
+ const char *buffer; /* address of buffer */
+ const char *cursor; /* address of cursor */
+ const char *lastchar; /* address of last character */
+} LineInfo;
+.Ed
+.It Fn el_insertstr
+Insert
+.Fa str
+into the line at the cursor.
+Returns -1 if
+.Fa str
+is empty or won't fit, and 0 otherwise.
+.It Fn el_deletestr
+Delete
+.Fa num
+characters before the cursor.
+.El
+.Sh HISTORY LIST FUNCTIONS
+The history functions use a common data structure,
+.Fa History ,
+which is created by
+.Fn history_init
+and freed by
+.Fn history_end .
+.Pp
+The following functions are available:
+.Bl -tag -width 4n
+.It Fn history_init
+Initialise the history list, and return a data structure
+to be used by all other history list functions.
+.It Fn history_end
+Clean up and finish with
+.Fa h ,
+assumed to have been created with
+.Fn history_init .
+.It Fn history
+Perform operation
+.Fa op
+on the history list, with optional arguments as needed by the
+operation.
+The following values for
+.Fa op
+are supported, along with the required argument list:
+.Bl -tag -width 4n
+.It Dv H_EVENT , Fa "int size"
+Set size of history to
+.Fa size
+elements.
+.It Dv H_END
+Cleans up and finishes with
+.Fa h ,
+assumed to be created with
+.Fn history_init .
+.It Dv H_CLEAR
+Clear the history.
+.It Dv H_FUNC , Xo
+.Fa "void *ptr" ,
+.Fa "history_gfun_t first" ,
+.Fa "history_gfun_t next" ,
+.Fa "history_gfun_t last" ,
+.Fa "history_gfun_t prev" ,
+.Fa "history_gfun_t curr" ,
+.Fa "history_vfun_t clear" ,
+.Fa "history_efun_t enter" ,
+.Fa "history_efun_t add"
+.Xc
+Define functions to perform various history operations.
+.Fa ptr
+is the argument given to a function when it's invoked.
+.It Dv H_FIRST
+Return the first element in the history.
+.It Dv H_LAST
+Return the last element in the history.
+.It Dv H_PREV
+Return the previous element in the history.
+.It Dv H_NEXT
+Return the next element in the history.
+.It Dv H_CURR
+Return the current element in the history.
+.It Dv H_ADD , Fa "const char *str"
+Append
+.Fa str
+to the current element of the history, or create an element with
+.Dv H_ENTER
+if there isn't one.
+.It Dv H_ENTER , Fa "const char *str"
+Add
+.Fa str
+as a new element to the history, and, if necessary,
+removing the oldest entry to keep the list to the created size.
+.It Dv H_PREV_STR , Fa "const char *str"
+Return the closest previous event that starts with
+.Fa str .
+.It Dv H_NEXT_STR , Fa "const char *str"
+Return the closest next event that starts with
+.Fa str .
+.It Dv H_PREV_EVENT , Fa "int e"
+Return the previous event numbered
+.Fa e .
+.It Dv H_NEXT_EVENT , Fa "int e"
+Return the next event numbered
+.Fa e .
+.It Dv H_LOAD , Fa "const char *file"
+Load the history list stored in
+.Fa file .
+.It Dv H_SAVE , Fa "const char *file"
+Save the history list to
+.Fa file .
+.El
+.El
+.\"XXX.Sh EXAMPLES
+.\"XXX: provide some examples
+.Sh SEE ALSO
+.Xr editrc 5 ,
+.Xr sh 1 ,
+.Xr signal 3 ,
+.Xr termcap 3
+.Sh HISTORY
+The
+.Nm
+library first appeared in
+.Bx 4.4 .
+.Sh AUTHORS
+The
+.Nm
+library was written by Christos Zoulas,
+and this manual was written by Luke Mewburn.
+.Sh BUGS
+This documentation is probably incomplete.
+.Pp
+.Fn el_parse
+should not modify the supplied
+.Va argv[0] .
+.Pp
+The tokenization functions are not publically defined in
+.Fd <histedit.h>
diff --git a/lib/libedit/editrc.5 b/lib/libedit/editrc.5
new file mode 100644
index 0000000..e9b2992
--- /dev/null
+++ b/lib/libedit/editrc.5
@@ -0,0 +1,292 @@
+.\" $NetBSD: editrc.5,v 1.4 1997/04/24 20:20:31 christos Exp $
+.\"
+.\" Copyright (c) 1997 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.
+.\" 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 REGENTS OR CONTRIBUTORS BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (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 January 11, 1997
+.Os BSD 4.4
+.Dt EDITRC 5
+.Sh NAME
+.Nm editrc
+.Nd configuration file for editline library
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+file defines various settings to be used by the
+.Xr editline 3
+library.
+.Pp
+The format of each line is either:
+.Dl prog:command [arg [...]]
+or
+.Dl command [arg [...]]
+.Pp
+.Ar command
+is one of the
+.Xr editline 3
+builtin commands.
+Refer to
+.Sx BUILTIN COMMANDS
+for more information.
+.Pp
+.Ar prog
+is the program name string that a program defines when it calls
+.Xr el_init 3
+to setup
+.Xr editline 3 ,
+which is usually
+.Va argv[0] .
+.Ar command
+will be executed for any program which matches
+.Ar prog .
+.Pp
+.Ar prog
+may also be a
+.Xr regex 3
+style
+regular expression, in which case
+.Ar command
+will be executed for any program that matches the regular expression.
+.Sh BUILTIN COMMANDS
+The
+.Nm editline
+library has some builtin commands, which affect the way
+that the line editing and history functions operate.
+These are based on similar named builtins present in the
+.Xr tcsh 1
+shell.
+.Pp
+The following builtin commands are available:
+.Bl -tag -width 4n
+.It Ic bind Xo
+.Op Fl a
+.Op Fl e
+.Op Fl k
+.Op Fl l
+.Op Fl r
+.Op Fl s
+.Op Fl v
+.Op Ar key Op Ar command
+.Xc
+Without options, list all bound keys, and the editor command to which
+each is bound.
+If
+.Ar key
+is supplied, show the bindings for
+.Ar key .
+If
+.Ar key command
+is supplied, bind
+.Ar command
+to
+.Ar key .
+Options include:
+.Bl -tag -width 4n
+.It Fl e
+Bind all keys to the standard GNU Emacs-like bindings.
+.It Fl v
+Bind all keys to the standard
+.Xr vi 1 -like
+bindings.
+.It Fl a
+List or change key bindings in the
+.Xr vi 1
+mode alternate (command mode) key map.
+.It Fl k
+.Ar key
+is interpreted as a symbolic arrow key name, which may be one of
+.Sq up ,
+.Sq down ,
+.Sq left
+or
+.Sq right .
+.It Fl l
+List all editor commands and a short description of each.
+.It Fl r
+Remove a key's binding.
+.It Fl s
+.Ar command
+is taken as a literal string and treated as terminal input when
+.Ar key
+is typed.
+Bound keys in
+.Ar command
+are themselves reinterpreted, and this continues for ten levels of
+interpretation.
+.El
+.Pp
+.Ar key
+and
+.Ar command
+can contain control characters of the form
+.Sm off
+.Sq No ^ Ar character
+.Sm on
+.Po
+e.g.
+.Sq ^A
+.Pc ,
+and the following backslashed escape sequences:
+.Pp
+.Bl -tag -compact -offset indent -width 4n
+.It Ic \ea
+Bell
+.It Ic \eb
+Backspace
+.It Ic \ee
+Escape
+.It Ic \ef
+Formfeed
+.It Ic \en
+Newline
+.It Ic \er
+Carriage return
+.It Ic \et
+Horizontal tab
+.It Ic \ev
+Vertical tab
+.Sm off
+.It Sy \e Ar nnn
+.Sm on
+The ASCII character corresponding to the octal number
+.Ar nnn .
+.El
+.Pp
+.Sq \e
+nullifies the special meaning of the following character,
+if it has any, notably
+.Sq \e
+and
+.Sq ^ .
+.It Ic echotc Xo
+.Op Fl sv
+.Ar arg
+.Ar ...
+.Xc
+Exercise terminal capabilities given in
+.Ar arg Ar ... .
+If
+.Ar arg
+is
+.Sq baud ,
+.Sq cols ,
+.Sq lines ,
+.Sq rows ,
+.Sq meta or
+.Sq tabs ,
+the value of that capability is printed, with
+.Dq yes
+or
+.Dq no
+indicating that the terminal does or does not have that capability.
+.Pp
+.Fl s
+returns an emptry string for non-existant capabilities, rather than
+causing an error.
+.Fl v
+causes messages to be verbose.
+.It Ic history
+List the history.
+.It Ic telltc
+List the values of all the terminal capabilities (see
+.Xr termcap 5 ).
+.It Ic settc Ar cap Ar val
+Set the terminal capability
+.Ar cap
+to
+.Ar val ,
+as defined in
+.Xr termcap 5 .
+No sanity checking is done.
+.It Ic setty Xo
+.Op Fl a
+.Op Fl d
+.Op Fl q
+.Op Fl x
+.Op Ar +mode
+.Op Ar -mode
+.Op Ar mode
+.Xc
+Control which tty modes that
+.Nm
+won't allow the user to change.
+.Fl d ,
+.Fl q
+or
+.Fl x
+tells
+.Ic setty
+to act on the
+.Sq edit ,
+.Sq quote
+or
+.Sq execute
+set of tty modes respectively; defaulting to
+.Fl x .
+.Pp
+Without other arguments,
+.Ic setty
+lists the modes in the chosen set which are fixed on
+.Po
+.Sq +mode
+.Pc
+or off
+.Po
+.Sq -mode
+.Pc .
+.Fl a
+lists all tty modes in the chosen set regardless of the setting.
+With
+.Ar +mode ,
+.Ar -mode
+or
+.Ar mode ,
+fixes
+.Ar mode
+on or off or removes control of
+.Ar mode
+in the chosen set.
+.El
+.Sh SEE ALSO
+.Xr editline 3 ,
+.Xr regex 3 ,
+.Xr termcap 5
+.Sh AUTHORS
+The
+.Nm editline
+library was written by Christos Zoulas,
+and this manual was written by Luke Mewburn,
+with some sections inspired by
+.Xr tcsh 1 .
diff --git a/lib/libedit/el.c b/lib/libedit/el.c
index 7314477..f163ec8 100644
--- a/lib/libedit/el.c
+++ b/lib/libedit/el.c
@@ -86,7 +86,7 @@ el_init(prog, fin, fout)
return NULL;
}
}
- else
+ else
#endif
el->el_errfile = stderr;
@@ -132,7 +132,7 @@ el_end(el)
el_free((ptr_t) el->el_prog);
el_free((ptr_t) el);
-} /* end el_end */
+} /* end el_end */
/* el_reset():
@@ -170,7 +170,7 @@ el_set(va_alist)
el = va_arg(va, EditLine *);
op = va_arg(va, int);
#endif
-
+
switch (op) {
case EL_PROMPT:
rv = prompt_set(el, va_arg(va, el_pfunc_t));
@@ -237,7 +237,7 @@ el_set(va_alist)
}
}
break;
-
+
case EL_ADDFN:
{
char *name = va_arg(va, char *);
@@ -291,23 +291,26 @@ el_source(el, fname)
if (fname == NULL) {
fname = &elpath[1];
if ((fp = fopen(fname, "r")) == NULL) {
- if ((ptr = getenv("HOME")) == NULL)
+ if ((ptr = getenv("HOME")) == NULL)
return -1;
- fname = strncpy(path, ptr, MAXPATHLEN);
- (void) strncat(path, elpath, MAXPATHLEN);
- path[MAXPATHLEN-1] = '\0';
+ (void)snprintf(path, sizeof(path), "%s%s", ptr, elpath);
+ fname = path;
}
}
- if ((fp = fopen(fname, "r")) == NULL)
+ if ((fp = fopen(fname, "r")) == NULL)
return -1;
- while ((ptr = fgetln(fp, &len)) != NULL)
- ptr[len - 1] = '\0';
+ while ((ptr = fgetln(fp, &len)) != NULL) {
+ if (ptr[len - 1] == '\n')
+ --len;
+ ptr[len] = '\0';
+
if (parse_line(el, ptr) == -1) {
(void) fclose(fp);
return -1;
}
+ }
(void) fclose(fp);
return 0;
diff --git a/lib/libedit/emacs.c b/lib/libedit/emacs.c
index f960a54..d84c360 100644
--- a/lib/libedit/emacs.c
+++ b/lib/libedit/emacs.c
@@ -38,7 +38,7 @@
static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
-/*
+/*
* emacs.c: Emacs functions
*/
#include "sys.h"
@@ -55,20 +55,16 @@ em_delete_or_list(el, c)
int c;
{
if (el->el_line.cursor == el->el_line.lastchar) { /* if I'm at the end */
-#ifdef notyet
if (el->el_line.cursor == el->el_line.buffer) { /* and the beginning */
-#endif
term_overwrite(el, STReof, 4);/* then do a EOF */
term__flush();
return CC_EOF;
-#ifdef notyet
}
else {
- re_goto_bottom(el);
- *el->el_line.lastchar = '\0'; /* just in case */
- return CC_LIST_CHOICES;
+ /* Here we could list completions, but it is an error right now */
+ term_beep(el);
+ return CC_ERROR;
}
-#endif
}
else {
c_delafter(el, el->el_state.argument); /* delete after dot */
@@ -94,7 +90,7 @@ em_delete_next_word(el, c)
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
- cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+ cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
@@ -124,8 +120,8 @@ em_yank(el, c)
if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
return CC_ERROR;
- if (el->el_line.lastchar +
- (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
+ if (el->el_line.lastchar +
+ (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
el->el_line.limit)
return CC_ERROR;
@@ -133,13 +129,13 @@ em_yank(el, c)
cp = el->el_line.cursor;
/* open the space, */
- c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
+ c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
/* copy the chars */
- for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
+ for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
*cp++ = *kp;
/* if an arg, cursor at beginning else cursor at end */
- if (el->el_state.argument == 1)
+ if (el->el_state.argument == 1)
el->el_line.cursor = cp;
return CC_REFRESH;
@@ -255,7 +251,7 @@ em_gosmacs_traspose(el, c)
el->el_line.cursor[-1] = c;
return CC_REFRESH;
}
- else
+ else
return CC_ERROR;
}
@@ -273,11 +269,11 @@ em_next_word(el, c)
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
- el->el_line.cursor = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+ el->el_line.cursor = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument,
ce__isword);
- if (el->el_map.type == MAP_VI)
+ if (el->el_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
@@ -298,12 +294,12 @@ em_upper_case(el, c)
{
char *cp, *ep;
- ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+ ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++)
- if (islower(*cp))
- *cp = toupper(*cp);
+ if (islower((unsigned char)*cp))
+ *cp = toupper((unsigned char)*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
@@ -324,20 +320,20 @@ em_capitol_case(el, c)
{
char *cp, *ep;
- ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+ ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++) {
- if (isalpha(*cp)) {
- if (islower(*cp))
- *cp = toupper(*cp);
+ if (isalpha((unsigned char)*cp)) {
+ if (islower((unsigned char)*cp))
+ *cp = toupper((unsigned char)*cp);
cp++;
break;
}
}
for (; cp < ep; cp++)
- if (isupper(*cp))
- *cp = tolower(*cp);
+ if (isupper((unsigned char)*cp))
+ *cp = tolower((unsigned char)*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
@@ -357,12 +353,12 @@ em_lower_case(el, c)
{
char *cp, *ep;
- ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+ ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++)
- if (isupper(*cp))
- *cp = tolower(*cp);
+ if (isupper((unsigned char)*cp))
+ *cp = tolower((unsigned char)*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
@@ -387,7 +383,7 @@ em_set_mark(el, c)
/* em_exchange_mark():
- * Exchange the cursor and mark
+ * Exchange the cursor and mark
* [^X^X]
*/
protected el_action_t
@@ -431,7 +427,7 @@ em_meta_next(el, c)
EditLine *el;
int c;
{
- el->el_state.metanext = 1;
+ el->el_state.metanext = 1;
return CC_ARGHACK;
}
@@ -445,7 +441,7 @@ em_toggle_overwrite(el, c)
EditLine *el;
int c;
{
- el->el_state.inputmode =
+ el->el_state.inputmode =
(el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT;
return CC_NORM;
}
@@ -467,8 +463,8 @@ em_copy_prev_word(el, c)
oldc = el->el_line.cursor;
/* does a bounds check */
- cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
- el->el_state.argument, ce__isword);
+ cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
+ el->el_state.argument, ce__isword);
c_insert(el, oldc - cp);
for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
diff --git a/lib/libedit/hist.c b/lib/libedit/hist.c
index 394df63..27dacd1 100644
--- a/lib/libedit/hist.c
+++ b/lib/libedit/hist.c
@@ -101,7 +101,7 @@ hist_get(el)
if (el->el_history.eventno == 0) { /* if really the current line */
(void) strncpy(el->el_line.buffer, el->el_history.buf, EL_BUFSIZ);
- el->el_line.lastchar = el->el_line.buffer +
+ el->el_line.lastchar = el->el_line.buffer +
(el->el_history.last - el->el_history.buf);
#ifdef KSHVI
diff --git a/lib/libedit/hist.h b/lib/libedit/hist.h
index 90c0569..3f0fb9e 100644
--- a/lib/libedit/hist.h
+++ b/lib/libedit/hist.h
@@ -65,6 +65,8 @@ typedef struct el_history_t {
#define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL)
#define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL)
#define HIST_EVENT(el, num) HIST_FUN(el, H_EVENT, num)
+#define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname)
+#define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname)
protected int hist_init __P((EditLine *));
protected void hist_end __P((EditLine *));
diff --git a/lib/libedit/history.c b/lib/libedit/history.c
index e866548..ac9c3a9 100644
--- a/lib/libedit/history.c
+++ b/lib/libedit/history.c
@@ -51,10 +51,13 @@ static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
#include <varargs.h>
#endif
+static const char hist_cookie[] = "_HiStOrY_V1_\n";
+
#include "histedit.h"
typedef const HistEvent * (*history_gfun_t) __P((ptr_t));
typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *));
+typedef void (*history_vfun_t) __P((ptr_t));
struct history {
ptr_t h_ref; /* Argument for history fcns */
@@ -63,6 +66,7 @@ struct history {
history_gfun_t h_last; /* Get the last element */
history_gfun_t h_prev; /* Get the previous element */
history_gfun_t h_curr; /* Get the current element */
+ history_vfun_t h_clear; /* Clear the history list */
history_efun_t h_enter; /* Add an element */
history_efun_t h_add; /* Append to an element */
};
@@ -72,6 +76,7 @@ struct history {
#define HPREV(h) (*(h)->h_prev)((h)->h_ref)
#define HLAST(h) (*(h)->h_last)((h)->h_ref)
#define HCURR(h) (*(h)->h_curr)((h)->h_ref)
+#define HCLEAR(h) (*(h)->h_clear)((h)->h_ref)
#define HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str)
#define HADD(h, str) (*(h)->h_add)((h)->h_ref, str)
@@ -80,13 +85,9 @@ struct history {
private int history_set_num __P((History *, int));
-private int history_set_fun __P((History *, history_gfun_t,
- history_gfun_t,
- history_gfun_t,
- history_gfun_t,
- history_gfun_t,
- history_efun_t,
- history_efun_t, ptr_t));
+private int history_set_fun __P((History *, History *));
+private int history_load __P((History *, const char *));
+private int history_save __P((History *, const char *));
private const HistEvent *history_prev_event __P((History *, int));
private const HistEvent *history_next_event __P((History *, int));
private const HistEvent *history_next_string __P((History *, const char *));
@@ -120,7 +121,7 @@ private const HistEvent *history_def_curr __P((ptr_t));
private const HistEvent *history_def_enter __P((ptr_t, const char *));
private const HistEvent *history_def_add __P((ptr_t, const char *));
private void history_def_init __P((ptr_t *, int));
-private void history_def_end __P((ptr_t));
+private void history_def_clear __P((ptr_t));
private const HistEvent *history_def_insert __P((history_t *, const char *));
private void history_def_delete __P((history_t *, hentry_t *));
@@ -130,7 +131,7 @@ private void history_def_delete __P((history_t *, hentry_t *));
/* history_def_first():
* Default function to return the first event in the history.
*/
-private const HistEvent *
+private const HistEvent *
history_def_first(p)
ptr_t p;
{
@@ -145,7 +146,7 @@ history_def_first(p)
/* history_def_last():
* Default function to return the last event in the history.
*/
-private const HistEvent *
+private const HistEvent *
history_def_last(p)
ptr_t p;
{
@@ -160,7 +161,7 @@ history_def_last(p)
/* history_def_next():
* Default function to return the next event in the history.
*/
-private const HistEvent *
+private const HistEvent *
history_def_next(p)
ptr_t p;
{
@@ -181,7 +182,7 @@ history_def_next(p)
/* history_def_prev():
* Default function to return the previous event in the history.
*/
-private const HistEvent *
+private const HistEvent *
history_def_prev(p)
ptr_t p;
{
@@ -202,7 +203,7 @@ history_def_prev(p)
/* history_def_curr():
* Default function to return the current event in the history.
*/
-private const HistEvent *
+private const HistEvent *
history_def_curr(p)
ptr_t p;
{
@@ -231,8 +232,8 @@ history_def_add(p, str)
return (history_def_enter(p, str));
len = strlen(h->cursor->ev.str) + strlen(str) + 1;
s = (char *) h_malloc(len);
- (void) strcpy(s, h->cursor->ev.str);
- (void) strcat(s, str);
+ (void)strcpy(s, h->cursor->ev.str); /* XXX strcpy is safe */
+ (void)strcat(s, str); /* XXX strcat is safe */
h_free((ptr_t) h->cursor->ev.str);
h->cursor->ev.str = s;
return &h->cursor->ev;
@@ -296,7 +297,7 @@ history_def_enter(p, str)
* Always keep at least one entry.
* This way we don't have to check for the empty list.
*/
- while (h->cur > h->max + 1)
+ while (h->cur > h->max + 1)
history_def_delete(h, h->list.prev);
return ev;
}
@@ -324,17 +325,19 @@ history_def_init(p, n)
}
-/* history_def_end():
+/* history_def_clear():
* Default history cleanup function
*/
private void
-history_def_end(p)
+history_def_clear(p)
ptr_t p;
{
history_t *h = (history_t *) p;
while (h->list.prev != &h->list)
history_def_delete(h, h->list.prev);
+ h->eventno = 0;
+ h->cur = 0;
}
/************************************************************************/
@@ -354,6 +357,7 @@ history_init()
h->h_last = history_def_last;
h->h_prev = history_def_prev;
h->h_curr = history_def_curr;
+ h->h_clear = history_def_clear;
h->h_enter = history_def_enter;
h->h_add = history_def_add;
@@ -369,7 +373,7 @@ history_end(h)
History *h;
{
if (h->h_next == history_def_next)
- history_def_end(h->h_ref);
+ history_def_clear(h->h_ref);
}
@@ -393,16 +397,13 @@ history_set_num(h, num)
* Set history functions
*/
private int
-history_set_fun(h, first, next, last, prev, curr, enter, add, ptr)
- History *h;
- history_gfun_t first, next, last, prev, curr;
- history_efun_t enter, add;
- ptr_t ptr;
+history_set_fun(h, nh)
+ History *h, *nh;
{
- if (first == NULL || next == NULL ||
- last == NULL || prev == NULL || curr == NULL ||
- enter == NULL || add == NULL ||
- ptr == NULL ) {
+ if (nh->h_first == NULL || nh->h_next == NULL ||
+ nh->h_last == NULL || nh->h_prev == NULL || nh->h_curr == NULL ||
+ nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
+ nh->h_ref == NULL) {
if (h->h_next != history_def_next) {
history_def_init(&h->h_ref, 0);
h->h_first = history_def_first;
@@ -410,6 +411,7 @@ history_set_fun(h, first, next, last, prev, curr, enter, add, ptr)
h->h_last = history_def_last;
h->h_prev = history_def_prev;
h->h_curr = history_def_curr;
+ h->h_clear = history_def_clear;
h->h_enter = history_def_enter;
h->h_add = history_def_add;
}
@@ -417,16 +419,78 @@ history_set_fun(h, first, next, last, prev, curr, enter, add, ptr)
}
if (h->h_next == history_def_next)
- history_def_end(h->h_ref);
-
- h->h_next = next;
- h->h_first = first;
- h->h_enter = enter;
- h->h_add = add;
+ history_def_clear(h->h_ref);
+
+ h->h_first = nh->h_first;
+ h->h_next = nh->h_next;
+ h->h_last = nh->h_last;
+ h->h_prev = nh->h_prev;
+ h->h_curr = nh->h_curr;
+ h->h_clear = nh->h_clear;
+ h->h_enter = nh->h_enter;
+ h->h_add = nh->h_add;
return 0;
}
+/* history_load():
+ * History load function
+ */
+private int
+history_load(h, fname)
+ History *h;
+ const char *fname;
+{
+ FILE *fp;
+ char *line;
+ size_t sz;
+ int i = -1;
+
+ if ((fp = fopen(fname, "r")) == NULL)
+ return i;
+
+ if ((line = fgetln(fp, &sz)) == NULL)
+ goto done;
+
+ if (strncmp(line, hist_cookie, sz) != 0)
+ goto done;
+
+ for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
+ char c = line[sz];
+ line[sz] = '\0';
+ HENTER(h, line);
+ line[sz] = c;
+ }
+
+done:
+ (void) fclose(fp);
+ return i;
+}
+
+
+/* history_save():
+ * History save function
+ */
+private int
+history_save(h, fname)
+ History *h;
+ const char *fname;
+{
+ FILE *fp;
+ const HistEvent *ev;
+ int i = 0;
+
+ if ((fp = fopen(fname, "w")) == NULL)
+ return -1;
+
+ (void) fputs(hist_cookie, fp);
+ for (ev = HLAST(h); ev != NULL; ev = HPREV(h), i++)
+ (void) fprintf(fp, "%s", ev->str);
+ (void) fclose(fp);
+ return i;
+}
+
+
/* history_prev_event():
* Find the previous event, with number given
*/
@@ -509,12 +573,12 @@ history(va_alist)
va_list va;
const HistEvent *ev = NULL;
const char *str;
- static const HistEvent sev = { 0, "" };
+ static HistEvent sev = { 0, "" };
#if __STDC__
va_start(va, fun);
#else
- History *h;
+ History *h;
int fun;
va_start(va);
h = va_arg(va, History *);
@@ -552,6 +616,20 @@ history(va_alist)
ev = HCURR(h);
break;
+ case H_CLEAR:
+ HCLEAR(h);
+ break;
+
+ case H_LOAD:
+ sev.num = history_load(h, va_arg(va, const char *));
+ ev = &sev;
+ break;
+
+ case H_SAVE:
+ sev.num = history_save(h, va_arg(va, const char *));
+ ev = &sev;
+ break;
+
case H_PREV_EVENT:
ev = history_prev_event(h, va_arg(va, int));
break;
@@ -569,24 +647,29 @@ history(va_alist)
break;
case H_EVENT:
- if (history_set_num(h, va_arg(va, int)) == 0)
+ if (history_set_num(h, va_arg(va, int)) == 0) {
+ sev.num = -1;
ev = &sev;
+ }
break;
case H_FUNC:
{
- history_gfun_t first = va_arg(va, history_gfun_t);
- history_gfun_t next = va_arg(va, history_gfun_t);
- history_gfun_t last = va_arg(va, history_gfun_t);
- history_gfun_t prev = va_arg(va, history_gfun_t);
- history_gfun_t curr = va_arg(va, history_gfun_t);
- history_efun_t enter = va_arg(va, history_efun_t);
- history_efun_t add = va_arg(va, history_efun_t);
- ptr_t ptr = va_arg(va, ptr_t);
-
- if (history_set_fun(h, first, next, last, prev,
- curr, enter, add, ptr) == 0)
+ History hf;
+ hf.h_ref = va_arg(va, ptr_t);
+ hf.h_first = va_arg(va, history_gfun_t);
+ hf.h_next = va_arg(va, history_gfun_t);
+ hf.h_last = va_arg(va, history_gfun_t);
+ hf.h_prev = va_arg(va, history_gfun_t);
+ hf.h_curr = va_arg(va, history_gfun_t);
+ hf.h_clear = va_arg(va, history_vfun_t);
+ hf.h_enter = va_arg(va, history_efun_t);
+ hf.h_add = va_arg(va, history_efun_t);
+
+ if (history_set_fun(h, &hf) == 0) {
+ sev.num = -1;
ev = &sev;
+ }
}
break;
diff --git a/lib/libedit/key.c b/lib/libedit/key.c
index 058da0e..3da65d5 100644
--- a/lib/libedit/key.c
+++ b/lib/libedit/key.c
@@ -42,10 +42,10 @@ static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93";
* key.c: This module contains the procedures for maintaining
* the extended-key map.
*
- * An extended-key (key) is a sequence of keystrokes introduced
- * with an sequence introducer and consisting of an arbitrary
- * number of characters. This module maintains a map (the el->el_key.map)
- * to convert these extended-key sequences into input strs
+ * An extended-key (key) is a sequence of keystrokes introduced
+ * with an sequence introducer and consisting of an arbitrary
+ * number of characters. This module maintains a map (the el->el_key.map)
+ * to convert these extended-key sequences into input strs
* (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE).
*
* Warning:
@@ -65,8 +65,8 @@ static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93";
#include "el.h"
-/*
- * The Nodes of the el->el_key.map. The el->el_key.map is a linked list
+/*
+ * The Nodes of the el->el_key.map. The el->el_key.map is a linked list
* of these node elements
*/
struct key_node_t {
@@ -78,9 +78,9 @@ struct key_node_t {
struct key_node_t *sibling; /* ptr to another key with same prefix */
};
-private int node_trav __P((EditLine *, key_node_t *, char *,
+private int node_trav __P((EditLine *, key_node_t *, char *,
key_value_t *));
-private int node__try __P((key_node_t *, char *,
+private int node__try __P((key_node_t *, char *,
key_value_t *, int));
private key_node_t *node__get __P((int));
private void node__put __P((key_node_t *));
@@ -104,7 +104,7 @@ key_init(el)
el->el_key.map = NULL;
key_reset(el);
return 0;
-}
+}
/* key_end():
@@ -118,7 +118,7 @@ key_end(el)
el->el_key.buf = NULL;
/* XXX: provide a function to clear the keys */
el->el_key.map = NULL;
-}
+}
/* key_map_cmd():
@@ -167,7 +167,7 @@ key_reset(el)
* Looks up *ch in map and then reads characters until a
* complete match is found or a mismatch occurs. Returns the
* type of the match found (XK_STR, XK_CMD, or XK_EXE).
- * Returns NULL in val.str and XK_STR for no match.
+ * Returns NULL in val.str and XK_STR for no match.
* The last character read is returned in *ch.
*/
protected int
@@ -195,7 +195,7 @@ key_add(el, key, val, ntype)
int ntype;
{
if (key[0] == '\0') {
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"key_add: Null extended-key not allowed.\n");
return;
}
@@ -211,7 +211,7 @@ key_add(el, key, val, ntype)
el->el_key.map = node__get(key[0]); /* it is properly initialized */
/* Now recurse through el->el_key.map */
- (void) node__try(el->el_key.map, key, val, ntype);
+ (void) node__try(el->el_key.map, key, val, ntype);
return;
}
@@ -226,9 +226,9 @@ key_clear(el, map, in)
char *in;
{
if ((map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN) &&
- ((map == el->el_map.key &&
+ ((map == el->el_map.key &&
el->el_map.alt[(unsigned char) *in] != ED_SEQUENCE_LEAD_IN) ||
- (map == el->el_map.alt &&
+ (map == el->el_map.alt &&
el->el_map.key[(unsigned char) *in] != ED_SEQUENCE_LEAD_IN)))
(void) key_delete(el, in);
}
@@ -244,7 +244,7 @@ key_delete(el, key)
char *key;
{
if (key[0] == '\0') {
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"key_delete: Null extended-key not allowed.\n");
return -1;
}
@@ -515,7 +515,7 @@ node_lookup(el, str, ptr, cnt)
/* If match put this char into el->el_key.buf. Recurse */
if (ptr->ch == *str) {
/* match found */
- ncnt = key__decode_char(el->el_key.buf, cnt,
+ ncnt = key__decode_char(el->el_key.buf, cnt,
(unsigned char) ptr->ch);
if (ptr->next != NULL)
/* not yet at leaf */
@@ -557,7 +557,7 @@ node_enum(el, ptr, cnt)
if (cnt >= KEY_BUFSIZ - 5) { /* buffer too small */
el->el_key.buf[++cnt] = '"';
el->el_key.buf[++cnt] = '\0';
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"Some extended keys too long for internal print buffer");
(void) fprintf(el->el_errfile, " \"%s...\"\n", el->el_key.buf);
return 0;
@@ -607,18 +607,18 @@ key_kprint(el, key, val, ntype)
switch (ntype) {
case XK_STR:
case XK_EXE:
- (void) fprintf(el->el_errfile, fmt, key,
- key__decode_str(val->str, unparsbuf,
+ (void) fprintf(el->el_errfile, fmt, key,
+ key__decode_str(val->str, unparsbuf,
ntype == XK_STR ? "\"\"" : "[]"));
break;
case XK_CMD:
- for (fp = el->el_map.help; fp->name; fp++)
+ for (fp = el->el_map.help; fp->name; fp++)
if (val->cmd == fp->func) {
(void) fprintf(el->el_errfile, fmt, key, fp->name);
break;
}
#ifdef DEBUG_KEY
- if (fp->name == NULL)
+ if (fp->name == NULL)
(void) fprintf(el->el_errfile, "BUG! Command not found.\n");
#endif
@@ -640,6 +640,8 @@ key__decode_char(buf, cnt, ch)
char *buf;
int cnt, ch;
{
+ ch = (unsigned char)ch;
+
if (ch == 0) {
buf[cnt++] = '^';
buf[cnt] = '@';
@@ -648,10 +650,10 @@ key__decode_char(buf, cnt, ch)
if (iscntrl(ch)) {
buf[cnt++] = '^';
- if (ch == '\177')
+ if (ch == 0177)
buf[cnt] = '?';
else
- buf[cnt] = ch | 0100;
+ buf[cnt] = toascii(ch) | 0100;
}
else if (ch == '^') {
buf[cnt++] = '\\';
@@ -702,13 +704,13 @@ key__decode_str(str, buf, sep)
if (*p == '\177')
*b++ = '?';
else
- *b++ = *p | 0100;
+ *b++ = toascii(*p) | 0100;
}
else if (*p == '^' || *p == '\\') {
*b++ = '\\';
*b++ = *p;
}
- else if (*p == ' ' || (isprint((unsigned char) *p) &&
+ else if (*p == ' ' || (isprint((unsigned char) *p) &&
!isspace((unsigned char) *p))) {
*b++ = *p;
}
diff --git a/lib/libedit/key.h b/lib/libedit/key.h
index 2ed3afc..eed0818 100644
--- a/lib/libedit/key.h
+++ b/lib/libedit/key.h
@@ -65,7 +65,7 @@ protected void key_end __P((EditLine *));
protected key_value_t * key_map_cmd __P((EditLine *, int));
protected key_value_t * key_map_str __P((EditLine *, char *));
protected void key_reset __P((EditLine *));
-protected int key_get __P((EditLine *, char *,
+protected int key_get __P((EditLine *, char *,
key_value_t *));
protected void key_add __P((EditLine *, char *, key_value_t *,
int));
@@ -73,7 +73,7 @@ protected void key_clear __P((EditLine *, el_action_t *,
char *));
protected int key_delete __P((EditLine *, char *));
protected void key_print __P((EditLine *, char *));
-protected void key_kprint __P((EditLine *, char *,
+protected void key_kprint __P((EditLine *, char *,
key_value_t *, int));
protected char *key__decode_str __P((char *, char *, char *));
diff --git a/lib/libedit/map.c b/lib/libedit/map.c
index 3378217..3b282cc 100644
--- a/lib/libedit/map.c
+++ b/lib/libedit/map.c
@@ -39,7 +39,7 @@ static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
- * map.c: Editor function definitions
+ * map.c: Editor function definitions
*/
#include "sys.h"
#include <stdlib.h>
@@ -660,8 +660,8 @@ private el_action_t el_map_vi_command[] = {
/* 41 */ ED_UNASSIGNED, /* ) */
/* 42 */ ED_UNASSIGNED, /* * */
/* 43 */ ED_NEXT_HISTORY, /* + */
- /* 44 */ VI_REPEAT_PREV_CHAR, /* , */
- /* 45 */ ED_PREV_HISTORY, /* - */
+ /* 44 */ VI_REPEAT_PREV_CHAR, /* , */
+ /* 45 */ ED_PREV_HISTORY, /* - */
/* 46 */ ED_UNASSIGNED, /* . */
/* 47 */ VI_SEARCH_PREV, /* / */
/* 48 */ VI_ZERO, /* 0 */
@@ -882,7 +882,7 @@ protected int
map_init(el)
EditLine *el;
{
-
+
/*
* Make sure those are correct before starting.
*/
@@ -902,7 +902,7 @@ map_init(el)
el->el_map.vii = el_map_vi_insert;
el->el_map.help = (el_bindings_t *) el_malloc(sizeof(el_bindings_t) *
EL_NUM_FCNS);
- (void) memcpy(el->el_map.help, help__get(),
+ (void) memcpy(el->el_map.help, help__get(),
sizeof(el_bindings_t) * EL_NUM_FCNS);
el->el_map.func = (el_func_t *) el_malloc(sizeof(el_func_t) * EL_NUM_FCNS);
memcpy(el->el_map.func, func__get(), sizeof(el_func_t) * EL_NUM_FCNS);
@@ -948,8 +948,8 @@ map_init_nls(el)
int i;
el_action_t *map = el->el_map.key;
- for (i = 0200; i <= 0377; i++)
- if (isprint(i))
+ for (i = 0200; i <= 0377; i++)
+ if (isprint(i))
map[i] = ED_INSERT;
}
@@ -977,12 +977,12 @@ map_init_meta(el)
if (el->el_map.type == MAP_VI)
map = alt;
}
- else
+ else
map = alt;
}
buf[0] = (char) i;
buf[2] = 0;
- for (i = 0200; i <= 0377; i++)
+ for (i = 0200; i <= 0377; i++)
switch (map[i]) {
case ED_INSERT:
case ED_UNASSIGNED:
@@ -1061,17 +1061,17 @@ map_init_emacs(el)
map_init_nls(el);
buf[0] = CONTROL('X');
- buf[2] = 0;
buf[1] = CONTROL('X');
+ buf[2] = 0;
key_add(el, buf, key_map_cmd(el, EM_EXCHANGE_MARK), XK_CMD);
-
+
tty_bind_char(el, 1);
term_bind_arrow(el);
}
/* map_set_editor():
- * Set the editor
+ * Set the editor
*/
protected int
map_set_editor(el, editor)
@@ -1106,12 +1106,12 @@ map_print_key(el, map, in)
(void) key__decode_str(in, outbuf, "");
for (bp = el->el_map.help; bp->name != NULL; bp++)
if (bp->func == map[(unsigned char) *in]) {
- (void) fprintf(el->el_outfile,
+ (void) fprintf(el->el_outfile,
"%s\t->\t%s\n", outbuf, bp->name);
return;
}
}
- else
+ else
key_print(el, in);
}
@@ -1144,13 +1144,13 @@ map_print_some_keys(el, map, first, last)
if (bp->func == map[first]) {
if (first == last) {
(void) fprintf(el->el_outfile, "%-15s-> %s\n",
- key__decode_str(firstbuf, unparsbuf, STRQQ),
+ key__decode_str(firstbuf, unparsbuf, STRQQ),
bp->name);
}
else {
(void) fprintf(el->el_outfile, "%-4s to %-7s-> %s\n",
key__decode_str(firstbuf, unparsbuf, STRQQ),
- key__decode_str(lastbuf, extrabuf, STRQQ),
+ key__decode_str(lastbuf, extrabuf, STRQQ),
bp->name);
}
return;
@@ -1160,13 +1160,13 @@ map_print_some_keys(el, map, first, last)
if (map == el->el_map.key) {
(void) fprintf(el->el_outfile, "BUG!!! %s isn't bound to anything.\n",
key__decode_str(firstbuf, unparsbuf, STRQQ));
- (void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n",
+ (void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n",
first, el->el_map.key[first]);
}
else {
(void) fprintf(el->el_outfile, "BUG!!! %s isn't bound to anything.\n",
key__decode_str(firstbuf, unparsbuf, STRQQ));
- (void) fprintf(el->el_outfile, "el->el_map.alt[%d] == %d\n",
+ (void) fprintf(el->el_outfile, "el->el_map.alt[%d] == %d\n",
first, el->el_map.alt[first]);
}
#endif
@@ -1268,8 +1268,8 @@ map_bind(el, argc, argv)
return 0;
case 'l':
- for (bp = el->el_map.help; bp->name != NULL; bp++)
- (void) fprintf(el->el_outfile, "%s\n\t%s\n",
+ for (bp = el->el_map.help; bp->name != NULL; bp++)
+ (void) fprintf(el->el_outfile, "%s\n\t%s\n",
bp->name, bp->description);
return 0;
default:
@@ -1298,11 +1298,11 @@ map_bind(el, argc, argv)
(void) term_clear_arrow(el, in);
return -1;
}
- if (in[1])
+ if (in[1])
(void) key_delete(el, in);
- else if (map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN)
+ else if (map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN)
(void) key_delete(el, in);
- else
+ else
map[(unsigned char) *in] = ED_UNASSIGNED;
return 0;
}
@@ -1326,7 +1326,7 @@ map_bind(el, argc, argv)
case XK_STR:
case XK_EXE:
if ((out = parse__string(outbuf, argv[argc])) == NULL) {
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"%s: Invalid \\ or ^ in outstring.\n", argv[0]);
return -1;
}
@@ -1339,7 +1339,7 @@ map_bind(el, argc, argv)
case XK_CMD:
if ((cmd = parse_cmd(el, argv[argc])) == -1) {
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"%s: Invalid command `%s'.\n", argv[0], argv[argc]);
return -1;
}
@@ -1379,7 +1379,7 @@ map_addfunc(el, name, help, func)
if (name == NULL || help == NULL || func == NULL)
return -1;
- el->el_map.func = (el_func_t *)
+ el->el_map.func = (el_func_t *)
el_realloc(el->el_map.func, nf * sizeof(el_func_t));
el->el_map.help = (el_bindings_t *)
el_realloc(el->el_map.help, nf * sizeof(el_bindings_t));
diff --git a/lib/libedit/map.h b/lib/libedit/map.h
index 71c93b4..c0f16f1 100644
--- a/lib/libedit/map.h
+++ b/lib/libedit/map.h
@@ -71,7 +71,7 @@ protected void map_end __P((EditLine *));
protected void map_init_vi __P((EditLine *));
protected void map_init_emacs __P((EditLine *));
protected int map_set_editor __P((EditLine *, char *));
-protected int map_addfunc __P((EditLine *, const char *,
+protected int map_addfunc __P((EditLine *, const char *,
const char *, el_func_t));
#endif /* _h_el_map */
diff --git a/lib/libedit/parse.c b/lib/libedit/parse.c
index 2fe746f..dd5bd94 100644
--- a/lib/libedit/parse.c
+++ b/lib/libedit/parse.c
@@ -47,6 +47,9 @@ static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
* echotc
* settc
* gettc
+ * history
+ * settc
+ * setty
*/
#include "sys.h"
#include "el.h"
@@ -97,12 +100,12 @@ el_parse(el, argc, argv)
char *ptr;
int i;
- for (ptr = argv[0]; *ptr && *ptr != ':'; ptr++)
- continue;
-
- if (*ptr == ':') {
- *ptr = '\0';
- if (el_match(el->el_prog, ptr))
+ if (argc < 1)
+ return -1;
+ ptr = strchr(argv[0], ':');
+ if (ptr != NULL) {
+ *ptr++ = '\0';
+ if (! el_match(el->el_prog, argv[0]))
return 0;
}
else
@@ -131,7 +134,7 @@ parse__escape(ptr)
p = *ptr;
- if (p[1] == 0)
+ if (p[1] == 0)
return -1;
if (*p == '\\') {
@@ -180,7 +183,7 @@ parse__escape(ptr)
}
c = (c << 3) | (ch - '0');
}
- if ((c & 0xffffff00) != 0)
+ if ((c & 0xffffff00) != 0)
return -1;
--p;
}
@@ -190,14 +193,14 @@ parse__escape(ptr)
break;
}
}
- else if (*p == '^' && isalpha((unsigned char) *p)) {
+ else if (*p == '^' && isascii(p[1]) && (p[1] == '?' || isalpha(p[1]))) {
p++;
c = (*p == '?') ? '\177' : (*p & 0237);
}
else
c = *p;
*ptr = ++p;
- return c;
+ return (unsigned char)c;
}
/* parse__string():
diff --git a/lib/libedit/parse.h b/lib/libedit/parse.h
index 263076b..0601746 100644
--- a/lib/libedit/parse.h
+++ b/lib/libedit/parse.h
@@ -42,7 +42,7 @@
#ifndef _h_el_parse
#define _h_el_parse
-protected int parse_line __P((EditLine *, const char *));
+protected int parse_line __P((EditLine *, const char *));
protected int parse__escape __P((const char ** const));
protected char * parse__string __P((char *, const char *));
protected int parse_cmd __P((EditLine *, const char *));
diff --git a/lib/libedit/prompt.c b/lib/libedit/prompt.c
index cea7ad7..59ba200 100644
--- a/lib/libedit/prompt.c
+++ b/lib/libedit/prompt.c
@@ -83,7 +83,7 @@ prompt_print(el)
/* prompt_init():
* Initialize the prompt stuff
*/
-protected int
+protected int
prompt_init(el)
EditLine *el;
{
@@ -98,7 +98,7 @@ prompt_init(el)
* Clean up the prompt stuff
*/
protected void
-/*ARGSUSED*/
+/*ARGSUSED*/
prompt_end(el)
EditLine *el;
{
@@ -108,7 +108,7 @@ prompt_end(el)
/* prompt_set():
* Install a prompt printing function
*/
-protected int
+protected int
prompt_set(el, prf)
EditLine *el;
el_pfunc_t prf;
diff --git a/lib/libedit/read.c b/lib/libedit/read.c
index ccfc88b..6475a25 100644
--- a/lib/libedit/read.c
+++ b/lib/libedit/read.c
@@ -86,13 +86,17 @@ read__fixio(fd, e)
#ifdef EWOULDBLOCK
case EWOULDBLOCK:
-# define TRY_AGAIN
+# ifndef TRY_AGAIN
+# define TRY_AGAIN
+# endif
#endif /* EWOULDBLOCK */
#if defined(POSIX) && defined(EAGAIN)
# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
case EAGAIN:
-# define TRY_AGAIN
+# ifndef TRY_AGAIN
+# define TRY_AGAIN
+# endif
# endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
#endif /* POSIX && EAGAIN */
@@ -104,7 +108,7 @@ read__fixio(fd, e)
if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
return -1;
- else
+ else
e = 1;
# endif /* F_SETFL && O_NDELAY */
@@ -233,7 +237,7 @@ read_getcmd(el, cmdnum, ch)
break;
}
}
- if (el->el_map.alt == NULL)
+ if (el->el_map.alt == NULL)
el->el_map.current = el->el_map.key;
}
*cmdnum = cmd;
@@ -261,9 +265,9 @@ el_getc(el, cp)
if (!read_preread(el))
break;
}
- if (ma->level < 0)
+ if (ma->level < 0)
break;
-
+
if (*ma->macro[ma->level] == 0) {
ma->level--;
continue;
@@ -347,7 +351,7 @@ el_gets(el, nread)
if (cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */
#ifdef DEBUG_EDIT
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"ERROR: illegal command from key 0%o\r\n", ch);
#endif /* DEBUG_EDIT */
continue; /* try again */
@@ -379,6 +383,11 @@ el_gets(el, nread)
re_refresh_cursor(el);
break;
+ case CC_REDISPLAY:
+ re_clear_lines(el);
+ re_clear_display(el);
+ /* FALLTHROUGH */
+
case CC_REFRESH:
el->el_state.argument = 1;
el->el_state.doingarg = 0;
@@ -399,7 +408,7 @@ el_gets(el, nread)
break;
case CC_NEWLINE: /* normal end of line */
- num = el->el_line.lastchar - el->el_line.buffer;
+ num = el->el_line.lastchar - el->el_line.buffer;
break;
case CC_FATAL: /* fatal error, reset to known state */
diff --git a/lib/libedit/refresh.c b/lib/libedit/refresh.c
index b64d011..6c3ee93 100644
--- a/lib/libedit/refresh.c
+++ b/lib/libedit/refresh.c
@@ -43,7 +43,6 @@ static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93";
*/
#include "sys.h"
#include <stdio.h>
-#include <ctype.h>
#include <unistd.h>
#include <string.h>
@@ -51,9 +50,9 @@ static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93";
private void re_addc __P((EditLine *, int));
private void re_update_line __P((EditLine *, char *, char *, int));
-private void re_insert __P((EditLine *, char *, int, int,
+private void re_insert __P((EditLine *, char *, int, int,
char *, int));
-private void re_delete __P((EditLine *, char *, int, int,
+private void re_delete __P((EditLine *, char *, int, int,
int));
private void re_fastputc __P((EditLine *, int));
@@ -61,7 +60,7 @@ private void re__strncopy __P((char *, char *, size_t));
private void re__copy_and_pad __P((char *, char *, size_t));
#ifdef DEBUG_REFRESH
-private void re_printstr __P((EditLine *, char *, char *,
+private void re_printstr __P((EditLine *, char *, char *,
char *));
# define __F el->el_errfile
# define RE_DEBUG(a, b, c) do \
@@ -83,7 +82,7 @@ re_printstr(el, str, f, t)
while (f < t)
RE_DEBUG(1,(__F, "%c", *f++ & 0177),);
RE_DEBUG(1,(__F, "\"\r\n"),);
-}
+}
#else
# define RE_DEBUG(a, b, c)
#endif
@@ -97,6 +96,8 @@ re_addc(el, c)
EditLine *el;
int c;
{
+ c = (unsigned char)c;
+
if (isprint(c)) {
re_putc(el, c);
return;
@@ -116,11 +117,11 @@ re_addc(el, c)
}
else if (iscntrl(c)) {
re_putc(el, '^');
- if (c == '\177')
+ if (c == 0177)
re_putc(el, '?');
- else
+ else
/* uncontrolify it; works only for iso8859-1 like sets */
- re_putc(el, (c | 0100));
+ re_putc(el, (toascii(c) | 0100));
}
else {
re_putc(el, '\\');
@@ -144,11 +145,11 @@ re_putc(el, c)
el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_refresh.r_cursor.h] = c;
el->el_refresh.r_cursor.h++; /* advance to next place */
if (el->el_refresh.r_cursor.h >= el->el_term.t_size.h) {
- el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_term.t_size.h] = '\0';
+ el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_term.t_size.h] = '\0';
/* assure end of line */
el->el_refresh.r_cursor.h = 0; /* reset it. */
el->el_refresh.r_cursor.v++;
- RE_DEBUG(el->el_refresh.r_cursor.v >= el->el_term.t_size.v,
+ RE_DEBUG(el->el_refresh.r_cursor.v >= el->el_term.t_size.v,
(__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n",
el->el_refresh.r_cursor.v, el->el_term.t_size.v), abort());
}
@@ -194,12 +195,12 @@ re_refresh(el)
cur.v = el->el_refresh.r_cursor.v;
}
/* must be done BEFORE the NUL is written */
- el->el_refresh.r_newcv = el->el_refresh.r_cursor.v;
+ el->el_refresh.r_newcv = el->el_refresh.r_cursor.v;
re_putc(el, '\0'); /* put NUL on end */
- RE_DEBUG(1,(__F,
+ RE_DEBUG(1,(__F,
"term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n",
- el->el_term.t_size.h, el->el_refresh.r_cursor.h,
+ el->el_term.t_size.h, el->el_refresh.r_cursor.h,
el->el_refresh.r_cursor.v, el->el_vdisplay[0]),);
RE_DEBUG(1,(__F, "updating %d lines.\r\n", el->el_refresh.r_newcv),);
@@ -213,14 +214,14 @@ re_refresh(el)
* cursor by writing the character that is at the end of the
* screen line, it won't be a NUL or some old leftover stuff.
*/
- re__copy_and_pad(el->el_display[i], el->el_vdisplay[i],
+ re__copy_and_pad(el->el_display[i], el->el_vdisplay[i],
el->el_term.t_size.h);
}
RE_DEBUG(1,(__F,
"\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n",
el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i),);
- if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv)
+ if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv)
for (; i <= el->el_refresh.r_oldcv; i++) {
term_move_to_line(el, i);
term_move_to_char(el, 0);
@@ -230,11 +231,11 @@ re_refresh(el)
#endif /* DEBUG_REFRESH */
*el->el_display[i] = '\0';
}
-
+
el->el_refresh.r_oldcv = el->el_refresh.r_newcv; /* set for next time */
- RE_DEBUG(1,(__F,
+ RE_DEBUG(1,(__F,
"\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n",
- el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v,
+ el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v,
cur.h, cur.v),);
term_move_to_line(el, cur.v); /* go to where the cursor is */
term_move_to_char(el, cur.h);
@@ -242,7 +243,7 @@ re_refresh(el)
/* re_goto_bottom():
- * used to go to last used screen line
+ * used to go to last used screen line
*/
protected void
re_goto_bottom(el)
@@ -258,7 +259,7 @@ re_goto_bottom(el)
/* re_insert():
* insert num characters of s into d (in front of the character)
- * at dat, maximum length of d is dlen
+ * at dat, maximum length of d is dlen
*/
private void
/*ARGSUSED*/
@@ -288,7 +289,7 @@ re_insert(el, d, dat, dlen, s, num)
*b-- = *a--;
d[dlen] = '\0'; /* just in case */
}
- RE_DEBUG(1,(__F,
+ RE_DEBUG(1,(__F,
"re_insert() after insert: %d at %d max %d, d == \"%s\"\n",
num, dat, dlen, d),);
RE_DEBUG(1,(__F, "s == \"%s\"n", s),);
@@ -304,7 +305,7 @@ re_insert(el, d, dat, dlen, s, num)
/* re_delete():
- * delete num characters d at dat, maximum length of d is dlen
+ * delete num characters d at dat, maximum length of d is dlen
*/
private void
/*ARGSUSED*/
@@ -399,7 +400,7 @@ re_update_line(el, old, new, i)
*/
while (*o)
o++;
- /*
+ /*
* Remove any trailing blanks off of the end, being careful not to
* back up past the beginning.
*/
@@ -410,7 +411,7 @@ re_update_line(el, old, new, i)
}
oe = o;
*oe = '\0';
-
+
while (*n)
n++;
@@ -422,7 +423,7 @@ re_update_line(el, old, new, i)
}
ne = n;
*ne = '\0';
-
+
/*
* if no diff, continue to next line of redraw
*/
@@ -573,7 +574,7 @@ re_update_line(el, old, new, i)
ofd - old, osb - old, ose - old, ols - old, oe - old),);
RE_DEBUG(1,(__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
nfd - new, nsb - new, nse - new, nls - new, ne - new),);
- RE_DEBUG(1,(__F,
+ RE_DEBUG(1,(__F,
"xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n"),);
RE_DEBUG(1,(__F,
"xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"),);
@@ -601,14 +602,14 @@ re_update_line(el, old, new, i)
/*
* at this point we have something like this:
- *
+ *
* /old /ofd /osb /ose /ols /oe
* v.....................v v..................v v........v
* eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
* eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
- * ^.....................^ ^..................^ ^........^
+ * ^.....................^ ^..................^ ^........^
* \new \nfd \nsb \nse \nls \ne
- *
+ *
* fx is the difference in length between the the chars between nfd and
* nsb, and the chars between ofd and osb, and is thus the number of
* characters to delete if < 0 (new is shorter than old, as above),
@@ -738,7 +739,7 @@ re_update_line(el, old, new, i)
* Again a duplicate test.
*/
if (sx < 0) {
- RE_DEBUG(!EL_CAN_DELETE,
+ RE_DEBUG(!EL_CAN_DELETE,
(__F, "ERROR: cannot delete in second diff\n"),);
term_deletechars(el, -sx);
}
@@ -768,7 +769,7 @@ re_update_line(el, old, new, i)
*/
if (nsb != ne) {
RE_DEBUG(1,(__F, "with stuff to keep at end\r\n"),);
- /*
+ /*
* We have to recalculate fx here because we set it
* to zero above as a flag saying that we hadn't done
* an early first insert.
@@ -863,7 +864,8 @@ protected void
re_refresh_cursor(el)
EditLine *el;
{
- char *cp, c;
+ char *cp;
+ int c;
int h, v, th;
/* first we must find where the cursor is... */
@@ -872,8 +874,8 @@ re_refresh_cursor(el)
th = el->el_term.t_size.h; /* optimize for speed */
/* do input buffer to el->el_line.cursor */
- for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) {
- c = *cp;
+ for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) {
+ c = (unsigned char)*cp;
h++; /* all chars at least this long */
if (c == '\n') { /* handle newline in data part too */
@@ -925,7 +927,7 @@ re_fastputc(el, c)
{
term__putc(c);
el->el_display[el->el_cursor.v][el->el_cursor.h++] = c;
- if (el->el_cursor.h >= el->el_term.t_size.h) {
+ if (el->el_cursor.h >= el->el_term.t_size.h) {
/* if we must overflow */
el->el_cursor.h = 0;
el->el_cursor.v++;
@@ -938,15 +940,15 @@ re_fastputc(el, c)
/* re_fastaddc():
* we added just one char, handle it fast.
- * Assumes that screen cursor == real cursor
+ * Assumes that screen cursor == real cursor
*/
protected void
re_fastaddc(el)
EditLine *el;
{
- char c;
+ int c;
- c = el->el_line.cursor[-1];
+ c = (unsigned char)el->el_line.cursor[-1];
if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) {
re_refresh(el); /* too hard to handle */
@@ -954,7 +956,7 @@ re_fastaddc(el)
} /* else (only do at end of line, no TAB) */
if (iscntrl(c)) { /* if control char, do caret */
- char mc = (c == '\177') ? '?' : (c | 0100);
+ char mc = (c == 0177) ? '?' : (toascii(c) | 0100);
re_fastputc(el, '^');
re_fastputc(el, mc);
}
@@ -972,7 +974,7 @@ re_fastaddc(el)
/* re_clear_display():
- * clear the screen buffers so that new new prompt starts fresh.
+ * clear the screen buffers so that new new prompt starts fresh.
*/
protected void
re_clear_display(el)
@@ -989,7 +991,7 @@ re_clear_display(el)
/* re_clear_lines():
- * Make sure all lines are *really* blank
+ * Make sure all lines are *really* blank
*/
protected void
re_clear_lines(el)
diff --git a/lib/libedit/search.c b/lib/libedit/search.c
index 4ff9c61..508835e 100644
--- a/lib/libedit/search.c
+++ b/lib/libedit/search.c
@@ -43,7 +43,9 @@ static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93";
*/
#include "sys.h"
#include <stdlib.h>
-#ifdef REGEXP
+#if defined(REGEX)
+#include <regex.h>
+#elif defined(REGEXP)
#include <regexp.h>
#endif
#include "el.h"
@@ -86,7 +88,7 @@ search_end(el)
/* regerror():
* Handle regular expression errors
*/
-public void
+public void
/*ARGSUSED*/
regerror(msg)
const char *msg;
@@ -102,31 +104,42 @@ el_match(str, pat)
const char *str;
const char *pat;
{
-#ifndef REGEXP
+#if defined (REGEX)
+ regex_t re;
+ int rv;
+#elif defined (REGEXP)
+ regexp *rp;
+ int rv;
+#else
extern char *re_comp __P((const char *));
extern int re_exec __P((const char *));
-#else
- regexp *re;
- int rv;
#endif
if (strstr(str, pat) != NULL)
return 1;
-#ifndef REGEXP
- if (re_comp(pat) != NULL)
- return 0;
- else
- return re_exec(str) == 1;
-#else
+
+#if defined(REGEX)
+ if (regcomp(&re, pat, 0) == 0) {
+ rv = regexec(&re, str, 0, NULL, 0) == 0;
+ regfree(&re);
+ } else {
+ rv = 0;
+ }
+ return rv;
+#elif defined(REGEXP)
if ((re = regcomp(pat)) != NULL) {
rv = regexec(re, str);
free((ptr_t) re);
- }
- else
+ } else {
rv = 0;
+ }
return rv;
+#else
+ if (re_comp(pat) != NULL)
+ return 0;
+ else
+ return re_exec(str) == 1;
#endif
-
}
@@ -142,25 +155,25 @@ c_hmatch(el, str)
(void) fprintf(el->el_errfile, "match `%s' with `%s'\n",
el->el_search.patbuf, str);
#endif /* SDEBUG */
-
+
return el_match(str, el->el_search.patbuf);
}
-/* c_setpat():
+/* c_setpat():
* Set the history seatch pattern
*/
protected void
c_setpat(el)
EditLine *el;
{
- if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY &&
+ if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY &&
el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) {
el->el_search.patlen = EL_CURSOR(el) - el->el_line.buffer;
- if (el->el_search.patlen >= EL_BUFSIZ)
+ if (el->el_search.patlen >= EL_BUFSIZ)
el->el_search.patlen = EL_BUFSIZ -1;
if (el->el_search.patlen >= 0) {
- (void) strncpy(el->el_search.patbuf, el->el_line.buffer,
+ (void) strncpy(el->el_search.patbuf, el->el_line.buffer,
el->el_search.patlen);
el->el_search.patbuf[el->el_search.patlen] = '\0';
}
@@ -171,8 +184,8 @@ c_setpat(el)
(void) fprintf(el->el_errfile, "\neventno = %d\n", el->el_history.eventno);
(void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen);
(void) fprintf(el->el_errfile, "patbuf = \"%s\"\n", el->el_search.patbuf);
- (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n",
- EL_CURSOR(el) - el->el_line.buffer,
+ (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n",
+ EL_CURSOR(el) - el->el_line.buffer,
el->el_line.lastchar - el->el_line.buffer);
#endif
}
@@ -199,7 +212,7 @@ ce_inc_search(el, dir)
newdir = dir,
done, redo;
- if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 +
+ if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 +
el->el_search.patlen >= el->el_line.limit)
return CC_ERROR;
@@ -214,12 +227,12 @@ ce_inc_search(el, dir)
}
done = redo = 0;
*el->el_line.lastchar++ = '\n';
- for (cp = newdir == ED_SEARCH_PREV_HISTORY ? STRbck : STRfwd;
+ for (cp = newdir == ED_SEARCH_PREV_HISTORY ? STRbck : STRfwd;
*cp; *el->el_line.lastchar++ = *cp++)
continue;
*el->el_line.lastchar++ = pchar;
- for (cp = &el->el_search.patbuf[1];
- cp < &el->el_search.patbuf[el->el_search.patlen];
+ for (cp = &el->el_search.patbuf[1];
+ cp < &el->el_search.patbuf[el->el_search.patlen];
*el->el_line.lastchar++ = *cp++)
continue;
*el->el_line.lastchar = '\0';
@@ -254,7 +267,7 @@ ce_inc_search(el, dir)
case ED_DELETE_PREV_CHAR:
if (el->el_search.patlen > 1)
done++;
- else
+ else
term_beep(el);
break;
@@ -270,15 +283,15 @@ ce_inc_search(el, dir)
for (cp = &el->el_search.patbuf[1]; ; cp++)
if (cp >= &el->el_search.patbuf[el->el_search.patlen]) {
el->el_line.cursor += el->el_search.patlen - 1;
- cp = c__next_word(el->el_line.cursor,
+ cp = c__next_word(el->el_line.cursor,
el->el_line.lastchar, 1, ce__isword);
- while (el->el_line.cursor < cp &&
+ while (el->el_line.cursor < cp &&
*el->el_line.cursor != '\n') {
if (el->el_search.patlen > EL_BUFSIZ - 3) {
term_beep(el);
break;
}
- el->el_search.patbuf[el->el_search.patlen++] =
+ el->el_search.patbuf[el->el_search.patlen++] =
*el->el_line.cursor;
*el->el_line.lastchar++ = *el->el_line.cursor++;
}
@@ -291,10 +304,10 @@ ce_inc_search(el, dir)
break;
}
break;
-
+
default: /* Terminate and execute cmd */
endcmd[0] = ch;
- el_push(el, endcmd);
+ el_push(el, endcmd);
/*FALLTHROUGH*/
case 0033: /* ESC: Terminate */
@@ -305,7 +318,7 @@ ce_inc_search(el, dir)
break;
}
- while (el->el_line.lastchar > el->el_line.buffer &&
+ while (el->el_line.lastchar > el->el_line.buffer &&
*el->el_line.lastchar != '\n')
*el->el_line.lastchar-- = '\0';
*el->el_line.lastchar = '\0';
@@ -313,7 +326,7 @@ ce_inc_search(el, dir)
if (!done) {
/* Can't search if unmatched '[' */
- for (cp = &el->el_search.patbuf[el->el_search.patlen-1], ch = ']';
+ for (cp = &el->el_search.patbuf[el->el_search.patlen-1], ch = ']';
cp > el->el_search.patbuf; cp--)
if (*cp == '[' || *cp == ']') {
ch = *cp;
@@ -323,7 +336,7 @@ ce_inc_search(el, dir)
if (el->el_search.patlen > 1 && ch != '[') {
if (redo && newdir == dir) {
if (pchar == '?') { /* wrap around */
- el->el_history.eventno =
+ el->el_history.eventno =
newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff;
if (hist_get(el) == CC_ERROR)
/* el->el_history.eventno was fixed by first call */
@@ -331,7 +344,7 @@ ce_inc_search(el, dir)
el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ?
el->el_line.lastchar : el->el_line.buffer;
} else
- el->el_line.cursor +=
+ el->el_line.cursor +=
newdir == ED_SEARCH_PREV_HISTORY ? -1 : 1;
}
#ifdef ANCHOR
@@ -339,19 +352,19 @@ ce_inc_search(el, dir)
el->el_search.patbuf[el->el_search.patlen++] = '*';
#endif
el->el_search.patbuf[el->el_search.patlen] = '\0';
- if (el->el_line.cursor < el->el_line.buffer ||
+ if (el->el_line.cursor < el->el_line.buffer ||
el->el_line.cursor > el->el_line.lastchar ||
- (ret = ce_search_line(el, &el->el_search.patbuf[1],
+ (ret = ce_search_line(el, &el->el_search.patbuf[1],
newdir)) == CC_ERROR) {
/* avoid c_setpat */
- el->el_state.lastcmd = (el_action_t) newdir;
+ el->el_state.lastcmd = (el_action_t) newdir;
ret = newdir == ED_SEARCH_PREV_HISTORY ?
- ed_search_prev_history(el, 0) :
+ ed_search_prev_history(el, 0) :
ed_search_next_history(el, 0);
if (ret != CC_ERROR) {
el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ?
el->el_line.lastchar : el->el_line.buffer;
- (void) ce_search_line(el, &el->el_search.patbuf[1],
+ (void) ce_search_line(el, &el->el_search.patbuf[1],
newdir);
}
}
@@ -372,7 +385,7 @@ ce_inc_search(el, dir)
ret = ce_inc_search(el, newdir);
- if (ret == CC_ERROR && pchar == '?' && oldpchar == ':')
+ if (ret == CC_ERROR && pchar == '?' && oldpchar == ':')
/* break abort of failed search at last non-failed */
ret = CC_NORM;
@@ -448,10 +461,11 @@ cv_search(el, dir)
}
#ifdef ANCHOR
if (el->el_search.patbuf[0] != '.' && el->el_search.patbuf[0] != '*') {
- (void) strcpy(tmpbuf, el->el_search.patbuf);
+ (void)strncpy(tmpbuf, el->el_search.patbuf, sizeof(tmpbuf) - 1);
el->el_search.patbuf[0] = '.';
el->el_search.patbuf[1] = '*';
- (void) strcpy(&el->el_search.patbuf[2], tmpbuf);
+ (void)strncpy(&el->el_search.patbuf[2], tmpbuf,
+ sizeof(el->el_search.patbuf) - 3);
el->el_search.patlen++;
el->el_search.patbuf[el->el_search.patlen++] = '.';
el->el_search.patbuf[el->el_search.patlen++] = '*';
@@ -465,12 +479,13 @@ cv_search(el, dir)
tmpbuf[tmplen++] = '*';
#endif
tmpbuf[tmplen] = '\0';
- (void) strcpy(el->el_search.patbuf, tmpbuf);
+ (void)strncpy(el->el_search.patbuf, tmpbuf,
+ sizeof(el->el_search.patbuf) - 1);
el->el_search.patlen = tmplen;
}
el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */
el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer;
- if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) :
+ if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) :
ed_search_next_history(el, 0)) == CC_ERROR) {
re_refresh(el);
return CC_ERROR;
@@ -508,7 +523,7 @@ ce_search_line(el, pattern, dir)
}
return CC_ERROR;
} else {
- for (cp = el->el_line.cursor; *cp != '\0' &&
+ for (cp = el->el_line.cursor; *cp != '\0' &&
cp < el->el_line.limit; cp++)
if (el_match(cp, pattern)) {
el->el_line.cursor = cp;
@@ -528,7 +543,7 @@ cv_repeat_srch(el, c)
int c;
{
#ifdef SDEBUG
- (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n",
+ (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n",
c, el->el_search.patlen, el->el_search.patbuf);
#endif
@@ -558,9 +573,9 @@ cv_csearch_back(el, ch, count, tflag)
cp = el->el_line.cursor;
while (count--) {
- if (*cp == ch)
+ if (*cp == ch)
cp--;
- while (cp > el->el_line.buffer && *cp != ch)
+ while (cp > el->el_line.buffer && *cp != ch)
cp--;
}
@@ -595,9 +610,9 @@ cv_csearch_fwd(el, ch, count, tflag)
cp = el->el_line.cursor;
while (count--) {
- if(*cp == ch)
+ if(*cp == ch)
cp++;
- while (cp < el->el_line.lastchar && *cp != ch)
+ while (cp < el->el_line.lastchar && *cp != ch)
cp++;
}
diff --git a/lib/libedit/search.h b/lib/libedit/search.h
index 51c58b4..346b38c 100644
--- a/lib/libedit/search.h
+++ b/lib/libedit/search.h
@@ -39,8 +39,8 @@
/*
* el.search.h: Line and history searching utilities
*/
-#ifndef _h_el_search
-#define _h_el_search
+#ifndef _h_el_search
+#define _h_el_search
#include "histedit.h"
diff --git a/lib/libedit/sig.c b/lib/libedit/sig.c
index 94ab4bb..d0a780a 100644
--- a/lib/libedit/sig.c
+++ b/lib/libedit/sig.c
@@ -91,7 +91,7 @@ sig_handler(signo)
break;
}
- for (i = 0; sighdl[i] != -1; i++)
+ for (i = 0; sighdl[i] != -1; i++)
if (signo == sighdl[i])
break;
@@ -120,8 +120,8 @@ sig_init(el)
#define SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(sig_t))
el->el_signal = (sig_t *) el_malloc(SIGSIZE);
- for (i = 0; sighdl[i] != -1; i++)
- el->el_signal[i] = BADSIG;
+ for (i = 0; sighdl[i] != -1; i++)
+ el->el_signal[i] = SIG_ERR;
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
@@ -184,8 +184,8 @@ sig_clr(el)
#undef _DO
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
- for (i = 0; sighdl[i] != -1; i++)
- if (el->el_signal[i] != BADSIG)
+ for (i = 0; sighdl[i] != -1; i++)
+ if (el->el_signal[i] != SIG_ERR)
(void) signal(sighdl[i], el->el_signal[i]);
sel = NULL; /* we are going to die if the handler is called */
diff --git a/lib/libedit/sys.h b/lib/libedit/sys.h
index cc260f5..9e5fd0f 100644
--- a/lib/libedit/sys.h
+++ b/lib/libedit/sys.h
@@ -76,9 +76,11 @@ typedef char* ioctl_t;
#endif
#include <stdio.h>
-#define REGEXP
+#define REGEX /* Use POSIX.2 regular expression functions */
+#undef REGEXP /* Use UNIX V8 regular expression functions */
#ifdef SUNOS
+# undef REGEX
# undef REGEXP
# include <malloc.h>
typedef void (*sig_t)__P((int));
diff --git a/lib/libedit/term.c b/lib/libedit/term.c
index 4b793b7..8de3027 100644
--- a/lib/libedit/term.c
+++ b/lib/libedit/term.c
@@ -49,8 +49,9 @@ static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95";
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
-#include "termcap.h" /* XXX: should be <termcap.h> */
+#include <termcap.h>
#include <sys/types.h>
+#include <sys/ioctl.h>
#include "el.h"
@@ -68,76 +69,6 @@ static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95";
#define Str(a) el->el_term.t_str[a]
#define Val(a) el->el_term.t_val[a]
-private struct {
- char *b_name;
- int b_rate;
-} baud_rate[] = {
-#ifdef B0
- { "0", B0 },
-#endif
-#ifdef B50
- { "50", B50 },
-#endif
-#ifdef B75
- { "75", B75 },
-#endif
-#ifdef B110
- { "110", B110 },
-#endif
-#ifdef B134
- { "134", B134 },
-#endif
-#ifdef B150
- { "150", B150 },
-#endif
-#ifdef B200
- { "200", B200 },
-#endif
-#ifdef B300
- { "300", B300 },
-#endif
-#ifdef B600
- { "600", B600 },
-#endif
-#ifdef B900
- { "900", B900 },
-#endif
-#ifdef B1200
- { "1200", B1200 },
-#endif
-#ifdef B1800
- { "1800", B1800 },
-#endif
-#ifdef B2400
- { "2400", B2400 },
-#endif
-#ifdef B3600
- { "3600", B3600 },
-#endif
-#ifdef B4800
- { "4800", B4800 },
-#endif
-#ifdef B7200
- { "7200", B7200 },
-#endif
-#ifdef B9600
- { "9600", B9600 },
-#endif
-#ifdef EXTA
- { "19200", EXTA },
-#endif
-#ifdef B19200
- { "19200", B19200 },
-#endif
-#ifdef EXTB
- { "38400", EXTB },
-#endif
-#ifdef B38400
- { "38400", B38400 },
-#endif
- { NULL, 0 }
-};
-
private struct termcapstr {
char *name;
char *long_name;
@@ -171,7 +102,7 @@ private struct termcapstr {
{ "ho", "home cursor" },
#define T_ic 13
{ "ic", "insert character" },
-#define T_im 14
+#define T_im 14
{ "im", "start insert mode" },
#define T_ip 15
{ "ip", "insert padding" },
@@ -245,7 +176,7 @@ private void term_rebuffer_display __P((EditLine *));
private void term_free_display __P((EditLine *));
private void term_alloc_display __P((EditLine *));
private void term_alloc __P((EditLine *,
- struct termcapstr *, char *));
+ struct termcapstr *, char *));
private void term_init_arrow __P((EditLine *));
private void term_reset_arrow __P((EditLine *));
@@ -261,7 +192,7 @@ term_setflags(el)
EditLine *el;
{
EL_FLAGS = 0;
- if (el->el_tty.t_tabs)
+ if (el->el_tty.t_tabs)
EL_FLAGS |= (Val(T_pt) && !Val(T_xt)) ? TERM_CAN_TAB : 0;
EL_FLAGS |= (Val(T_km) || Val(T_MT)) ? TERM_HAS_META : 0;
@@ -304,6 +235,7 @@ term_init(el)
el->el_term.t_buf = (char *) el_malloc(TC_BUFSIZE);
el->el_term.t_cap = (char *) el_malloc(TC_BUFSIZE);
el->el_term.t_fkey = (fkey_t *) el_malloc(4 * sizeof(fkey_t));
+ (void) memset(el->el_term.t_fkey, 0, 4 * sizeof(fkey_t));
el->el_term.t_loc = 0;
el->el_term.t_str = (char **) el_malloc(T_str * sizeof(char*));
(void) memset(el->el_term.t_str, 0, T_str * sizeof(char*));
@@ -362,7 +294,7 @@ term_alloc(el, t, cap)
* New string is shorter; no need to allocate space
*/
if (clen <= tlen) {
- (void) strcpy(*str, cap);
+ (void)strcpy(*str, cap); /* XXX strcpy is safe */
return;
}
@@ -370,7 +302,8 @@ term_alloc(el, t, cap)
* New string is longer; see if we have enough space to append
*/
if (el->el_term.t_loc + 3 < TC_BUFSIZE) {
- (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap);
+ /* XXX strcpy is safe */
+ (void)strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap);
el->el_term.t_loc += clen + 1; /* one for \0 */
return;
}
@@ -394,7 +327,8 @@ term_alloc(el, t, cap)
(void) fprintf(el->el_errfile, "Out of termcap string space.\n");
return;
}
- (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap);
+ /* XXX strcpy is safe */
+ (void)strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap);
el->el_term.t_loc += clen + 1; /* one for \0 */
return;
} /* end term_alloc */
@@ -479,7 +413,7 @@ term_free_display(el)
protected void
term_move_to_line(el, where)
EditLine *el;
- int where;
+ int where;
{
int del, i;
@@ -488,7 +422,7 @@ term_move_to_line(el, where)
if (where > el->el_term.t_size.v) {
#ifdef DEBUG_SCREEN
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"term_move_to_line: where is ridiculous: %d\r\n", where);
#endif /* DEBUG_SCREEN */
return;
@@ -532,7 +466,7 @@ mc_again:
if (where > (el->el_term.t_size.h + 1)) {
#ifdef DEBUG_SCREEN
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"term_move_to_char: where is riduculous: %d\r\n", where);
#endif /* DEBUG_SCREEN */
return;
@@ -557,7 +491,7 @@ mc_again:
if (EL_CAN_TAB) { /* if I can do tabs, use them */
if ((el->el_cursor.h & 0370) != (where & 0370)) {
/* if not within tab stop */
- for (i = (el->el_cursor.h & 0370);
+ for (i = (el->el_cursor.h & 0370);
i < (where & 0370); i += 8)
term__putc('\t'); /* then tab over */
el->el_cursor.h = where & 0370;
@@ -566,8 +500,8 @@ mc_again:
/* it's usually cheaper to just write the chars, so we do. */
/* NOTE THAT term_overwrite() WILL CHANGE el->el_cursor.h!!! */
- term_overwrite(el,
- &el->el_display[el->el_cursor.v][el->el_cursor.h],
+ term_overwrite(el,
+ &el->el_display[el->el_cursor.v][el->el_cursor.h],
where - el->el_cursor.h);
}
@@ -638,7 +572,7 @@ term_deletechars(el, num)
if (num > el->el_term.t_size.h) {
#ifdef DEBUG_SCREEN
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"term_deletechars: num is riduculous: %d\r\n", num);
#endif /* DEBUG_SCREEN */
return;
@@ -663,11 +597,11 @@ term_deletechars(el, num)
/* term_insertwrite():
- * Puts terminal in insert character mode or inserts num
- * characters in the line
+ * Puts terminal in insert character mode or inserts num
+ * characters in the line
*/
protected void
-term_insertwrite(el, cp, num)
+term_insertwrite(el, cp, num)
EditLine *el;
char *cp;
int num;
@@ -699,7 +633,7 @@ term_insertwrite(el, cp, num)
(void) tputs(Str(T_im), 1, term__putc);
el->el_cursor.h += num;
- do
+ do
term__putc(*cp++);
while (--num);
@@ -726,10 +660,10 @@ term_insertwrite(el, cp, num)
/* term_clear_EOL():
- * clear to end of line. There are num characters to clear
+ * clear to end of line. There are num characters to clear
*/
protected void
-term_clear_EOL(el, num)
+term_clear_EOL(el, num)
EditLine *el;
int num;
{
@@ -746,7 +680,7 @@ term_clear_EOL(el, num)
/* term_clear_screen():
- * Clear the screen
+ * Clear the screen
*/
protected void
term_clear_screen(el)
@@ -833,11 +767,11 @@ term_set(el, term)
i = tgetent(el->el_term.t_cap, term);
if (i <= 0) {
- if (i == -1)
- (void) fprintf(el->el_errfile, "Cannot open /etc/termcap.\n");
- else if (i == 0)
- (void) fprintf(el->el_errfile,
- "No entry for terminal type \"%s\"\n", term);
+ if (i == -1)
+ (void) fprintf(el->el_errfile, "Cannot read termcap database;\n");
+ else if (i == 0)
+ (void) fprintf(el->el_errfile,
+ "No entry for terminal type \"%s\";\n", term);
(void) fprintf(el->el_errfile, "using dumb terminal settings.\n");
Val(T_co) = 80; /* do a dumb terminal */
Val(T_pt) = Val(T_km) = Val(T_li) = 0;
@@ -873,13 +807,13 @@ term_set(el, term)
term_change_size(el, lins, cols);
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
term_bind_arrow(el);
- return 0;
+ return i <= 0 ? -1 : 0;
} /* end term_set */
/* term_get_size():
* Return the new window size in lines and cols, and
- * true if the size was changed.
+ * true if the size was changed.
*/
protected int
term_get_size(el, lins, cols)
@@ -971,7 +905,7 @@ term_init_arrow(el)
* Reset arrow key bindings
*/
private void
-term_reset_arrow(el)
+term_reset_arrow(el)
EditLine *el;
{
fkey_t *arrow = el->el_term.t_fkey;
@@ -1095,8 +1029,8 @@ term_bind_arrow(el)
/*
* Assign the arrow keys only if:
*
- * 1. They are multi-character arrow keys and the user
- * has not re-assigned the leading character, or
+ * 1. They are multi-character arrow keys and the user
+ * has not re-assigned the leading character, or
* has re-assigned the leading character to be
* ED_SEQUENCE_LEAD_IN
* 2. They are single arrow keys pointing to an unassigned key.
@@ -1104,7 +1038,7 @@ term_bind_arrow(el)
if (arrow[i].type == XK_NOD)
key_clear(el, map, p);
else {
- if (p[1] && (dmap[j] == map[j] ||
+ if (p[1] && (dmap[j] == map[j] ||
map[j] == ED_SEQUENCE_LEAD_IN)) {
key_add(el, p, &arrow[i].fun, arrow[i].type);
map[j] = ED_SEQUENCE_LEAD_IN;
@@ -1125,11 +1059,11 @@ term_bind_arrow(el)
/* term__putc():
* Add a character
*/
-protected void
+protected int
term__putc(c)
int c;
{
- (void) fputc(c, term_outfile);
+ return fputc(c, term_outfile);
} /* end term__putc */
@@ -1161,21 +1095,21 @@ term_telltc(el, argc, argv)
(void) fprintf(el->el_outfile, "\tfollowing characteristics:\n\n");
(void) fprintf(el->el_outfile, "\tIt has %d columns and %d lines\n",
Val(T_co), Val(T_li));
- (void) fprintf(el->el_outfile,
+ (void) fprintf(el->el_outfile,
"\tIt has %s meta key\n", EL_HAS_META ? "a" : "no");
- (void) fprintf(el->el_outfile,
+ (void) fprintf(el->el_outfile,
"\tIt can%suse tabs\n", EL_CAN_TAB ? " " : "not ");
#ifdef notyet
- (void) fprintf(el->el_outfile, "\tIt %s automatic margins\n",
+ (void) fprintf(el->el_outfile, "\tIt %s automatic margins\n",
(T_Margin&MARGIN_AUTO)? "has": "does not have");
if (T_Margin & MARGIN_AUTO)
- (void) fprintf(el->el_outfile, "\tIt %s magic margins\n",
+ (void) fprintf(el->el_outfile, "\tIt %s magic margins\n",
(T_Margin&MARGIN_MAGIC)?"has":"does not have");
#endif
for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++)
- (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n", t->long_name,
- t->name, *ts && **ts ?
+ (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n", t->long_name,
+ t->name, *ts && **ts ?
key__decode_str(*ts, upbuf, "") : "(empty)");
(void) fputc('\n', el->el_outfile);
return 0;
@@ -1223,7 +1157,7 @@ term_settc(el, argc, argv)
break;
if (tv->name != NULL) {
- if (tv == &tval[T_pt] || tv == &tval[T_km]
+ if (tv == &tval[T_pt] || tv == &tval[T_km]
#ifdef notyet
|| tv == &tval[T_am] || tv == &tval[T_xn]
#endif
@@ -1303,25 +1237,18 @@ term_echotc(el, argc, argv)
}
#ifdef notyet
else if (strcmp(*argv, "xn") == 0) {
- (void) fprintf(el->el_outfile, fmts, T_Margin & MARGIN_MAGIC ?
+ (void) fprintf(el->el_outfile, fmts, T_Margin & MARGIN_MAGIC ?
"yes" : "no");
return 0;
}
else if (strcmp(*argv, "am") == 0) {
- (void) fprintf(el->el_outfile, fmts, T_Margin & MARGIN_AUTO ?
+ (void) fprintf(el->el_outfile, fmts, T_Margin & MARGIN_AUTO ?
"yes" : "no");
return 0;
}
#endif
else if (strcmp(*argv, "baud") == 0) {
- int i;
-
- for (i = 0; baud_rate[i].b_name != NULL; i++)
- if (el->el_tty.t_speed == baud_rate[i].b_rate) {
- (void) fprintf(el->el_outfile, fmts, baud_rate[i].b_name);
- return 0;
- }
- (void) fprintf(el->el_outfile, fmtd, 0);
+ (void) fprintf(el->el_outfile, "%ld\n", el->el_tty.t_speed);
return 0;
}
else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) {
@@ -1333,7 +1260,7 @@ term_echotc(el, argc, argv)
return 0;
}
- /*
+ /*
* Try to use our local definition first
*/
scap = NULL;
@@ -1346,7 +1273,7 @@ term_echotc(el, argc, argv)
scap = tgetstr(*argv, &area);
if (!scap || scap[0] == '\0') {
if (!silent)
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"echotc: Termcap parameter `%s' not found.\n", *argv);
return -1;
}
@@ -1377,7 +1304,7 @@ term_echotc(el, argc, argv)
* hpux has lot's of them...
*/
if (verbose)
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"echotc: Warning: unknown termcap %% `%c'.\n", *cap);
/* This is bad, but I won't complain */
break;
@@ -1388,7 +1315,7 @@ term_echotc(el, argc, argv)
argv++;
if (*argv && *argv[0]) {
if (!silent)
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"echotc: Warning: Extra argument `%s'.\n", *argv);
return -1;
}
@@ -1398,7 +1325,7 @@ term_echotc(el, argc, argv)
argv++;
if (!*argv || *argv[0] == '\0') {
if (!silent)
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"echotc: Warning: Missing argument.\n");
return -1;
}
@@ -1407,7 +1334,7 @@ term_echotc(el, argc, argv)
argv++;
if (*argv && *argv[0]) {
if (!silent)
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"echotc: Warning: Extra argument `%s'.\n", *argv);
return -1;
}
@@ -1416,15 +1343,15 @@ term_echotc(el, argc, argv)
default:
/* This is wrong, but I will ignore it... */
if (verbose)
- (void) fprintf(el->el_errfile,
- "echotc: Warning: Too many required arguments (%d).\n",
+ (void) fprintf(el->el_errfile,
+ "echotc: Warning: Too many required arguments (%d).\n",
arg_need);
/*FALLTHROUGH*/
case 2:
argv++;
if (!*argv || *argv[0] == '\0') {
if (!silent)
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"echotc: Warning: Missing argument.\n");
return -1;
}
@@ -1432,7 +1359,7 @@ term_echotc(el, argc, argv)
argv++;
if (!*argv || *argv[0] == '\0') {
if (!silent)
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"echotc: Warning: Missing argument.\n");
return -1;
}
@@ -1440,7 +1367,7 @@ term_echotc(el, argc, argv)
argv++;
if (*argv && *argv[0]) {
if (!silent)
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"echotc: Warning: Extra argument `%s'.\n", *argv);
return -1;
}
diff --git a/lib/libedit/term.h b/lib/libedit/term.h
index 416e73e..f9de221 100644
--- a/lib/libedit/term.h
+++ b/lib/libedit/term.h
@@ -92,7 +92,7 @@ protected int term_init __P((EditLine *));
protected void term_bind_arrow __P((EditLine *));
protected void term_print_arrow __P((EditLine *, char *));
protected int term_clear_arrow __P((EditLine *, char *));
-protected int term_set_arrow __P((EditLine *, char *,
+protected int term_set_arrow __P((EditLine *, char *,
key_value_t *, int));
protected void term_end __P((EditLine *));
protected int term_set __P((EditLine *, char *));
@@ -100,7 +100,7 @@ protected int term_settc __P((EditLine *, int, char **));
protected int term_telltc __P((EditLine *, int, char **));
protected int term_echotc __P((EditLine *, int, char **));
-protected void term__putc __P((int));
+protected int term__putc __P((int));
protected void term__flush __P((void));
/*
diff --git a/lib/libedit/tokenizer.c b/lib/libedit/tokenizer.c
index 41095fa..bbe847e 100644
--- a/lib/libedit/tokenizer.c
+++ b/lib/libedit/tokenizer.c
@@ -155,7 +155,7 @@ tok_end(tok)
* 3: Quoted return
* 2: Unmatched double quote
* 1: Unmatched single quote
- * 0: Ok
+ * 0: Ok
*/
public int
tok_line(tok, line, argc, argv)
@@ -225,7 +225,7 @@ tok_line(tok, line, argc, argv)
*tok->wptr++ = *ptr;
break;
- default:
+ default:
return(-1);
}
break;
@@ -242,7 +242,7 @@ tok_line(tok, line, argc, argv)
tok->quote = Q_doubleone;/* Quote next character */
break;
- case Q_one:
+ case Q_one:
*tok->wptr++ = *ptr;
tok->quote = Q_none; /* Quote this, restore state */
break;
@@ -274,7 +274,7 @@ tok_line(tok, line, argc, argv)
case Q_double:
*tok->wptr++ = *ptr; /* Add the return */
break;
-
+
case Q_doubleone:
tok->flags |= TOK_EAT;
tok->quote = Q_double; /* Back to double, eat the '\n' */
@@ -377,7 +377,7 @@ tok_line(tok, line, argc, argv)
if (tok->argc >= tok->amax - 4) {
tok->amax += AINCR;
- tok->argv = (char **) tok_realloc(tok->argv,
+ tok->argv = (char **) tok_realloc(tok->argv,
tok->amax * sizeof(char*));
}
diff --git a/lib/libedit/tokenizer.h b/lib/libedit/tokenizer.h
index d495dc6..86911e1 100644
--- a/lib/libedit/tokenizer.h
+++ b/lib/libedit/tokenizer.h
@@ -47,7 +47,7 @@ typedef struct tokenizer Tokenizer;
Tokenizer *tok_init __P((const char *));
void tok_reset __P((Tokenizer *));
void tok_end __P((Tokenizer *));
-int tok_line __P((Tokenizer *, const char *,
+int tok_line __P((Tokenizer *, const char *,
int *, char ***));
#endif /* _h_tokenizer */
diff --git a/lib/libedit/tty.c b/lib/libedit/tty.c
index ac99843..961e340 100644
--- a/lib/libedit/tty.c
+++ b/lib/libedit/tty.c
@@ -38,7 +38,7 @@
static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
-/*
+/*
* tty.c: tty interface stuff
*/
#include "sys.h"
@@ -47,7 +47,7 @@ static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
typedef struct ttymodes_t {
char *m_name;
- int m_value;
+ u_int m_value;
int m_type;
} ttymodes_t;
@@ -57,7 +57,7 @@ typedef struct ttymap_t {
} ttymap_t;
-private ttyperm_t ttyperm = {
+private ttyperm_t ttyperm = {
{
{ "iflag:", ICRNL, (INLCR|IGNCR) },
{ "oflag:", (OPOST|ONLCR), ONLRET },
@@ -87,8 +87,8 @@ private ttyperm_t ttyperm = {
private ttychar_t ttychar = {
{
- CINTR, CQUIT, CERASE, CKILL,
- CEOF, CEOL, CEOL2, CSWTCH,
+ CINTR, CQUIT, CERASE, CKILL,
+ CEOF, CEOL, CEOL2, CSWTCH,
CDSWTCH, CERASE2, CSTART, CSTOP,
CWERASE, CSUSP, CDSUSP, CREPRINT,
CDISCARD, CLNEXT, CSTATUS, CPAGE,
@@ -96,15 +96,15 @@ private ttychar_t ttychar = {
CTIME
},
{
- CINTR, CQUIT, CERASE, CKILL,
- _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
- _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
- _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
- CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ CINTR, CQUIT, CERASE, CKILL,
+ _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
+ _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
0
},
- {
+ {
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
@@ -117,38 +117,38 @@ private ttychar_t ttychar = {
private ttymap_t tty_map[] = {
#ifdef VERASE
- { C_ERASE, VERASE,
+ { C_ERASE, VERASE,
{ ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR } },
#endif /* VERASE */
#ifdef VERASE2
- { C_ERASE2, VERASE2,
+ { C_ERASE2, VERASE2,
{ ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR } },
#endif /* VERASE2 */
#ifdef VKILL
- { C_KILL, VKILL,
+ { C_KILL, VKILL,
{ EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } },
#endif /* VKILL */
#ifdef VKILL2
- { C_KILL2, VKILL2,
+ { C_KILL2, VKILL2,
{ EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } },
#endif /* VKILL2 */
#ifdef VEOF
- { C_EOF, VEOF,
+ { C_EOF, VEOF,
{ EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED } },
#endif /* VEOF */
#ifdef VWERASE
- { C_WERASE, VWERASE,
+ { C_WERASE, VWERASE,
{ ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD } },
#endif /* VWERASE */
#ifdef VREPRINT
- { C_REPRINT, VREPRINT,
+ { C_REPRINT, VREPRINT,
{ ED_REDISPLAY, ED_INSERT, ED_REDISPLAY } },
#endif /* VREPRINT */
#ifdef VLNEXT
- { C_LNEXT, VLNEXT,
+ { C_LNEXT, VLNEXT,
{ ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED } },
#endif /* VLNEXT */
- { -1, -1,
+ { -1, -1,
{ ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED } }
};
@@ -359,7 +359,7 @@ private ttymodes_t ttymodes[] = {
{ "extproc",EXTPROC, M_LIN },
# endif /* EXTPROC */
-# if defined(VINTR)
+# if defined(VINTR)
{ "intr", C_SH(C_INTR), M_CHAR },
# endif /* VINTR */
# if defined(VQUIT)
@@ -422,7 +422,7 @@ private ttymodes_t ttymodes[] = {
# if defined(VPGOFF)
{ "pgoff", C_SH(C_PGOFF), M_CHAR },
# endif /* VPGOFF */
-# if defined(VKILL2)
+# if defined(VKILL2)
{ "kill2", C_SH(C_KILL2), M_CHAR },
# endif /* VKILL2 */
# if defined(VBRK)
@@ -440,7 +440,7 @@ private ttymodes_t ttymodes[] = {
#define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
-#define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
+#define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
#define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
#define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
@@ -457,14 +457,14 @@ private int tty_setup __P((EditLine *));
/* tty_setup():
* Get the tty parameters and initialize the editing state
*/
-private int
+private int
tty_setup(el)
EditLine *el;
{
int rst = 1;
if (tty_getty(el, &el->el_tty.t_ed) == -1) {
#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile,
+ (void) fprintf(el->el_errfile,
"tty_setup: tty_getty: %s\n", strerror(errno));
#endif /* DEBUG_TTY */
return(-1);
@@ -509,7 +509,7 @@ tty_setup(el)
tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
if (tty_setty(el, &el->el_tty.t_ex) == -1) {
#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile, "tty_setup: tty_setty: %s\n",
+ (void) fprintf(el->el_errfile, "tty_setup: tty_setty: %s\n",
strerror(errno));
#endif /* DEBUG_TTY */
return(-1);
@@ -580,7 +580,7 @@ private void
tty__getchar(td, s)
struct termios *td;
unsigned char *s;
-{
+{
# ifdef VINTR
s[C_INTR] = td->c_cc[VINTR];
# endif /* VINTR */
@@ -663,7 +663,7 @@ private void
tty__setchar(td, s)
struct termios *td;
unsigned char *s;
-{
+{
# ifdef VINTR
td->c_cc[VINTR] = s[C_INTR];
# endif /* VINTR */
@@ -810,7 +810,7 @@ tty_rawmode(el)
el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
- if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
+ if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
(void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
(void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
@@ -819,7 +819,7 @@ tty_rawmode(el)
}
if (tty__cooked_mode(&el->el_tty.t_ts)) {
- if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
+ if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
el->el_tty.t_ex.c_cflag = el->el_tty.t_ts.c_cflag;
el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask;
el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][M_CTL].t_setmask;
@@ -862,9 +862,9 @@ tty_rawmode(el)
el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][M_OUT].t_setmask;
}
- if (tty__gettabs(&el->el_tty.t_ex) == 0)
+ if (tty__gettabs(&el->el_tty.t_ex) == 0)
el->el_tty.t_tabs = 0;
- else
+ else
el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
{
@@ -879,7 +879,7 @@ tty_rawmode(el)
for (i = 0; i < C_NCC; i++)
if (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])
break;
-
+
if (i != C_NCC) {
/*
* Propagate changes only to the unprotected chars
@@ -910,7 +910,7 @@ tty_rawmode(el)
if (tty_setty(el, &el->el_tty.t_ed) == -1) {
#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
+ (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
strerror(errno));
#endif /* DEBUG_TTY */
return -1;
@@ -932,7 +932,7 @@ tty_cookedmode(el)
if (tty_setty(el, &el->el_tty.t_ex) == -1) {
#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n",
+ (void) fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n",
strerror(errno));
#endif /* DEBUG_TTY */
return -1;
@@ -968,7 +968,7 @@ tty_quotemode(el)
if (tty_setty(el, &el->el_tty.t_qu) == -1) {
#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
+ (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
strerror(errno));
#endif /* DEBUG_TTY */
return -1;
@@ -989,7 +989,7 @@ tty_noquotemode(el)
return 0;
if (tty_setty(el, &el->el_tty.t_ed) == -1) {
#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
+ (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
strerror(errno));
#endif /* DEBUG_TTY */
return -1;
@@ -1019,7 +1019,7 @@ tty_stty(el, argc, argv)
return -1;
name = *argv++;
- while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
+ while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
switch (argv[0][1]) {
case 'a':
aflag++;
@@ -1048,7 +1048,7 @@ tty_stty(el, argc, argv)
int len = 0, st = 0, cu;
for (m = ttymodes; m->m_name; m++) {
if (m->m_type != i) {
- (void) fprintf(el->el_outfile, "%s%s", i != -1 ? "\n" : "",
+ (void) fprintf(el->el_outfile, "%s%s", i != -1 ? "\n" : "",
el->el_tty.t_t[z][m->m_type].t_name);
i = m->m_type;
st = len = strlen(el->el_tty.t_t[z][m->m_type].t_name);
@@ -1065,7 +1065,7 @@ tty_stty(el, argc, argv)
(void) fprintf(el->el_outfile, "\n%*s", st, "");
len = st + cu;
}
- else
+ else
len += cu;
if (x != '\0')
@@ -1131,7 +1131,7 @@ tty_printchar(el, s)
int i;
for (i = 0; i < C_NCC; i++) {
- for (m = el->el_tty.t_t; m->m_name; m++)
+ for (m = el->el_tty.t_t; m->m_name; m++)
if (m->m_type == M_CHAR && C_SH(i) == m->m_value)
break;
if (m->m_name)
@@ -1139,6 +1139,6 @@ tty_printchar(el, s)
if (i % 5 == 0)
(void) fprintf(el->el_errfile, "\n");
}
- (void) fprintf(el->el_errfile, "\n");
+ (void) fprintf(el->el_errfile, "\n");
}
#endif /* notyet */
diff --git a/lib/libedit/tty.h b/lib/libedit/tty.h
index 12da50d..294c36a 100644
--- a/lib/libedit/tty.h
+++ b/lib/libedit/tty.h
@@ -46,7 +46,7 @@
#include <termios.h>
/* Define our own since everyone gets it wrong! */
-#define CONTROL(A) ((A) & 037)
+#define CONTROL(A) ((A) & 037)
/*
* Aix compatible names
@@ -145,7 +145,12 @@
# endif /* IEXTEN != 0 */
#endif /* convex || __convex__ */
-
+/*
+ * So that we don't lose job control.
+ */
+#ifdef __SVR4
+# undef CSWTCH
+#endif
#ifndef _POSIX_VDISABLE
# define _POSIX_VDISABLE ((unsigned char) -1)
@@ -444,10 +449,10 @@
#define M_CHAR 4
#define M_NN 5
-typedef struct {
+typedef struct {
char *t_name;
- int t_setmask;
- int t_clrmask;
+ u_int t_setmask;
+ u_int t_clrmask;
} ttyperm_t[NN_IO][M_NN];
typedef unsigned char ttychar_t[NN_IO][C_NCC];
diff --git a/lib/libedit/vi.c b/lib/libedit/vi.c
index 030ee22..3a8ef05 100644
--- a/lib/libedit/vi.c
+++ b/lib/libedit/vi.c
@@ -59,7 +59,7 @@ cv_action(el, c)
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = 0;
-
+
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
kp = el->el_chared.c_undo.buf;
@@ -67,14 +67,14 @@ cv_action(el, c)
*kp++ = *cp;
el->el_chared.c_undo.dsize++;
}
-
+
el->el_chared.c_undo.action = INSERT;
el->el_chared.c_undo.ptr = el->el_line.buffer;
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
if (c & INSERT)
el->el_map.current = el->el_map.key;
-
+
return CC_REFRESH;
}
@@ -111,7 +111,7 @@ cv_paste(el, c)
char *ptr;
c_undo_t *un = &el->el_chared.c_undo;
#ifdef DEBUG_PASTE
- (void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
+ (void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
un->action, un->buf, un->isize, un->dsize);
#endif
if (un->isize == 0)
@@ -120,7 +120,7 @@ cv_paste(el, c)
if (!c && el->el_line.cursor < el->el_line.lastchar)
el->el_line.cursor++;
ptr = el->el_line.cursor;
-
+
c_insert(el, un->isize);
if (el->el_line.cursor + un->isize > el->el_line.lastchar)
return CC_ERROR;
@@ -129,7 +129,7 @@ cv_paste(el, c)
}
-/* vi_paste_next():
+/* vi_paste_next():
* Vi paste previous deletion to the right of the cursor
* [p]
*/
@@ -143,7 +143,7 @@ vi_paste_next(el, c)
}
-/* vi_paste_prev():
+/* vi_paste_prev():
* Vi paste previous deletion to the left of the cursor
* [P]
*/
@@ -157,7 +157,7 @@ vi_paste_prev(el, c)
}
-/* vi_prev_space_word():
+/* vi_prev_space_word():
* Vi move to the previous space delimited word
* [B]
*/
@@ -170,10 +170,10 @@ vi_prev_space_word(el, c)
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
- el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
- el->el_line.buffer,
- el->el_state.argument,
- cv__isword);
+ el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
+ el->el_line.buffer,
+ el->el_state.argument,
+ cv__isword);
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
@@ -184,7 +184,7 @@ vi_prev_space_word(el, c)
}
-/* vi_prev_word():
+/* vi_prev_word():
* Vi move to the previous word
* [B]
*/
@@ -197,10 +197,10 @@ vi_prev_word(el, c)
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
- el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
- el->el_line.buffer,
- el->el_state.argument,
- ce__isword);
+ el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
+ el->el_line.buffer,
+ el->el_state.argument,
+ ce__isword);
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
@@ -211,7 +211,7 @@ vi_prev_word(el, c)
}
-/* vi_next_space_word():
+/* vi_next_space_word():
* Vi move to the next space delimited word
* [W]
*/
@@ -224,9 +224,9 @@ vi_next_space_word(el, c)
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
- el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
- el->el_line.lastchar,
- el->el_state.argument,
+ el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
+ el->el_line.lastchar,
+ el->el_state.argument,
cv__isword);
if (el->el_map.type == MAP_VI)
@@ -238,7 +238,7 @@ vi_next_space_word(el, c)
return CC_CURSOR;
}
-/* vi_next_word():
+/* vi_next_word():
* Vi move to the next word
* [w]
*/
@@ -251,8 +251,8 @@ vi_next_word(el, c)
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
- el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
- el->el_line.lastchar,
+ el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
+ el->el_line.lastchar,
el->el_state.argument,
ce__isword);
@@ -267,7 +267,7 @@ vi_next_word(el, c)
-/* vi_change_case():
+/* vi_change_case():
* Vi change case of character under the cursor and advance one character
* [~]
*/
@@ -277,7 +277,7 @@ vi_change_case(el, c)
int c;
{
if (el->el_line.cursor < el->el_line.lastchar) {
- c = *el->el_line.cursor;
+ c = (unsigned char)*el->el_line.cursor;
if (isupper(c))
*el->el_line.cursor++ = tolower(c);
else if (islower(c))
@@ -291,7 +291,7 @@ vi_change_case(el, c)
}
-/* vi_change_meta():
+/* vi_change_meta():
* Vi change prefix command
* [c]
*/
@@ -309,7 +309,7 @@ vi_change_meta(el, c)
}
-/* vi_insert_at_bol():
+/* vi_insert_at_bol():
* Vi enter insert mode at the beginning of line
* [I]
*/
@@ -330,7 +330,7 @@ vi_insert_at_bol(el, c)
}
-/* vi_replace_char():
+/* vi_replace_char():
* Vi replace character under the cursor with the next character typed
* [r]
*/
@@ -350,7 +350,7 @@ vi_replace_char(el, c)
}
-/* vi_replace_mode():
+/* vi_replace_mode():
* Vi enter replace mode
* [R]
*/
@@ -370,7 +370,7 @@ vi_replace_mode(el, c)
}
-/* vi_substitute_char():
+/* vi_substitute_char():
* Vi replace character under the cursor and enter insert mode
* [r]
*/
@@ -386,7 +386,7 @@ vi_substitute_char(el, c)
}
-/* vi_substitute_line():
+/* vi_substitute_line():
* Vi substitute entire line
* [S]
*/
@@ -402,7 +402,7 @@ vi_substitute_line(el, c)
}
-/* vi_change_to_eol():
+/* vi_change_to_eol():
* Vi change to end of line
* [C]
*/
@@ -439,7 +439,7 @@ vi_insert(el, c)
/* vi_add():
- * Vi enter insert mode after the cursor
+ * Vi enter insert mode after the cursor
* [a]
*/
protected el_action_t
@@ -481,7 +481,7 @@ vi_add_at_eol(el, c)
el->el_line.cursor = el->el_line.lastchar;
/* Mark where insertion begins */
- el->el_chared.c_vcmd.ins = el->el_line.lastchar;
+ el->el_chared.c_vcmd.ins = el->el_line.lastchar;
el->el_chared.c_undo.ptr = el->el_line.lastchar;
el->el_chared.c_undo.action = DELETE;
return CC_CURSOR;
@@ -489,7 +489,7 @@ vi_add_at_eol(el, c)
/* vi_delete_meta():
- * Vi delete prefix command
+ * Vi delete prefix command
* [d]
*/
protected el_action_t
@@ -503,8 +503,8 @@ vi_delete_meta(el, c)
/* vi_end_word():
- * Vi move to the end of the current space delimited word
- * [E]
+ * Vi move to the end of the current space delimited word
+ * [E]
*/
protected el_action_t
/*ARGSUSED*/
@@ -515,7 +515,7 @@ vi_end_word(el, c)
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
- el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
+ el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument);
if (el->el_chared.c_vcmd.action & DELETE) {
@@ -541,7 +541,7 @@ vi_to_end_word(el, c)
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
- el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
+ el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument);
if (el->el_chared.c_vcmd.action & DELETE) {
@@ -570,12 +570,12 @@ vi_undo(el, c)
c_undo_t *un = &el->el_chared.c_undo;
#ifdef DEBUG_UNDO
- (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
+ (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
un->action, un->buf, un->isize, un->dsize);
#endif
switch (un->action) {
case DELETE:
- if (un->dsize == 0)
+ if (un->dsize == 0)
return CC_NORM;
(void) memcpy(un->buf, un->ptr, un->dsize);
@@ -584,7 +584,7 @@ vi_undo(el, c)
el->el_line.lastchar -= un->dsize;
el->el_line.cursor = un->ptr;
-
+
un->action = INSERT;
un->isize = un->dsize;
un->dsize = 0;
@@ -592,9 +592,9 @@ vi_undo(el, c)
case DELETE|INSERT:
size = un->isize - un->dsize;
- if (size > 0)
+ if (size > 0)
i = un->dsize;
- else
+ else
i = un->isize;
cp = un->ptr;
kp = un->buf;
@@ -627,7 +627,7 @@ vi_undo(el, c)
break;
case INSERT:
- if (un->isize == 0)
+ if (un->isize == 0)
return CC_NORM;
el->el_line.cursor = un->ptr;
@@ -639,11 +639,11 @@ vi_undo(el, c)
break;
case CHANGE:
- if (un->isize == 0)
+ if (un->isize == 0)
return CC_NORM;
el->el_line.cursor = un->ptr;
- size = (int) (el->el_line.cursor - el->el_line.lastchar);
+ size = (int) (el->el_line.cursor - el->el_line.lastchar);
if (size < un->isize)
size = un->isize;
cp = un->ptr;
@@ -677,7 +677,7 @@ vi_command_mode(el, c)
int size;
/* [Esc] cancels pending action */
el->el_chared.c_vcmd.ins = 0;
- el->el_chared.c_vcmd.action = NOP;
+ el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = 0;
el->el_state.doingarg = 0;
@@ -700,7 +700,7 @@ vi_command_mode(el, c)
}
/* vi_zero():
- * Vi move to the beginning of line
+ * Vi move to the beginning of line
* [0]
*/
protected el_action_t
@@ -711,7 +711,7 @@ vi_zero(el, c)
if (el->el_state.doingarg) {
if (el->el_state.argument > 1000000)
return CC_ERROR;
- el->el_state.argument =
+ el->el_state.argument =
(el->el_state.argument * 10) + (c - '0');
return CC_ARGHACK;
}
@@ -727,23 +727,23 @@ vi_zero(el, c)
/* vi_delete_prev_char():
- * Vi move to previous character (backspace)
+ * Vi move to previous character (backspace)
* [^H]
- */
+ */
protected el_action_t
/*ARGSUSED*/
vi_delete_prev_char(el, c)
EditLine *el;
int c;
{
- if (el->el_chared.c_vcmd.ins == 0)
+ if (el->el_chared.c_vcmd.ins == 0)
return CC_ERROR;
- if (el->el_chared.c_vcmd.ins >
+ if (el->el_chared.c_vcmd.ins >
el->el_line.cursor - el->el_state.argument)
return CC_ERROR;
- c_delbefore(el, el->el_state.argument);
+ c_delbefore(el, el->el_state.argument);
el->el_line.cursor -= el->el_state.argument;
return CC_REFRESH;
@@ -761,7 +761,7 @@ vi_list_or_eof(el, c)
int c;
{
#ifdef notyet
- if (el->el_line.cursor == el->el_line.lastchar &&
+ if (el->el_line.cursor == el->el_line.lastchar &&
el->el_line.cursor == el->el_line.buffer) {
#endif
term_overwrite(el, STReof, 4); /* then do a EOF */
@@ -779,7 +779,7 @@ vi_list_or_eof(el, c)
/* vi_kill_line_prev():
- * Vi cut from beginning of line to cursor
+ * Vi cut from beginning of line to cursor
* [^U]
*/
protected el_action_t
@@ -839,7 +839,7 @@ vi_repeat_search_next(el, c)
EditLine *el;
int c;
{
- if (el->el_search.patlen == 0)
+ if (el->el_search.patlen == 0)
return CC_ERROR;
else
return cv_repeat_srch(el, el->el_search.patdir);
@@ -856,10 +856,10 @@ vi_repeat_search_prev(el, c)
EditLine *el;
int c;
{
- if (el->el_search.patlen == 0)
+ if (el->el_search.patlen == 0)
return CC_ERROR;
else
- return cv_repeat_srch(el,
+ return cv_repeat_srch(el,
el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY);
}
@@ -961,8 +961,8 @@ vi_repeat_next_char(el, c)
if (el->el_search.chacha == 0)
return CC_ERROR;
- return el->el_search.chadir == CHAR_FWD ?
- cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
+ return el->el_search.chadir == CHAR_FWD ?
+ cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
}
@@ -980,7 +980,7 @@ vi_repeat_prev_char(el, c)
if (el->el_search.chacha == 0)
return CC_ERROR;
- return el->el_search.chadir == CHAR_BACK ?
- cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
+ return el->el_search.chadir == CHAR_BACK ?
+ cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
}
diff --git a/lib/libf2c/Makefile b/lib/libf2c/Makefile
new file mode 100644
index 0000000..e054130
--- /dev/null
+++ b/lib/libf2c/Makefile
@@ -0,0 +1,38 @@
+.PATH: ${.CURDIR}/../libF77 ${.CURDIR}/../libI77
+
+LIB=f2c
+CFLAGS+= -DIEEE_drem -DNON_ANSI_RW_MODES -DNON_UNIX_STDIO -DPedantic -I${.CURDIR}/../../usr.bin/f2c
+
+MISC = Version.c main.c s_rnge.c abort_.c getarg_.c iargc_.c getenv_.c\
+ signal_.c s_stop.c s_paus.c system_.c cabs.c\
+ derf_.c derfc_.c erf_.c erfc_.c sig_die.c F77_aloc.c
+POW = pow_ci.c pow_dd.c pow_di.c pow_hh.c pow_ii.c pow_ri.c pow_zi.c pow_zz.c
+CX = c_abs.c c_cos.c c_div.c c_exp.c c_log.c c_sin.c c_sqrt.c
+DCX = z_cos.c z_div.c z_exp.c z_log.c z_sin.c z_sqrt.c
+REAL = r_abs.c r_acos.c r_asin.c r_atan.c r_atn2.c r_cnjg.c r_cos.c\
+ r_cosh.c r_dim.c r_exp.c r_imag.c r_int.c\
+ r_lg10.c r_log.c r_mod.c r_nint.c r_sign.c\
+ r_sin.c r_sinh.c r_sqrt.c r_tan.c r_tanh.c
+DBL = d_abs.c d_acos.c d_asin.c d_atan.c d_atn2.c\
+ d_cnjg.c d_cos.c d_cosh.c d_dim.c d_exp.c\
+ d_imag.c d_int.c d_lg10.c d_log.c d_mod.c\
+ d_nint.c d_prod.c d_sign.c d_sin.c d_sinh.c\
+ d_sqrt.c d_tan.c d_tanh.c
+INT = i_abs.c i_dim.c i_dnnt.c i_indx.c i_len.c i_mod.c i_nint.c i_sign.c
+HALF = h_abs.c h_dim.c h_dnnt.c h_indx.c h_len.c h_mod.c h_nint.c h_sign.c
+CMP = l_ge.c l_gt.c l_le.c l_lt.c hl_ge.c hl_gt.c hl_le.c hl_lt.c
+EFL = ef1asc_.c ef1cmc_.c
+CHAR = s_cat.c s_cmp.c s_copy.c
+F90BIT = lbitbits.c lbitshft.c
+
+F77SRCS= $(MISC) $(POW) $(CX) $(DCX) $(REAL) $(DBL) $(INT) \
+ $(HALF) $(CMP) $(EFL) $(CHAR) $(F90BIT)
+
+I77SRCS = Version.c backspace.c close.c dfe.c dolio.c due.c endfile.c err.c \
+ fmt.c fmtlib.c iio.c ilnw.c inquire.c lread.c lwrite.c open.c \
+ rdfmt.c rewind.c rsfe.c rsli.c rsne.c sfe.c sue.c typesize.c uio.c \
+ util.c wref.c wrtfmt.c wsfe.c wsle.c wsne.c xwsne.c
+
+SRCS= ${F77SRCS} ${I77SRCS}
+
+.include <bsd.lib.mk>
diff --git a/lib/libftpio/Makefile b/lib/libftpio/Makefile
new file mode 100644
index 0000000..ce86c16
--- /dev/null
+++ b/lib/libftpio/Makefile
@@ -0,0 +1,28 @@
+LIB= ftpio
+CFLAGS+= -I${.CURDIR} -Wall
+SRCS= ftpio.c ftperr.c
+MAN3= ftpio.3
+CLEANFILES+= ftperr.c
+
+SHLIB_MAJOR= 4
+SHLIB_MINOR= 0
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/ftpio.h \
+ ${DESTDIR}/usr/include
+
+ftperr.c: ftp.errors
+ @echo '#include <stdio.h>' > ${.TARGET}
+ @echo '#include "ftpio.h"' >> ${.TARGET}
+ @echo "struct ftperr ftpErrList[] = {" \ >> ${.TARGET}
+ @cat ${.ALLSRC} \
+ | grep -v ^# \
+ | sort \
+ | while read NUM STRING; do \
+ echo " { $${NUM}, \"$${STRING}\" },"; \
+ done >> ${.TARGET}
+ @echo "};" >> ${.TARGET}
+ @echo -n "int const ftpErrListLength = " >> ${.TARGET}
+ @echo "sizeof(ftpErrList) / sizeof(*ftpErrList);" >> ${.TARGET}
+
+.include <bsd.lib.mk>
diff --git a/lib/libftpio/ftp.errors b/lib/libftpio/ftp.errors
new file mode 100644
index 0000000..26cb4f6
--- /dev/null
+++ b/lib/libftpio/ftp.errors
@@ -0,0 +1,44 @@
+# $Id$
+#
+# This list is taken from RFC 959.
+# It probably needs a going over.
+#
+110 Restart marker reply
+120 Service ready in a few minutes
+125 Data connection already open; transfer starting
+150 File status okay; about to open data connection
+200 Command okay
+202 Command not implemented, superfluous at this site
+211 System status, or system help reply
+212 Directory status
+213 File status
+214 Help message
+215 Set system type
+220 Service ready for new user
+221 Service closing control connection
+225 Data connection open; no transfer in progress
+226 Requested file action successful
+227 Entering Passive Mode
+230 User logged in, proceed
+250 Requested file action okay, completed
+257 File/directory created
+331 User name okay, need password
+332 Need account for login
+350 Requested file action pending further information
+421 Service not available, closing control connection
+425 Can't open data connection
+426 Connection closed; transfer aborted
+450 File unavailable (e.g., file busy)
+451 Requested action aborted: local error in processing
+452 Insufficient storage space in system
+500 Syntax error, command unrecognized
+501 Syntax error in parameters or arguments
+502 Command not implemented
+503 Bad sequence of commands
+504 Command not implemented for that parameter
+530 Not logged in
+532 Need account for storing files
+550 File unavailable (e.g., file not found, no access)
+551 Requested action aborted. Page type unknown
+552 Exceeded storage allocation
+553 File name not allowed
diff --git a/lib/libftpio/ftpio.3 b/lib/libftpio/ftpio.3
new file mode 100644
index 0000000..11e7cdb
--- /dev/null
+++ b/lib/libftpio/ftpio.3
@@ -0,0 +1,198 @@
+.\" Copyright (c) 1996 Jordan Hubbard (jkh@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 JORDAN HUBBARD ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (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: ftpio.3,v 1.14 1997/02/22 15:06:48 peter Exp $
+.\"
+.Dd June 17, 1996
+.Dt ftpio 3
+.Os
+.Sh NAME
+.Nm ftpLogin ,
+.Nm ftpChdir ,
+.Nm ftpErrno ,
+.Nm ftpGetModtime ,
+.Nm ftpGetSize ,
+.Nm ftpGet ,
+.Nm ftpPut ,
+.Nm ftpBinary ,
+.Nm ftpPassive ,
+.Nm ftpVerbose ,
+.Nm ftpGetURL ,
+.Nm ftpPutURL
+.Nd FTPIO User library
+.Sh SYNOPSIS
+.Fd #include <ftpio.h>
+.Ft FILE *
+.Fn ftpLogin "char *host" "char *user" "char *passwd" "int ftp_port" "int verbose" "int *retcode"
+.Ft int
+.Fn ftpChdir "FILE *stream, char *dirname"
+.Ft int
+.Fn ftpErrno "FILE *stream"
+.Ft const char *
+.Fn ftpErrString "int errno"
+.Ft time_t
+.Fn ftpGetModtime "FILE *stream, char *file"
+.Ft off_t
+.Fn ftpGetSize "FILE *stream, char *file"
+.Ft FILE *
+.Fn ftpGet "FILE *stream, char *file, off_t *seekto"
+.Ft FILE *
+.Fn ftpPut "FILE *stream, char *file"
+.Ft int
+.Fn ftpAscii "FILE *stream"
+.Ft int
+.Fn ftpBinary "FILE *stream"
+.Ft int
+.Fn ftpPassive "FILE *stream, int status"
+.Ft void
+.Fn ftpVerbose "FILE *stream, int status"
+.Ft FILE *
+.Fn ftpGetURL "char *url, char *user, char *passwd, int *retcode"
+.Ft FILE *
+.Fn ftpPutURL "char *url, char *user, char *passwd, int *retcode"
+
+.Sh DESCRIPTION
+These functions implement a high-level library for managing FTP connections.
+.Pp
+.Fn ftpLogin
+attempts to log in using the supplied
+.Fa user ,
+.Fa passwd,
+.Fa ftp_port
+(if passed as 0,
+.Fa ftp_port
+defaults to the standard ftp port of 21) and
+.Fa verbose
+fields. If it is successful, a
+standard stream descriptor is returned which should be passed to
+subsequent FTP operations. On failure, NULL is returned and
+.Fa retcode
+will have the error code returned by the foreign server.
+.Pp
+.Fn ftpChdir
+attempts to issue a server CD command to the directory named in
+.Fa dir.
+On success, zero is returned. On failure, the error code from the server.
+.Pp
+.Fn ftpErrno
+returns the server failure code for the last operation (useful for seeing
+more about what happened if you're familiar with FTP error codes).
+.Fn ftpErrString
+returns a human readable version of the supplied server failure code.
+.Pp
+.Fn ftpGet
+attempts to retreive the file named by the
+.Fa file
+argument (which is assumed to be relative to the FTP server's current directory,
+see
+.Fn ftpChdir )
+and returns a new FILE* pointer for the file or NULL on failure. If
+.Fa seekto
+is non-NULL, the contents of the integer it points to will be used
+as a restart point for the file, that is to say that the stream
+returned will point
+.Fa *seekto
+bytes into the file gotten (this is handy for restarting failed
+transfers efficiently). If the seek operation fails, the value
+of
+.Fa *seekto
+will be zero'd.
+.Pp
+.Fn ftpGetModtime
+returns the last modification time of the file named by the
+.Fa file
+argument. If the file could not be opened or stat'd, 0 is returned.
+.Pp
+.Fn ftpGetSize
+returns the size in bytes of the file named by the
+.Fa file
+argument. If the file could not be opened or stat'd, -1 is returned.
+.Pp
+.Fn ftpPut
+attempts to create a new file named by the
+.Fa file
+argument (which is assumed to be relative to the FTP server's current directory,
+see
+.Fn ftpChdir )
+and returns a new
+.Fa stream
+pointer for the file or NULL on failure.
+.Pp
+.Fn ftpAscii
+sets ascii mode for the current server connection named by
+.Fa stream .
+.Pp
+.Fn ftpBinary
+sets binary mode for the current server connection named by
+.Fa stream .
+.Pp
+.Fn ftpPassive
+sets passive mode (for firewalls) for the current server connection named by
+.Fa stream
+to boolean value
+.Fa status .
+.Pp
+.Fn ftpVerbose
+sets the verbosity mode for the current server connection named by
+.Fa stream
+to boolean value
+.Fa status .
+.Pp
+.Fn ftpGetURL
+attempts to retreive the file named by the supplied
+.Fa URL
+and can be considered equivalent to the combined
+.Fn ftpLogin ,
+.Fn ftpChdir
+and
+.Fn ftpGet
+operations except that no server
+.Fa stream
+is ever returned - the connection to the server closes when
+the file has been completely read. Use the lower-level routines
+if multiple gets are required as it will be far more efficient.
+.Pp
+.Fn ftpPutURL
+attempts to create the file named by the supplied
+.Fa URL
+and can be considered equivalent to the combined
+.Fn ftpLogin ,
+.Fn ftpChdir
+and
+.Fn ftpPut
+operations except that no server stream is ever returned - the connection
+to the server closes when the file has been completely written. Use the
+lower-level routines if multiple puts are required as it will be far more
+efficient.
+.Sh BUGS
+I'm sure you can get this thing's internal state machine confused if
+you really work at it, but so far it's proven itself pretty robust in
+all my tests.
+.Sh HISTORY
+Started life as Poul-Henning Kamp's ftp driver for the system installation
+utility, later significantly mutated into a more general form as an
+extension of stdio by Jordan Hubbard. Also incorporates some ideas and
+extensions from Jean-Marc Zucconi.
+.Sh AUTHORS
+Jordan Hubbard, Poul-Henning Kamp and Jean-Marc Zucconi
diff --git a/lib/libftpio/ftpio.c b/lib/libftpio/ftpio.c
new file mode 100644
index 0000000..bdb7d2e
--- /dev/null
+++ b/lib/libftpio/ftpio.c
@@ -0,0 +1,865 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * Major Changelog:
+ *
+ * Jordan K. Hubbard
+ * 17 Jan 1996
+ *
+ * Turned inside out. Now returns xfers as new file ids, not as a special
+ * `state' of FTP_t
+ *
+ * $Id$
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <ftpio.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define SUCCESS 0
+#define FAILURE -1
+
+#ifndef TRUE
+#define TRUE (1)
+#define FALSE (0)
+#endif
+
+/* How to see by a given code whether or not the connection has timed out */
+#define FTP_TIMEOUT(code) (FtpTimedOut || code == FTP_TIMED_OUT)
+
+/* Internal routines - deal only with internal FTP_t type */
+static FTP_t ftp_new(void);
+static void check_passive(FILE *fp);
+static int ftp_read_method(void *n, char *buf, int nbytes);
+static int ftp_write_method(void *n, const char *buf, int nbytes);
+static int ftp_close_method(void *n);
+static int writes(int fd, char *s);
+static __inline char *get_a_line(FTP_t ftp);
+static int get_a_number(FTP_t ftp, char **q);
+static int botch(char *func, char *botch_state);
+static int cmd(FTP_t ftp, const char *fmt, ...);
+static int ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port, int verbose);
+static int ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto);
+static int ftp_close(FTP_t ftp);
+static int get_url_info(char *url_in, char *host_ret, int *port_ret, char *name_ret);
+static void ftp_timeout(int sig);
+static void ftp_set_timeout(void);
+static void ftp_clear_timeout(void);
+
+
+/* Global status variable - ick */
+int FtpTimedOut;
+
+/* FTP happy status codes */
+#define FTP_GENERALLY_HAPPY 200
+#define FTP_ASCII_HAPPY FTP_GENERALLY_HAPPY
+#define FTP_BINARY_HAPPY FTP_GENERALLY_HAPPY
+#define FTP_PORT_HAPPY FTP_GENERALLY_HAPPY
+#define FTP_HAPPY_COMMENT 220
+#define FTP_QUIT_HAPPY 221
+#define FTP_TRANSFER_HAPPY 226
+#define FTP_PASSIVE_HAPPY 227
+#define FTP_CHDIR_HAPPY 250
+
+/* FTP unhappy status codes */
+#define FTP_TIMED_OUT 421
+
+/*
+ * XXX
+ * gross! evil! bad! We really need an access primitive for cookie in stdio itself.
+ * it's too convenient a hook to bury and it's already exported through funopen as it is, so...
+ * XXX
+ */
+#define fcookie(fp) ((fp)->_cookie)
+
+/* Placeholder in case we want to do any pre-init stuff at some point */
+int
+networkInit()
+{
+ return SUCCESS; /* XXX dummy function for now XXX */
+}
+
+/* Check a return code with some lenience for back-dated garbage that might be in the buffer */
+static int
+check_code(FTP_t ftp, int var, int preferred)
+{
+ ftp->errno = 0;
+ while (1) {
+ if (var == preferred)
+ return 0;
+ else if (var == FTP_TRANSFER_HAPPY) /* last operation succeeded */
+ var = get_a_number(ftp, NULL);
+ else if (var == FTP_HAPPY_COMMENT) /* chit-chat */
+ var = get_a_number(ftp, NULL);
+ else if (var == FTP_GENERALLY_HAPPY) /* general success code */
+ var = get_a_number(ftp, NULL);
+ else {
+ ftp->errno = var;
+ return 1;
+ }
+ }
+}
+
+int
+ftpAscii(FILE *fp)
+{
+ FTP_t ftp = fcookie(fp);
+ int i;
+
+ if (!ftp->is_binary)
+ return SUCCESS;
+ i = cmd(ftp, "TYPE A");
+ if (i < 0 || check_code(ftp, i, FTP_ASCII_HAPPY))
+ return i;
+ ftp->is_binary = FALSE;
+ return SUCCESS;
+}
+
+int
+ftpBinary(FILE *fp)
+{
+ FTP_t ftp = fcookie(fp);
+ int i;
+
+ if (ftp->is_binary)
+ return SUCCESS;
+ i = cmd(ftp, "TYPE I");
+ if (i < 0 || check_code(ftp, i, FTP_BINARY_HAPPY))
+ return i;
+ ftp->is_binary = TRUE;
+ return SUCCESS;
+}
+void
+ftpVerbose(FILE *fp, int status)
+{
+ FTP_t ftp = fcookie(fp);
+ ftp->is_verbose = status;
+}
+
+int
+ftpChdir(FILE *fp, char *dir)
+{
+ int i;
+ FTP_t ftp = fcookie(fp);
+
+ i = cmd(ftp, "CWD %s", dir);
+ if (i < 0 || check_code(ftp, i, FTP_CHDIR_HAPPY))
+ return i;
+ return SUCCESS;
+}
+
+int
+ftpErrno(FILE *fp)
+{
+ FTP_t ftp = fcookie(fp);
+ return ftp->errno;
+}
+
+const char *
+ftpErrString(int errno)
+{
+ int k;
+
+ if (errno == -1)
+ return("connection in wrong state");
+ for (k = 0; k < ftpErrListLength; k++)
+ if (ftpErrList[k].num == errno)
+ return(ftpErrList[k].string);
+ return("Unknown error");
+}
+
+off_t
+ftpGetSize(FILE *fp, char *name)
+{
+ int i;
+ char p[BUFSIZ], *cp, *ep;
+ FTP_t ftp = fcookie(fp);
+ off_t size;
+
+ check_passive(fp);
+ sprintf(p, "SIZE %s\r\n", name);
+ if (ftp->is_verbose)
+ fprintf(stderr, "Sending %s", p);
+ if (writes(ftp->fd_ctrl, p))
+ return (off_t)-1;
+ i = get_a_number(ftp, &cp);
+ if (check_code(ftp, i, 213))
+ return (off_t)-1;
+
+ errno = 0; /* to check for ERANGE */
+ size = (off_t)strtoq(cp, &ep, 10);
+ if (*ep != '\0' || errno == ERANGE)
+ return (off_t)-1;
+ return size;
+}
+
+time_t
+ftpGetModtime(FILE *fp, char *name)
+{
+ char p[BUFSIZ], *cp;
+ struct tm t;
+ time_t t0 = time (0);
+ FTP_t ftp = fcookie(fp);
+ int i;
+
+ check_passive(fp);
+ sprintf(p, "MDTM %s\r\n", name);
+ if (ftp->is_verbose)
+ fprintf(stderr, "Sending %s", p);
+ if (writes(ftp->fd_ctrl, p))
+ return (time_t)0;
+ i = get_a_number(ftp, &cp);
+ if (check_code(ftp, i, 213))
+ return (time_t)0;
+ while (*cp && !isdigit(*cp))
+ cp++;
+ if (!*cp)
+ return (time_t)0;
+ t0 = localtime (&t0)->tm_gmtoff;
+ sscanf(cp, "%04d%02d%02d%02d%02d%02d", &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec);
+ t.tm_mon--;
+ t.tm_year -= 1900;
+ t.tm_isdst=-1;
+ t.tm_gmtoff = 0;
+ t0 += mktime (&t);
+ return t0;
+}
+
+FILE *
+ftpGet(FILE *fp, char *file, off_t *seekto)
+{
+ FILE *fp2;
+ FTP_t ftp = fcookie(fp);
+
+ check_passive(fp);
+ if (ftpBinary(fp) != SUCCESS)
+ return NULL;
+
+ if (ftp_file_op(ftp, "RETR", file, &fp2, "r", seekto) == SUCCESS)
+ return fp2;
+ return NULL;
+}
+
+/* Returns a standard FILE pointer type representing an open control connection */
+FILE *
+ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retcode)
+{
+ FTP_t n;
+ FILE *fp;
+
+ if (retcode)
+ *retcode = 0;
+ if (networkInit() != SUCCESS)
+ return NULL;
+
+ n = ftp_new();
+ fp = NULL;
+ if (n && ftp_login_session(n, host, user, passwd, port, verbose) == SUCCESS) {
+ fp = funopen(n, ftp_read_method, ftp_write_method, NULL, ftp_close_method); /* BSD 4.4 function! */
+ fp->_file = n->fd_ctrl;
+ }
+ if (retcode) {
+ if (!n)
+ *retcode = (FtpTimedOut ? FTP_TIMED_OUT : -1);
+ /* Poor attempt at mapping real errnos to FTP error codes */
+ else switch(n->errno) {
+ case EADDRNOTAVAIL:
+ *retcode = FTP_TIMED_OUT; /* Actually no such host, but we have no way of saying that. :-( */
+ break;
+
+ case ETIMEDOUT:
+ *retcode = FTP_TIMED_OUT;
+ break;
+
+ default:
+ *retcode = n->errno;
+ break;
+ }
+ }
+ return fp;
+}
+
+FILE *
+ftpPut(FILE *fp, char *file)
+{
+ FILE *fp2;
+ FTP_t ftp = fcookie(fp);
+
+ check_passive(fp);
+ if (ftp_file_op(ftp, "STOR", file, &fp2, "w", NULL) == SUCCESS)
+ return fp2;
+ return NULL;
+}
+
+/* Unlike binary mode, passive mode is a toggle! :-( */
+int
+ftpPassive(FILE *fp, int st)
+{
+ FTP_t ftp = fcookie(fp);
+ int i;
+
+ if (ftp->is_passive == st)
+ return SUCCESS;
+ i = cmd(ftp, "PASV");
+ if (i < 0)
+ return i;
+ ftp->is_passive = !ftp->is_passive;
+ return SUCCESS;
+}
+
+FILE *
+ftpGetURL(char *url, char *user, char *passwd, int *retcode)
+{
+ char host[255], name[255];
+ int port;
+ FILE *fp2;
+ static FILE *fp = NULL;
+ static char *prev_host;
+
+ if (retcode)
+ *retcode = 0;
+ if (get_url_info(url, host, &port, name) == SUCCESS) {
+ if (fp && prev_host) {
+ if (!strcmp(prev_host, host)) {
+ /* Try to use cached connection */
+ fp2 = ftpGet(fp, name, NULL);
+ if (!fp2) {
+ /* Connection timed out or was no longer valid */
+ fclose(fp);
+ free(prev_host);
+ prev_host = NULL;
+ }
+ else
+ return fp2;
+ }
+ else {
+ /* It's a different host now, flush old */
+ fclose(fp);
+ free(prev_host);
+ prev_host = NULL;
+ }
+ }
+ fp = ftpLogin(host, user, passwd, port, 0, retcode);
+ if (fp) {
+ fp2 = ftpGet(fp, name, NULL);
+ if (!fp2) {
+ /* Connection timed out or was no longer valid */
+ if (retcode)
+ *retcode = ftpErrno(fp);
+ fclose(fp);
+ fp = NULL;
+ }
+ else
+ prev_host = strdup(host);
+ return fp2;
+ }
+ }
+ return NULL;
+}
+
+FILE *
+ftpPutURL(char *url, char *user, char *passwd, int *retcode)
+{
+ char host[255], name[255];
+ int port;
+ static FILE *fp = NULL;
+ FILE *fp2;
+
+ if (retcode)
+ *retcode = 0;
+ if (fp) { /* Close previous managed connection */
+ fclose(fp);
+ fp = NULL;
+ }
+ if (get_url_info(url, host, &port, name) == SUCCESS) {
+ fp = ftpLogin(host, user, passwd, port, 0, retcode);
+ if (fp) {
+ fp2 = ftpPut(fp, name);
+ if (!fp2) {
+ if (retcode)
+ *retcode = ftpErrno(fp);
+ fclose(fp);
+ fp = NULL;
+ }
+ return fp2;
+ }
+ }
+ return NULL;
+}
+
+/* Internal workhorse function for dissecting URLs. Takes a URL as the first argument and returns the
+ result of such disection in the host, user, passwd, port and name variables. */
+static int
+get_url_info(char *url_in, char *host_ret, int *port_ret, char *name_ret)
+{
+ char *name, *host, *cp, url[BUFSIZ];
+ int port;
+
+ name = host = NULL;
+ /* XXX add http:// here or somewhere reasonable at some point XXX */
+ if (strncmp("ftp://", url_in, 6) != NULL)
+ return FAILURE;
+ /* We like to stomp a lot on the URL string in dissecting it, so copy it first */
+ strncpy(url, url_in, BUFSIZ);
+ host = url + 6;
+ if ((cp = index(host, ':')) != NULL) {
+ *(cp++) = '\0';
+ port = strtol(cp, 0, 0);
+ }
+ else
+ port = 0; /* use default */
+ if (port_ret)
+ *port_ret = port;
+
+ if ((name = index(cp ? cp : host, '/')) != NULL)
+ *(name++) = '\0';
+ if (host_ret)
+ strcpy(host_ret, host);
+ if (name && name_ret)
+ strcpy(name_ret, name);
+ return SUCCESS;
+}
+
+static FTP_t
+ftp_new(void)
+{
+ FTP_t ftp;
+
+ ftp = (FTP_t)malloc(sizeof *ftp);
+ if (!ftp)
+ return NULL;
+ memset(ftp, 0, sizeof *ftp);
+ ftp->fd_ctrl = -1;
+ ftp->con_state = init;
+ ftp->is_binary = FALSE;
+ ftp->is_passive = FALSE;
+ ftp->is_verbose = FALSE;
+ ftp->errno = 0;
+ return ftp;
+}
+
+static int
+ftp_read_method(void *vp, char *buf, int nbytes)
+{
+ int i, fd;
+ FTP_t n = (FTP_t)vp;
+
+ fd = n->fd_ctrl;
+ i = (fd >= 0) ? read(fd, buf, nbytes) : EOF;
+ return i;
+}
+
+static int
+ftp_write_method(void *vp, const char *buf, int nbytes)
+{
+ int i, fd;
+ FTP_t n = (FTP_t)vp;
+
+ fd = n->fd_ctrl;
+ i = (fd >= 0) ? write(fd, buf, nbytes) : EOF;
+ return i;
+}
+
+static int
+ftp_close_method(void *n)
+{
+ int i;
+
+ i = ftp_close((FTP_t)n);
+ free(n);
+ return i;
+}
+
+static void
+check_passive(FILE *fp)
+{
+ if (getenv("FTP_PASSIVE_MODE"))
+ ftpPassive(fp, TRUE);
+}
+
+static void
+ftp_timeout(int sig)
+{
+ FtpTimedOut = TRUE;
+ /* Debug("ftp_pkg: ftp_timeout called - operation timed out"); */
+}
+
+static struct sigaction new;
+
+static void
+ftp_set_timeout(void)
+{
+ char *cp;
+ int ival;
+
+ FtpTimedOut = FALSE;
+ new.sa_handler = ftp_timeout;
+ sigaction(SIGALRM, &new, NULL);
+ cp = getenv("FTP_TIMEOUT");
+ if (!cp || !(ival = atoi(cp)))
+ ival = 120;
+ alarm(ival);
+}
+
+static void
+ftp_clear_timeout(void)
+{
+ alarm(0);
+ new.sa_handler = SIG_DFL;
+ sigaction(SIGALRM, &new, NULL);
+}
+
+static int
+writes(int fd, char *s)
+{
+ int n, i = strlen(s);
+
+ ftp_set_timeout();
+ n = write(fd, s, i);
+ ftp_clear_timeout();
+ if (FtpTimedOut || i != n)
+ return TRUE;
+ return FALSE;
+}
+
+static __inline char *
+get_a_line(FTP_t ftp)
+{
+ static char buf[BUFSIZ];
+ int i,j;
+
+ /* Debug("ftp_pkg: trying to read a line from %d", ftp->fd_ctrl); */
+ for(i = 0; i < BUFSIZ;) {
+ ftp_set_timeout();
+ j = read(ftp->fd_ctrl, buf + i, 1);
+ ftp_clear_timeout();
+ if (FtpTimedOut || j != 1)
+ return NULL;
+ if (buf[i] == '\r' || buf[i] == '\n') {
+ if (!i)
+ continue;
+ buf[i] = '\0';
+ if (ftp->is_verbose == TRUE)
+ fprintf(stderr, "%s\n",buf+4);
+ return buf;
+ }
+ i++;
+ }
+ /* Debug("ftp_pkg: read string \"%s\" from %d", buf, ftp->fd_ctrl); */
+ return buf;
+}
+
+static int
+get_a_number(FTP_t ftp, char **q)
+{
+ char *p;
+ int i = -1, j;
+
+ while(1) {
+ p = get_a_line(ftp);
+ if (!p) {
+ ftp_close(ftp);
+ if (FtpTimedOut)
+ return FTP_TIMED_OUT;
+ return FAILURE;
+ }
+ if (!(isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2])))
+ continue;
+ if (i == -1 && p[3] == '-') {
+ i = strtol(p, 0, 0);
+ continue;
+ }
+ if (p[3] != ' ' && p[3] != '\t')
+ continue;
+ j = strtol(p, 0, 0);
+ if (i == -1) {
+ if (q) *q = p+4;
+ /* Debug("ftp_pkg: read reply %d from server (%s)", j, p); */
+ return j;
+ } else if (j == i) {
+ if (q) *q = p+4;
+ /* Debug("ftp_pkg: read reply %d from server (%s)", j, p); */
+ return j;
+ }
+ }
+}
+
+static int
+ftp_close(FTP_t ftp)
+{
+ int i;
+
+ if (ftp->con_state == isopen) {
+ ftp->con_state = quit;
+ /* If last operation timed out, don't try to quit - just close */
+ if (ftp->errno != FTP_TIMED_OUT)
+ i = cmd(ftp, "QUIT");
+ else
+ i = FTP_QUIT_HAPPY;
+ close(ftp->fd_ctrl);
+ ftp->fd_ctrl = -1;
+ if (check_code(ftp, i, FTP_QUIT_HAPPY)) {
+ ftp->errno = i;
+ return FAILURE;
+ }
+ /* Debug("ftp_pkg: ftp_close() - proper shutdown"); */
+ return SUCCESS;
+ }
+ /* Debug("ftp_pkg: ftp_close() - improper shutdown"); */
+ return FAILURE;
+}
+
+static int
+botch(char *func, char *botch_state)
+{
+ /* Debug("ftp_pkg: botch: %s(%s)", func, botch_state); */
+ return FAILURE;
+}
+
+static int
+cmd(FTP_t ftp, const char *fmt, ...)
+{
+ char p[BUFSIZ];
+ int i;
+
+ va_list ap;
+ va_start(ap, fmt);
+ (void)vsnprintf(p, sizeof p, fmt, ap);
+ va_end(ap);
+
+ if (ftp->con_state == init)
+ return botch("cmd", "open");
+
+ strcat(p, "\r\n");
+ if (ftp->is_verbose)
+ fprintf(stderr, "Sending: %s", p);
+ if (writes(ftp->fd_ctrl, p)) {
+ if (FtpTimedOut)
+ return FTP_TIMED_OUT;
+ return FAILURE;
+ }
+ while ((i = get_a_number(ftp, NULL)) == FTP_HAPPY_COMMENT);
+ return i;
+}
+
+static int
+ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port, int verbose)
+{
+ struct hostent *he = NULL;
+ struct sockaddr_in sin;
+ int s;
+ unsigned long temp;
+ int i;
+
+ if (networkInit() != SUCCESS)
+ return FAILURE;
+
+ if (ftp->con_state != init) {
+ ftp_close(ftp);
+ ftp->errno = -1;
+ return FAILURE;
+ }
+
+ if (!user)
+ user = "ftp";
+
+ if (!passwd)
+ passwd = "setup@";
+
+ if (!port)
+ port = 21;
+
+ temp = inet_addr(host);
+ if (temp != INADDR_NONE) {
+ ftp->addrtype = sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = temp;
+ }
+ else {
+ he = gethostbyname(host);
+ if (!he) {
+ ftp->errno = 0;
+ return FAILURE;
+ }
+ ftp->addrtype = sin.sin_family = he->h_addrtype;
+ bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);
+ }
+
+ sin.sin_port = htons(port);
+
+ if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0) {
+ ftp->errno = -1;
+ return FAILURE;
+ }
+
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ (void)close(s);
+ ftp->errno = errno;
+ return FAILURE;
+ }
+
+ ftp->fd_ctrl = s;
+ ftp->con_state = isopen;
+ ftp->is_verbose = verbose;
+
+ i = cmd(ftp, "USER %s", user);
+ if (i >= 300 && i < 400)
+ i = cmd(ftp, "PASS %s", passwd);
+ if (i >= 299 || i < 0) {
+ ftp_close(ftp);
+ if (i > 0)
+ ftp->errno = i;
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
+static int
+ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto)
+{
+ int i,s;
+ char *q;
+ unsigned char addr[64];
+ struct sockaddr_in sin;
+ u_long a;
+
+ if (!fp)
+ return FAILURE;
+ *fp = NULL;
+
+ if (ftp->con_state != isopen)
+ return botch("ftp_file_op", "open");
+
+ if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0) {
+ ftp->errno = errno;
+ return FAILURE;
+ }
+
+ if (ftp->is_passive) {
+ if (ftp->is_verbose)
+ fprintf(stderr, "Sending PASV\n");
+ if (writes(ftp->fd_ctrl, "PASV\r\n")) {
+ ftp_close(ftp);
+ if (FtpTimedOut)
+ ftp->errno = FTP_TIMED_OUT;
+ return FTP_TIMED_OUT;
+ }
+ i = get_a_number(ftp, &q);
+ if (check_code(ftp, i, FTP_PASSIVE_HAPPY)) {
+ ftp_close(ftp);
+ return i;
+ }
+ while (*q && !isdigit(*q))
+ q++;
+ if (!*q) {
+ ftp_close(ftp);
+ return FAILURE;
+ }
+ q--;
+ for (i = 0; i < 6; i++) {
+ q++;
+ addr[i] = strtol(q, &q, 10);
+ }
+
+ sin.sin_family = ftp->addrtype;
+ bcopy(addr, (char *)&sin.sin_addr, 4);
+ bcopy(addr + 4, (char *)&sin.sin_port, 2);
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ (void)close(s);
+ return FAILURE;
+ }
+
+ if (seekto && *seekto) {
+ i = cmd(ftp, "REST %d", *seekto);
+ if (i < 0 || FTP_TIMEOUT(i)) {
+ close(s);
+ ftp->errno = i;
+ *seekto = (off_t)0;
+ return i;
+ }
+ }
+ i = cmd(ftp, "%s %s", operation, file);
+ if (i < 0 || i > 299) {
+ close(s);
+ ftp->errno = i;
+ return i;
+ }
+ *fp = fdopen(s, mode);
+ }
+ else {
+ int fd;
+
+ i = sizeof sin;
+ getsockname(ftp->fd_ctrl, (struct sockaddr *)&sin, &i);
+ sin.sin_port = 0;
+ i = sizeof sin;
+ if (bind(s, (struct sockaddr *)&sin, i) < 0) {
+ close(s);
+ return FAILURE;
+ }
+ getsockname(s,(struct sockaddr *)&sin,&i);
+ if (listen(s, 1) < 0) {
+ close(s);
+ return FAILURE;
+ }
+ a = ntohl(sin.sin_addr.s_addr);
+ i = cmd(ftp, "PORT %d,%d,%d,%d,%d,%d",
+ (a >> 24) & 0xff,
+ (a >> 16) & 0xff,
+ (a >> 8) & 0xff,
+ a & 0xff,
+ (ntohs(sin.sin_port) >> 8) & 0xff,
+ ntohs(sin.sin_port) & 0xff);
+ if (check_code(ftp, i, FTP_PORT_HAPPY)) {
+ close(s);
+ return i;
+ }
+ if (seekto && *seekto) {
+ i = cmd(ftp, "REST %d", *seekto);
+ if (i < 0 || FTP_TIMEOUT(i)) {
+ close(s);
+ ftp->errno = i;
+ return i;
+ }
+ else if (i != 350)
+ *seekto = (off_t)0;
+ }
+ i = cmd(ftp, "%s %s", operation, file);
+ if (i < 0 || i > 299) {
+ close(s);
+ ftp->errno = i;
+ return FAILURE;
+ }
+ fd = accept(s, 0, 0);
+ if (fd < 0) {
+ close(s);
+ ftp->errno = 401;
+ return FAILURE;
+ }
+ close(s);
+ *fp = fdopen(fd, mode);
+ }
+ if (*fp)
+ return SUCCESS;
+ else
+ return FAILURE;
+}
diff --git a/lib/libftpio/ftpio.h b/lib/libftpio/ftpio.h
new file mode 100644
index 0000000..4dee7d9
--- /dev/null
+++ b/lib/libftpio/ftpio.h
@@ -0,0 +1,68 @@
+#ifndef _FTP_H_INCLUDE
+#define _FTP_H_INCLUDE
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <time.h>
+
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * Major Changelog:
+ *
+ * Jordan K. Hubbard
+ * 17 Jan 1996
+ *
+ * Turned inside out. Now returns xfers as new file ids, not as a special
+ * `state' of FTP_t
+ *
+ * $Id: ftpio.h,v 1.12 1997/02/22 15:06:52 peter Exp $
+ */
+
+/* Internal housekeeping data structure for FTP sessions */
+typedef struct {
+ enum { init, isopen, quit } con_state;
+ int fd_ctrl;
+ int addrtype;
+ char *host;
+ char *file;
+ int errno;
+ int is_binary;
+ int is_passive;
+ int is_verbose;
+} *FTP_t;
+
+/* Structure we use to match FTP error codes with readable strings */
+struct ftperr {
+ const int num;
+ const char *string;
+};
+
+__BEGIN_DECLS
+extern struct ftperr ftpErrList[];
+extern int const ftpErrListLength;
+
+/* Exported routines - deal only with FILE* type */
+extern FILE *ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retcode);
+extern int ftpChdir(FILE *fp, char *dir);
+extern int ftpErrno(FILE *fp);
+extern off_t ftpGetSize(FILE *fp, char *file);
+extern FILE *ftpGet(FILE *fp, char *file, off_t *seekto);
+extern FILE *ftpPut(FILE *fp, char *file);
+extern int ftpAscii(FILE *fp);
+extern int ftpBinary(FILE *fp);
+extern int ftpPassive(FILE *fp, int status);
+extern void ftpVerbose(FILE *fp, int status);
+extern FILE *ftpGetURL(char *url, char *user, char *passwd, int *retcode);
+extern FILE *ftpPutURL(char *url, char *user, char *passwd, int *retcode);
+extern time_t ftpGetModtime(FILE *fp, char *s);
+extern const char *ftpErrString(int errno);
+__END_DECLS
+
+#endif /* _FTP_H_INCLUDE */
diff --git a/lib/libgnumalloc/Makefile b/lib/libgnumalloc/Makefile
new file mode 100644
index 0000000..9d30fa2
--- /dev/null
+++ b/lib/libgnumalloc/Makefile
@@ -0,0 +1,30 @@
+# $Id$
+
+LIB= gnumalloc
+INTERNALLIB= yes # Do not build or install ${LIB}*.a
+SHLIB_MAJOR= 2
+SHLIB_MINOR= 0
+
+SRCS= cfree.c
+
+#
+# Before complaining about this, please *double-check* that you have
+# updated the ldconfig path in /etc/rc to include /usr/lib/compat that
+# was added in src/etc/rc rev 1.98.
+# This is so that programs that use autoconf will not "detect" -lgnumalloc
+# and continue to propagate the bogosity. The ldconfig path fix will enable
+# you to run programs that were linked with -lgnumalloc (such as XFree86).
+#
+beforeinstall:
+ rm -f ${DESTDIR}${LIBDIR}/lib${LIB}.a \
+ ${DESTDIR}${LIBDIR}/lib${LIB}_p.a \
+ ${DESTDIR}${ORIG_SHLIBDIR}/lib${LIB}.so.${SHLIB_MAJOR}.${SHLIB_MINOR}
+
+.include <bsd.lib.mk>
+
+# This must follow the .include in case SHLIBDIR is defined there.
+ORIG_SHLIBDIR:= ${SHLIBDIR}
+
+# The ldconfig line in/etc/rc doesn't depend on ${LIBDIR} or ${SHLIBDIR},
+# so neither does this.
+SHLIBDIR= /usr/lib/compat
diff --git a/lib/libgnumalloc/cfree.c b/lib/libgnumalloc/cfree.c
new file mode 100644
index 0000000..5191fd6
--- /dev/null
+++ b/lib/libgnumalloc/cfree.c
@@ -0,0 +1,5 @@
+void
+cfree(void *foo)
+{
+ free(foo);
+}
diff --git a/lib/libipx/Makefile b/lib/libipx/Makefile
new file mode 100644
index 0000000..7158df8
--- /dev/null
+++ b/lib/libipx/Makefile
@@ -0,0 +1,9 @@
+LIB= ipx
+#CFLAGS+=-DLIBC_SCCS -I/sys
+SRCS= ipx_addr.c ipx_ntoa.c
+
+MAN3= ipx.3
+
+MLINKS+=ipx.3 ipx_addr.3 ipx.3 ipx_ntoa.3
+
+.include <bsd.lib.mk>
diff --git a/lib/libipx/ipx.3 b/lib/libipx/ipx.3
new file mode 100644
index 0000000..cf68ffd
--- /dev/null
+++ b/lib/libipx/ipx.3
@@ -0,0 +1,125 @@
+.\" 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.
+.\" 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.
+.\"
+.\"
+.Dd June 4, 1993
+.Dt IPX 3
+.Os BSD 4.3
+.Sh NAME
+.Nm ipx_addr ,
+.Nm ipx_ntoa
+.Nd IPX address conversion routines
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <netipx/ipx.h>
+.Ft struct ipx_addr
+.Fn ipx_addr "const char *cp"
+.Ft char *
+.Fn ipx_ntoa "struct ipx_addr ipx"
+.Sh DESCRIPTION
+The routine
+.Fn ipx_addr
+interprets character strings representing
+.Tn IPX
+addresses, returning binary information suitable
+for use in system calls.
+The routine
+.Fn ipx_ntoa
+takes
+.Tn IPX
+addresses and returns
+.Tn ASCII
+strings representing the address in a
+notation in common use:
+.Bd -filled -offset indent
+<network number>.<host number>.<port number>
+.Ed
+.Pp
+Trailing zero fields are suppressed, and each number is printed in hexadecimal,
+in a format suitable for input to
+.Fn ipx_addr .
+Any fields lacking super-decimal digits will have a
+trailing
+.Ql H
+appended.
+.Pp
+An effort has been made to insure that
+.Fn ipx_addr
+be compatible with most formats in common use.
+It will first separate an address into 1 to 3 fields using a single delimiter
+chosen from
+period
+.Ql \&. ,
+colon
+.Ql \&:
+or pound-sign
+.Ql \&# .
+Each field is then examined for byte separators (colon or period).
+If there are byte separators, each subfield separated is taken to be
+a small hexadecimal number, and the entirety is taken as a network-byte-ordered
+quantity to be zero extended in the high-network-order bytes.
+Next, the field is inspected for hyphens, in which case
+the field is assumed to be a number in decimal notation
+with hyphens separating the millenia.
+Next, the field is assumed to be a number:
+It is interpreted
+as hexadecimal if there is a leading
+.Ql 0x
+(as in C),
+a trailing
+.Ql H
+(as in Mesa), or there are any super-decimal digits present.
+It is interpreted as octal is there is a leading
+.Ql 0
+and there are no super-octal digits.
+Otherwise, it is converted as a decimal number.
+.Sh RETURN VALUES
+None. (See
+.Sx BUGS . )
+.Sh SEE ALSO
+.\" .Xr ns 4 ,
+.Xr hosts 5 ,
+.Xr networks 5
+.Sh HISTORY
+The precursor
+.Fn ns_addr
+and
+.Fn ns_toa
+functions appeared in
+.Bx 4.3 .
+.Sh BUGS
+The string returned by
+.Fn ipx_ntoa
+resides in a static memory area.
+The function
+.Fn ipx_addr
+should diagnose improperly formed input, and there should be an unambiguous
+way to recognize this.
diff --git a/lib/libipx/ipx_addr.c b/lib/libipx/ipx_addr.c
new file mode 100644
index 0000000..b83f8be
--- /dev/null
+++ b/lib/libipx/ipx_addr.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * J.Q. Johnson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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[] = "@(#)ipx_addr.c";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netipx/ipx.h>
+#include <stdio.h>
+#include <string.h>
+
+static struct ipx_addr addr, zero_addr;
+
+static void Field(), cvtbase();
+
+struct ipx_addr
+ipx_addr(name)
+ const char *name;
+{
+ char separator;
+ char *hostname, *socketname, *cp;
+ char buf[50];
+
+ (void)strncpy(buf, name, sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+
+ /*
+ * First, figure out what he intends as a field separtor.
+ * Despite the way this routine is written, the prefered
+ * form 2-272.AA001234H.01777, i.e. XDE standard.
+ * Great efforts are made to insure backward compatability.
+ */
+ if ( (hostname = strchr(buf, '#')) )
+ separator = '#';
+ else {
+ hostname = strchr(buf, '.');
+ if ((cp = strchr(buf, ':')) &&
+ ((hostname && cp < hostname) || (hostname == 0))) {
+ hostname = cp;
+ separator = ':';
+ } else
+ separator = '.';
+ }
+ if (hostname)
+ *hostname++ = 0;
+
+ addr = zero_addr;
+ Field(buf, addr.x_net.c_net, 4);
+ if (hostname == 0)
+ return (addr); /* No separator means net only */
+
+ socketname = strchr(hostname, separator);
+ if (socketname) {
+ *socketname++ = 0;
+ Field(socketname, (u_char *)&addr.x_port, 2);
+ }
+
+ Field(hostname, addr.x_host.c_host, 6);
+
+ return (addr);
+}
+
+static void
+Field(buf, out, len)
+ char *buf;
+ u_char *out;
+ int len;
+{
+ register char *bp = buf;
+ int i, ibase, base16 = 0, base10 = 0, clen = 0;
+ int hb[6], *hp;
+ char *fmt;
+
+ /*
+ * first try 2-273#2-852-151-014#socket
+ */
+ if ((*buf != '-') &&
+ (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
+ &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
+ cvtbase(1000L, 256, hb, i, out, len);
+ return;
+ }
+ /*
+ * try form 8E1#0.0.AA.0.5E.E6#socket
+ */
+ if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
+ &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
+ cvtbase(256L, 256, hb, i, out, len);
+ return;
+ }
+ /*
+ * try form 8E1#0:0:AA:0:5E:E6#socket
+ */
+ if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
+ &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
+ cvtbase(256L, 256, hb, i, out, len);
+ return;
+ }
+ /*
+ * This is REALLY stretching it but there was a
+ * comma notation separting shorts -- definitely non standard
+ */
+ if (1 < (i = sscanf(buf,"%x,%x,%x",
+ &hb[0], &hb[1], &hb[2]))) {
+ hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
+ hb[2] = htons(hb[2]);
+ cvtbase(65536L, 256, hb, i, out, len);
+ return;
+ }
+
+ /* Need to decide if base 10, 16 or 8 */
+ while (*bp) switch (*bp++) {
+
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '-':
+ break;
+
+ case '8': case '9':
+ base10 = 1;
+ break;
+
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ base16 = 1;
+ break;
+
+ case 'x': case 'X':
+ *--bp = '0';
+ base16 = 1;
+ break;
+
+ case 'h': case 'H':
+ base16 = 1;
+ /* fall into */
+
+ default:
+ *--bp = 0; /* Ends Loop */
+ }
+ if (base16) {
+ fmt = "%3x";
+ ibase = 4096;
+ } else if (base10 == 0 && *buf == '0') {
+ fmt = "%3o";
+ ibase = 512;
+ } else {
+ fmt = "%3d";
+ ibase = 1000;
+ }
+
+ for (bp = buf; *bp++; ) clen++;
+ if (clen == 0) clen++;
+ if (clen > 18) clen = 18;
+ i = ((clen - 1) / 3) + 1;
+ bp = clen + buf - 3;
+ hp = hb + i - 1;
+
+ while (hp > hb) {
+ (void)sscanf(bp, fmt, hp);
+ bp[0] = 0;
+ hp--;
+ bp -= 3;
+ }
+ (void)sscanf(buf, fmt, hp);
+ cvtbase((long)ibase, 256, hb, i, out, len);
+}
+
+static void
+cvtbase(oldbase,newbase,input,inlen,result,reslen)
+ long oldbase;
+ int newbase;
+ int input[];
+ int inlen;
+ unsigned char result[];
+ int reslen;
+{
+ int d, e;
+ long sum;
+
+ e = 1;
+ while (e > 0 && reslen > 0) {
+ d = 0; e = 0; sum = 0;
+ /* long division: input=input/newbase */
+ while (d < inlen) {
+ sum = sum*oldbase + (long) input[d];
+ e += (sum > 0);
+ input[d++] = sum / newbase;
+ sum %= newbase;
+ }
+ result[--reslen] = sum; /* accumulate remainder */
+ }
+ for (d=0; d < reslen; d++)
+ result[d] = 0;
+}
diff --git a/lib/libipx/ipx_ntoa.c b/lib/libipx/ipx_ntoa.c
new file mode 100644
index 0000000..21e60a1
--- /dev/null
+++ b/lib/libipx/ipx_ntoa.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1986, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ipx_ntoa.c";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netipx/ipx.h>
+#include <stdio.h>
+
+char *
+ipx_ntoa(addr)
+ struct ipx_addr addr;
+{
+ static char obuf[40];
+ union { union ipx_net net_e; u_long long_e; } net;
+ u_short port = htons(addr.x_port);
+ register char *cp;
+ char *cp2;
+ register u_char *up = addr.x_host.c_host;
+ u_char *uplim = up + 6;
+ static char *spectHex();
+
+ net.net_e = addr.x_net;
+ sprintf(obuf, "%lx", ntohl(net.long_e));
+ cp = spectHex(obuf);
+ cp2 = cp + 1;
+ while (*up==0 && up < uplim) up++;
+ if (up == uplim) {
+ if (port) {
+ sprintf(cp, ".0");
+ cp += 2;
+ }
+ } else {
+ sprintf(cp, ".%x", *up++);
+ while (up < uplim) {
+ while (*cp) cp++;
+ sprintf(cp, "%02x", *up++);
+ }
+ cp = spectHex(cp2);
+ }
+ if (port) {
+ sprintf(cp, ".%x", port);
+ spectHex(cp + 1);
+ }
+ return (obuf);
+}
+
+static char *
+spectHex(p0)
+ char *p0;
+{
+ int ok = 0;
+ int nonzero = 0;
+ register char *p = p0;
+ for (; *p; p++) switch (*p) {
+
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ ok = 1;
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ nonzero = 1;
+ }
+ if (nonzero && !ok) { *p++ = 'H'; *p = 0; }
+ return (p);
+}
diff --git a/lib/libkse/Makefile b/lib/libkse/Makefile
new file mode 100644
index 0000000..363f308
--- /dev/null
+++ b/lib/libkse/Makefile
@@ -0,0 +1,21 @@
+# $Id$
+#
+# All library objects contain rcsid strings by default; they may be
+# excluded as a space-saving measure. To produce a library that does
+# not contain these strings, delete -DLIBC_RCS and -DSYSLIBC_RCS
+# from CFLAGS below. To remove these strings from just the system call
+# stubs, remove just -DSYSLIBC_RCS from CFLAGS.
+LIB=c_r
+SHLIB_MAJOR= 3
+SHLIB_MINOR= 0
+CFLAGS+=-DLIBC_RCS -DSYSLIBC_RCS
+CFLAGS+=-DPTHREAD_KERNEL -D_THREAD_SAFE -I${.CURDIR}/uthread
+AINC= -I${.CURDIR}/../libc/${MACHINE} -I${.CURDIR}/uthread
+PRECIOUSLIB= yes
+
+.include "${.CURDIR}/../libc/Makefile.inc"
+.include "${.CURDIR}/man/Makefile.inc"
+.include "${.CURDIR}/uthread/Makefile.inc"
+.include "${.CURDIR}/sys/Makefile.inc"
+
+.include <bsd.lib.mk>
diff --git a/lib/libkse/sys/Makefile.inc b/lib/libkse/sys/Makefile.inc
new file mode 100644
index 0000000..16fd33d
--- /dev/null
+++ b/lib/libkse/sys/Makefile.inc
@@ -0,0 +1,5 @@
+# $Id$
+
+.PATH: ${.CURDIR}/sys
+
+SRCS+= __error.c
diff --git a/lib/libkse/thread/Makefile.inc b/lib/libkse/thread/Makefile.inc
new file mode 100644
index 0000000..3fbc97b
--- /dev/null
+++ b/lib/libkse/thread/Makefile.inc
@@ -0,0 +1,93 @@
+# $Id: Makefile.inc,v 1.8 1997/02/22 15:05:31 peter Exp $
+
+# uthread sources
+.PATH: ${.CURDIR}/uthread
+
+SRCS+= \
+ uthread_accept.c \
+ uthread_attr_destroy.c \
+ uthread_attr_init.c \
+ uthread_attr_getdetachstate.c \
+ uthread_attr_getstackaddr.c \
+ uthread_attr_getstacksize.c \
+ uthread_attr_setcreatesuspend_np.c \
+ uthread_attr_setdetachstate.c \
+ uthread_attr_setstackaddr.c \
+ uthread_attr_setstacksize.c \
+ uthread_autoinit.cc \
+ uthread_bind.c \
+ uthread_clean.c \
+ uthread_close.c \
+ uthread_cond.c \
+ uthread_condattr_destroy.c \
+ uthread_condattr_init.c \
+ uthread_connect.c \
+ uthread_create.c \
+ uthread_detach.c \
+ uthread_dup.c \
+ uthread_dup2.c \
+ uthread_equal.c \
+ uthread_execve.c \
+ uthread_exit.c \
+ uthread_fchmod.c \
+ uthread_fchown.c \
+ uthread_fcntl.c \
+ uthread_fd.c \
+ uthread_file.c \
+ uthread_flock.c \
+ uthread_fork.c \
+ uthread_fstat.c \
+ uthread_fstatfs.c \
+ uthread_fsync.c \
+ uthread_getdirentries.c \
+ uthread_getpeername.c \
+ uthread_getprio.c \
+ uthread_getsockname.c \
+ uthread_getsockopt.c \
+ uthread_info.c \
+ uthread_init.c \
+ uthread_ioctl.c \
+ uthread_join.c \
+ uthread_kern.c \
+ uthread_kill.c \
+ uthread_listen.c \
+ uthread_longjmp.c \
+ uthread_mattr_init.c \
+ uthread_mattr_kind_np.c \
+ uthread_multi_np.c \
+ uthread_mutex.c \
+ uthread_mutexattr_destroy.c \
+ uthread_nanosleep.c \
+ uthread_once.c \
+ uthread_open.c \
+ uthread_pipe.c \
+ uthread_queue.c \
+ uthread_read.c \
+ uthread_readv.c \
+ uthread_recvfrom.c \
+ uthread_resume_np.c \
+ uthread_select.c \
+ uthread_self.c \
+ uthread_sendto.c \
+ uthread_seterrno.c \
+ uthread_setjmp.c \
+ uthread_setprio.c \
+ uthread_setsockopt.c \
+ uthread_shutdown.c \
+ uthread_sig.c \
+ uthread_sigaction.c \
+ uthread_sigblock.c \
+ uthread_single_np.c \
+ uthread_sigmask.c \
+ uthread_signal.c \
+ uthread_sigprocmask.c \
+ uthread_sigsetmask.c \
+ uthread_sigsuspend.c \
+ uthread_socket.c \
+ uthread_socketpair.c \
+ uthread_spec.c \
+ uthread_suspend_np.c \
+ uthread_wait4.c \
+ uthread_write.c \
+ uthread_writev.c \
+ uthread_yield.c
diff --git a/lib/libkse/thread/thr_attr_destroy.c b/lib/libkse/thread/thr_attr_destroy.c
new file mode 100644
index 0000000..1f4b2c8
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_destroy.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_destroy(pthread_attr_t *attr)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL)
+ /* Invalid argument: */
+ ret = EINVAL;
+ else {
+ /* Free the memory allocated to the attribute object: */
+ free(*attr);
+
+ /*
+ * Leave the attribute pointer NULL now that the memory
+ * has been freed:
+ */
+ *attr = NULL;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_attr_getdetachstate.c b/lib/libkse/thread/thr_attr_getdetachstate.c
new file mode 100644
index 0000000..4715cb6
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_getdetachstate.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || detachstate == NULL)
+ ret = EINVAL;
+ else {
+ /* Check if the detached flag is set: */
+ if ((*attr)->flags & PTHREAD_DETACHED)
+ /* Return detached: */
+ *detachstate = PTHREAD_CREATE_DETACHED;
+ else
+ /* Return joinable: */
+ *detachstate = PTHREAD_CREATE_JOINABLE;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_attr_getstackaddr.c b/lib/libkse/thread/thr_attr_getstackaddr.c
new file mode 100644
index 0000000..1850a32
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_getstackaddr.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stackaddr)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stackaddr == NULL)
+ ret = EINVAL;
+ else {
+ /* Return the stack address: */
+ *stackaddr = (*attr)->stackaddr_attr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_attr_getstacksize.c b/lib/libkse/thread/thr_attr_getstacksize.c
new file mode 100644
index 0000000..de81106
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_getstacksize.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stacksize == NULL)
+ ret = EINVAL;
+ else {
+ /* Return the stack size: */
+ *stacksize = (*attr)->stacksize_attr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_attr_init.c b/lib/libkse/thread/thr_attr_init.c
new file mode 100644
index 0000000..c64e29f
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_init.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_init(pthread_attr_t *attr)
+{
+ int ret;
+ pthread_attr_t pattr;
+
+ /* Allocate memory for the attribute object: */
+ if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL)
+ /* Insufficient memory: */
+ ret = ENOMEM;
+ else {
+ /* Initialise the attribute object with the defaults: */
+ memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr));
+
+ /* Return a pointer to the attribute object: */
+ *attr = pattr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_attr_setcreatesuspend_np.c b/lib/libkse/thread/thr_attr_setcreatesuspend_np.c
new file mode 100644
index 0000000..afe6b23
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_setcreatesuspend_np.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ (*attr)->suspend = PTHREAD_CREATE_SUSPENDED;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_attr_setdetachstate.c b/lib/libkse/thread/thr_attr_setdetachstate.c
new file mode 100644
index 0000000..6ec0dbc
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_setdetachstate.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL ||
+ (detachstate != PTHREAD_CREATE_DETACHED &&
+ detachstate != PTHREAD_CREATE_JOINABLE))
+ ret = EINVAL;
+ else {
+ /* Check if detached state: */
+ if (detachstate == PTHREAD_CREATE_DETACHED)
+ /* Set the detached flag: */
+ (*attr)->flags |= PTHREAD_DETACHED;
+ else
+ /* Reset the detached flag: */
+ (*attr)->flags &= ~PTHREAD_DETACHED;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_attr_setstackaddr.c b/lib/libkse/thread/thr_attr_setstackaddr.c
new file mode 100644
index 0000000..ce54915
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_setstackaddr.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stackaddr == NULL)
+ ret = EINVAL;
+ else {
+ /* Save the stack address: */
+ (*attr)->stackaddr_attr = stackaddr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_attr_setstacksize.c b/lib/libkse/thread/thr_attr_setstacksize.c
new file mode 100644
index 0000000..94e575e
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_setstacksize.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN)
+ ret = EINVAL;
+ else {
+ /* Save the stack size: */
+ (*attr)->stacksize_attr = stacksize;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_clean.c b/lib/libkse/thread/thr_clean.c
new file mode 100644
index 0000000..9319f85
--- /dev/null
+++ b/lib/libkse/thread/thr_clean.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+pthread_cleanup_push(void (*routine) (void *), void *routine_arg)
+{
+ struct pthread_cleanup *new;
+
+ if ((new = (struct pthread_cleanup *) malloc(sizeof(struct pthread_cleanup))) != NULL) {
+ new->routine = routine;
+ new->routine_arg = routine_arg;
+ new->next = _thread_run->cleanup;
+
+ _thread_run->cleanup = new;
+ }
+}
+
+void
+pthread_cleanup_pop(int execute)
+{
+ struct pthread_cleanup *old;
+
+ if ((old = _thread_run->cleanup) != NULL) {
+ _thread_run->cleanup = old->next;
+ if (execute) {
+ old->routine(old->routine_arg);
+ }
+ free(old);
+ }
+}
+
+#endif
diff --git a/lib/libkse/thread/thr_close.c b/lib/libkse/thread/thr_close.c
new file mode 100644
index 0000000..26a8fbf
--- /dev/null
+++ b/lib/libkse/thread/thr_close.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+close(int fd)
+{
+ int flags;
+ int ret;
+ int status;
+ struct stat sb;
+
+ /* Lock the file descriptor while the file is closed: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Get file descriptor status. */
+ fstat(fd, &sb);
+
+ /*
+ * Check if the file should be left as blocking.
+ *
+ * This is so that the file descriptors shared with a parent
+ * process aren't left set to non-blocking if the child
+ * closes them prior to exit. An example where this causes
+ * problems with /bin/sh is when a child closes stdin.
+ *
+ * Setting a file as blocking causes problems if a threaded
+ * parent accesses the file descriptor before the child exits.
+ * Once the threaded parent receives a SIGCHLD then it resets
+ * all of its files to non-blocking, and so it is then safe
+ * to access them.
+ *
+ * Pipes are not set to blocking when they are closed, as
+ * the parent and child will normally close the file
+ * descriptor of the end of the pipe that they are not
+ * using, which would then cause any reads to block
+ * indefinitely.
+ */
+ if ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) && (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0) {
+ /* Get the current flags: */
+ flags = _thread_sys_fcntl(fd, F_GETFL, NULL);
+ /* Clear the nonblocking file descriptor flag: */
+ _thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+ }
+
+ /* Close the file descriptor: */
+ ret = _thread_sys_close(fd);
+
+ /* Free the file descriptor table entry: */
+ free(_thread_fd_table[fd]);
+ _thread_fd_table[fd] = NULL;
+
+ /* Unblock signals again: */
+ _thread_kern_sig_unblock(status);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_cond.c b/lib/libkse/thread/thr_cond.c
new file mode 100644
index 0000000..09ebb4e
--- /dev/null
+++ b/lib/libkse/thread/thr_cond.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * cond_attr)
+{
+ enum pthread_cond_type type;
+ pthread_cond_t pcond;
+ int rval = 0;
+
+ if (cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /*
+ * Check if a pointer to a condition variable attribute
+ * structure was passed by the caller:
+ */
+ if (cond_attr != NULL && *cond_attr != NULL) {
+ /* Default to a fast condition variable: */
+ type = (*cond_attr)->c_type;
+ } else {
+ /* Default to a fast condition variable: */
+ type = COND_TYPE_FAST;
+ }
+
+ /* Process according to condition variable type: */
+ switch (type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Check for no errors: */
+ if (rval == 0) {
+ if ((pcond = (pthread_cond_t)
+ malloc(sizeof(struct pthread_cond))) == NULL) {
+ errno = ENOMEM;
+ rval = -1;
+ } else {
+ /*
+ * Initialise the condition variable
+ * structure:
+ */
+ _thread_queue_init(&pcond->c_queue);
+ pcond->c_flags |= COND_FLAGS_INITED;
+ pcond->c_type = type;
+ *cond = pcond;
+ }
+ }
+ }
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_destroy(pthread_cond_t * cond)
+{
+ int rval = 0;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Check for errors: */
+ if (rval == 0) {
+ /* Destroy the contents of the condition structure: */
+ _thread_queue_init(&(*cond)->c_queue);
+ (*cond)->c_flags = 0;
+ free(*cond);
+ *cond = NULL;
+ }
+ }
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
+{
+ int rval = 0;
+ int status;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /*
+ * Queue the running thread for the condition
+ * variable:
+ */
+ _thread_queue_enq(&(*cond)->c_queue, _thread_run);
+
+ /* Unlock the mutex: */
+ pthread_mutex_unlock(mutex);
+
+ /* Wait forever: */
+ _thread_run->wakeup_time.tv_sec = -1;
+
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_COND_WAIT,
+ __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Lock the mutex: */
+ rval = pthread_mutex_lock(mutex);
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
+ const struct timespec * abstime)
+{
+ int rval = 0;
+ int status;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Set the wakeup time: */
+ _thread_run->wakeup_time.tv_sec = abstime->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = abstime->tv_nsec;
+
+ /* Reset the timeout flag: */
+ _thread_run->timeout = 0;
+
+ /*
+ * Queue the running thread for the condition
+ * variable:
+ */
+ _thread_queue_enq(&(*cond)->c_queue, _thread_run);
+
+ /* Unlock the mutex: */
+ if ((rval = pthread_mutex_unlock(mutex)) != 0) {
+ /*
+ * Cannot unlock the mutex, so remove the
+ * running thread from the condition
+ * variable queue:
+ */
+ _thread_queue_deq(&(*cond)->c_queue);
+ } else {
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_COND_WAIT,
+ __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Lock the mutex: */
+ if ((rval = pthread_mutex_lock(mutex)) != 0) {
+ }
+ /* Check if the wait timed out: */
+ else if (_thread_run->timeout) {
+ /* Return a timeout error: */
+ errno = EAGAIN;
+ rval = -1;
+ }
+ }
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_signal(pthread_cond_t * cond)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Bring the next thread off the condition queue: */
+ if ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
+ /* Allow the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_broadcast(pthread_cond_t * cond)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /*
+ * Enter a loop to bring all threads off the
+ * condition queue:
+ */
+ while ((pthread =
+ _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
+ /* Allow the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libkse/thread/thr_condattr_destroy.c b/lib/libkse/thread/thr_condattr_destroy.c
new file mode 100644
index 0000000..b20f183
--- /dev/null
+++ b/lib/libkse/thread/thr_condattr_destroy.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_condattr_destroy(pthread_condattr_t *attr)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ free(*attr);
+ *attr = NULL;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_condattr_init.c b/lib/libkse/thread/thr_condattr_init.c
new file mode 100644
index 0000000..f94e438
--- /dev/null
+++ b/lib/libkse/thread/thr_condattr_init.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_condattr_init(pthread_condattr_t *attr)
+{
+ int ret;
+ pthread_condattr_t pattr;
+
+ if ((pattr = (pthread_condattr_t)
+ malloc(sizeof(struct pthread_cond_attr))) == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ memcpy(pattr, &pthread_condattr_default,
+ sizeof(struct pthread_cond_attr));
+ *attr = pattr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_create.c b/lib/libkse/thread/thr_create.c
new file mode 100644
index 0000000..e4925a9
--- /dev/null
+++ b/lib/libkse/thread/thr_create.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <machine/reg.h>
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+_thread_create(pthread_t * thread, const pthread_attr_t * attr,
+ void *(*start_routine) (void *), void *arg, pthread_t parent)
+{
+ int i;
+ int ret = 0;
+ int status;
+ pthread_t new_thread;
+ pthread_attr_t pattr;
+ void *stack;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Allocate memory for the thread structure: */
+ if ((new_thread = (pthread_t) malloc(sizeof(struct pthread))) == NULL) {
+ /* Insufficient memory to create a thread: */
+ ret = EAGAIN;
+ } else {
+ /* Check if default thread attributes are required: */
+ if (attr == NULL || *attr == NULL) {
+ /* Use the default thread attributes: */
+ pattr = &pthread_attr_default;
+ } else {
+ pattr = *attr;
+ }
+ /* Check if a stack was specified in the thread attributes: */
+ if ((stack = pattr->stackaddr_attr) != NULL) {
+ }
+ /* Allocate memory for the stack: */
+ else if ((stack = (void *) malloc(pattr->stacksize_attr)) == NULL) {
+ /* Insufficient memory to create a thread: */
+ ret = EAGAIN;
+ free(new_thread);
+ }
+ /* Check for errors: */
+ if (ret != 0) {
+ } else {
+ /* Initialise the thread structure: */
+ memset(new_thread, 0, sizeof(struct pthread));
+ new_thread->slice_usec = -1;
+ new_thread->sig_saved = 0;
+ new_thread->stack = stack;
+ new_thread->start_routine = start_routine;
+ new_thread->arg = arg;
+ if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) {
+ PTHREAD_NEW_STATE(new_thread,PS_SUSPENDED);
+ } else {
+ PTHREAD_NEW_STATE(new_thread,PS_RUNNING);
+ }
+
+ /* Initialise the thread for signals: */
+ new_thread->sigmask = _thread_run->sigmask;
+
+ /*
+ * Enter a loop to initialise the signal handler
+ * array:
+ */
+ for (i = 1; i < NSIG; i++) {
+ /* Default the signal handler: */
+ sigfillset(&new_thread->act[i - 1].sa_mask);
+ new_thread->act[i - 1].sa_handler = _thread_run->act[i - 1].sa_handler;
+ new_thread->act[i - 1].sa_flags = _thread_run->act[i - 1].sa_flags;
+ }
+
+ /* Initialise the jump buffer: */
+ _thread_sys_setjmp(new_thread->saved_jmp_buf);
+
+ /*
+ * Set up new stack frame so that it looks like it
+ * returned from a longjmp() to the beginning of
+ * _thread_start(). Check if this is a user thread:
+ */
+ if (parent == NULL) {
+ /* Use the user start function: */
+#if defined(__FreeBSD__)
+ new_thread->saved_jmp_buf[0]._jb[0] = (long) _thread_start;
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[2] = (long) _thread_start;
+ new_thread->saved_jmp_buf[4 + R_RA] = 0;
+ new_thread->saved_jmp_buf[4 + R_T12] = (long) _thread_start;
+#else
+ new_thread->saved_jmp_buf[0] = (long) _thread_start;
+#endif
+#else
+#error "Don't recognize this operating system!"
+#endif
+ } else {
+ /*
+ * Use the (funny) signal handler start
+ * function:
+ */
+#if defined(__FreeBSD__)
+ new_thread->saved_jmp_buf[0]._jb[0] = (int) _thread_start_sig_handler;
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[2] = (long) _thread_start_sig_handler;
+ new_thread->saved_jmp_buf[4 + R_RA] = 0;
+ new_thread->saved_jmp_buf[4 + R_T12] = (long) _thread_start_sig_handler;
+#else
+ new_thread->saved_jmp_buf[0] = (long) _thread_start_sig_handler;
+#endif
+#else
+#error "Don't recognize this operating system!"
+#endif
+ }
+
+ /* The stack starts high and builds down: */
+#if defined(__FreeBSD__)
+ new_thread->saved_jmp_buf[0]._jb[2] = (int) (new_thread->stack + pattr->stacksize_attr - sizeof(double));
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[4 + R_SP] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
+#else
+ new_thread->saved_jmp_buf[2] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
+#endif
+#else
+#error "Don't recognize this operating system!"
+#endif
+
+ /* Copy the thread attributes: */
+ memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr));
+
+ /*
+ * Check if this thread is to inherit the scheduling
+ * attributes from its parent:
+ */
+ if (new_thread->attr.flags & PTHREAD_INHERIT_SCHED) {
+ /* Copy the scheduling attributes: */
+ new_thread->pthread_priority = _thread_run->pthread_priority;
+ new_thread->attr.prio = _thread_run->pthread_priority;
+ new_thread->attr.schedparam_policy = _thread_run->attr.schedparam_policy;
+ } else {
+ /*
+ * Use just the thread priority, leaving the
+ * other scheduling attributes as their
+ * default values:
+ */
+ new_thread->pthread_priority = new_thread->attr.prio;
+ }
+
+ /* Initialise the join queue for the new thread: */
+ _thread_queue_init(&(new_thread->join_queue));
+
+ /* Initialise hooks in the thread structure: */
+ new_thread->specific_data = NULL;
+ new_thread->cleanup = NULL;
+ new_thread->queue = NULL;
+ new_thread->qnxt = NULL;
+ new_thread->parent_thread = parent;
+ new_thread->flags = 0;
+
+ /* Add the thread to the linked list of all threads: */
+ new_thread->nxt = _thread_link_list;
+ _thread_link_list = new_thread;
+
+ /* Return a pointer to the thread structure: */
+ (*thread) = new_thread;
+
+ /* Check if a parent thread was specified: */
+ if (parent != NULL) {
+ /*
+ * A parent thread was specified, so this is
+ * a signal handler thread which must now
+ * wait for the signal handler to complete:
+ */
+ PTHREAD_NEW_STATE(parent,PS_SIGTHREAD);
+ } else {
+ /* Schedule the new user thread: */
+ _thread_kern_sched(NULL);
+ }
+ }
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the status: */
+ return (ret);
+}
+
+int
+pthread_create(pthread_t * thread, const pthread_attr_t * attr,
+ void *(*start_routine) (void *), void *arg)
+{
+ int ret = 0;
+
+ /*
+ * Call the low level thread creation function which allows a parent
+ * thread to be specified:
+ */
+ ret = _thread_create(thread, attr, start_routine, arg, NULL);
+
+ /* Return the status: */
+ return (ret);
+}
+
+void
+_thread_start(void)
+{
+ /* Run the current thread's start routine with argument: */
+ pthread_exit(_thread_run->start_routine(_thread_run->arg));
+
+ /* This point should never be reached. */
+ PANIC("Thread has resumed after exit");
+}
+
+void
+_thread_start_sig_handler(void)
+{
+ int sig;
+ long arg;
+ void (*sig_routine) (int);
+
+ /*
+ * Cast the argument from 'void *' to a variable that is NO SMALLER
+ * than a pointer (otherwise gcc under NetBSD/Alpha will complain):
+ */
+ arg = (long) _thread_run->arg;
+
+ /* Cast the argument as a signal number: */
+ sig = (int) arg;
+
+ /* Cast a pointer to the signal handler function: */
+ sig_routine = (void (*) (int)) _thread_run->start_routine;
+
+ /* Call the signal handler function: */
+ (*sig_routine) (sig);
+
+ /* Exit the signal handler thread: */
+ pthread_exit(&arg);
+
+ /* This point should never be reached. */
+ PANIC("Signal handler thread has resumed after exit");
+}
+#endif
diff --git a/lib/libkse/thread/thr_detach.c b/lib/libkse/thread/thr_detach.c
new file mode 100644
index 0000000..08cace4
--- /dev/null
+++ b/lib/libkse/thread/thr_detach.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_detach(pthread_t * p_pthread)
+{
+ int rval = 0;
+ int status;
+ pthread_t next_thread;
+ pthread_t pthread;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Check for invalid calling parameters: */
+ if (p_pthread == NULL || (pthread = *p_pthread) == NULL) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ }
+ /* Check if the thread has not been detached: */
+ else if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) {
+ /* Flag the thread as detached: */
+ pthread->attr.flags |= PTHREAD_DETACHED;
+
+ /* Enter a loop to bring all threads off the join queue: */
+ while ((next_thread = _thread_queue_deq(&pthread->join_queue)) != NULL) {
+ /* Make the thread run: */
+ PTHREAD_NEW_STATE(next_thread,PS_RUNNING);
+ }
+
+ /*
+ * NULL the thread pointer now that the thread has been
+ * detached:
+ */
+ *p_pthread = NULL;
+ } else {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libkse/thread/thr_equal.c b/lib/libkse/thread/thr_equal.c
new file mode 100644
index 0000000..99ffb5d
--- /dev/null
+++ b/lib/libkse/thread/thr_equal.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_equal(pthread_t t1, pthread_t t2)
+{
+ /* Compare the two thread pointers: */
+ return (t1 == t2);
+}
+#endif
diff --git a/lib/libkse/thread/thr_exit.c b/lib/libkse/thread/thr_exit.c
new file mode 100644
index 0000000..15bcfa3
--- /dev/null
+++ b/lib/libkse/thread/thr_exit.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void _exit(int status)
+{
+ int flags;
+ int i;
+ struct itimerval itimer;
+
+ /* Disable the interval timer: */
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+ itimer.it_value.tv_sec = 0;
+ itimer.it_value.tv_usec = 0;
+ setitimer(ITIMER_VIRTUAL, &itimer, NULL);
+
+ /* Close the pthread kernel pipe: */
+ _thread_sys_close(_thread_kern_pipe[0]);
+ _thread_sys_close(_thread_kern_pipe[1]);
+
+ /*
+ * Enter a loop to set all file descriptors to blocking
+ * if they were not created as non-blocking:
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Check if this file descriptor is in use: */
+ if (_thread_fd_table[i] != NULL &&
+ !(_thread_fd_table[i]->flags & O_NONBLOCK)) {
+ /* Get the current flags: */
+ flags = _thread_sys_fcntl(i, F_GETFL, NULL);
+ /* Clear the nonblocking file descriptor flag: */
+ _thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+
+ /* Call the _exit syscall: */
+ _thread_sys__exit(status);
+}
+
+void
+_thread_exit(char *fname, int lineno, char *string)
+{
+ char s[256];
+
+ /* Prepare an error message string: */
+ strcpy(s, "Fatal error '");
+ strcat(s, string);
+ strcat(s, "' at line ? ");
+ strcat(s, "in file ");
+ strcat(s, fname);
+ strcat(s, " (errno = ?");
+ strcat(s, ")\n");
+
+ /* Write the string to the standard error file descriptor: */
+ _thread_sys_write(2, s, strlen(s));
+
+ /* Force this process to exit: */
+ _exit(1);
+}
+
+void
+pthread_exit(void *status)
+{
+ int sig;
+ long l;
+ pthread_t pthread;
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Save the return value: */
+ _thread_run->ret = status;
+
+ while (_thread_run->cleanup != NULL) {
+ pthread_cleanup_pop(1);
+ }
+
+ if (_thread_run->attr.cleanup_attr != NULL) {
+ _thread_run->attr.cleanup_attr(_thread_run->attr.arg_attr);
+ }
+ /* Check if there is thread specific data: */
+ if (_thread_run->specific_data != NULL) {
+ /* Run the thread-specific data destructors: */
+ _thread_cleanupspecific();
+ }
+ /* Check if there are any threads joined to this one: */
+ while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) {
+ /* Wake the joined thread and let it detach this thread: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+
+ /* Check if the running thread is at the head of the linked list: */
+ if (_thread_link_list == _thread_run) {
+ /* There is no previous thread: */
+ _thread_link_list = _thread_run->nxt;
+ } else {
+ /* Point to the first thread in the list: */
+ pthread = _thread_link_list;
+
+ /*
+ * Enter a loop to find the thread in the linked list before
+ * the running thread:
+ */
+ while (pthread != NULL && pthread->nxt != _thread_run) {
+ /* Point to the next thread: */
+ pthread = pthread->nxt;
+ }
+
+ /* Check that a previous thread was found: */
+ if (pthread != NULL) {
+ /*
+ * Point the previous thread to the one after the
+ * running thread:
+ */
+ pthread->nxt = _thread_run->nxt;
+ }
+ }
+
+ /* Check if this is a signal handler thread: */
+ if (_thread_run->parent_thread != NULL) {
+ /*
+ * Enter a loop to search for other threads with the same
+ * parent:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Compare the parent thread pointers: */
+ if (pthread->parent_thread == _thread_run->parent_thread) {
+ /*
+ * The parent thread is waiting on at least
+ * one other signal handler. Exit the loop
+ * now that this is known.
+ */
+ break;
+ }
+ }
+
+ /*
+ * Check if the parent is not waiting on any other signal
+ * handler threads and if it hasn't died in the meantime:
+ */
+ if (pthread == NULL && _thread_run->parent_thread->state != PS_DEAD) {
+ /* Allow the parent thread to run again: */
+ PTHREAD_NEW_STATE(_thread_run->parent_thread,PS_RUNNING);
+ }
+ /* Get the signal number: */
+ l = (long) _thread_run->arg;
+ sig = (int) l;
+
+ /* Unblock the signal from the parent thread: */
+ sigdelset(&_thread_run->parent_thread->sigmask, sig);
+ }
+ /*
+ * This thread will never run again. Add it to the list of dead
+ * threads:
+ */
+ _thread_run->nxt = _thread_dead;
+ _thread_dead = _thread_run;
+
+ /*
+ * The running thread is no longer in the thread link list so it will
+ * now die:
+ */
+ _thread_kern_sched_state(PS_DEAD, __FILE__, __LINE__);
+
+ /* This point should not be reached. */
+ PANIC("Dead thread has resumed");
+}
+#endif
diff --git a/lib/libkse/thread/thr_fcntl.c b/lib/libkse/thread/thr_fcntl.c
new file mode 100644
index 0000000..f83ee50
--- /dev/null
+++ b/lib/libkse/thread/thr_fcntl.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fcntl(int fd, int cmd,...)
+{
+ int flags = 0;
+ int oldfd;
+ int ret;
+ int status;
+ va_list ap;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Lock the file descriptor: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Initialise the variable argument list: */
+ va_start(ap, cmd);
+
+ /* Process according to file control command type: */
+ switch (cmd) {
+ /* Duplicate a file descriptor: */
+ case F_DUPFD:
+ /*
+ * Get the file descriptor that the caller wants to
+ * use:
+ */
+ oldfd = va_arg(ap, int);
+
+ /* Initialise the file descriptor table entry: */
+ if ((ret = _thread_sys_fcntl(fd, cmd, oldfd)) < 0) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(ret);
+
+ /* Reset the file descriptor: */
+ ret = -1;
+ } else {
+ /*
+ * Save the file open flags so that they can
+ * be checked later:
+ */
+ _thread_fd_table[ret]->flags = _thread_fd_table[fd]->flags;
+ }
+ break;
+ case F_SETFD:
+ break;
+ case F_GETFD:
+ break;
+ case F_GETFL:
+ ret = _thread_fd_table[fd]->flags;
+ break;
+ case F_SETFL:
+ flags = va_arg(ap, int);
+ if ((ret = _thread_sys_fcntl(fd, cmd, flags | O_NONBLOCK)) == 0) {
+ _thread_fd_table[fd]->flags = flags;
+ }
+ break;
+ default:
+ /* Might want to make va_arg use a union */
+ ret = _thread_sys_fcntl(fd, cmd, va_arg(ap, void *));
+ break;
+ }
+
+ /* Free variable arguments: */
+ va_end(ap);
+
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_fork.c b/lib/libkse/thread/thr_fork.c
new file mode 100644
index 0000000..19f674d
--- /dev/null
+++ b/lib/libkse/thread/thr_fork.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pid_t
+fork(void)
+{
+ int flags;
+ pid_t ret;
+
+ /* Fork a new process: */
+ if ((ret = _thread_sys_fork()) <= 0) {
+ /* Parent process or error. Nothing to do here. */
+ } else {
+ /* Close the pthread kernel pipe: */
+ _thread_sys_close(_thread_kern_pipe[0]);
+ _thread_sys_close(_thread_kern_pipe[1]);
+
+ /* Reset signals pending for the running thread: */
+ memset(_thread_run->sigpend, 0, sizeof(_thread_run->sigpend));
+
+ /*
+ * Create a pipe that is written to by the signal handler to
+ * prevent signals being missed in calls to
+ * _thread_sys_select:
+ */
+ if (_thread_sys_pipe(_thread_kern_pipe) != 0) {
+ /* Cannot create pipe, so abort: */
+ PANIC("Cannot create pthread kernel pipe for forked process");
+ }
+ /* Get the flags for the read pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Make the read pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Get the flags for the write pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Make the write pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ }
+
+ /* Return the process ID: */
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_fsync.c b/lib/libkse/thread/thr_fsync.c
new file mode 100644
index 0000000..51078e5
--- /dev/null
+++ b/lib/libkse/thread/thr_fsync.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fsync(int fd)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_fsync(fd);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_getprio.c b/lib/libkse/thread/thr_getprio.c
new file mode 100644
index 0000000..85bd261
--- /dev/null
+++ b/lib/libkse/thread/thr_getprio.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_getprio(pthread_t pthread)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread_p;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the first thread in the list: */
+ pthread_p = _thread_link_list;
+
+ /* Enter a loop to search for the thread: */
+ while (pthread_p != NULL && pthread_p != pthread) {
+ /* Point to the next thread: */
+ pthread_p = pthread_p->nxt;
+ }
+
+ /* Check if the thread pointer is NULL: */
+ if (pthread == NULL || pthread_p == NULL) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Get the thread priority: */
+ rval = pthread->pthread_priority;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the thread priority or an error status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libkse/thread/thr_info.c b/lib/libkse/thread/thr_info.c
new file mode 100644
index 0000000..be25d45
--- /dev/null
+++ b/lib/libkse/thread/thr_info.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+struct s_thread_info {
+ enum pthread_state state;
+ char *name;
+};
+
+/* Static variables: */
+static const struct s_thread_info thread_info[] = {
+ {PS_RUNNING , "Running"},
+ {PS_SIGTHREAD , "Waiting on signal thread"},
+ {PS_MUTEX_WAIT , "Waiting on a mutex"},
+ {PS_COND_WAIT , "Waiting on a condition variable"},
+ {PS_FDLR_WAIT , "Waiting for a file read lock"},
+ {PS_FDLW_WAIT , "Waiting for a file write lock"},
+ {PS_FDR_WAIT , "Waiting for read"},
+ {PS_FDW_WAIT , "Waitingfor write"},
+ {PS_SELECT_WAIT , "Waiting on select"},
+ {PS_SLEEP_WAIT , "Sleeping"},
+ {PS_WAIT_WAIT , "Waiting process"},
+ {PS_SIGWAIT , "Waiting for a signal"},
+ {PS_JOIN , "Waiting to join"},
+ {PS_SUSPENDED , "Suspended"},
+ {PS_DEAD , "Dead"},
+ {PS_STATE_MAX , "Not a real state!"}
+};
+
+void
+_thread_dump_info(void)
+{
+ char s[128];
+ int fd;
+ int i;
+ int j;
+ pthread_t pthread;
+
+ /* Open the dump file for append and create it if necessary: */
+ if ((fd = _thread_sys_open("/tmp/uthread.dump", O_RDWR | O_CREAT | O_APPEND, 0666)) < 0) {
+ /* Can't open the dump file. */
+ } else {
+ /* Output a header for active threads: */
+ strcpy(s, "\n\n=============\nACTIVE THREADS\n\n");
+ _thread_sys_write(fd, s, strlen(s));
+
+ /* Enter a loop to report each thread in the global list: */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Find the state: */
+ for (j = 0; j < (sizeof(thread_info) / sizeof(struct s_thread_info)) - 1; j++)
+ if (thread_info[j].state == pthread->state)
+ break;
+ /* Output a record for the current thread: */
+ sprintf(s, "--------------------\nThread %p prio %3d state %s [%s:%d]\n",
+ pthread, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno);
+ _thread_sys_write(fd, s, strlen(s));
+
+ /* Check if this is the running thread: */
+ if (pthread == _thread_run) {
+ /* Output a record for the running thread: */
+ strcpy(s, "This is the running thread\n");
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ /* Check if this is the initial thread: */
+ if (pthread == _thread_initial) {
+ /* Output a record for the initial thread: */
+ strcpy(s, "This is the initial thread\n");
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /* File descriptor read lock wait: */
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_FDR_WAIT:
+ case PS_FDW_WAIT:
+ /* Write the lock details: */
+ sprintf(s, "fd %d[%s:%d]", pthread->data.fd.fd, pthread->data.fd.fname, pthread->data.fd.branch);
+ _thread_sys_write(fd, s, strlen(s));
+ sprintf(s, "owner %pr/%pw\n", _thread_fd_table[pthread->data.fd.fd]->r_owner, _thread_fd_table[pthread->data.fd.fd]->w_owner);
+ _thread_sys_write(fd, s, strlen(s));
+ break;
+
+ /*
+ * Trap other states that are not explicitly
+ * coded to dump information:
+ */
+ default:
+ /* Nothing to do here. */
+ break;
+ }
+ }
+
+ /* Check if there are no dead threads: */
+ if (_thread_dead == NULL) {
+ /* Output a record: */
+ strcpy(s, "\n\nTHERE ARE NO DEAD THREADS\n");
+ _thread_sys_write(fd, s, strlen(s));
+ } else {
+ /* Output a header for dead threads: */
+ strcpy(s, "\n\nDEAD THREADS\n\n");
+ _thread_sys_write(fd, s, strlen(s));
+
+ /*
+ * Enter a loop to report each thread in the global
+ * dead thread list:
+ */
+ for (pthread = _thread_dead; pthread != NULL; pthread = pthread->nxt) {
+ /* Output a record for the current thread: */
+ sprintf(s, "Thread %p prio %3d [%s:%d]\n", pthread, pthread->pthread_priority,pthread->fname,pthread->lineno);
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ }
+
+ /* Output a header for file descriptors: */
+ strcpy(s, "\n\n=============\nFILE DESCRIPTOR TABLE\n\n");
+ _thread_sys_write(fd, s, strlen(s));
+
+ /* Enter a loop to report file descriptor lock usage: */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /*
+ * Check if memory is allocated for this file
+ * descriptor:
+ */
+ if (_thread_fd_table[i] != NULL) {
+ /* Report the file descriptor lock status: */
+ sprintf(s, "fd[%3d] read owner %p count %d [%s:%d]\n write owner %p count %d [%s:%d]\n",
+ i,
+ _thread_fd_table[i]->r_owner,
+ _thread_fd_table[i]->r_lockcount,
+ _thread_fd_table[i]->r_fname,
+ _thread_fd_table[i]->r_lineno,
+ _thread_fd_table[i]->w_owner,
+ _thread_fd_table[i]->w_lockcount,
+ _thread_fd_table[i]->w_fname,
+ _thread_fd_table[i]->w_lineno);
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ }
+
+ /* Close the dump file: */
+ _thread_sys_close(fd);
+ }
+ return;
+}
+#endif
diff --git a/lib/libkse/thread/thr_init.c b/lib/libkse/thread/thr_init.c
new file mode 100644
index 0000000..5833cdf
--- /dev/null
+++ b/lib/libkse/thread/thr_init.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+
+/* Allocate space for global thread variables here: */
+#define GLOBAL_PTHREAD_PRIVATE
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <machine/reg.h>
+#include <pthread.h>
+#include "pthread_private.h"
+extern int _thread_autoinit_dummy_decl;
+
+/*
+ * Threaded process initialization
+ */
+void
+_thread_init(void)
+{
+ int flags;
+ int i;
+ struct sigaction act;
+
+ /* Ensure that the auto-initialization routine is linked in: */
+ _thread_autoinit_dummy_decl = 1;
+
+ /* Check if this function has already been called: */
+ if (_thread_initial)
+ /* Only initialise the threaded application once. */
+ return;
+
+ /* Get the standard I/O flags before messing with them : */
+ for (i = 0; i < 3; i++)
+ if ((_pthread_stdio_flags[i] =
+ _thread_sys_fcntl(i,F_GETFL, NULL)) == -1)
+ PANIC("Cannot get stdio flags");
+
+ /*
+ * Create a pipe that is written to by the signal handler to prevent
+ * signals being missed in calls to _thread_sys_select:
+ */
+ if (_thread_sys_pipe(_thread_kern_pipe) != 0) {
+ /* Cannot create pipe, so abort: */
+ PANIC("Cannot create kernel pipe");
+ }
+ /* Get the flags for the read pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel read pipe flags");
+ }
+ /* Make the read pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot make kernel read pipe non-blocking");
+ }
+ /* Get the flags for the write pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel write pipe flags");
+ }
+ /* Make the write pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel write pipe flags");
+ }
+ /* Allocate memory for the thread structure of the initial thread: */
+ else if ((_thread_initial = (pthread_t) malloc(sizeof(struct pthread))) == NULL) {
+ /*
+ * Insufficient memory to initialise this application, so
+ * abort:
+ */
+ PANIC("Cannot allocate memory for initial thread");
+ } else {
+ /* Zero the global kernel thread structure: */
+ memset(&_thread_kern_thread, 0, sizeof(struct pthread));
+ memset(_thread_initial, 0, sizeof(struct pthread));
+
+ /* Default the priority of the initial thread: */
+ _thread_initial->pthread_priority = PTHREAD_DEFAULT_PRIORITY;
+
+ /* Initialise the state of the initial thread: */
+ _thread_initial->state = PS_RUNNING;
+
+ /* Initialise the queue: */
+ _thread_queue_init(&(_thread_initial->join_queue));
+
+ /* Initialise the rest of the fields: */
+ _thread_initial->parent_thread = NULL;
+ _thread_initial->specific_data = NULL;
+ _thread_initial->cleanup = NULL;
+ _thread_initial->queue = NULL;
+ _thread_initial->qnxt = NULL;
+ _thread_initial->nxt = NULL;
+ _thread_initial->flags = 0;
+ _thread_initial->error = 0;
+ _thread_link_list = _thread_initial;
+ _thread_run = _thread_initial;
+
+ /* Enter a loop to get the existing signal status: */
+ for (i = 1; i < NSIG; i++) {
+ /* Check for signals which cannot be trapped: */
+ if (i == SIGKILL || i == SIGSTOP) {
+ }
+ /* Get the signal handler details: */
+ else if (_thread_sys_sigaction(i, NULL, &act) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot read signal handler info");
+ }
+ /* Set the signal handler for the initial thread: */
+ else if (sigaction(i, &act, NULL) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot initialise signal handler for initial thread");
+ }
+ }
+
+ /* Initialise the global signal action structure: */
+ sigfillset(&act.sa_mask);
+ act.sa_handler = (void (*) ()) _thread_sig_handler;
+ act.sa_flags = SA_RESTART;
+
+ /* Enter a loop to initialise the rest of the signals: */
+ for (i = 1; i < NSIG; i++) {
+ /* Check for signals which cannot be trapped: */
+ if (i == SIGKILL || i == SIGSTOP) {
+ }
+ /* Initialise the signal for default handling: */
+ else if (_thread_sys_sigaction(i, &act, NULL) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot initialise signal handler");
+ }
+ }
+
+ /* Get the table size: */
+ if ((_thread_dtablesize = getdtablesize()) < 0) {
+ /*
+ * Cannot get the system defined table size, so abort
+ * this process.
+ */
+ PANIC("Cannot get dtablesize");
+ }
+ /* Allocate memory for the file descriptor table: */
+ if ((_thread_fd_table = (struct fd_table_entry **) malloc(sizeof(struct fd_table_entry *) * _thread_dtablesize)) == NULL) {
+ /*
+ * Cannot allocate memory for the file descriptor
+ * table, so abort this process.
+ */
+ PANIC("Cannot allocate memory for file descriptor table");
+ } else {
+ /*
+ * Enter a loop to initialise the file descriptor
+ * table:
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Initialise the file descriptor table: */
+ _thread_fd_table[i] = NULL;
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * Special start up code for NetBSD/Alpha
+ */
+#if defined(__NetBSD__) && defined(__alpha__)
+int
+main(int argc, char *argv[], char *env);
+
+int
+_thread_main(int argc, char *argv[], char *env)
+{
+ _thread_init();
+ return (main(argc, argv, env));
+}
+#endif
+#else
+/*
+ * A stub for non-threaded programs.
+ */
+void
+_thread_init(void)
+{
+}
+#endif
diff --git a/lib/libkse/thread/thr_join.c b/lib/libkse/thread/thr_join.c
new file mode 100644
index 0000000..161482e
--- /dev/null
+++ b/lib/libkse/thread/thr_join.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_join(pthread_t pthread, void **thread_return)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread1;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the first thread in the list: */
+ pthread1 = _thread_link_list;
+
+ /* Search for the thread to join to: */
+ while (pthread1 != NULL && pthread1 != pthread) {
+ /* Point to the next thread: */
+ pthread1 = pthread1->nxt;
+ }
+
+ if (pthread1 == NULL) {
+ /* Point to the first thread in the dead thread list: */
+ pthread1 = _thread_dead;
+
+ /* Search for the thread to join to: */
+ while (pthread1 != NULL && pthread1 != pthread) {
+ /* Point to the next thread: */
+ pthread1 = pthread1->nxt;
+ }
+ }
+
+ if (pthread1 == NULL) {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+
+ /* Check if this thread has been detached: */
+ } else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+ }
+ /* Check if the thread is not dead: */
+ else if (pthread->state != PS_DEAD) {
+ /* Add the running thread to the join queue: */
+ _thread_queue_enq(&(pthread->join_queue), _thread_run);
+
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__);
+
+ /* Block signals again: */
+ _thread_kern_sig_block(NULL);
+
+ /* Check if the thread is not detached: */
+ if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) {
+ /* Check if the return value is required: */
+ if (thread_return) {
+ /* Return the thread's return value: */
+ *thread_return = pthread->ret;
+ }
+ } else {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+ }
+ } else {
+ /* Check if the return value is required: */
+ if (thread_return != NULL) {
+ /* Return the thread's return value: */
+ *thread_return = pthread->ret;
+ }
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libkse/thread/thr_kern.c b/lib/libkse/thread/thr_kern.c
new file mode 100644
index 0000000..ba8e250
--- /dev/null
+++ b/lib/libkse/thread/thr_kern.c
@@ -0,0 +1,1739 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/syscall.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* Static variables: */
+static sigset_t sig_to_block = 0xffffffff;
+static sigset_t sig_to_unblock = 0;
+
+/* Static function prototype definitions: */
+static void
+_thread_kern_select(int wait_reqd);
+static void
+_thread_signal(pthread_t pthread, int sig);
+
+void
+_thread_kern_sched(struct sigcontext * scp)
+{
+#ifndef __alpha
+ char *fdata;
+#endif
+ int i;
+ int prio = -1;
+ pthread_t pthread;
+ pthread_t pthread_h = NULL;
+ pthread_t pthread_nxt = NULL;
+ pthread_t pthread_prv = NULL;
+ pthread_t pthread_s = NULL;
+ struct itimerval itimer;
+ struct timespec ts;
+ struct timespec ts1;
+ struct timeval tv;
+ struct timeval tv1;
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Check if this function was called from the signal handler: */
+ if (scp != NULL) {
+ /*
+ * Copy the signal context to the current thread's jump
+ * buffer:
+ */
+ memcpy(&_thread_run->saved_sigcontext, scp, sizeof(_thread_run->saved_sigcontext));
+
+#ifndef __alpha
+ /* Point to the floating point data in the running thread: */
+ fdata = _thread_run->saved_fp;
+
+ /* Save the floating point data: */
+__asm__("fnsave %0": :"m"(*fdata));
+#endif
+
+ /* Flag the signal context as the last state saved: */
+ _thread_run->sig_saved = 1;
+ }
+ /* Save the state of the current thread: */
+ else if (_thread_sys_setjmp(_thread_run->saved_jmp_buf) != 0) {
+ /* Unblock signals (just in case): */
+ _thread_kern_sig_unblock(0);
+
+ /*
+ * This point is reached when a longjmp() is called to
+ * restore the state of a thread.
+ */
+ return;
+ } else {
+ /* Flag the jump buffer was the last state saved: */
+ _thread_run->sig_saved = 0;
+ }
+
+ /* Point to the first dead thread (if there are any): */
+ pthread = _thread_dead;
+
+ /* There is no previous dead thread: */
+ pthread_prv = NULL;
+
+ /* Enter a loop to cleanup after dead threads: */
+ while (pthread != NULL) {
+ /* Save a pointer to the next thread: */
+ pthread_nxt = pthread->nxt;
+
+ /* Check if this thread is one which is running: */
+ if (pthread == _thread_run || pthread == _thread_initial) {
+ /*
+ * Don't destroy the running thread or the initial
+ * thread.
+ */
+ pthread_prv = pthread;
+ }
+ /*
+ * Check if this thread has detached or if it is a signal
+ * handler thread:
+ */
+ else if (((pthread->attr.flags & PTHREAD_DETACHED) != 0) || pthread->parent_thread != NULL) {
+ /* Check if there is no previous dead thread: */
+ if (pthread_prv == NULL) {
+ /*
+ * The dead thread is at the head of the
+ * list:
+ */
+ _thread_dead = pthread_nxt;
+ } else {
+ /*
+ * The dead thread is not at the head of the
+ * list:
+ */
+ pthread_prv->nxt = pthread->nxt;
+ }
+
+ /*
+ * Check if the stack was not specified by the caller
+ * to pthread_create and has not been destroyed yet:
+ */
+ if (pthread->attr.stackaddr_attr == NULL && pthread->stack != NULL) {
+ /* Free the stack of the dead thread: */
+ free(pthread->stack);
+ }
+ /* Free the memory allocated to the thread structure: */
+ free(pthread);
+ } else {
+ /*
+ * This thread has not detached, so do not destroy
+ * it:
+ */
+ pthread_prv = pthread;
+
+ /*
+ * Check if the stack was not specified by the caller
+ * to pthread_create and has not been destroyed yet:
+ */
+ if (pthread->attr.stackaddr_attr == NULL && pthread->stack != NULL) {
+ /* Free the stack of the dead thread: */
+ free(pthread->stack);
+
+ /*
+ * NULL the stack pointer now that the memory
+ * has been freed:
+ */
+ pthread->stack = NULL;
+ }
+ }
+
+ /* Point to the next thread: */
+ pthread = pthread_nxt;
+ }
+
+ /*
+ * Enter a the scheduling loop that finds the next thread that is
+ * ready to run. This loop completes when there are no more threads
+ * in the global list or when a thread has its state restored by
+ * either a sigreturn (if the state was saved as a sigcontext) or a
+ * longjmp (if the state was saved by a setjmp).
+ */
+ while (_thread_link_list != NULL) {
+ /* Get the current time of day: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+
+ /*
+ * Poll file descriptors to update the state of threads
+ * waiting on file I/O where data may be available:
+ */
+ _thread_kern_select(0);
+
+ /*
+ * Enter a loop to look for sleeping threads that are ready
+ * or threads with pending signals that are no longer
+ * blocked:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Enter a loop to process the sending signals: */
+ for (i = 1; i < NSIG; i++) {
+ /*
+ * Check if there are no pending signals of
+ * this type:
+ */
+ if (pthread->sigpend[i] == 0) {
+ }
+ /* Check if this signal type is not masked: */
+ else if (sigismember(&pthread->sigmask, i) == 0) {
+ /*
+ * Delete the signal from the set of
+ * pending signals for this thread:
+ */
+ pthread->sigpend[i] -= 1;
+
+ /*
+ * Act on the signal for the current
+ * thread:
+ */
+ _thread_signal(pthread, i);
+ } else {
+ /*
+ * This signal is masked, so make
+ * sure the count does not exceed 1:
+ */
+ pthread->sigpend[i] = 1;
+ }
+ }
+
+ /* Check if this thread is to timeout: */
+ if (pthread->state == PS_COND_WAIT ||
+ pthread->state == PS_SLEEP_WAIT ||
+ pthread->state == PS_FDR_WAIT ||
+ pthread->state == PS_FDW_WAIT ||
+ pthread->state == PS_SELECT_WAIT) {
+ /* Check if this thread is to wait forever: */
+ if (pthread->wakeup_time.tv_sec == -1) {
+ }
+ /*
+ * Check if this thread is to wakeup
+ * immediately or if it is past its wakeup
+ * time:
+ */
+ else if ((pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) ||
+ (ts.tv_sec > pthread->wakeup_time.tv_sec) ||
+ ((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
+ (ts.tv_nsec >= pthread->wakeup_time.tv_nsec))) {
+ /*
+ * Check if this thread is waiting on
+ * select:
+ */
+ if (pthread->state == PS_SELECT_WAIT) {
+ /*
+ * The select has timed out,
+ * so zero the file
+ * descriptor sets:
+ */
+ FD_ZERO(&pthread->data.select_data->readfds);
+ FD_ZERO(&pthread->data.select_data->writefds);
+ FD_ZERO(&pthread->data.select_data->exceptfds);
+ pthread->data.select_data->nfds = 0;
+ }
+ /*
+ * Return an error as an interrupted
+ * wait:
+ */
+ _thread_seterrno(pthread, EINTR);
+
+ /*
+ * Flag the timeout in the thread
+ * structure:
+ */
+ pthread->timeout = 1;
+
+ /*
+ * Change the threads state to allow
+ * it to be restarted:
+ */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ }
+ }
+
+ /* Check if there is a current thread: */
+ if (_thread_run != &_thread_kern_thread) {
+ /*
+ * Save the current time as the time that the thread
+ * became inactive:
+ */
+ _thread_run->last_inactive.tv_sec = tv.tv_sec;
+ _thread_run->last_inactive.tv_usec = tv.tv_usec;
+
+ /*
+ * Accumulate the number of microseconds that this
+ * thread has run for:
+ */
+ _thread_run->slice_usec += (_thread_run->last_inactive.tv_sec -
+ _thread_run->last_active.tv_sec) * 1000000 +
+ _thread_run->last_inactive.tv_usec -
+ _thread_run->last_active.tv_usec;
+
+ /*
+ * Check if this thread has reached its allocated
+ * time slice period:
+ */
+ if (_thread_run->slice_usec > TIMESLICE_USEC) {
+ /*
+ * Flag the allocated time slice period as
+ * up:
+ */
+ _thread_run->slice_usec = -1;
+ }
+ }
+ /* Check if an incremental priority update is required: */
+ if (((tv.tv_sec - kern_inc_prio_time.tv_sec) * 1000000 +
+ tv.tv_usec - kern_inc_prio_time.tv_usec) > INC_PRIO_USEC) {
+ /*
+ * Enter a loop to look for run-enabled threads that
+ * have not run since the last time that an
+ * incremental priority update was performed:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if this thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ }
+ /*
+ * Check if the last time that this thread
+ * was run (as indicated by the last time it
+ * became inactive) is before the time that
+ * the last incremental priority check was
+ * made:
+ */
+ else if (timercmp(&_thread_run->last_inactive, &kern_inc_prio_time, >)) {
+ /*
+ * Increment the incremental priority
+ * for this thread in the hope that
+ * it will eventually get a chance to
+ * run:
+ */
+ (pthread->inc_prio)++;
+ }
+ }
+
+ /* Save the new incremental priority update time: */
+ kern_inc_prio_time.tv_sec = tv.tv_sec;
+ kern_inc_prio_time.tv_usec = tv.tv_usec;
+ }
+ /*
+ * Enter a loop to look for the first thread of the highest
+ * priority that is ready to run:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
+ /* Check if the current thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ }
+ /*
+ * Check if no run-enabled thread has been seen or if
+ * the current thread has a priority higher than the
+ * highest seen so far:
+ */
+ else if (pthread_h == NULL || (pthread->pthread_priority + pthread->inc_prio) > prio) {
+ /*
+ * Save this thread as the highest priority
+ * thread seen so far:
+ */
+ pthread_h = pthread;
+ prio = pthread->pthread_priority + pthread->inc_prio;
+ }
+ }
+
+ /*
+ * Enter a loop to look for a thread that: 1. Is run-enabled.
+ * 2. Has the required agregate priority. 3. Has not been
+ * allocated its allocated time slice. 4. Became inactive
+ * least recently.
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
+ /* Check if the current thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ /* Ignore threads that are not ready to run. */
+ }
+ /*
+ * Check if the current thread as an agregate
+ * priority not equal to the highest priority found
+ * above:
+ */
+ else if ((pthread->pthread_priority + pthread->inc_prio) != prio) {
+ /*
+ * Ignore threads which have lower agregate
+ * priority.
+ */
+ }
+ /*
+ * Check if the current thread reached its time slice
+ * allocation last time it ran (or if it has not run
+ * yet):
+ */
+ else if (pthread->slice_usec == -1) {
+ }
+ /*
+ * Check if an eligible thread has not been found
+ * yet, or if the current thread has an inactive time
+ * earlier than the last one seen:
+ */
+ else if (pthread_s == NULL || timercmp(&pthread->last_inactive, &tv1, <)) {
+ /*
+ * Save the pointer to the current thread as
+ * the most eligible thread seen so far:
+ */
+ pthread_s = pthread;
+
+ /*
+ * Save the time that the selected thread
+ * became inactive:
+ */
+ tv1.tv_sec = pthread->last_inactive.tv_sec;
+ tv1.tv_usec = pthread->last_inactive.tv_usec;
+ }
+ }
+
+ /*
+ * Check if no thread was selected according to incomplete
+ * time slice allocation:
+ */
+ if (pthread_s == NULL) {
+ /*
+ * Enter a loop to look for any other thread that: 1.
+ * Is run-enabled. 2. Has the required agregate
+ * priority. 3. Became inactive least recently.
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
+ /*
+ * Check if the current thread is unable to
+ * run:
+ */
+ if (pthread->state != PS_RUNNING) {
+ /*
+ * Ignore threads that are not ready
+ * to run.
+ */
+ }
+ /*
+ * Check if the current thread as an agregate
+ * priority not equal to the highest priority
+ * found above:
+ */
+ else if ((pthread->pthread_priority + pthread->inc_prio) != prio) {
+ /*
+ * Ignore threads which have lower
+ * agregate priority.
+ */
+ }
+ /*
+ * Check if an eligible thread has not been
+ * found yet, or if the current thread has an
+ * inactive time earlier than the last one
+ * seen:
+ */
+ else if (pthread_s == NULL || timercmp(&pthread->last_inactive, &tv1, <)) {
+ /*
+ * Save the pointer to the current
+ * thread as the most eligible thread
+ * seen so far:
+ */
+ pthread_s = pthread;
+
+ /*
+ * Save the time that the selected
+ * thread became inactive:
+ */
+ tv1.tv_sec = pthread->last_inactive.tv_sec;
+ tv1.tv_usec = pthread->last_inactive.tv_usec;
+ }
+ }
+ }
+ /* Check if there are no threads ready to run: */
+ if (pthread_s == NULL) {
+ /*
+ * Lock the pthread kernel by changing the pointer to
+ * the running thread to point to the global kernel
+ * thread structure:
+ */
+ _thread_run = &_thread_kern_thread;
+
+ /*
+ * There are no threads ready to run, so wait until
+ * something happens that changes this condition:
+ */
+ _thread_kern_select(1);
+ } else {
+ /* Make the selected thread the current thread: */
+ _thread_run = pthread_s;
+
+ /*
+ * Save the current time as the time that the thread
+ * became active:
+ */
+ _thread_run->last_active.tv_sec = tv.tv_sec;
+ _thread_run->last_active.tv_usec = tv.tv_usec;
+
+ /*
+ * Check if this thread is running for the first time
+ * or running again after using its full time slice
+ * allocation:
+ */
+ if (_thread_run->slice_usec == -1) {
+ /* Reset the accumulated time slice period: */
+ _thread_run->slice_usec = 0;
+ }
+ /*
+ * Reset the incremental priority now that this
+ * thread has been given the chance to run:
+ */
+ _thread_run->inc_prio = 0;
+
+ /* Check if there is more than one thread: */
+ if (_thread_run != _thread_link_list || _thread_run->nxt != NULL) {
+ /*
+ * Define the maximum time before a SIGVTALRM
+ * is required:
+ */
+ itimer.it_value.tv_sec = 0;
+ itimer.it_value.tv_usec = TIMESLICE_USEC;
+
+ /*
+ * The interval timer is not reloaded when it
+ * times out. The interval time needs to be
+ * calculated every time.
+ */
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+
+ /*
+ * Enter a loop to look for threads waiting
+ * for a time:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /*
+ * Check if this thread is to
+ * timeout:
+ */
+ if (pthread->state == PS_COND_WAIT ||
+ pthread->state == PS_SLEEP_WAIT ||
+ pthread->state == PS_FDR_WAIT ||
+ pthread->state == PS_FDW_WAIT ||
+ pthread->state == PS_SELECT_WAIT) {
+ /*
+ * Check if this thread is to
+ * wait forever:
+ */
+ if (pthread->wakeup_time.tv_sec == -1) {
+ }
+ /*
+ * Check if this thread is to
+ * wakeup immediately:
+ */
+ else if (pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) {
+ }
+ /*
+ * Check if the current time
+ * is after the wakeup time:
+ */
+ else if ((ts.tv_sec > pthread->wakeup_time.tv_sec) ||
+ ((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
+ (ts.tv_nsec > pthread->wakeup_time.tv_nsec))) {
+ } else {
+ /*
+ * Calculate the time
+ * until this thread
+ * is ready, allowing
+ * for the clock
+ * resolution:
+ */
+ ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
+ ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
+ CLOCK_RES_NSEC;
+
+ /*
+ * Check for
+ * underflow of the
+ * nanosecond field:
+ */
+ if (ts1.tv_nsec < 0) {
+ /*
+ * Allow for
+ * the
+ * underflow
+ * of the
+ * nanosecond
+ * field:
+ */
+ ts1.tv_sec--;
+ ts1.tv_nsec += 1000000000;
+ }
+ /*
+ * Check for overflow
+ * of the nanosecond
+ * field:
+ */
+ if (ts1.tv_nsec >= 1000000000) {
+ /*
+ * Allow for
+ * the
+ * overflow
+ * of the
+ * nanosecond
+ * field:
+ */
+ ts1.tv_sec++;
+ ts1.tv_nsec -= 1000000000;
+ }
+ /*
+ * Convert the
+ * timespec structure
+ * to a timeval
+ * structure:
+ */
+ TIMESPEC_TO_TIMEVAL(&tv, &ts1);
+
+ /*
+ * Check if the
+ * thread will be
+ * ready sooner than
+ * the earliest one
+ * found so far:
+ */
+ if (timercmp(&tv, &itimer.it_value, <)) {
+ /*
+ * Update the
+ * time
+ * value:
+ */
+ itimer.it_value.tv_sec = tv.tv_sec;
+ itimer.it_value.tv_usec = tv.tv_usec;
+ }
+ }
+ }
+ }
+
+ /*
+ * Start the interval timer for the
+ * calculated time interval:
+ */
+ if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) != 0) {
+ /*
+ * Cannot initialise the timer, so
+ * abort this process:
+ */
+ PANIC("Cannot set virtual timer");
+ }
+ }
+ /* Check if a signal context was saved: */
+ if (_thread_run->sig_saved == 1) {
+#ifndef __alpha
+ /*
+ * Point to the floating point data in the
+ * running thread:
+ */
+ fdata = _thread_run->saved_fp;
+
+ /* Restore the floating point state: */
+ __asm__("frstor %0": :"m"(*fdata));
+#endif
+
+ /*
+ * Do a sigreturn to restart the thread that
+ * was interrupted by a signal:
+ */
+ _thread_sys_sigreturn(&_thread_run->saved_sigcontext);
+ } else {
+ /*
+ * Do a longjmp to restart the thread that
+ * was context switched out (by a longjmp to
+ * a different thread):
+ */
+ _thread_sys_longjmp(_thread_run->saved_jmp_buf, 1);
+ }
+
+ /* This point should not be reached. */
+ PANIC("Thread has returned from sigreturn or longjmp");
+ }
+ }
+
+ /* There are no more threads, so exit this process: */
+ exit(0);
+}
+
+static void
+_thread_signal(pthread_t pthread, int sig)
+{
+ int done;
+ long l;
+ pthread_t new_pthread;
+ struct sigaction act;
+ void *arg;
+
+ /*
+ * Assume that the signal will not be dealt with according
+ * to the thread state:
+ */
+ done = 0;
+
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /* States which do not change when a signal is trapped: */
+ case PS_COND_WAIT:
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_RUNNING:
+ case PS_STATE_MAX:
+ case PS_SIGTHREAD:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* Wait for child: */
+ case PS_WAIT_WAIT:
+ /* Check if the signal is from a child exiting: */
+ if (sig == SIGCHLD) {
+ /* Reset the error: */
+ _thread_seterrno(pthread, 0);
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ } else {
+ /* Return the 'interrupted' error: */
+ _thread_seterrno(pthread, EINTR);
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ pthread->interrupted = 1;
+ break;
+
+ /* Waiting on I/O for zero or more file descriptors: */
+ case PS_SELECT_WAIT:
+ pthread->data.select_data->nfds = -1;
+
+ /* Return the 'interrupted' error: */
+ _thread_seterrno(pthread, EINTR);
+ pthread->interrupted = 1;
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ break;
+
+ /*
+ * States that are interrupted by the occurrence of a signal
+ * other than the scheduling alarm:
+ */
+ case PS_FDR_WAIT:
+ case PS_FDW_WAIT:
+ case PS_SLEEP_WAIT:
+ /* Return the 'interrupted' error: */
+ _thread_seterrno(pthread, EINTR);
+ pthread->interrupted = 1;
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+
+ /* Return the signal number: */
+ pthread->signo = sig;
+ break;
+
+ /* Waiting on a signal: */
+ case PS_SIGWAIT:
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+
+ /* Return the signal number: */
+ pthread->signo = sig;
+
+ /* Flag the signal as dealt with: */
+ done = 1;
+ break;
+ }
+
+ /*
+ * Check if this signal has been dealt with, or is being
+ * ignored:
+ */
+ if (done || pthread->act[sig - 1].sa_handler == SIG_IGN) {
+ /* Ignore the signal for this thread. */
+ }
+ /* Check if this signal is to use the default handler: */
+ else if (pthread->act[sig - 1].sa_handler == SIG_DFL) {
+ /* Process according to signal type: */
+ switch (sig) {
+ /* Signals which cause core dumps: */
+ case SIGQUIT:
+ case SIGILL:
+ case SIGTRAP:
+ case SIGABRT:
+ case SIGEMT:
+ case SIGFPE:
+ case SIGBUS:
+ case SIGSEGV:
+ case SIGSYS:
+ /* Clear the signal action: */
+ sigfillset(&act.sa_mask);
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = SA_RESTART;
+ _thread_sys_sigaction(sig, &act, NULL);
+
+ /*
+ * Do a sigreturn back to where the signal was
+ * detected and a core dump should occur:
+ */
+ _thread_sys_sigreturn(&pthread->saved_sigcontext);
+ break;
+
+ /* Default processing for other signals: */
+ default:
+ /*
+ * ### Default processing is a problem to resolve!
+ * ###
+ */
+ break;
+ }
+ } else {
+ /*
+ * Cast the signal number as a long and then to a void
+ * pointer. Sigh. This is POSIX.
+ */
+ l = (long) sig;
+ arg = (void *) l;
+
+ /* Create a signal handler thread, but don't run it yet: */
+ if (_thread_create(&new_pthread, NULL, (void *) pthread->act[sig - 1].sa_handler, arg, pthread) != 0) {
+ /*
+ * Error creating signal handler thread, so abort
+ * this process:
+ */
+ PANIC("Cannot create signal handler thread");
+ }
+ }
+
+ /* Nothing to return. */
+ return;
+}
+
+void
+_thread_kern_sig_block(int *status)
+{
+ sigset_t oset;
+
+ /*
+ * Block all signals so that the process will not be interrupted by
+ * signals:
+ */
+ _thread_sys_sigprocmask(SIG_SETMASK, &sig_to_block, &oset);
+
+ /* Check if the caller wants the current block status returned: */
+ if (status != NULL) {
+ /* Return the previous signal block status: */
+ *status = (oset != 0);
+ }
+ return;
+}
+
+void
+_thread_kern_sig_unblock(int status)
+{
+ sigset_t oset;
+
+ /*
+ * Check if the caller thinks that signals weren't blocked when it
+ * called _thread_kern_sig_block:
+ */
+ if (status == 0) {
+ /*
+ * Unblock all signals so that the process will be
+ * interrupted when a signal occurs:
+ */
+ _thread_sys_sigprocmask(SIG_SETMASK, &sig_to_unblock, &oset);
+ }
+ return;
+}
+
+void
+_thread_kern_sched_state(enum pthread_state state, char *fname, int lineno)
+{
+ /* Change the state of the current thread: */
+ _thread_run->state = state;
+ _thread_run->fname = fname;
+ _thread_run->lineno = lineno;
+
+ /* Schedule the next thread that is ready: */
+ _thread_kern_sched(NULL);
+ return;
+}
+
+static void
+_thread_kern_select(int wait_reqd)
+{
+ char bufr[128];
+ fd_set fd_set_except;
+ fd_set fd_set_read;
+ fd_set fd_set_write;
+ int count = 0;
+ int count_dec;
+ int found_one;
+ int i;
+ int nfds = -1;
+ int settimeout;
+ pthread_t pthread;
+ ssize_t num;
+ struct timespec ts;
+ struct timespec ts1;
+ struct timeval *p_tv;
+ struct timeval tv;
+ struct timeval tv1;
+
+ /* Zero the file descriptor sets: */
+ FD_ZERO(&fd_set_read);
+ FD_ZERO(&fd_set_write);
+ FD_ZERO(&fd_set_except);
+
+ /* Check if the caller wants to wait: */
+ if (wait_reqd) {
+ /*
+ * Add the pthread kernel pipe file descriptor to the read
+ * set:
+ */
+ FD_SET(_thread_kern_pipe[0], &fd_set_read);
+ nfds = _thread_kern_pipe[0];
+
+ /* Get the current time of day: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+ }
+ /* Initialise the time value structure: */
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ /*
+ * Enter a loop to process threads waiting on either file descriptors
+ * or times:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Assume that this state does not time out: */
+ settimeout = 0;
+
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /*
+ * States which do not depend on file descriptor I/O
+ * operations or timeouts:
+ */
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_RUNNING:
+ case PS_SIGTHREAD:
+ case PS_SIGWAIT:
+ case PS_STATE_MAX:
+ case PS_WAIT_WAIT:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* File descriptor read wait: */
+ case PS_FDR_WAIT:
+ /* Add the file descriptor to the read set: */
+ FD_SET(pthread->data.fd.fd, &fd_set_read);
+
+ /*
+ * Check if this file descriptor is greater than any
+ * of those seen so far:
+ */
+ if (pthread->data.fd.fd > nfds) {
+ /* Remember this file descriptor: */
+ nfds = pthread->data.fd.fd;
+ }
+ /* Increment the file descriptor count: */
+ count++;
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+
+ /* File descriptor write wait: */
+ case PS_FDW_WAIT:
+ /* Add the file descriptor to the write set: */
+ FD_SET(pthread->data.fd.fd, &fd_set_write);
+
+ /*
+ * Check if this file descriptor is greater than any
+ * of those seen so far:
+ */
+ if (pthread->data.fd.fd > nfds) {
+ /* Remember this file descriptor: */
+ nfds = pthread->data.fd.fd;
+ }
+ /* Increment the file descriptor count: */
+ count++;
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+
+ /* States that time out: */
+ case PS_SLEEP_WAIT:
+ case PS_COND_WAIT:
+ /* Flag a timeout as required: */
+ settimeout = 1;
+ break;
+
+ /* Select wait: */
+ case PS_SELECT_WAIT:
+ /*
+ * Enter a loop to process each file descriptor in
+ * the thread-specific file descriptor sets:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ /*
+ * Check if this file descriptor is set for
+ * exceptions:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
+ /*
+ * Add the file descriptor to the
+ * exception set:
+ */
+ FD_SET(i, &fd_set_except);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ /*
+ * Check if this file descriptor is set for
+ * write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
+ /*
+ * Add the file descriptor to the
+ * write set:
+ */
+ FD_SET(i, &fd_set_write);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ /*
+ * Check if this file descriptor is set for
+ * read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
+ /*
+ * Add the file descriptor to the
+ * read set:
+ */
+ FD_SET(i, &fd_set_read);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ }
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+ }
+
+ /*
+ * Check if the caller wants to wait and if the thread state
+ * is one that times out:
+ */
+ if (wait_reqd && settimeout) {
+ /* Check if this thread wants to wait forever: */
+ if (pthread->wakeup_time.tv_sec == -1) {
+ }
+ /* Check if this thread doesn't want to wait at all: */
+ else if (pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) {
+ /* Override the caller's request to wait: */
+ wait_reqd = 0;
+ } else {
+ /*
+ * Calculate the time until this thread is
+ * ready, allowing for the clock resolution:
+ */
+ ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
+ ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
+ CLOCK_RES_NSEC;
+
+ /*
+ * Check for underflow of the nanosecond
+ * field:
+ */
+ if (ts1.tv_nsec < 0) {
+ /*
+ * Allow for the underflow of the
+ * nanosecond field:
+ */
+ ts1.tv_sec--;
+ ts1.tv_nsec += 1000000000;
+ }
+ /*
+ * Check for overflow of the nanosecond
+ * field:
+ */
+ if (ts1.tv_nsec >= 1000000000) {
+ /*
+ * Allow for the overflow of the
+ * nanosecond field:
+ */
+ ts1.tv_sec++;
+ ts1.tv_nsec -= 1000000000;
+ }
+ /*
+ * Convert the timespec structure to a
+ * timeval structure:
+ */
+ TIMESPEC_TO_TIMEVAL(&tv1, &ts1);
+
+ /*
+ * Check if no time value has been found yet,
+ * or if the thread will be ready sooner that
+ * the earliest one found so far:
+ */
+ if ((tv.tv_sec == 0 && tv.tv_usec == 0) || timercmp(&tv1, &tv, <)) {
+ /* Update the time value: */
+ tv.tv_sec = tv1.tv_sec;
+ tv.tv_usec = tv1.tv_usec;
+ }
+ }
+ }
+ }
+
+ /* Check if the caller wants to wait: */
+ if (wait_reqd) {
+ /* Check if no threads were found with timeouts: */
+ if (tv.tv_sec == 0 && tv.tv_usec == 0) {
+ /* Wait forever: */
+ p_tv = NULL;
+ } else {
+ /*
+ * Point to the time value structure which contains
+ * the earliest time that a thread will be ready:
+ */
+ p_tv = &tv;
+ }
+
+ /*
+ * Flag the pthread kernel as in a select. This is to avoid
+ * the window between the next statement that unblocks
+ * signals and the select statement which follows.
+ */
+ _thread_kern_in_select = 1;
+
+ /* Unblock all signals: */
+ _thread_kern_sig_unblock(0);
+
+ /*
+ * Wait for a file descriptor to be ready for read, write, or
+ * an exception, or a timeout to occur:
+ */
+ count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
+
+ /* Block all signals again: */
+ _thread_kern_sig_block(NULL);
+
+ /* Reset the kernel in select flag: */
+ _thread_kern_in_select = 0;
+
+ /*
+ * Check if it is possible that there are bytes in the kernel
+ * read pipe waiting to be read:
+ */
+ if (count < 0 || FD_ISSET(_thread_kern_pipe[0], &fd_set_read)) {
+ /*
+ * Check if the kernel read pipe was included in the
+ * count:
+ */
+ if (count > 0) {
+ /*
+ * Remove the kernel read pipe from the
+ * count:
+ */
+ FD_CLR(_thread_kern_pipe[0], &fd_set_read);
+
+ /* Decrement the count of file descriptors: */
+ count--;
+ }
+ /*
+ * Enter a loop to read (and trash) bytes from the
+ * pthread kernel pipe:
+ */
+ while ((num = _thread_sys_read(_thread_kern_pipe[0], bufr, sizeof(bufr))) > 0) {
+ /*
+ * The buffer read contains one byte per
+ * signal and each byte is the signal number.
+ * This data is not used, but the fact that
+ * the signal handler wrote to the pipe *is*
+ * used to cause the _thread_sys_select call
+ * to complete if the signal occurred between
+ * the time when signals were unblocked and
+ * the _thread_sys_select select call being
+ * made.
+ */
+ }
+ }
+ }
+ /* Check if there are file descriptors to poll: */
+ else if (count > 0) {
+ /*
+ * Point to the time value structure which has been zeroed so
+ * that the call to _thread_sys_select will not wait:
+ */
+ p_tv = &tv;
+
+ /* Poll file descrptors without wait: */
+ count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
+ }
+ /*
+ * Check if the select call was interrupted, or some other error
+ * occurred:
+ */
+ if (count < 0) {
+ /* Check if the select call was interrupted: */
+ if (errno == EINTR) {
+ /*
+ * Interrupted calls are expected. The interrupting
+ * signal will be in the sigpend array.
+ */
+ } else {
+ /* This should not occur: */
+ }
+ }
+ /* Check if no file descriptors are ready: */
+ else if (count == 0) {
+ /* Nothing to do here. */
+ } else {
+ /*
+ * Enter a loop to look for threads waiting on file
+ * descriptors that are flagged as available by the
+ * _thread_sys_select syscall:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /*
+ * States which do not depend on file
+ * descriptor I/O operations:
+ */
+ case PS_RUNNING:
+ case PS_COND_WAIT:
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_SIGWAIT:
+ case PS_SLEEP_WAIT:
+ case PS_WAIT_WAIT:
+ case PS_SIGTHREAD:
+ case PS_STATE_MAX:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* File descriptor read wait: */
+ case PS_FDR_WAIT:
+ /*
+ * Check if the file descriptor is available
+ * for read:
+ */
+ if (FD_ISSET(pthread->data.fd.fd, &fd_set_read)) {
+ /*
+ * Change the thread state to allow
+ * it to read from the file when it
+ * is scheduled next:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+
+ /* File descriptor write wait: */
+ case PS_FDW_WAIT:
+ /*
+ * Check if the file descriptor is available
+ * for write:
+ */
+ if (FD_ISSET(pthread->data.fd.fd, &fd_set_write)) {
+ /*
+ * Change the thread state to allow
+ * it to write to the file when it is
+ * scheduled next:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+
+ /* Select wait: */
+ case PS_SELECT_WAIT:
+ /*
+ * Reset the flag that indicates if a file
+ * descriptor is ready for some type of
+ * operation:
+ */
+ count_dec = 0;
+
+ /*
+ * Enter a loop to search though the
+ * thread-specific select file descriptors
+ * for the first descriptor that is ready:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds && count_dec == 0; i++) {
+ /*
+ * Check if this file descriptor does
+ * not have an exception:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds) && FD_ISSET(i, &fd_set_except)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ /*
+ * Check if this file descriptor is
+ * not ready for write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds) && FD_ISSET(i, &fd_set_write)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ /*
+ * Check if this file descriptor is
+ * not ready for read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds) && FD_ISSET(i, &fd_set_read)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ }
+
+ /*
+ * Check if any file descriptors are ready
+ * for the current thread:
+ */
+ if (count_dec) {
+ /*
+ * Reset the count of file
+ * descriptors that are ready for
+ * this thread:
+ */
+ found_one = 0;
+
+ /*
+ * Enter a loop to search though the
+ * thread-specific select file
+ * descriptors:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ /*
+ * Reset the count of
+ * operations for which the
+ * current file descriptor is
+ * ready:
+ */
+ count_dec = 0;
+
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * exceptions:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
+ /*
+ * Check if this file
+ * descriptor has an
+ * exception:
+ */
+ if (FD_ISSET(i, &fd_set_except)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->exceptfds);
+ }
+ }
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
+ /*
+ * Check if this file
+ * descriptor is
+ * ready for write:
+ */
+ if (FD_ISSET(i, &fd_set_write)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->writefds);
+ }
+ }
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
+ /*
+ * Check if this file
+ * descriptor is
+ * ready for read:
+ */
+ if (FD_ISSET(i, &fd_set_read)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->readfds);
+ }
+ }
+ /*
+ * Check if the current file
+ * descriptor is ready for
+ * any one of the operations:
+ */
+ if (count_dec > 0) {
+ /*
+ * Increment the
+ * count of file
+ * descriptors that
+ * are ready for the
+ * current thread:
+ */
+ found_one++;
+ }
+ }
+
+ /*
+ * Return the number of file
+ * descriptors that are ready:
+ */
+ pthread->data.select_data->nfds = found_one;
+
+ /*
+ * Change the state of the current
+ * thread to run:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+ }
+ }
+ }
+
+ /* Nothing to return. */
+ return;
+}
+
+void
+_thread_kern_set_timeout(struct timespec * timeout)
+{
+ struct timespec current_time;
+ struct timeval tv;
+
+ /* Reset the timeout flag for the running thread: */
+ _thread_run->timeout = 0;
+
+ /* Check if the thread is to wait forever: */
+ if (timeout == NULL) {
+ /*
+ * Set the wakeup time to something that can be recognised as
+ * different to an actual time of day:
+ */
+ _thread_run->wakeup_time.tv_sec = -1;
+ _thread_run->wakeup_time.tv_nsec = -1;
+ }
+ /* Check if no waiting is required: */
+ else if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
+ /* Set the wake up time to 'immediately': */
+ _thread_run->wakeup_time.tv_sec = 0;
+ _thread_run->wakeup_time.tv_nsec = 0;
+ } else {
+ /* Get the current time: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &current_time);
+
+ /* Calculate the time for the current thread to wake up: */
+ _thread_run->wakeup_time.tv_sec = current_time.tv_sec + timeout->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + timeout->tv_nsec;
+
+ /* Check if the nanosecond field needs to wrap: */
+ if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
+ /* Wrap the nanosecond field: */
+ _thread_run->wakeup_time.tv_sec += 1;
+ _thread_run->wakeup_time.tv_nsec -= 1000000000;
+ }
+ }
+ return;
+}
+#endif
diff --git a/lib/libkse/thread/thr_kill.c b/lib/libkse/thread/thr_kill.c
new file mode 100644
index 0000000..eb2c6b7
--- /dev/null
+++ b/lib/libkse/thread/thr_kill.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_kill(pthread_t pthread, int sig)
+{
+ int rval = 0;
+ int status;
+ pthread_t p_pthread;
+
+ /* Check for invalid signal numbers: */
+ if (sig < 0 || sig >= NSIG)
+ /* Invalid signal: */
+ rval = EINVAL;
+ else {
+ /* Assume that the search will succeed: */
+ rval = 0;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Search for the thread: */
+ p_pthread = _thread_link_list;
+ while (p_pthread != NULL && p_pthread != pthread) {
+ p_pthread = p_pthread->nxt;
+ }
+
+ /* Check if the thread was not found: */
+ if (p_pthread == NULL)
+ /* Can't find the thread: */
+ rval = ESRCH;
+ else
+ /* Increment the pending signal count: */
+ p_pthread->sigpend[sig] += 1;
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libkse/thread/thr_mattr_init.c b/lib/libkse/thread/thr_mattr_init.c
new file mode 100644
index 0000000..323c982
--- /dev/null
+++ b/lib/libkse/thread/thr_mattr_init.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1996 Jeffrey Hsu <hsu@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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_mutexattr_init(pthread_mutexattr_t *attr)
+{
+ int ret;
+ pthread_mutexattr_t pattr;
+
+ if ((pattr = (pthread_mutexattr_t)
+ malloc(sizeof(struct pthread_mutex_attr))) == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ memcpy(pattr, &pthread_mutexattr_default,
+ sizeof(struct pthread_mutex_attr));
+ *attr = pattr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_mattr_kind_np.c b/lib/libkse/thread/thr_mattr_kind_np.c
new file mode 100644
index 0000000..3eeabff
--- /dev/null
+++ b/lib/libkse/thread/thr_mattr_kind_np.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1996 Jeffrey Hsu <hsu@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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ (*attr)->m_type = kind;
+ ret = 0;
+ }
+ return(ret);
+}
+
+int
+pthread_mutexattr_getkind_np(pthread_mutexattr_t attr)
+{
+ int ret;
+ if (attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ ret = attr->m_type;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_multi_np.c b/lib/libkse/thread/thr_multi_np.c
new file mode 100644
index 0000000..64f360f
--- /dev/null
+++ b/lib/libkse/thread/thr_multi_np.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_multi_np()
+{
+ /* Return to multi-threaded scheduling mode: */
+ _thread_single = NULL;
+ return(0);
+}
+#endif
diff --git a/lib/libkse/thread/thr_mutex.c b/lib/libkse/thread/thr_mutex.c
new file mode 100644
index 0000000..82a26e8
--- /dev/null
+++ b/lib/libkse/thread/thr_mutex.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_mutex_init(pthread_mutex_t * mutex,
+ const pthread_mutexattr_t * mutex_attr)
+{
+ enum pthread_mutextype type;
+ pthread_mutex_t pmutex;
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Check if default mutex attributes: */
+ if (mutex_attr == NULL || *mutex_attr == NULL) {
+ /* Default to a fast mutex: */
+ type = MUTEX_TYPE_FAST;
+ } else if ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Use the requested mutex type: */
+ type = (*mutex_attr)->m_type;
+ }
+
+ /* Check no errors so far: */
+ if (ret == 0) {
+ if ((pmutex = (pthread_mutex_t) malloc(sizeof(struct pthread_mutex))) == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ /* Reset the mutex flags: */
+ pmutex->m_flags = 0;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch (type) {
+ /* Fast mutex: */
+ case MUTEX_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Reset the mutex count: */
+ pmutex->m_data.m_count = 0;
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+ if (ret == 0) {
+ /* Initialise the rest of the mutex: */
+ _thread_queue_init(&pmutex->m_queue);
+ pmutex->m_flags |= MUTEX_FLAGS_INITED;
+ pmutex->m_owner = NULL;
+ pmutex->m_type = type;
+ *mutex = pmutex;
+ } else {
+ free(pmutex);
+ *mutex = NULL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+ }
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_destroy(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutex: */
+ case MUTEX_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Reset the mutex count: */
+ (*mutex)->m_data.m_count = 0;
+ break;
+
+ /* Trap undefined mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Clean up the mutex in case that others want to use it: */
+ _thread_queue_init(&(*mutex)->m_queue);
+ (*mutex)->m_owner = NULL;
+ (*mutex)->m_flags = 0;
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_trylock(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutex: */
+ case MUTEX_TYPE_FAST:
+ /* Check if this mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for the running thread: */
+ (*mutex)->m_owner = _thread_run;
+ } else {
+ /* Return a busy error: */
+ errno = EBUSY;
+ ret = -1;
+ }
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Check if this mutex is locked: */
+ if ((*mutex)->m_owner != NULL) {
+ /*
+ * Check if the mutex is locked by the running
+ * thread:
+ */
+ if ((*mutex)->m_owner == _thread_run) {
+ /* Increment the lock count: */
+ (*mutex)->m_data.m_count++;
+ } else {
+ /* Return a busy error: */
+ errno = EBUSY;
+ ret = -1;
+ }
+ } else {
+ /* Lock the mutex for the running thread: */
+ (*mutex)->m_owner = _thread_run;
+ }
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_lock(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutexes do not check for any error conditions: */
+ case MUTEX_TYPE_FAST:
+ /*
+ * Enter a loop to wait for the mutex to be locked by the
+ * current thread:
+ */
+ while ((*mutex)->m_owner != _thread_run) {
+ /* Check if the mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for this thread: */
+ (*mutex)->m_owner = _thread_run;
+ } else {
+ /*
+ * Join the queue of threads waiting to lock
+ * the mutex:
+ */
+ _thread_queue_enq(&(*mutex)->m_queue, _thread_run);
+
+ /* Block signals: */
+ _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+ }
+ }
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /*
+ * Enter a loop to wait for the mutex to be locked by the
+ * current thread:
+ */
+ while ((*mutex)->m_owner != _thread_run) {
+ /* Check if the mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for this thread: */
+ (*mutex)->m_owner = _thread_run;
+
+ /* Reset the lock count for this mutex: */
+ (*mutex)->m_data.m_count = 0;
+ } else {
+ /*
+ * Join the queue of threads waiting to lock
+ * the mutex:
+ */
+ _thread_queue_enq(&(*mutex)->m_queue, _thread_run);
+
+ /* Block signals: */
+ _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+ }
+ }
+
+ /* Increment the lock count for this mutex: */
+ (*mutex)->m_data.m_count++;
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_unlock(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutexes do not check for any error conditions: */
+ case MUTEX_TYPE_FAST:
+ /* Check if the running thread is not the owner of the mutex: */
+ if ((*mutex)->m_owner != _thread_run) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ }
+ /*
+ * Get the next thread from the queue of threads waiting on
+ * the mutex:
+ */
+ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
+ /* Allow the new owner of the mutex to run: */
+ PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING);
+ }
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Check if the running thread is not the owner of the mutex: */
+ if ((*mutex)->m_owner != _thread_run) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ }
+ /* Check if there are still counts: */
+ else if ((*mutex)->m_data.m_count) {
+ /* Decrement the count: */
+ (*mutex)->m_data.m_count--;
+ }
+ /*
+ * Get the next thread from the queue of threads waiting on
+ * the mutex:
+ */
+ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
+ /* Allow the new owner of the mutex to run: */
+ PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING);
+ }
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_mutexattr_destroy.c b/lib/libkse/thread/thr_mutexattr_destroy.c
new file mode 100644
index 0000000..cf2e09f
--- /dev/null
+++ b/lib/libkse/thread/thr_mutexattr_destroy.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ free(*attr);
+ *attr = NULL;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_nanosleep.c b/lib/libkse/thread/thr_nanosleep.c
new file mode 100644
index 0000000..39c7dad
--- /dev/null
+++ b/lib/libkse/thread/thr_nanosleep.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdio.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+nanosleep(const struct timespec * time_to_sleep,
+ struct timespec * time_remaining)
+{
+ int ret = 0;
+ struct timespec current_time;
+ struct timespec current_time1;
+ struct timespec remaining_time;
+ struct timeval tv;
+
+ /* Check if the time to sleep is legal: */
+ if (time_to_sleep == NULL || time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec > 1000000000) {
+ /* Return an EINVAL error : */
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Get the current time: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &current_time);
+
+ /* Calculate the time for the current thread to wake up: */
+ _thread_run->wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec;
+
+ /* Check if the nanosecond field has overflowed: */
+ if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
+ /* Wrap the nanosecond field: */
+ _thread_run->wakeup_time.tv_sec += 1;
+ _thread_run->wakeup_time.tv_nsec -= 1000000000;
+ }
+
+ /* Reschedule the current thread to sleep: */
+ _thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__);
+
+ /* Get the current time: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &current_time1);
+
+ /* Calculate the remaining time to sleep: */
+ remaining_time.tv_sec = time_to_sleep->tv_sec + current_time.tv_sec - current_time1.tv_sec;
+ remaining_time.tv_nsec = time_to_sleep->tv_nsec + current_time.tv_nsec - current_time1.tv_nsec;
+
+ /* Check if the nanosecond field has underflowed: */
+ if (remaining_time.tv_nsec < 0) {
+ /* Handle the underflow: */
+ remaining_time.tv_sec -= 1;
+ remaining_time.tv_nsec += 1000000000;
+ }
+
+ /* Check if the nanosecond field has overflowed: */
+ if (remaining_time.tv_nsec >= 1000000000) {
+ /* Handle the overflow: */
+ remaining_time.tv_sec += 1;
+ remaining_time.tv_nsec -= 1000000000;
+ }
+
+ /* Check if the sleep was longer than the required time: */
+ if (remaining_time.tv_sec < 0) {
+ /* Reset the time left: */
+ remaining_time.tv_sec = 0;
+ remaining_time.tv_nsec = 0;
+ }
+
+ /* Check if the time remaining is to be returned: */
+ if (time_remaining != NULL) {
+ /* Return the actual time slept: */
+ time_remaining->tv_sec = remaining_time.tv_sec;
+ time_remaining->tv_nsec = remaining_time.tv_nsec;
+ }
+
+ /* Check if the entire sleep was not completed: */
+ if (remaining_time.tv_nsec != 0 || remaining_time.tv_sec != 0) {
+ /* Return an EINTR error : */
+ errno = EINTR;
+ ret = -1;
+ }
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_once.c b/lib/libkse/thread/thr_once.c
new file mode 100644
index 0000000..c55ba9e
--- /dev/null
+++ b/lib/libkse/thread/thr_once.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_once(pthread_once_t * once_control, void (*init_routine) (void))
+{
+ if (once_control->state == PTHREAD_NEEDS_INIT) {
+ pthread_mutex_lock(&(once_control->mutex));
+ if (once_control->state == PTHREAD_NEEDS_INIT) {
+ init_routine();
+ once_control->state = PTHREAD_DONE_INIT;
+ }
+ pthread_mutex_unlock(&(once_control->mutex));
+ }
+ return (0);
+}
+#endif
diff --git a/lib/libkse/thread/thr_open.c b/lib/libkse/thread/thr_open.c
new file mode 100644
index 0000000..ef7a504
--- /dev/null
+++ b/lib/libkse/thread/thr_open.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+open(const char *path, int flags,...)
+{
+ int fd;
+ int mode = 0;
+ int status;
+ va_list ap;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Check if the file is being created: */
+ if (flags & O_CREAT) {
+ /* Get the creation mode: */
+ va_start(ap, flags);
+ mode = va_arg(ap, int);
+ va_end(ap);
+ }
+ /* Open the file: */
+ if ((fd = _thread_sys_open(path, flags, mode)) < 0) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(fd) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(fd);
+
+ /* Reset the file descriptor: */
+ fd = -1;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the file descriptor or -1 on error: */
+ return (fd);
+}
+#endif
diff --git a/lib/libkse/thread/thr_private.h b/lib/libkse/thread/thr_private.h
new file mode 100644
index 0000000..e0a0511
--- /dev/null
+++ b/lib/libkse/thread/thr_private.h
@@ -0,0 +1,783 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * Private thread definitions for the uthread kernel.
+ *
+ */
+
+#ifndef _PTHREAD_PRIVATE_H
+#define _PTHREAD_PRIVATE_H
+
+/*
+ * Evaluate the storage class specifier.
+ */
+#ifdef GLOBAL_PTHREAD_PRIVATE
+#define SCLASS
+#else
+#define SCLASS extern
+#endif
+
+/*
+ * Include files.
+ */
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+/*
+ * Kernel fatal error handler macro.
+ */
+#define PANIC(string) _thread_exit(__FILE__,__LINE__,string)
+
+/*
+ * State change macro:
+ */
+#define PTHREAD_NEW_STATE(thrd, newstate) { \
+ (thrd)->state = newstate; \
+ (thrd)->fname = __FILE__; \
+ (thrd)->lineno = __LINE__; \
+}
+
+/*
+ * Queue definitions.
+ */
+struct pthread_queue {
+ struct pthread *q_next;
+ struct pthread *q_last;
+ void *q_data;
+};
+
+/*
+ * Static queue initialization values.
+ */
+#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL }
+
+/*
+ * Mutex definitions.
+ */
+union pthread_mutex_data {
+ void *m_ptr;
+ int m_count;
+};
+
+struct pthread_mutex {
+ enum pthread_mutextype m_type;
+ struct pthread_queue m_queue;
+ struct pthread *m_owner;
+ union pthread_mutex_data m_data;
+ long m_flags;
+};
+
+/*
+ * Flags for mutexes.
+ */
+#define MUTEX_FLAGS_PRIVATE 0x01
+#define MUTEX_FLAGS_INITED 0x02
+#define MUTEX_FLAGS_BUSY 0x04
+
+/*
+ * Static mutex initialization values.
+ */
+#define PTHREAD_MUTEX_INITIALIZER \
+ { MUTEX_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, \
+ NULL, { NULL }, MUTEX_FLAGS_INITED }
+
+struct pthread_mutex_attr {
+ enum pthread_mutextype m_type;
+ long m_flags;
+};
+
+/*
+ * Condition variable definitions.
+ */
+enum pthread_cond_type {
+ COND_TYPE_FAST,
+ COND_TYPE_MAX
+};
+
+struct pthread_cond {
+ enum pthread_cond_type c_type;
+ struct pthread_queue c_queue;
+ void *c_data;
+ long c_flags;
+};
+
+struct pthread_cond_attr {
+ enum pthread_cond_type c_type;
+ long c_flags;
+};
+
+/*
+ * Flags for condition variables.
+ */
+#define COND_FLAGS_PRIVATE 0x01
+#define COND_FLAGS_INITED 0x02
+#define COND_FLAGS_BUSY 0x04
+
+/*
+ * Static cond initialization values.
+ */
+#define PTHREAD_COND_INITIALIZER \
+ { COND_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, NULL, COND_FLAGS_INITED }
+
+/*
+ * Cleanup definitions.
+ */
+struct pthread_cleanup {
+ struct pthread_cleanup *next;
+ void (*routine) ();
+ void *routine_arg;
+};
+
+/*
+ * Scheduling definitions.
+ */
+enum schedparam_policy {
+ SCHED_RR,
+ SCHED_IO,
+ SCHED_FIFO,
+ SCHED_OTHER
+};
+
+struct pthread_attr {
+ enum schedparam_policy schedparam_policy;
+ int prio;
+ int suspend;
+ int flags;
+ void *arg_attr;
+ void (*cleanup_attr) ();
+ void *stackaddr_attr;
+ size_t stacksize_attr;
+};
+
+struct sched_param {
+ int prio;
+ void *no_data;
+};
+
+/*
+ * Thread creation state attributes.
+ */
+#define PTHREAD_CREATE_RUNNING 0
+#define PTHREAD_CREATE_SUSPENDED 1
+
+/*
+ * Miscellaneous definitions.
+ */
+#define PTHREAD_STACK_DEFAULT 65536
+#define PTHREAD_DEFAULT_PRIORITY 64
+#define PTHREAD_MAX_PRIORITY 126
+#define PTHREAD_MIN_PRIORITY 0
+#define _POSIX_THREAD_ATTR_STACKSIZE
+
+/*
+ * Clock resolution in nanoseconds.
+ */
+#define CLOCK_RES_NSEC 10000000
+
+/*
+ * Number of microseconds between incremental priority updates for
+ * threads that are ready to run, but denied being run.
+ */
+#define INC_PRIO_USEC 500000
+
+/*
+ * Time slice period in microseconds.
+ */
+#define TIMESLICE_USEC 100000
+
+struct pthread_key {
+ pthread_mutex_t mutex;
+ long count;
+ void (*destructor) ();
+};
+
+/*
+ * Thread states.
+ */
+enum pthread_state {
+ PS_RUNNING,
+ PS_SIGTHREAD,
+ PS_MUTEX_WAIT,
+ PS_COND_WAIT,
+ PS_FDLR_WAIT,
+ PS_FDLW_WAIT,
+ PS_FDR_WAIT,
+ PS_FDW_WAIT,
+ PS_SELECT_WAIT,
+ PS_SLEEP_WAIT,
+ PS_WAIT_WAIT,
+ PS_SIGWAIT,
+ PS_JOIN,
+ PS_SUSPENDED,
+ PS_DEAD,
+ PS_STATE_MAX
+};
+
+
+/*
+ * File descriptor locking definitions.
+ */
+#define FD_READ 0x1
+#define FD_WRITE 0x2
+#define FD_RDWR (FD_READ | FD_WRITE)
+
+/*
+ * File descriptor table structure.
+ */
+struct fd_table_entry {
+ struct pthread_queue r_queue; /* Read queue. */
+ struct pthread_queue w_queue; /* Write queue. */
+ struct pthread *r_owner; /* Ptr to thread owning read lock. */
+ struct pthread *w_owner; /* Ptr to thread owning write lock. */
+ char *r_fname; /* Ptr to read lock source file name */
+ int r_lineno; /* Read lock source line number. */
+ char *w_fname; /* Ptr to write lock source file name */
+ int w_lineno; /* Write lock source line number. */
+ int r_lockcount; /* Count for FILE read locks. */
+ int w_lockcount; /* Count for FILE write locks. */
+ int flags; /* Flags used in open. */
+};
+
+struct pthread_select_data {
+ int nfds;
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+};
+
+union pthread_wait_data {
+ pthread_mutex_t *mutex;
+ pthread_cond_t *cond;
+ const sigset_t *sigwait; /* Waiting on a signal in sigwait */
+ struct {
+ short fd; /* Used when thread waiting on fd */
+ short branch; /* Line number, for debugging. */
+ char *fname; /* Source file name for debugging.*/
+ } fd;
+ struct pthread_select_data * select_data;
+};
+
+/*
+ * Thread structure.
+ */
+struct pthread {
+ /*
+ * Pointer to the next thread in the thread linked list.
+ */
+ struct pthread *nxt;
+
+ /*
+ * Thread start routine, argument, stack pointer and thread
+ * attributes.
+ */
+ void *(*start_routine)(void *);
+ void *arg;
+ void *stack;
+ struct pthread_attr attr;
+
+ /*
+ * Thread-specific signal handler interface:
+ *
+ * Array of signal actions for this thread.
+ */
+ struct sigaction act[NSIG];
+
+#if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(__i386__)
+ /*
+ * Saved floating point registers on systems where they are not
+ * saved in the signal context.
+ */
+ char saved_fp[108];
+#endif
+
+ /*
+ * Saved signal context used in call to sigreturn by
+ * _thread_kern_sched if sig_saved is TRUE.
+ */
+ struct sigcontext saved_sigcontext;
+
+ /*
+ * Saved jump buffer used in call to longjmp by _thread_kern_sched
+ * if sig_saved is FALSE.
+ */
+ jmp_buf saved_jmp_buf;
+
+ /*
+ * TRUE if the last state saved was a signal context. FALSE if the
+ * last state saved was a jump buffer.
+ */
+ int sig_saved;
+
+ /*
+ * Current signal mask and array of pending signals.
+ */
+ sigset_t sigmask;
+ int sigpend[NSIG];
+
+ /*
+ * Pointer to the parent thread for which the current thread is
+ * a signal handler thread, otherwise NULL if the current thread
+ * is not a signal handler thread.
+ */
+ struct pthread *parent_thread;
+
+ /* Thread state: */
+ enum pthread_state state;
+
+ /* Time that this thread was last made active. */
+ struct timeval last_active;
+
+ /* Time that this thread was last made inactive. */
+ struct timeval last_inactive;
+
+ /*
+ * Number of microseconds accumulated by this thread when
+ * time slicing is active.
+ */
+ long slice_usec;
+
+ /*
+ * Incremental priority accumulated by thread while it is ready to
+ * run but is denied being run.
+ */
+ int inc_prio;
+
+ /*
+ * Time to wake up thread. This is used for sleeping threads and
+ * for any operation which may time out (such as select).
+ */
+ struct timespec wakeup_time;
+
+ /* TRUE if operation has timed out. */
+ int timeout;
+
+ /*
+ * Error variable used instead of errno. The function __error()
+ * returns a pointer to this.
+ */
+ int error;
+
+ /* Join queue for waiting threads: */
+ struct pthread_queue join_queue;
+
+ /*
+ * The current thread can belong to only one queue at a time.
+ *
+ * Pointer to queue (if any) on which the current thread is waiting.
+ */
+ struct pthread_queue *queue;
+
+ /* Pointer to next element in queue. */
+ struct pthread *qnxt;
+
+ /* Wait data. */
+ union pthread_wait_data data;
+
+ /*
+ * Set to TRUE if a blocking operation was
+ * interrupted by a signal:
+ */
+ int interrupted;
+
+ /* Signal number when in state PS_SIGWAIT: */
+ int signo;
+
+ /* Miscellaneous data. */
+ char flags;
+ char pthread_priority;
+ void *ret;
+ const void **specific_data;
+ int specific_data_count;
+
+ /* Cleanup handlers Link List */
+ struct pthread_cleanup *cleanup;
+ char *fname; /* Ptr to source file name */
+ int lineno; /* Source line number. */
+};
+
+/*
+ * Global variables for the uthread kernel.
+ */
+
+/* Kernel thread structure used when there are no running threads: */
+SCLASS struct pthread _thread_kern_thread;
+
+/* Ptr to the thread structure for the running thread: */
+SCLASS struct pthread * volatile _thread_run
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= &_thread_kern_thread;
+#else
+;
+#endif
+
+/*
+ * Ptr to the thread running in single-threaded mode or NULL if
+ * running multi-threaded (default POSIX behaviour).
+ */
+SCLASS struct pthread * volatile _thread_single
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/* Ptr to the first thread in the thread linked list: */
+SCLASS struct pthread * volatile _thread_link_list
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/*
+ * Array of kernel pipe file descriptors that are used to ensure that
+ * no signals are missed in calls to _thread_sys_select.
+ */
+SCLASS int _thread_kern_pipe[2]
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= {
+ -1,
+ -1
+};
+#else
+;
+#endif
+SCLASS int _thread_kern_in_select
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 0;
+#else
+;
+#endif
+
+/* Last time that an incremental priority update was performed: */
+SCLASS struct timeval kern_inc_prio_time
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { 0, 0 };
+#else
+;
+#endif
+
+/* Dead threads: */
+SCLASS struct pthread * volatile _thread_dead
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/* Initial thread: */
+SCLASS struct pthread *_thread_initial
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/* Default thread attributes: */
+SCLASS struct pthread_attr pthread_attr_default
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { SCHED_RR, PTHREAD_DEFAULT_PRIORITY, PTHREAD_CREATE_RUNNING,
+ PTHREAD_CREATE_JOINABLE, NULL, NULL, NULL, PTHREAD_STACK_DEFAULT };
+#else
+;
+#endif
+
+/* Default mutex attributes: */
+SCLASS struct pthread_mutex_attr pthread_mutexattr_default
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { MUTEX_TYPE_FAST, 0 };
+#else
+;
+#endif
+
+/* Default condition variable attributes: */
+SCLASS struct pthread_cond_attr pthread_condattr_default
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { COND_TYPE_FAST, 0 };
+#else
+;
+#endif
+
+/*
+ * Standard I/O file descriptors need special flag treatment since
+ * setting one to non-blocking does all on *BSD. Sigh. This array
+ * is used to store the initial flag settings.
+ */
+SCLASS int _pthread_stdio_flags[3];
+
+/* File table information: */
+SCLASS struct fd_table_entry **_thread_fd_table
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+SCLASS const int dtablecount
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 4096/sizeof(struct fd_table_entry);
+#else
+;
+#endif
+SCLASS int _thread_dtablesize /* Descriptor table size. */
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 1024;
+#else
+;
+#endif
+
+/* Undefine the storage class specifier: */
+#undef SCLASS
+
+/*
+ * Function prototype definitions.
+ */
+__BEGIN_DECLS
+char *__ttyname_basic(int);
+char *__ttyname_r_basic(int, char *, size_t);
+char *ttyname_r(int, char *, size_t);
+int _thread_create(pthread_t *,const pthread_attr_t *,void *(*start_routine)(void *),void *,pthread_t);
+int _thread_fd_lock(int, int, struct timespec *,char *fname,int lineno);
+void _thread_exit(char *, int, char *);
+void _thread_fd_unlock(int, int);
+void *_thread_cleanup(pthread_t);
+void _thread_cleanupspecific(void);
+void _thread_dump_info(void);
+void _thread_init(void);
+void _thread_kern_sched(struct sigcontext *);
+void _thread_kern_sched_state(enum pthread_state,char *fname,int lineno);
+void _thread_kern_set_timeout(struct timespec *);
+void _thread_kern_sig_block(int *);
+void _thread_kern_sig_unblock(int);
+void _thread_sig_handler(int, int, struct sigcontext *);
+void _thread_start(void);
+void _thread_start_sig_handler(void);
+void _thread_seterrno(pthread_t,int);
+void _thread_queue_init(struct pthread_queue *);
+void _thread_queue_enq(struct pthread_queue *, struct pthread *);
+int _thread_queue_remove(struct pthread_queue *, struct pthread *);
+int _thread_fd_table_init(int fd);
+struct pthread *_thread_queue_get(struct pthread_queue *);
+struct pthread *_thread_queue_deq(struct pthread_queue *);
+
+/* #include <signal.h> */
+int _thread_sys_sigaction(int, const struct sigaction *, struct sigaction *);
+int _thread_sys_sigpending(sigset_t *);
+int _thread_sys_sigprocmask(int, const sigset_t *, sigset_t *);
+int _thread_sys_sigsuspend(const sigset_t *);
+int _thread_sys_sigblock(int);
+int _thread_sys_siginterrupt(int, int);
+int _thread_sys_sigpause(int);
+int _thread_sys_sigreturn(struct sigcontext *);
+int _thread_sys_sigsetmask(int);
+int _thread_sys_sigstack(const struct sigstack *, struct sigstack *);
+int _thread_sys_sigvec(int, struct sigvec *, struct sigvec *);
+void _thread_sys_psignal(unsigned int, const char *);
+void (*_thread_sys_signal(int, void (*)(int)))(int);
+
+/* #include <sys/stat.h> */
+#ifdef _SYS_STAT_H_
+int _thread_sys_fchmod(int, mode_t);
+int _thread_sys_fstat(int, struct stat *);
+int _thread_sys_fchflags(int, u_long);
+#endif
+
+/* #include <sys/mount.h> */
+#ifdef _SYS_MOUNT_H_
+int _thread_sys_fstatfs(int, struct statfs *);
+#endif
+int _thread_sys_pipe(int *);
+
+/* #include <sys/socket.h> */
+#ifdef _SYS_SOCKET_H_
+int _thread_sys_accept(int, struct sockaddr *, int *);
+int _thread_sys_bind(int, const struct sockaddr *, int);
+int _thread_sys_connect(int, const struct sockaddr *, int);
+int _thread_sys_getpeername(int, struct sockaddr *, int *);
+int _thread_sys_getsockname(int, struct sockaddr *, int *);
+int _thread_sys_getsockopt(int, int, int, void *, int *);
+int _thread_sys_listen(int, int);
+int _thread_sys_setsockopt(int, int, int, const void *, int);
+int _thread_sys_shutdown(int, int);
+int _thread_sys_socket(int, int, int);
+int _thread_sys_socketpair(int, int, int, int *);
+ssize_t _thread_sys_recv(int, void *, size_t, int);
+ssize_t _thread_sys_recvfrom(int, void *, size_t, int, struct sockaddr *, int *);
+ssize_t _thread_sys_recvmsg(int, struct msghdr *, int);
+ssize_t _thread_sys_send(int, const void *, size_t, int);
+ssize_t _thread_sys_sendmsg(int, const struct msghdr *, int);
+ssize_t _thread_sys_sendto(int, const void *,size_t, int, const struct sockaddr *, int);
+#endif
+
+/* #include <stdio.h> */
+#ifdef _STDIO_H_
+void _thread_flockfile(FILE *fp,char *fname,int lineno);
+void _thread_funlockfile(FILE *fp);
+FILE *_thread_sys_fdopen(int, const char *);
+FILE *_thread_sys_fopen(const char *, const char *);
+FILE *_thread_sys_freopen(const char *, const char *, FILE *);
+FILE *_thread_sys_popen(const char *, const char *);
+FILE *_thread_sys_tmpfile(void);
+char *_thread_sys_ctermid(char *);
+char *_thread_sys_cuserid(char *);
+char *_thread_sys_fgetln(FILE *, size_t *);
+char *_thread_sys_fgets(char *, int, FILE *);
+char *_thread_sys_gets(char *);
+char *_thread_sys_tempnam(const char *, const char *);
+char *_thread_sys_tmpnam(char *);
+int _thread_sys_fclose(FILE *);
+int _thread_sys_feof(FILE *);
+int _thread_sys_ferror(FILE *);
+int _thread_sys_fflush(FILE *);
+int _thread_sys_fgetc(FILE *);
+int _thread_sys_fgetpos(FILE *, fpos_t *);
+int _thread_sys_fileno(FILE *);
+int _thread_sys_fprintf(FILE *, const char *, ...);
+int _thread_sys_fpurge(FILE *);
+int _thread_sys_fputc(int, FILE *);
+int _thread_sys_fputs(const char *, FILE *);
+int _thread_sys_fscanf(FILE *, const char *, ...);
+int _thread_sys_fseek(FILE *, long, int);
+int _thread_sys_fsetpos(FILE *, const fpos_t *);
+int _thread_sys_getc(FILE *);
+int _thread_sys_getchar(void);
+int _thread_sys_getw(FILE *);
+int _thread_sys_pclose(FILE *);
+int _thread_sys_printf(const char *, ...);
+int _thread_sys_putc(int, FILE *);
+int _thread_sys_putchar(int);
+int _thread_sys_puts(const char *);
+int _thread_sys_putw(int, FILE *);
+int _thread_sys_remove(const char *);
+int _thread_sys_rename (const char *, const char *);
+int _thread_sys_scanf(const char *, ...);
+int _thread_sys_setlinebuf(FILE *);
+int _thread_sys_setvbuf(FILE *, char *, int, size_t);
+int _thread_sys_snprintf(char *, size_t, const char *, ...);
+int _thread_sys_sprintf(char *, const char *, ...);
+int _thread_sys_sscanf(const char *, const char *, ...);
+int _thread_sys_ungetc(int, FILE *);
+int _thread_sys_vfprintf(FILE *, const char *, _BSD_VA_LIST_);
+int _thread_sys_vprintf(const char *, _BSD_VA_LIST_);
+int _thread_sys_vscanf(const char *, _BSD_VA_LIST_);
+int _thread_sys_vsnprintf(char *, size_t, const char *, _BSD_VA_LIST_);
+int _thread_sys_vsprintf(char *, const char *, _BSD_VA_LIST_);
+int _thread_sys_vsscanf(const char *, const char *, _BSD_VA_LIST_);
+long _thread_sys_ftell(FILE *);
+size_t _thread_sys_fread(void *, size_t, size_t, FILE *);
+size_t _thread_sys_fwrite(const void *, size_t, size_t, FILE *);
+void _thread_sys_clearerr(FILE *);
+void _thread_sys_perror(const char *);
+void _thread_sys_rewind(FILE *);
+void _thread_sys_setbuf(FILE *, char *);
+void _thread_sys_setbuffer(FILE *, char *, int);
+#endif
+
+/* #include <unistd.h> */
+#ifdef _UNISTD_H_
+char *_thread_sys_ttyname(int);
+int _thread_sys_close(int);
+int _thread_sys_dup(int);
+int _thread_sys_dup2(int, int);
+int _thread_sys_exect(const char *, char * const *, char * const *);
+int _thread_sys_execve(const char *, char * const *, char * const *);
+int _thread_sys_fchdir(int);
+int _thread_sys_fchown(int, uid_t, gid_t);
+int _thread_sys_fsync(int);
+int _thread_sys_ftruncate(int, off_t);
+int _thread_sys_pause(void);
+int _thread_sys_pipe(int *);
+int _thread_sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+off_t _thread_sys_lseek(int, off_t, int);
+pid_t _thread_sys_fork(void);
+pid_t _thread_sys_tcgetpgrp(int);
+ssize_t _thread_sys_read(int, void *, size_t);
+ssize_t _thread_sys_write(int, const void *, size_t);
+void _thread_sys__exit(int);
+#endif
+
+/* #include <fcntl.h> */
+#ifdef _SYS_FCNTL_H_
+int _thread_sys_creat(const char *, mode_t);
+int _thread_sys_fcntl(int, int, ...);
+int _thread_sys_flock(int, int);
+int _thread_sys_open(const char *, int, ...);
+#endif
+
+/* #include <setjmp.h> */
+#ifdef _SETJMP_H_
+int __thread_sys_setjmp(jmp_buf);
+int _thread_sys_setjmp(jmp_buf);
+int _thread_sys_sigsetjmp(sigjmp_buf, int);
+void __thread_sys_longjmp(jmp_buf, int);
+void _thread_sys_longjmp(jmp_buf, int);
+void _thread_sys_longjmperror(void);
+void _thread_sys_siglongjmp(sigjmp_buf, int);
+#endif
+
+/* #include <sys/ioctl.h> */
+#ifdef _SYS_IOCTL_H_
+int _thread_sys_ioctl(int, unsigned long, ...);
+#endif
+
+/* #include <dirent.h> */
+#ifdef _DIRENT_H_
+DIR *___thread_sys_opendir2(const char *, int);
+DIR *_thread_sys_opendir(const char *);
+int _thread_sys_alphasort(const void *, const void *);
+int _thread_sys_scandir(const char *, struct dirent ***,
+ int (*)(struct dirent *), int (*)(const void *, const void *));
+int _thread_sys_closedir(DIR *);
+int _thread_sys_getdirentries(int, char *, int, long *);
+long _thread_sys_telldir(const DIR *);
+struct dirent *_thread_sys_readdir(DIR *);
+void _thread_sys_rewinddir(DIR *);
+void _thread_sys_seekdir(DIR *, long);
+#endif
+
+/* #include <sys/uio.h> */
+#ifdef _SYS_UIO_H_
+ssize_t _thread_sys_readv(int, const struct iovec *, int);
+ssize_t _thread_sys_writev(int, const struct iovec *, int);
+#endif
+
+/* #include <sys/wait.h> */
+#ifdef WNOHANG
+pid_t _thread_sys_wait(int *);
+pid_t _thread_sys_waitpid(pid_t, int *, int);
+pid_t _thread_sys_wait3(int *, int, struct rusage *);
+pid_t _thread_sys_wait4(pid_t, int *, int, struct rusage *);
+#endif
+__END_DECLS
+
+#endif /* !_PTHREAD_PRIVATE_H */
diff --git a/lib/libkse/thread/thr_read.c b/lib/libkse/thread/thr_read.c
new file mode 100644
index 0000000..242014e
--- /dev/null
+++ b/lib/libkse/thread/thr_read.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+read(int fd, void *buf, size_t nbytes)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read: */
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking read syscall: */
+ while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDR_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_readv.c b/lib/libkse/thread/thr_readv.c
new file mode 100644
index 0000000..3ea065e
--- /dev/null
+++ b/lib/libkse/thread/thr_readv.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+readv(int fd, const struct iovec * iov, int iovcnt)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read: */
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking readv syscall: */
+ while ((ret = _thread_sys_readv(fd, iov, iovcnt)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDR_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_resume_np.c b/lib/libkse/thread/thr_resume_np.c
new file mode 100644
index 0000000..934df58
--- /dev/null
+++ b/lib/libkse/thread/thr_resume_np.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_resume_np(pthread_t thread)
+{
+ int ret = -1;
+ pthread_t pthread;
+ /*
+ * Search for the thread in the linked list.
+ */
+ for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
+ /* Is this the thread? */
+ if (pthread == thread) {
+ /* Found the thread. Is it suspended? */
+ if (pthread->state == PS_SUSPENDED) {
+ /* Allow the thread to run. */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ ret = 0;
+ } else if (pthread->state == PS_RUNNING) {
+ /* Thread is already running. */
+ ret = 0;
+ } else {
+ /* Thread is in some other state. */
+ errno = EINVAL;
+ }
+ }
+ }
+ /* Check if thread was not found. */
+ if (ret == -1) {
+ /* No such thread */
+ errno = ESRCH;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_select.c b/lib/libkse/thread/thr_select.c
new file mode 100644
index 0000000..7db3ed2
--- /dev/null
+++ b/lib/libkse/thread/thr_select.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+select(int numfds, fd_set * readfds, fd_set * writefds,
+ fd_set * exceptfds, struct timeval * timeout)
+{
+ fd_set read_locks, write_locks, rdwr_locks;
+ struct timespec ts;
+ struct timeval zero_timeout = {0, 0};
+ int i, ret = 0, got_all_locks = 1;
+ struct pthread_select_data data;
+
+ if (numfds > _thread_dtablesize) {
+ numfds = _thread_dtablesize;
+ }
+ /* Check if a timeout was specified: */
+ if (timeout) {
+ /* Convert the timeval to a timespec: */
+ TIMEVAL_TO_TIMESPEC(timeout, &ts);
+
+ /* Set the wake up time: */
+ _thread_kern_set_timeout(&ts);
+ } else {
+ /* Wait for ever: */
+ _thread_kern_set_timeout(NULL);
+ }
+
+ FD_ZERO(&read_locks);
+ FD_ZERO(&write_locks);
+ FD_ZERO(&rdwr_locks);
+
+ /* lock readfds */
+ if (readfds || writefds || exceptfds) {
+ for (i = 0; i < numfds; i++) {
+ if ((readfds && (FD_ISSET(i, readfds))) || (exceptfds && FD_ISSET(i, exceptfds))) {
+ if (writefds && FD_ISSET(i, writefds)) {
+ if ((ret = _thread_fd_lock(i, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &rdwr_locks);
+ } else {
+ if ((ret = _thread_fd_lock(i, FD_READ, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &read_locks);
+ }
+ } else {
+ if (writefds && FD_ISSET(i, writefds)) {
+ if ((ret = _thread_fd_lock(i, FD_WRITE, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &write_locks);
+ }
+ }
+ }
+ }
+ if (got_all_locks) {
+ data.nfds = numfds;
+ FD_ZERO(&data.readfds);
+ FD_ZERO(&data.writefds);
+ FD_ZERO(&data.exceptfds);
+ if (readfds != NULL) {
+ memcpy(&data.readfds, readfds, sizeof(data.readfds));
+ }
+ if (writefds != NULL) {
+ memcpy(&data.writefds, writefds, sizeof(data.writefds));
+ }
+ if (exceptfds != NULL) {
+ memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds));
+ }
+ if ((ret = _thread_sys_select(data.nfds, &data.readfds, &data.writefds, &data.exceptfds, &zero_timeout)) == 0) {
+ data.nfds = numfds;
+ FD_ZERO(&data.readfds);
+ FD_ZERO(&data.writefds);
+ FD_ZERO(&data.exceptfds);
+ if (readfds != NULL) {
+ memcpy(&data.readfds, readfds, sizeof(data.readfds));
+ }
+ if (writefds != NULL) {
+ memcpy(&data.writefds, writefds, sizeof(data.writefds));
+ }
+ if (exceptfds != NULL) {
+ memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds));
+ }
+ _thread_run->data.select_data = &data;
+ _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__);
+ ret = data.nfds;
+ }
+ }
+ /* clean up the locks */
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &read_locks))
+ _thread_fd_unlock(i, FD_READ);
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &rdwr_locks))
+ _thread_fd_unlock(i, FD_RDWR);
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &write_locks))
+ _thread_fd_unlock(i, FD_WRITE);
+
+ if (ret > 0) {
+ if (readfds != NULL) {
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, readfds) &&
+ !FD_ISSET(i, &data.readfds)) {
+ FD_CLR(i, readfds);
+ }
+ }
+ }
+ if (writefds != NULL) {
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, writefds) &&
+ !FD_ISSET(i, &data.writefds)) {
+ FD_CLR(i, writefds);
+ }
+ }
+ }
+ if (exceptfds != NULL) {
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, exceptfds) &&
+ !FD_ISSET(i, &data.exceptfds)) {
+ FD_CLR(i, exceptfds);
+ }
+ }
+ }
+ }
+
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_self.c b/lib/libkse/thread/thr_self.c
new file mode 100644
index 0000000..a0a2d2a
--- /dev/null
+++ b/lib/libkse/thread/thr_self.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pthread_t
+pthread_self(void)
+{
+ /* Return the running thread pointer: */
+ return (_thread_run);
+}
+#endif
diff --git a/lib/libkse/thread/thr_seterrno.c b/lib/libkse/thread/thr_seterrno.c
new file mode 100644
index 0000000..c4fe08b6
--- /dev/null
+++ b/lib/libkse/thread/thr_seterrno.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/*
+ * This function needs to reference the global error variable which is
+ * normally hidden from the user.
+ */
+#ifdef errno
+#undef errno;
+#endif
+extern int errno;
+
+void
+_thread_seterrno(pthread_t thread, int error)
+{
+ /* Check for the initial thread: */
+ if (thread == _thread_initial) {
+ /* The initial thread always uses the global error variable: */
+ errno = error;
+ } else {
+ /*
+ * Threads other than the initial thread always use the error
+ * field in the thread structureL
+ */
+ thread->error = error;
+ }
+}
+#endif
diff --git a/lib/libkse/thread/thr_setprio.c b/lib/libkse/thread/thr_setprio.c
new file mode 100644
index 0000000..4b49ed0
--- /dev/null
+++ b/lib/libkse/thread/thr_setprio.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_setprio(pthread_t pthread, int prio)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread_p;
+
+ /* Check if the priority is invalid: */
+ if (prio < PTHREAD_MIN_PRIORITY || prio > PTHREAD_MAX_PRIORITY) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the first thread in the list: */
+ pthread_p = _thread_link_list;
+
+ /* Enter a loop to search for the thread: */
+ while (pthread_p != NULL && pthread_p != pthread) {
+ /* Point to the next thread: */
+ pthread_p = pthread_p->nxt;
+ }
+
+ /* Check if the thread pointer is NULL: */
+ if (pthread == NULL || pthread_p == NULL) {
+ /* Return a 'search' error: */
+ errno = ESRCH;
+ rval = -1;
+ } else {
+ /* Set the thread priority: */
+ pthread->pthread_priority = prio;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the error status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libkse/thread/thr_sig.c b/lib/libkse/thread/thr_sig.c
new file mode 100644
index 0000000..e73d5a2
--- /dev/null
+++ b/lib/libkse/thread/thr_sig.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+_thread_sig_handler(int sig, int code, struct sigcontext * scp)
+{
+ char c;
+ int i;
+ pthread_t pthread;
+
+ /*
+ * Check if the pthread kernel has unblocked signals (or is about to)
+ * and was on its way into a _thread_sys_select when the current
+ * signal interrupted it:
+ */
+ if (_thread_kern_in_select) {
+ /* Cast the signal number to a character variable: */
+ c = sig;
+
+ /*
+ * Write the signal number to the kernel pipe so that it will
+ * be ready to read when this signal handler returns. This
+ * means that the _thread_sys_select call will complete
+ * immediately.
+ */
+ if (_thread_sys_write(_thread_kern_pipe[1], &c, 1) != 1) {
+ }
+ }
+ /* Check if the signal requires a dump of thread information: */
+ if (sig == SIGINFO) {
+ /* Dump thread information to file: */
+ _thread_dump_info();
+ } else {
+ /* Handle depending on signal type: */
+ switch (sig) {
+ /* Interval timer used for timeslicing: */
+ case SIGVTALRM:
+ /*
+ * Don't add the signal to any thread. Just want to
+ * call the scheduler:
+ */
+ break;
+
+ /* Child termination: */
+ case SIGCHLD:
+ /*
+ * Enter a loop to process each thread in the linked
+ * list:
+ */
+ for (pthread = _thread_link_list; pthread != NULL;
+ pthread = pthread->nxt) {
+ /*
+ * Add the signal to the set of pending
+ * signals:
+ */
+ pthread->sigpend[sig] += 1;
+ if (pthread->state == PS_WAIT_WAIT) {
+ /* Reset the error: */
+ /* There should be another flag so that this is not required! ### */
+ _thread_seterrno(pthread, 0);
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ }
+
+ /*
+ * Go through the file list and set all files
+ * to non-blocking again in case the child
+ * set some of them to block. Sigh.
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Check if this file is used: */
+ if (_thread_fd_table[i] != NULL) {
+ /* Set the file descriptor to non-blocking: */
+ _thread_sys_fcntl(i, F_SETFL, _thread_fd_table[i]->flags | O_NONBLOCK);
+ }
+ }
+ break;
+
+ /* Signals specific to the running thread: */
+ case SIGBUS:
+ case SIGEMT:
+ case SIGFPE:
+ case SIGILL:
+ case SIGPIPE:
+ case SIGSEGV:
+ case SIGSYS:
+ /* Add the signal to the set of pending signals: */
+ _thread_run->sigpend[sig] += 1;
+ break;
+
+ /* Signals to send to all threads: */
+ default:
+ /*
+ * Enter a loop to process each thread in the linked
+ * list:
+ */
+ for (pthread = _thread_link_list; pthread != NULL;
+ pthread = pthread->nxt) {
+ /*
+ * Add the signal to the set of pending
+ * signals:
+ */
+ pthread->sigpend[sig] += 1;
+ }
+ break;
+ }
+
+ /* Check if the kernel is not locked: */
+ if (_thread_run != &_thread_kern_thread) {
+ /*
+ * Schedule the next thread. This function is not
+ * expected to return because it will do a longjmp
+ * instead.
+ */
+ _thread_kern_sched(scp);
+
+ /*
+ * This point should not be reached, so abort the
+ * process:
+ */
+ PANIC("Returned to signal function from scheduler");
+ }
+ }
+
+ /* Returns nothing. */
+ return;
+}
+#endif
diff --git a/lib/libkse/thread/thr_sigaction.c b/lib/libkse/thread/thr_sigaction.c
new file mode 100644
index 0000000..dd08405
--- /dev/null
+++ b/lib/libkse/thread/thr_sigaction.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
+{
+ int ret = 0;
+ int status;
+
+ /* Check if the signal number is out of range: */
+ if (sig < 1 || sig > NSIG) {
+ /* Return an invalid argument: */
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /*
+ * Check if the existing signal action structure contents are
+ * to be returned:
+ */
+ if (oact != NULL) {
+ /* Return the existing signal action contents: */
+ oact->sa_handler = _thread_run->act[sig - 1].sa_handler;
+ oact->sa_mask = _thread_run->act[sig - 1].sa_mask;
+ oact->sa_flags = _thread_run->act[sig - 1].sa_flags;
+ }
+ /* Check if a signal action was supplied: */
+ if (act != NULL) {
+ /* Block signals while the signal handler is changed: */
+ _thread_kern_sig_block(&status);
+
+ /* Set the new signal handler: */
+ _thread_run->act[sig - 1].sa_handler = act->sa_handler;
+ _thread_run->act[sig - 1].sa_mask = act->sa_mask;
+ _thread_run->act[sig - 1].sa_flags = act->sa_flags;
+
+ /*
+ * Unblock signals to allow the new signal handler to
+ * take effect:
+ */
+ _thread_kern_sig_unblock(status);
+ }
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_sigmask.c b/lib/libkse/thread/thr_sigmask.c
new file mode 100644
index 0000000..94f64cb
--- /dev/null
+++ b/lib/libkse/thread/thr_sigmask.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
+{
+ int ret = 0;
+ int status;
+
+ /* Check if the existing signal process mask is to be returned: */
+ if (oset != NULL) {
+ /* Return the current mask: */
+ *oset = _thread_run->sigmask;
+ }
+ /* Check if a new signal set was provided by the caller: */
+ if (set != NULL) {
+ /* Block signals while the signal mask is changed: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to what to do: */
+ switch (how) {
+ /* Block signals: */
+ case SIG_BLOCK:
+ /* Add signals to the existing mask: */
+ _thread_run->sigmask |= *set;
+ break;
+
+ /* Unblock signals: */
+ case SIG_UNBLOCK:
+ /* Clear signals from the existing mask: */
+ _thread_run->sigmask &= ~(*set);
+ break;
+
+ /* Set the signal process mask: */
+ case SIG_SETMASK:
+ /* Set the new mask: */
+ _thread_run->sigmask = *set;
+ break;
+
+ /* Trap invalid actions: */
+ default:
+ /* Return an invalid argument: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /*
+ * Schedule the next thread in case there are signals that
+ * now need to be acted on:
+ */
+ _thread_kern_sched(NULL);
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_sigprocmask.c b/lib/libkse/thread/thr_sigprocmask.c
new file mode 100644
index 0000000..b4a8d84
--- /dev/null
+++ b/lib/libkse/thread/thr_sigprocmask.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigprocmask(int how, const sigset_t * set, sigset_t * oset)
+{
+ int ret = 0;
+ int status;
+
+ /* Check if the existing signal process mask is to be returned: */
+ if (oset != NULL) {
+ /* Return the current mask: */
+ *oset = _thread_run->sigmask;
+ }
+ /* Check if a new signal set was provided by the caller: */
+ if (set != NULL) {
+ /* Block signals while the signal mask is changed: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to what to do: */
+ switch (how) {
+ /* Block signals: */
+ case SIG_BLOCK:
+ /* Add signals to the existing mask: */
+ _thread_run->sigmask |= *set;
+ break;
+
+ /* Unblock signals: */
+ case SIG_UNBLOCK:
+ /* Clear signals from the existing mask: */
+ _thread_run->sigmask &= ~(*set);
+ break;
+
+ /* Set the signal process mask: */
+ case SIG_SETMASK:
+ /* Set the new mask: */
+ _thread_run->sigmask = *set;
+ break;
+
+ /* Trap invalid actions: */
+ default:
+ /* Return an invalid argument: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /*
+ * Schedule the next thread in case there are signals that
+ * now need to be acted on:
+ */
+ _thread_kern_sched(NULL);
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_sigsuspend.c b/lib/libkse/thread/thr_sigsuspend.c
new file mode 100644
index 0000000..14cf74b
--- /dev/null
+++ b/lib/libkse/thread/thr_sigsuspend.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigsuspend(const sigset_t * set)
+{
+ int ret = -1;
+ sigset_t oset;
+
+ /* Check if a new signal set was provided by the caller: */
+ if (set != NULL) {
+ /* Save the current sigmal mask: */
+ oset = _thread_run->sigmask;
+
+ /* Combine the caller's mask with the current one: */
+ _thread_run->sigmask |= *set;
+
+ /* Wait for a signal: */
+ _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__);
+
+ /* Restore the signal mask: */
+ _thread_run->sigmask = oset;
+ } else {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_sigwait.c b/lib/libkse/thread/thr_sigwait.c
new file mode 100644
index 0000000..4f95190
--- /dev/null
+++ b/lib/libkse/thread/thr_sigwait.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigwait(const sigset_t * set, int *sig)
+{
+ int ret;
+ int status;
+ sigset_t oset;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Save the current sigmal mask: */
+ oset = _thread_run->sigmask;
+
+ /* Combine the caller's mask with the current one: */
+ _thread_run->sigmask |= *set;
+
+ /* Wait for a signal: */
+ _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__);
+
+ /* Block signals again: */
+ _thread_kern_sig_block(NULL);
+
+ /* Return the signal number to the caller: */
+ *sig = _thread_run->signo;
+
+ /* Restore the signal mask: */
+ _thread_run->sigmask = oset;
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_single_np.c b/lib/libkse/thread/thr_single_np.c
new file mode 100644
index 0000000..e36c856
--- /dev/null
+++ b/lib/libkse/thread/thr_single_np.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_single_np()
+{
+ /* Enter single-threaded (non-POSIX) scheduling mode: */
+ _thread_single = _thread_run;
+ return(0);
+}
+#endif
diff --git a/lib/libkse/thread/thr_spec.c b/lib/libkse/thread/thr_spec.c
new file mode 100644
index 0000000..8d06c52
--- /dev/null
+++ b/lib/libkse/thread/thr_spec.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* Static variables: */
+static struct pthread_key key_table[PTHREAD_KEYS_MAX];
+
+int
+pthread_key_create(pthread_key_t * key, void (*destructor) (void *))
+{
+ for ((*key) = 0; (*key) < PTHREAD_KEYS_MAX; (*key)++) {
+ if (key_table[(*key)].count == 0) {
+ key_table[(*key)].count++;
+ key_table[(*key)].destructor = destructor;
+ return (0);
+ }
+ }
+ return (EAGAIN);
+}
+
+int
+pthread_key_delete(pthread_key_t key)
+{
+ int ret;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ if (key < PTHREAD_KEYS_MAX) {
+ switch (key_table[key].count) {
+ case 1:
+ key_table[key].destructor = NULL;
+ key_table[key].count = 0;
+ case 0:
+ ret = 0;
+ break;
+ default:
+ ret = EBUSY;
+ }
+ } else {
+ ret = EINVAL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+
+void
+_thread_cleanupspecific(void)
+{
+ void *data;
+ int key;
+ int itr;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ for (itr = 0; itr < PTHREAD_DESTRUCTOR_ITERATIONS; itr++) {
+ for (key = 0; key < PTHREAD_KEYS_MAX; key++) {
+ if (_thread_run->specific_data_count) {
+ if (_thread_run->specific_data[key]) {
+ data = (void *) _thread_run->specific_data[key];
+ _thread_run->specific_data[key] = NULL;
+ _thread_run->specific_data_count--;
+ if (key_table[key].destructor) {
+ key_table[key].destructor(data);
+ }
+ key_table[key].count--;
+ }
+ } else {
+ free(_thread_run->specific_data);
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return;
+ }
+ }
+ }
+ free(_thread_run->specific_data);
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+}
+
+static inline const void **
+pthread_key_allocate_data(void)
+{
+ const void **new_data;
+ if ((new_data = (const void **) malloc(sizeof(void *) * PTHREAD_KEYS_MAX)) != NULL) {
+ memset((void *) new_data, 0, sizeof(void *) * PTHREAD_KEYS_MAX);
+ }
+ return (new_data);
+}
+
+int
+pthread_setspecific(pthread_key_t key, const void *value)
+{
+ pthread_t pthread;
+ int ret = 0;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the running thread: */
+ pthread = _thread_run;
+
+ /*
+ * Enter a loop for signal handler threads to find the parent thread
+ * which has the specific data associated with it:
+ */
+ while (pthread->parent_thread != NULL) {
+ /* Point to the parent thread: */
+ pthread = pthread->parent_thread;
+ }
+
+ if ((pthread->specific_data) || (pthread->specific_data = pthread_key_allocate_data())) {
+ if ((key < PTHREAD_KEYS_MAX) && (key_table)) {
+ if (key_table[key].count) {
+ if (pthread->specific_data[key] == NULL) {
+ if (value != NULL) {
+ pthread->specific_data_count++;
+ key_table[key].count++;
+ }
+ } else {
+ if (value == NULL) {
+ pthread->specific_data_count--;
+ key_table[key].count--;
+ }
+ }
+ pthread->specific_data[key] = value;
+ ret = 0;
+ } else {
+ ret = EINVAL;
+ }
+ } else {
+ ret = EINVAL;
+ }
+ } else {
+ ret = ENOMEM;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+
+void *
+pthread_getspecific(pthread_key_t key)
+{
+ pthread_t pthread;
+ int status;
+ void *data;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the running thread: */
+ pthread = _thread_run;
+
+ /*
+ * Enter a loop for signal handler threads to find the parent thread
+ * which has the specific data associated with it:
+ */
+ while (pthread->parent_thread != NULL) {
+ /* Point to the parent thread: */
+ pthread = pthread->parent_thread;
+ }
+
+ /* Check for errors: */
+ if (pthread == NULL) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ data = NULL;
+ }
+ /* Check if there is specific data: */
+ else if (pthread->specific_data != NULL && (key < PTHREAD_KEYS_MAX) && (key_table)) {
+ /* Check if this key has been used before: */
+ if (key_table[key].count) {
+ /* Return the value: */
+ data = (void *) pthread->specific_data[key];
+ } else {
+ /*
+ * This key has not been used before, so return NULL
+ * instead:
+ */
+ data = NULL;
+ }
+ } else {
+ /* No specific data has been created, so just return NULL: */
+ data = NULL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (data);
+}
+#endif
diff --git a/lib/libkse/thread/thr_suspend_np.c b/lib/libkse/thread/thr_suspend_np.c
new file mode 100644
index 0000000..d065b73
--- /dev/null
+++ b/lib/libkse/thread/thr_suspend_np.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_suspend_np(pthread_t thread)
+{
+ int ret = -1;
+ pthread_t pthread;
+ /*
+ * Search for the thread in the linked list.
+ */
+ for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
+ /* Is this the thread? */
+ if (pthread == thread) {
+ /* Found the thread. Is it running? */
+ if (pthread->state != PS_RUNNING &&
+ pthread->state != PS_SUSPENDED) {
+ /* The thread operation has been interrupted */
+ _thread_seterrno(pthread,EINTR);
+ }
+ /* Suspend the thread. */
+ PTHREAD_NEW_STATE(pthread,PS_SUSPENDED);
+ ret = 0;
+ }
+ }
+ /* Check if thread was not found. */
+ if (ret == -1) {
+ /* No such thread */
+ errno = ESRCH;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_wait4.c b/lib/libkse/thread/thr_wait4.c
new file mode 100644
index 0000000..0a721af4f
--- /dev/null
+++ b/lib/libkse/thread/thr_wait4.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <sys/wait.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pid_t
+wait4(pid_t pid, int *istat, int options, struct rusage * rusage)
+{
+ int status;
+ pid_t ret;
+ _thread_kern_sig_block(&status);
+
+ /* Perform a non-blocking wait4 syscall: */
+ while ((ret = _thread_sys_wait4(pid, istat, options | WNOHANG, rusage)) == 0 && (options & WNOHANG) == 0) {
+ /* Schedule the next thread while this one waits: */
+ _thread_kern_sched_state(PS_WAIT_WAIT, __FILE__, __LINE__);
+
+ /* Check if this call was interrupted by a signal: */
+ if (errno == EINTR) {
+ ret = -1;
+ break;
+ }
+ _thread_kern_sig_block(NULL);
+ }
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_write.c b/lib/libkse/thread/thr_write.c
new file mode 100644
index 0000000..eab105d
--- /dev/null
+++ b/lib/libkse/thread/thr_write.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+write(int fd, const void *buf, size_t nbytes)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read and write: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking write syscall: */
+ while ((ret = _thread_sys_write(fd, buf, nbytes)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDW_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_writev.c b/lib/libkse/thread/thr_writev.c
new file mode 100644
index 0000000..5ad1ce9
--- /dev/null
+++ b/lib/libkse/thread/thr_writev.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+writev(int fd, const struct iovec * iov, int iovcnt)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read and write: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking writev syscall: */
+ while ((ret = _thread_sys_writev(fd, iov, iovcnt)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDW_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_yield.c b/lib/libkse/thread/thr_yield.c
new file mode 100644
index 0000000..a88a948
--- /dev/null
+++ b/lib/libkse/thread/thr_yield.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+pthread_yield(void)
+{
+ /* Reset the accumulated time slice value for the current thread: */
+ _thread_run->slice_usec = -1;
+
+ /* Schedule the next thread: */
+ _thread_kern_sched(NULL);
+
+ /* Nothing to return. */
+ return;
+}
+#endif
diff --git a/lib/libkvm/Makefile b/lib/libkvm/Makefile
index 0a5ca38..925594d 100644
--- a/lib/libkvm/Makefile
+++ b/lib/libkvm/Makefile
@@ -1,11 +1,11 @@
-# @(#)Makefile 8.3 (Berkeley) 5/4/95
+# @(#)Makefile 8.1 (Berkeley) 6/4/93
LIB= kvm
CFLAGS+=-DLIBC_SCCS -I/sys
SRCS= kvm.c kvm_${MACHINE}.c kvm_file.c kvm_getloadavg.c kvm_proc.c
-MAN3= kvm.0 kvm_geterr.0 kvm_getfiles.0 kvm_getloadavg.0 kvm_getprocs.0 \
- kvm_nlist.0 kvm_open.0 kvm_read.0
+MAN3= kvm.3 kvm_geterr.3 kvm_getfiles.3 kvm_getloadavg.3 kvm_getprocs.3 \
+ kvm_nlist.3 kvm_open.3 kvm_read.3
MLINKS+=kvm_getprocs.3 kvm_getargv.3 kvm_getprocs.3 kvm_getenvv.3
MLINKS+=kvm_open.3 kvm_openfiles.3 kvm_open.3 kvm_close.3
diff --git a/lib/libkvm/kvm.3 b/lib/libkvm/kvm.3
index 0343d46..e0b12eb 100644
--- a/lib/libkvm/kvm.3
+++ b/lib/libkvm/kvm.3
@@ -45,10 +45,10 @@
The
.Xr kvm 3
library provides a uniform interface for accessing kernel virtual memory
-images, including live systems and crashdumps.
+images, including live systems and crash dumps.
Access to live systems is via
/dev/mem
-while crashdumps can be examined via the core file generated by
+while crash dumps can be examined via the core file generated by
.Xr savecore 8 .
The interface behaves identically in both cases.
Memory can be read and written, kernel symbol addresses can be
diff --git a/lib/libkvm/kvm.c b/lib/libkvm/kvm.c
index a76f61e..a2ea42a 100644
--- a/lib/libkvm/kvm.c
+++ b/lib/libkvm/kvm.c
@@ -155,8 +155,9 @@ _kvm_malloc(kd, n)
{
void *p;
- if ((p = malloc(n)) == NULL)
- _kvm_err(kd, kd->program, strerror(errno));
+ if ((p = calloc(n, sizeof(char))) == NULL)
+ _kvm_err(kd, kd->program, "can't allocate %u bytes: %s",
+ n, strerror(errno));
return (p);
}
@@ -182,7 +183,7 @@ _kvm_open(kd, uf, mf, sf, flag, errout)
kd->argv = 0;
if (uf == 0)
- uf = _PATH_UNIX;
+ uf = getbootfile();
else if (strlen(uf) >= MAXPATHLEN) {
_kvm_err(kd, kd->program, "exec file name too long");
goto failed;
@@ -226,13 +227,13 @@ _kvm_open(kd, uf, mf, sf, flag, errout)
}
/*
* Open kvm nlist database. We go ahead and do this
- * here so that we don't have to hold on to the vmunix
+ * here so that we don't have to hold on to the kernel
* path name. Since a kvm application will surely do
* a kvm_nlist(), this probably won't be a wasted effort.
* If the database cannot be opened, open the namelist
* argument so we revert to slow nlist() calls.
*/
- if (kvm_dbopen(kd, uf) < 0 &&
+ if (kvm_dbopen(kd, uf) < 0 &&
(kd->nlfd = open(uf, O_RDONLY, 0)) < 0) {
_kvm_syserr(kd, kd->program, "%s", uf);
goto failed;
@@ -275,25 +276,29 @@ kvm_openfiles(uf, mf, sf, flag, errout)
(void)strcpy(errout, strerror(errno));
return (0);
}
+ memset(kd, 0, sizeof(*kd));
kd->program = 0;
return (_kvm_open(kd, uf, mf, sf, flag, errout));
}
kvm_t *
-kvm_open(uf, mf, sf, flag, program)
+kvm_open(uf, mf, sf, flag, errstr)
const char *uf;
const char *mf;
const char *sf;
int flag;
- const char *program;
+ const char *errstr;
{
register kvm_t *kd;
- if ((kd = malloc(sizeof(*kd))) == NULL && program != NULL) {
- (void)fprintf(stderr, "%s: %s\n", strerror(errno));
+ if ((kd = malloc(sizeof(*kd))) == NULL) {
+ if (errstr != NULL)
+ (void)fprintf(stderr, "%s: %s\n",
+ errstr, strerror(errno));
return (0);
}
- kd->program = program;
+ memset(kd, 0, sizeof(*kd));
+ kd->program = errstr;
return (_kvm_open(kd, uf, mf, sf, flag, NULL));
}
@@ -326,7 +331,7 @@ kvm_close(kd)
/*
* Set up state necessary to do queries on the kernel namelist
- * data base. If the data base is out-of-data/incompatible with
+ * data base. If the data base is out-of-data/incompatible with
* given executable, set up things so we revert to standard nlist call.
* Only called for live kernels. Return 0 on success, -1 on failure.
*/
@@ -374,7 +379,7 @@ kvm_dbopen(kd, uf)
if (rec.data == 0 || rec.size != sizeof(struct nlist))
goto close;
bcopy((char *)rec.data, (char *)&nitem, sizeof(nitem));
- if (kvm_read(kd, (u_long)nitem.n_value, kversion, dbversionlen) !=
+ if (kvm_read(kd, (u_long)nitem.n_value, kversion, dbversionlen) !=
dbversionlen)
goto close;
/*
@@ -399,7 +404,7 @@ kvm_nlist(kd, nl)
register int nvalid;
/*
- * If we can't use the data base, revert to the
+ * If we can't use the data base, revert to the
* slow library call.
*/
if (kd->db == 0)
@@ -430,10 +435,10 @@ kvm_nlist(kd, nl)
* Avoid alignment issues.
*/
bcopy((char *)&((struct nlist *)rec.data)->n_type,
- (char *)&p->n_type,
+ (char *)&p->n_type,
sizeof(p->n_type));
bcopy((char *)&((struct nlist *)rec.data)->n_value,
- (char *)&p->n_value,
+ (char *)&p->n_value,
sizeof(p->n_value));
}
/*
@@ -473,7 +478,7 @@ kvm_read(kd, kva, buf, len)
cp = buf;
while (len > 0) {
u_long pa;
-
+
cc = _kvm_kvatop(kd, kva, &pa);
if (cc == 0)
return (0);
diff --git a/lib/libkvm/kvm.h b/lib/libkvm/kvm.h
new file mode 100644
index 0000000..6c437b9
--- /dev/null
+++ b/lib/libkvm/kvm.h
@@ -0,0 +1,73 @@
+/*-
+ * 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.
+ *
+ * @(#)kvm.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _KVM_H_
+#define _KVM_H_
+
+/* Default version symbol. */
+#define VRS_SYM "_version"
+#define VRS_KEY "VERSION"
+
+#include <nlist.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+typedef struct __kvm kvm_t;
+
+struct kinfo_proc;
+int kvm_close __P((kvm_t *));
+char **kvm_getargv __P((kvm_t *, const struct kinfo_proc *, int));
+char **kvm_getenvv __P((kvm_t *, const struct kinfo_proc *, int));
+char *kvm_geterr __P((kvm_t *));
+int kvm_getloadavg __P((kvm_t *, double [], int));
+char *kvm_getfiles __P((kvm_t *, int, int, int *));
+struct kinfo_proc *
+ kvm_getprocs __P((kvm_t *, int, int, int *));
+int kvm_nlist __P((kvm_t *, struct nlist *));
+kvm_t *kvm_open
+ __P((const char *, const char *, const char *, int, const char *));
+kvm_t *kvm_openfiles
+ __P((const char *, const char *, const char *, int, char *));
+int kvm_read __P((kvm_t *, unsigned long, void *, unsigned int));
+int kvm_write __P((kvm_t *, unsigned long, const void *, unsigned int));
+/* Comment this out until it can be fixed correctly.
+ssize_t kvm_uread
+ __P((kvm_t *, struct proc *, unsigned long, char *, size_t));
+*/
+
+__END_DECLS
+
+#endif /* !_KVM_H_ */
diff --git a/lib/libkvm/kvm_amd64.c b/lib/libkvm/kvm_amd64.c
new file mode 100644
index 0000000..c32fd53
--- /dev/null
+++ b/lib/libkvm/kvm_amd64.c
@@ -0,0 +1,181 @@
+/*-
+ * Copyright (c) 1989, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software 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.
+ * 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[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * i386 machine dependent routines for kvm. Hopefully, the forthcoming
+ * vm code will one day obsolete this module.
+ */
+
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <nlist.h>
+#include <kvm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#include <limits.h>
+#include <db.h>
+
+#include "kvm_private.h"
+
+#ifndef btop
+#define btop(x) (i386_btop(x))
+#define ptob(x) (i386_ptob(x))
+#endif
+
+struct vmstate {
+ pd_entry_t *PTD;
+};
+
+void
+_kvm_freevtop(kvm_t *kd)
+{
+ if (kd->vmst != 0) {
+ if (kd->vmst->PTD) {
+ free(kd->vmst->PTD);
+ }
+ free(kd->vmst);
+ }
+}
+
+int
+_kvm_initvtop(kvm_t *kd)
+{
+ struct vmstate *vm;
+ struct nlist nlist[2];
+ u_long pa;
+ pd_entry_t *PTD;
+
+ vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
+ if (vm == 0) {
+ _kvm_err(kd, kd->program, "cannot allocate vm");
+ return (-1);
+ }
+ kd->vmst = vm;
+ vm->PTD = 0;
+
+ nlist[0].n_name = "_IdlePTD";
+ nlist[1].n_name = 0;
+
+ if (kvm_nlist(kd, nlist) != 0) {
+ _kvm_err(kd, kd->program, "bad namelist");
+ return (-1);
+ }
+ if (kvm_read(kd, (nlist[0].n_value - KERNBASE), &pa, sizeof(pa)) != sizeof(pa)) {
+ _kvm_err(kd, kd->program, "cannot read IdlePTD");
+ return (-1);
+ }
+ PTD = _kvm_malloc(kd, PAGE_SIZE);
+ if (kvm_read(kd, pa, PTD, PAGE_SIZE) != PAGE_SIZE) {
+ _kvm_err(kd, kd->program, "cannot read PTD");
+ return (-1);
+ }
+ vm->PTD = PTD;
+ return (0);
+}
+
+static int
+_kvm_vatop(kvm_t *kd, u_long va, u_long *pa)
+{
+ struct vmstate *vm;
+ u_long offset;
+ u_long pte_pa;
+ pd_entry_t pde;
+ pt_entry_t pte;
+ u_long pdeindex;
+ u_long pteindex;
+ int i;
+
+ if (ISALIVE(kd)) {
+ _kvm_err(kd, 0, "vatop called in live kernel!");
+ return((off_t)0);
+ }
+
+ vm = kd->vmst;
+ offset = va & (PAGE_SIZE - 1);
+
+ /*
+ * If we are initializing (kernel page table descriptor pointer
+ * not yet set) then return pa == va to avoid infinite recursion.
+ */
+ if (vm->PTD == 0) {
+ *pa = va;
+ return (PAGE_SIZE - offset);
+ }
+
+ pdeindex = va >> PDRSHIFT;
+ pde = vm->PTD[pdeindex];
+ if (((u_long)pde & PG_V) == 0)
+ goto invalid;
+
+ pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1);
+ pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pt_entry_t));
+
+ /* XXX This has to be a physical address read, kvm_read is virtual */
+ if (lseek(kd->pmfd, pte_pa, 0) == -1) {
+ _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek");
+ goto invalid;
+ }
+ if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) {
+ _kvm_syserr(kd, kd->program, "_kvm_vatop: read");
+ goto invalid;
+ }
+ if (((u_long)pte & PG_V) == 0)
+ goto invalid;
+
+ *pa = ((u_long)pte & PG_FRAME) + offset;
+ return (PAGE_SIZE - offset);
+
+invalid:
+ _kvm_err(kd, 0, "invalid address (%x)", va);
+ return (0);
+}
+
+int
+_kvm_kvatop(kvm_t *kd, u_long va, u_long *pa)
+{
+ return (_kvm_vatop(kd, va, pa));
+}
diff --git a/lib/libkvm/kvm_file.c b/lib/libkvm/kvm_file.c
index 6786209..c4cede3 100644
--- a/lib/libkvm/kvm_file.c
+++ b/lib/libkvm/kvm_file.c
@@ -32,11 +32,11 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)kvm_file.c 8.2 (Berkeley) 8/20/94";
+static char sccsid[] = "@(#)kvm_file.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
/*
- * File list interface for kvm. pstat, fstat and netstat are
+ * File list interface for kvm. pstat, fstat and netstat are
* users of this code, so we've factored it out into a separate module.
* Thus, we keep this grunge out of the other kvm applications (i.e.,
* most other applications are interested only in open/close/read/nlist).
@@ -45,13 +45,11 @@ static char sccsid[] = "@(#)kvm_file.c 8.2 (Berkeley) 8/20/94";
#include <sys/param.h>
#include <sys/user.h>
#include <sys/proc.h>
-#include <sys/exec.h>
#define KERNEL
#include <sys/file.h>
#undef KERNEL
#include <sys/stat.h>
#include <sys/ioctl.h>
-#include <sys/tty.h>
#include <nlist.h>
#include <kvm.h>
@@ -73,17 +71,16 @@ static char sccsid[] = "@(#)kvm_file.c 8.2 (Berkeley) 8/20/94";
/*
* Get file structures.
*/
-static
+static int
kvm_deadfiles(kd, op, arg, filehead_o, nfiles)
kvm_t *kd;
int op, arg, nfiles;
long filehead_o;
{
- int buflen = kd->arglen, needed = buflen, error, n = 0;
- struct file *fp, file;
- struct filelist filehead;
+ int buflen = kd->arglen, n = 0;
+ struct file *fp;
register char *where = kd->argspc;
- char *start = where;
+ struct filelist filehead;
/*
* first copyout filehead
diff --git a/lib/libkvm/kvm_getfiles.3 b/lib/libkvm/kvm_getfiles.3
index bad2e74..54a3270 100644
--- a/lib/libkvm/kvm_getfiles.3
+++ b/lib/libkvm/kvm_getfiles.3
@@ -43,7 +43,6 @@
.Nd survey open files
.Sh SYNOPSIS
.Fd #include <kvm.h>
-.Fd #include <sys/kinfo.h>
.Fd #define KERNEL
.Fd #include <sys/file.h>
.Fd #undef KERNEL
@@ -77,10 +76,10 @@ will return NULL on failure.
This routine does not belong in the kvm interface.
.Sh SEE ALSO
.Xr kvm 3 ,
+.Xr kvm_close 3 ,
+.Xr kvm_geterr 3 ,
+.Xr kvm_nlist 3 ,
.Xr kvm_open 3 ,
.Xr kvm_openfiles 3 ,
-.Xr kvm_close 3 ,
.Xr kvm_read 3 ,
-.Xr kvm_write 3 ,
-.Xr kvm_nlist 3 ,
-.Xr kvm_geterr 3
+.Xr kvm_write 3
diff --git a/lib/libkvm/kvm_getloadavg.3 b/lib/libkvm/kvm_getloadavg.3
index 80dc3b1..4910fa5 100644
--- a/lib/libkvm/kvm_getloadavg.3
+++ b/lib/libkvm/kvm_getloadavg.3
@@ -36,11 +36,9 @@
.Os
.Sh NAME
.Nm kvm_getloadavg
-.Nd get error message on kvm descriptor
+.Nd get load average of the system
.Sh SYNOPSIS
-.Fd #include <sys/resource.h>
.Fd #include <kvm.h>
-.br
.Ft int
.Fn kvm_getloadavg "kvm_t *kd" "double loadavg[]" "int nelem"
.Sh DESCRIPTION
@@ -61,5 +59,5 @@ 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 3 ,
-.Xr getloadavg 3
+.Xr getloadavg 3 ,
+.Xr kvm 3
diff --git a/lib/libkvm/kvm_getloadavg.c b/lib/libkvm/kvm_getloadavg.c
index e13ee1d..3368e63 100644
--- a/lib/libkvm/kvm_getloadavg.c
+++ b/lib/libkvm/kvm_getloadavg.c
@@ -42,6 +42,7 @@ static char sccsid[] = "@(#)kvm_getloadavg.c 8.1 (Berkeley) 6/4/93";
#include <sys/sysctl.h>
#include <vm/vm_param.h>
+#include <stdlib.h>
#include <db.h>
#include <fcntl.h>
#include <limits.h>
diff --git a/lib/libkvm/kvm_getprocs.3 b/lib/libkvm/kvm_getprocs.3
index a5eacb9..1ecfe14 100644
--- a/lib/libkvm/kvm_getprocs.3
+++ b/lib/libkvm/kvm_getprocs.3
@@ -34,6 +34,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)kvm_getprocs.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt KVM_GETPROCS 3
@@ -45,8 +46,8 @@
.Nd access user process state
.Sh SYNOPSIS
.Fd #include <kvm.h>
-.Fd #include <sys/kinfo.h>
-.Fd #include <sys/kinfo_proc.h>
+.Fd #include <sys/param.h>
+.Fd #include <sys/sysctl.h>
.\" .Fa kvm_t *kd
.br
.Ft struct kinfo_proc *
@@ -69,24 +70,24 @@ returned. The value of
describes the filtering predicate as follows:
.Pp
.Bl -tag -width 20n -offset indent -compact
-.It Sy KINFO_PROC_ALL
+.It Sy KERN_PROC_ALL
all processes
-.It Sy KINFO_PROC_PID
+.It Sy KERN_PROC_PID
processes with process id
.Fa arg
-.It Sy KINFO_PROC_PGRP
+.It Sy KERN_PROC_PGRP
processes with process group
.Fa arg
-.It Sy KINFO_PROC_SESSION
+.It Sy KERN_PROC_SESSION
processes with session
.Fa arg
-.It Sy KINFO_PROC_TTY
+.It Sy KERN_PROC_TTY
processes with tty
.Fa arg
-.It Sy KINFO_PROC_UID
+.It Sy KERN_PROC_UID
processes with effective user id
.Fa arg
-.It Sy KINFO_PROC_RUID
+.It Sy KERN_PROC_RUID
processes with real user id
.Fa arg
.El
diff --git a/lib/libkvm/kvm_hp300.c b/lib/libkvm/kvm_hp300.c
index 2154a23..c84691e 100644
--- a/lib/libkvm/kvm_hp300.c
+++ b/lib/libkvm/kvm_hp300.c
@@ -40,7 +40,7 @@ static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
/*
- * Hp300 machine dependent routines for kvm. Hopefully, the forthcoming
+ * Hp300 machine dependent routines for kvm. Hopefully, the forthcoming
* vm code will one day obsolete this module.
*/
@@ -161,7 +161,7 @@ _kvm_vatop(kd, sta, va, pa)
addr = (u_long)&sta[va >> SG4_SHIFT1];
/*
* Can't use KREAD to read kernel segment table entries.
- * Fortunately it is 1-to-1 mapped so we don't have to.
+ * Fortunately it is 1-to-1 mapped so we don't have to.
*/
if (sta == vm->Sysseg) {
if (lseek(kd->pmfd, (off_t)addr, 0) == -1 ||
@@ -180,7 +180,7 @@ _kvm_vatop(kd, sta, va, pa)
* Address from level 1 STE is a physical address,
* so don't use kvm_read.
*/
- if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 ||
+ if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 ||
read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0)
goto invalid;
if ((ste & SG_V) == 0) {
@@ -194,7 +194,7 @@ _kvm_vatop(kd, sta, va, pa)
addr = (u_long)&sta[va >> SEGSHIFT];
/*
* Can't use KREAD to read kernel segment table entries.
- * Fortunately it is 1-to-1 mapped so we don't have to.
+ * Fortunately it is 1-to-1 mapped so we don't have to.
*/
if (sta == vm->Sysseg) {
if (lseek(kd->pmfd, (off_t)addr, 0) == -1 ||
@@ -212,7 +212,7 @@ _kvm_vatop(kd, sta, va, pa)
/*
* Address from STE is a physical address so don't use kvm_read.
*/
- if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 ||
+ if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 ||
read(kd->pmfd, (char *)&pte, sizeof(pte)) < 0)
goto invalid;
addr = pte & PG_FRAME;
@@ -221,7 +221,7 @@ _kvm_vatop(kd, sta, va, pa)
return (0);
}
*pa = addr - lowram + offset;
-
+
return (NBPG - offset);
invalid:
_kvm_err(kd, 0, "invalid address (%x)", va);
diff --git a/lib/libkvm/kvm_i386.c b/lib/libkvm/kvm_i386.c
new file mode 100644
index 0000000..c32fd53
--- /dev/null
+++ b/lib/libkvm/kvm_i386.c
@@ -0,0 +1,181 @@
+/*-
+ * Copyright (c) 1989, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software 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.
+ * 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[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * i386 machine dependent routines for kvm. Hopefully, the forthcoming
+ * vm code will one day obsolete this module.
+ */
+
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <nlist.h>
+#include <kvm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#include <limits.h>
+#include <db.h>
+
+#include "kvm_private.h"
+
+#ifndef btop
+#define btop(x) (i386_btop(x))
+#define ptob(x) (i386_ptob(x))
+#endif
+
+struct vmstate {
+ pd_entry_t *PTD;
+};
+
+void
+_kvm_freevtop(kvm_t *kd)
+{
+ if (kd->vmst != 0) {
+ if (kd->vmst->PTD) {
+ free(kd->vmst->PTD);
+ }
+ free(kd->vmst);
+ }
+}
+
+int
+_kvm_initvtop(kvm_t *kd)
+{
+ struct vmstate *vm;
+ struct nlist nlist[2];
+ u_long pa;
+ pd_entry_t *PTD;
+
+ vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
+ if (vm == 0) {
+ _kvm_err(kd, kd->program, "cannot allocate vm");
+ return (-1);
+ }
+ kd->vmst = vm;
+ vm->PTD = 0;
+
+ nlist[0].n_name = "_IdlePTD";
+ nlist[1].n_name = 0;
+
+ if (kvm_nlist(kd, nlist) != 0) {
+ _kvm_err(kd, kd->program, "bad namelist");
+ return (-1);
+ }
+ if (kvm_read(kd, (nlist[0].n_value - KERNBASE), &pa, sizeof(pa)) != sizeof(pa)) {
+ _kvm_err(kd, kd->program, "cannot read IdlePTD");
+ return (-1);
+ }
+ PTD = _kvm_malloc(kd, PAGE_SIZE);
+ if (kvm_read(kd, pa, PTD, PAGE_SIZE) != PAGE_SIZE) {
+ _kvm_err(kd, kd->program, "cannot read PTD");
+ return (-1);
+ }
+ vm->PTD = PTD;
+ return (0);
+}
+
+static int
+_kvm_vatop(kvm_t *kd, u_long va, u_long *pa)
+{
+ struct vmstate *vm;
+ u_long offset;
+ u_long pte_pa;
+ pd_entry_t pde;
+ pt_entry_t pte;
+ u_long pdeindex;
+ u_long pteindex;
+ int i;
+
+ if (ISALIVE(kd)) {
+ _kvm_err(kd, 0, "vatop called in live kernel!");
+ return((off_t)0);
+ }
+
+ vm = kd->vmst;
+ offset = va & (PAGE_SIZE - 1);
+
+ /*
+ * If we are initializing (kernel page table descriptor pointer
+ * not yet set) then return pa == va to avoid infinite recursion.
+ */
+ if (vm->PTD == 0) {
+ *pa = va;
+ return (PAGE_SIZE - offset);
+ }
+
+ pdeindex = va >> PDRSHIFT;
+ pde = vm->PTD[pdeindex];
+ if (((u_long)pde & PG_V) == 0)
+ goto invalid;
+
+ pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1);
+ pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pt_entry_t));
+
+ /* XXX This has to be a physical address read, kvm_read is virtual */
+ if (lseek(kd->pmfd, pte_pa, 0) == -1) {
+ _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek");
+ goto invalid;
+ }
+ if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) {
+ _kvm_syserr(kd, kd->program, "_kvm_vatop: read");
+ goto invalid;
+ }
+ if (((u_long)pte & PG_V) == 0)
+ goto invalid;
+
+ *pa = ((u_long)pte & PG_FRAME) + offset;
+ return (PAGE_SIZE - offset);
+
+invalid:
+ _kvm_err(kd, 0, "invalid address (%x)", va);
+ return (0);
+}
+
+int
+_kvm_kvatop(kvm_t *kd, u_long va, u_long *pa)
+{
+ return (_kvm_vatop(kd, va, pa));
+}
diff --git a/lib/libkvm/kvm_mips.c b/lib/libkvm/kvm_mips.c
index b0f4cfe..2087981 100644
--- a/lib/libkvm/kvm_mips.c
+++ b/lib/libkvm/kvm_mips.c
@@ -39,7 +39,7 @@
static char sccsid[] = "@(#)kvm_mips.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
/*
- * MIPS machine dependent routines for kvm. Hopefully, the forthcoming
+ * MIPS machine dependent routines for kvm. Hopefully, the forthcoming
* vm code will one day obsolete this module.
*/
@@ -146,7 +146,7 @@ _kvm_kvatop(kd, va, pa)
addr = (u_long)(vm->Sysmap + ((va - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT));
/*
* Can't use KREAD to read kernel segment table entries.
- * Fortunately it is 1-to-1 mapped so we don't have to.
+ * Fortunately it is 1-to-1 mapped so we don't have to.
*/
if (lseek(kd->pmfd, (off_t)addr, 0) < 0 ||
read(kd->pmfd, (char *)&pte, sizeof(pte)) < 0)
diff --git a/lib/libkvm/kvm_nlist.3 b/lib/libkvm/kvm_nlist.3
index 1c0cd89..f620f55 100644
--- a/lib/libkvm/kvm_nlist.3
+++ b/lib/libkvm/kvm_nlist.3
@@ -71,8 +71,8 @@ The
function returns the number of invalid entries found.
If the kernel symbol table was unreadable, -1 is returned.
.Sh FILES
-.Bl -tag -width /var/db/kvm_vmunix.db -compact
-.It Pa /var/db/kvm_vmunix.db
+.Bl -tag -width /var/db/kvm_kernel.db -compact
+.It Pa /var/db/kvm_kernel.db
.El
.Sh SEE ALSO
.Xr kvm 3 ,
diff --git a/lib/libkvm/kvm_open.3 b/lib/libkvm/kvm_open.3
index dd6895b..93fe0f7 100644
--- a/lib/libkvm/kvm_open.3
+++ b/lib/libkvm/kvm_open.3
@@ -48,9 +48,9 @@
.Fd #include <kvm.h>
.br
.Ft kvm_t *
-.Fn kvm_open "const char *execfile" "const char *corefile" "char *swapfile" "int flags" "const char *errstr"
+.Fn kvm_open "const char *execfile" "const char *corefile" "const char *swapfile" "int flags" "const char *errstr"
.Ft kvm_t *
-.Fn kvm_openfiles "const char *execfile" "const char *corefile" "char *swapfile" "int flags" "char *errbuf"
+.Fn kvm_openfiles "const char *execfile" "const char *corefile" "const char *swapfile" "int flags" "char *errbuf"
.Ft int
.Fn kvm_close "kvm_t *kd"
.Sh DESCRIPTION
@@ -70,9 +70,8 @@ This file must contain a symbol table.
If this argument is
.Dv NULL ,
the currently running system is assumed,
-which is indicated by
-.Dv _PATH_UNIX
-in <paths.h>.
+as determined from
+.Xr getbootfile 3 .
.Pp
.Fa corefile
is the kernel memory device file. It can be either /dev/mem
diff --git a/lib/libkvm/kvm_private.h b/lib/libkvm/kvm_private.h
index baaeb05..92ab146 100644
--- a/lib/libkvm/kvm_private.h
+++ b/lib/libkvm/kvm_private.h
@@ -51,12 +51,13 @@ struct __kvm {
int pmfd; /* physical memory file (or crashdump) */
int vmfd; /* virtual memory file (-1 if crashdump) */
int swfd; /* swap file (e.g., /dev/drum) */
- int nlfd; /* namelist file (e.g., /vmunix) */
+ int nlfd; /* namelist file (e.g., /kernel) */
struct kinfo_proc *procbase;
char *argspc; /* (dynamic) storage for argv strings */
int arglen; /* length of the above */
char **argv; /* (dynamic) storage for argv pointers */
int argc; /* length of above (not actual # present) */
+ char *argbuf; /* (dynamic) temporary storage */
/*
* Kernel virtual address translation state. This only gets filled
* in for dead kernels; otherwise, the running kernel (i.e. kmem)
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c
index 7a36ef6..d167f34 100644
--- a/lib/libkvm/kvm_proc.c
+++ b/lib/libkvm/kvm_proc.c
@@ -36,7 +36,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)kvm_proc.c 8.4 (Berkeley) 8/20/94";
+static char sccsid[] = "@(#)kvm_proc.c 8.3 (Berkeley) 9/23/93";
#endif /* LIBC_SCCS and not lint */
/*
@@ -53,6 +53,9 @@ static char sccsid[] = "@(#)kvm_proc.c 8.4 (Berkeley) 8/20/94";
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
#include <nlist.h>
#include <kvm.h>
@@ -64,11 +67,13 @@ static char sccsid[] = "@(#)kvm_proc.c 8.4 (Berkeley) 8/20/94";
#include <sys/sysctl.h>
#include <limits.h>
+#include <memory.h>
#include <db.h>
#include <paths.h>
#include "kvm_private.h"
+#if used
static char *
kvm_readswap(kd, p, va, cnt)
kvm_t *kd;
@@ -76,97 +81,13 @@ kvm_readswap(kd, p, va, cnt)
u_long va;
u_long *cnt;
{
- register int ix;
- register u_long addr, head;
- register u_long offset, pagestart, sbstart, pgoff;
- register off_t seekpoint;
- struct vm_map_entry vme;
- struct vm_object vmo;
- struct pager_struct pager;
- struct swpager swap;
- struct swblock swb;
- static char page[NBPG];
-
- head = (u_long)&p->p_vmspace->vm_map.header;
- /*
- * Look through the address map for the memory object
- * that corresponds to the given virtual address.
- * The header just has the entire valid range.
- */
- addr = head;
- while (1) {
- if (kvm_read(kd, addr, (char *)&vme, sizeof(vme)) !=
- sizeof(vme))
- return (0);
-
- if (va >= vme.start && va <= vme.end &&
- vme.object.vm_object != 0)
- break;
-
- addr = (u_long)vme.next;
- if (addr == 0 || addr == head)
- return (0);
- }
- /*
- * We found the right object -- follow shadow links.
- */
- offset = va - vme.start + vme.offset;
- addr = (u_long)vme.object.vm_object;
- while (1) {
- if (kvm_read(kd, addr, (char *)&vmo, sizeof(vmo)) !=
- sizeof(vmo))
- return (0);
- addr = (u_long)vmo.shadow;
- if (addr == 0)
- break;
- offset += vmo.shadow_offset;
- }
- if (vmo.pager == 0)
- return (0);
-
- offset += vmo.paging_offset;
- /*
- * Read in the pager info and make sure it's a swap device.
- */
- addr = (u_long)vmo.pager;
- if (kvm_read(kd, addr, (char *)&pager, sizeof(pager)) != sizeof(pager)
- || pager.pg_type != PG_SWAP)
- return (0);
-
- /*
- * Read in the swap_pager private data, and compute the
- * swap offset.
- */
- addr = (u_long)pager.pg_data;
- if (kvm_read(kd, addr, (char *)&swap, sizeof(swap)) != sizeof(swap))
- return (0);
- ix = offset / dbtob(swap.sw_bsize);
- if (swap.sw_blocks == 0 || ix >= swap.sw_nblocks)
- return (0);
-
- addr = (u_long)&swap.sw_blocks[ix];
- if (kvm_read(kd, addr, (char *)&swb, sizeof(swb)) != sizeof(swb))
- return (0);
-
- sbstart = (offset / dbtob(swap.sw_bsize)) * dbtob(swap.sw_bsize);
- sbstart /= NBPG;
- pagestart = offset / NBPG;
- pgoff = pagestart - sbstart;
-
- if (swb.swb_block == 0 || (swb.swb_mask & (1 << pgoff)) == 0)
- return (0);
-
- seekpoint = dbtob(swb.swb_block) + ctob(pgoff);
- errno = 0;
- if (lseek(kd->swfd, seekpoint, 0) == -1 && errno != 0)
- return (0);
- if (read(kd->swfd, page, sizeof(page)) != sizeof(page))
- return (0);
-
- offset %= NBPG;
- *cnt = NBPG - offset;
- return (&page[offset]);
+#ifdef __FreeBSD__
+ /* XXX Stubbed out, our vm system is differnet */
+ _kvm_err(kd, kd->program, "kvm_readswap not implemented");
+ return(0);
+#endif /* __FreeBSD__ */
}
+#endif
#define KREAD(kd, addr, obj) \
(kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj))
@@ -189,18 +110,19 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
struct session sess;
struct tty tty;
struct proc proc;
+ struct proc pproc;
- for (; cnt < maxcnt && p != 0; p = proc.p_list.le_next) {
+ for (; cnt < maxcnt && p != NULL; p = proc.p_list.le_next) {
if (KREAD(kd, (u_long)p, &proc)) {
_kvm_err(kd, kd->program, "can't read proc at %x", p);
return (-1);
}
if (KREAD(kd, (u_long)proc.p_cred, &eproc.e_pcred) == 0)
- KREAD(kd, (u_long)eproc.e_pcred.pc_ucred,
- &eproc.e_ucred);
+ (void)(KREAD(kd, (u_long)eproc.e_pcred.pc_ucred,
+ &eproc.e_ucred));
switch(what) {
-
+
case KERN_PROC_PID:
if (proc.p_pid != (pid_t)arg)
continue;
@@ -234,14 +156,27 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
proc.p_pgrp);
return (-1);
}
+ if (proc.p_oppid)
+ eproc.e_ppid = proc.p_oppid;
+ else if (proc.p_pptr) {
+ if (KREAD(kd, (u_long)proc.p_pptr, &pproc)) {
+ _kvm_err(kd, kd->program, "can't read pproc at %x",
+ proc.p_pptr);
+ return (-1);
+ }
+ eproc.e_ppid = pproc.p_pid;
+ } else
+ eproc.e_ppid = 0;
eproc.e_sess = pgrp.pg_session;
eproc.e_pgid = pgrp.pg_id;
eproc.e_jobc = pgrp.pg_jobc;
if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) {
- _kvm_err(kd, kd->program, "can't read session at %x",
+ _kvm_err(kd, kd->program, "can't read session at %x",
pgrp.pg_session);
return (-1);
}
+ (void)memcpy(eproc.e_login, sess.s_login,
+ sizeof(eproc.e_login));
if ((proc.p_flag & P_CONTROLT) && sess.s_ttyp != NULL) {
if (KREAD(kd, (u_long)sess.s_ttyp, &tty)) {
_kvm_err(kd, kd->program,
@@ -253,7 +188,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
if (tty.t_pgrp != NULL) {
if (KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) {
_kvm_err(kd, kd->program,
- "can't read tpgrp at &x",
+ "can't read tpgrp at &x",
tty.t_pgrp);
return (-1);
}
@@ -266,7 +201,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
if (sess.s_leader == p)
eproc.e_flag |= EPROC_SLEADER;
if (proc.p_wmesg)
- (void)kvm_read(kd, (u_long)proc.p_wmesg,
+ (void)kvm_read(kd, (u_long)proc.p_wmesg,
eproc.e_wmesg, WMESGLEN);
#ifdef sparc
@@ -291,7 +226,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
break;
case KERN_PROC_TTY:
- if ((proc.p_flag & P_CONTROLT) == 0 ||
+ if ((proc.p_flag & P_CONTROLT) == 0 ||
eproc.e_tdev != (dev_t)arg)
continue;
break;
@@ -349,7 +284,7 @@ kvm_getprocs(kd, op, arg, cnt)
if (kd->procbase != 0) {
free((void *)kd->procbase);
- /*
+ /*
* Clear this pointer in case this call fails. Otherwise,
* kvm_close() will free it again.
*/
@@ -361,7 +296,7 @@ kvm_getprocs(kd, op, arg, cnt)
mib[1] = KERN_PROC;
mib[2] = op;
mib[3] = arg;
- st = sysctl(mib, 4, NULL, &size, NULL, 0);
+ st = sysctl(mib, op == KERN_PROC_ALL ? 3 : 4, NULL, &size, NULL, 0);
if (st == -1) {
_kvm_syserr(kd, kd->program, "kvm_getprocs");
return (0);
@@ -369,7 +304,7 @@ kvm_getprocs(kd, op, arg, cnt)
kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size);
if (kd->procbase == 0)
return (0);
- st = sysctl(mib, 4, kd->procbase, &size, NULL, 0);
+ st = sysctl(mib, op == KERN_PROC_ALL ? 3 : 4, kd->procbase, &size, NULL, 0);
if (st == -1) {
_kvm_syserr(kd, kd->program, "kvm_getprocs");
return (0);
@@ -445,19 +380,20 @@ _kvm_realloc(kd, p, n)
/*
* Read in an argument vector from the user address space of process p.
- * addr if the user-space base address of narg null-terminated contiguous
+ * addr if the user-space base address of narg null-terminated contiguous
* strings. This is used to read in both the command arguments and
* environment strings. Read at most maxcnt characters of strings.
*/
static char **
kvm_argv(kd, p, addr, narg, maxcnt)
kvm_t *kd;
- struct proc *p;
+ const struct proc *p;
register u_long addr;
register int narg;
register int maxcnt;
{
- register char *cp;
+ register char *np, *cp, *ep, *ap;
+ register u_long oaddr = -1;
register int len, cc;
register char **argv;
@@ -468,39 +404,104 @@ kvm_argv(kd, p, addr, narg, maxcnt)
if (narg > 512 || addr < VM_MIN_ADDRESS || addr >= VM_MAXUSER_ADDRESS)
return (0);
+ /*
+ * kd->argv : work space for fetching the strings from the target
+ * process's space, and is converted for returning to caller
+ */
if (kd->argv == 0) {
/*
* Try to avoid reallocs.
*/
kd->argc = MAX(narg + 1, 32);
- kd->argv = (char **)_kvm_malloc(kd, kd->argc *
+ kd->argv = (char **)_kvm_malloc(kd, kd->argc *
sizeof(*kd->argv));
if (kd->argv == 0)
return (0);
} else if (narg + 1 > kd->argc) {
kd->argc = MAX(2 * kd->argc, narg + 1);
- kd->argv = (char **)_kvm_realloc(kd, kd->argv, kd->argc *
+ kd->argv = (char **)_kvm_realloc(kd, kd->argv, kd->argc *
sizeof(*kd->argv));
if (kd->argv == 0)
return (0);
}
+ /*
+ * kd->argspc : returned to user, this is where the kd->argv
+ * arrays are left pointing to the collected strings.
+ */
if (kd->argspc == 0) {
- kd->argspc = (char *)_kvm_malloc(kd, NBPG);
+ kd->argspc = (char *)_kvm_malloc(kd, PAGE_SIZE);
if (kd->argspc == 0)
return (0);
- kd->arglen = NBPG;
+ kd->arglen = PAGE_SIZE;
}
- cp = kd->argspc;
+ /*
+ * kd->argbuf : used to pull in pages from the target process.
+ * the strings are copied out of here.
+ */
+ if (kd->argbuf == 0) {
+ kd->argbuf = (char *)_kvm_malloc(kd, PAGE_SIZE);
+ if (kd->argbuf == 0)
+ return (0);
+ }
+
+ /* Pull in the target process'es argv vector */
+ cc = sizeof(char *) * narg;
+ if (kvm_uread(kd, p, addr, (char *)kd->argv, cc) != cc)
+ return (0);
+ /*
+ * ap : saved start address of string we're working on in kd->argspc
+ * np : pointer to next place to write in kd->argspc
+ * len: length of data in kd->argspc
+ * argv: pointer to the argv vector that we are hunting around the
+ * target process space for, and converting to addresses in
+ * our address space (kd->argspc).
+ */
+ ap = np = kd->argspc;
argv = kd->argv;
- *argv = cp;
len = 0;
/*
* Loop over pages, filling in the argument vector.
+ * Note that the argv strings could be pointing *anywhere* in
+ * the user address space and are no longer contiguous.
+ * Note that *argv is modified when we are going to fetch a string
+ * that crosses a page boundary. We copy the next part of the string
+ * into to "np" and eventually convert the pointer.
*/
- while (addr < VM_MAXUSER_ADDRESS) {
- cc = NBPG - (addr & PGOFSET);
+ while (argv < kd->argv + narg && *argv != 0) {
+
+ /* get the address that the current argv string is on */
+ addr = (u_long)*argv & ~(PAGE_SIZE - 1);
+
+ /* is it the same page as the last one? */
+ if (addr != oaddr) {
+ if (kvm_uread(kd, p, addr, kd->argbuf, PAGE_SIZE) !=
+ PAGE_SIZE)
+ return (0);
+ oaddr = addr;
+ }
+
+ /* offset within the page... kd->argbuf */
+ addr = (u_long)*argv & (PAGE_SIZE - 1);
+
+ /* cp = start of string, cc = count of chars in this chunk */
+ cp = kd->argbuf + addr;
+ cc = PAGE_SIZE - addr;
+
+ /* dont get more than asked for by user process */
if (maxcnt > 0 && cc > maxcnt - len)
- cc = maxcnt - len;;
+ cc = maxcnt - len;
+
+ /* pointer to end of string if we found it in this page */
+ ep = memchr(cp, '\0', cc);
+ if (ep != 0)
+ cc = ep - cp + 1;
+ /*
+ * at this point, cc is the count of the chars that we are
+ * going to retrieve this time. we may or may not have found
+ * the end of it. (ep points to the null if the end is known)
+ */
+
+ /* will we exceed the malloc/realloced buffer? */
if (len + cc > kd->arglen) {
register int off;
register char **pp;
@@ -511,44 +512,52 @@ kvm_argv(kd, p, addr, narg, maxcnt)
kd->arglen);
if (kd->argspc == 0)
return (0);
- cp = &kd->argspc[len];
/*
* Adjust argv pointers in case realloc moved
* the string space.
*/
off = kd->argspc - op;
- for (pp = kd->argv; pp < argv; ++pp)
+ for (pp = kd->argv; pp < argv; pp++)
*pp += off;
+ ap += off;
+ np += off;
}
- if (kvm_uread(kd, p, addr, cp, cc) != cc)
- /* XXX */
- return (0);
+ /* np = where to put the next part of the string in kd->argspc*/
+ /* np is kinda redundant.. could use "kd->argspc + len" */
+ memcpy(np, cp, cc);
+ np += cc; /* inc counters */
len += cc;
- addr += cc;
-
- if (maxcnt == 0 && len > 16 * NBPG)
- /* sanity */
- return (0);
- while (--cc >= 0) {
- if (*cp++ == 0) {
- if (--narg <= 0) {
- *++argv = 0;
- return (kd->argv);
- } else
- *++argv = cp;
- }
+ /*
+ * if end of string found, set the *argv pointer to the
+ * saved beginning of string, and advance. argv points to
+ * somewhere in kd->argv.. This is initially relative
+ * to the target process, but when we close it off, we set
+ * it to point in our address space.
+ */
+ if (ep != 0) {
+ *argv++ = ap;
+ ap = np;
+ } else {
+ /* update the address relative to the target process */
+ *argv += cc;
}
+
if (maxcnt > 0 && len >= maxcnt) {
/*
* We're stopping prematurely. Terminate the
- * argv and current string.
+ * current string.
*/
- *++argv = 0;
- *cp = 0;
- return (kd->argv);
+ if (ep == 0) {
+ *np = '\0';
+ *argv++ = ap;
+ }
+ break;
}
}
+ /* Make sure argv is terminated. */
+ *argv = 0;
+ return (kd->argv);
}
static void
@@ -588,7 +597,7 @@ proc_verify(kd, kernp, p)
* Just read in the whole proc. It's not that big relative
* to the cost of the read system call.
*/
- if (kvm_read(kd, kernp, (char *)&kernproc, sizeof(kernproc)) !=
+ if (kvm_read(kd, kernp, (char *)&kernproc, sizeof(kernproc)) !=
sizeof(kernproc))
return (0);
return (p->p_pid == kernproc.p_pid &&
@@ -600,23 +609,35 @@ kvm_doargv(kd, kp, nchr, info)
kvm_t *kd;
const struct kinfo_proc *kp;
int nchr;
- int (*info)(struct ps_strings*, u_long *, int *);
+ void (*info)(struct ps_strings *, u_long *, int *);
{
register const struct proc *p = &kp->kp_proc;
register char **ap;
u_long addr;
int cnt;
- struct ps_strings arginfo;
+ struct ps_strings arginfo, *ps_strings;
+ int mib[2];
+ size_t len;
+
+ ps_strings = NULL;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PS_STRINGS;
+ len = sizeof(ps_strings);
+ if (sysctl(mib, 2, &ps_strings, &len, NULL, 0) < 0 ||
+ ps_strings == NULL)
+ ps_strings = PS_STRINGS;
/*
* Pointers are stored at the top of the user stack.
*/
- if (p->p_stat == SZOMB ||
- kvm_uread(kd, p, USRSTACK - sizeof(arginfo), (char *)&arginfo,
+ if (p->p_stat == SZOMB ||
+ kvm_uread(kd, p, ps_strings, (char *)&arginfo,
sizeof(arginfo)) != sizeof(arginfo))
return (0);
(*info)(&arginfo, &addr, &cnt);
+ if (cnt == 0)
+ return (0);
ap = kvm_argv(kd, p, addr, cnt, nchr);
/*
* For live kernels, make sure this process didn't go away.
@@ -654,52 +675,48 @@ kvm_getenvv(kd, kp, nchr)
ssize_t
kvm_uread(kd, p, uva, buf, len)
kvm_t *kd;
- register struct proc *p;
+ register const struct proc *p;
register u_long uva;
register char *buf;
register size_t len;
{
register char *cp;
+ char procfile[MAXPATHLEN];
+ ssize_t amount;
+ int fd;
+
+ if (!ISALIVE(kd)) {
+ _kvm_err(kd, kd->program, "cannot read user space from dead kernel");
+ return(0);
+ }
cp = buf;
+
+ sprintf(procfile, "/proc/%d/mem", p->p_pid);
+ fd = open(procfile, O_RDONLY, 0);
+
+ if (fd < 0) {
+ _kvm_err(kd, kd->program, "cannot open %s", procfile);
+ close(fd);
+ return (0);
+ }
+
+
while (len > 0) {
- u_long pa;
- register int cc;
-
- cc = _kvm_uvatop(kd, p, uva, &pa);
- if (cc > 0) {
- if (cc > len)
- cc = len;
- errno = 0;
- if (lseek(kd->pmfd, (off_t)pa, 0) == -1 && errno != 0) {
- _kvm_err(kd, 0, "invalid address (%x)", uva);
- break;
- }
- cc = read(kd->pmfd, cp, cc);
- if (cc < 0) {
- _kvm_syserr(kd, 0, _PATH_MEM);
- break;
- } else if (cc < len) {
- _kvm_err(kd, kd->program, "short read");
- break;
- }
- } else if (ISALIVE(kd)) {
- /* try swap */
- register char *dp;
- int cnt;
-
- dp = kvm_readswap(kd, p, uva, &cnt);
- if (dp == 0) {
- _kvm_err(kd, 0, "invalid address (%x)", uva);
- return (0);
- }
- cc = MIN(cnt, len);
- bcopy(dp, cp, cc);
- } else
+ if (lseek(fd, (off_t)uva, 0) == -1 && errno != 0) {
+ _kvm_err(kd, kd->program, "invalid address (%x) in %s", uva, procfile);
+ break;
+ }
+ amount = read(fd, cp, len);
+ if (amount < 0) {
+ _kvm_err(kd, kd->program, "error reading %s", procfile);
break;
- cp += cc;
- uva += cc;
- len -= cc;
+ }
+ cp += amount;
+ uva += amount;
+ len -= amount;
}
+
+ close(fd);
return (ssize_t)(cp - buf);
}
diff --git a/lib/libkvm/kvm_read.3 b/lib/libkvm/kvm_read.3
index b560959..1e8e3ad 100644
--- a/lib/libkvm/kvm_read.3
+++ b/lib/libkvm/kvm_read.3
@@ -43,6 +43,7 @@
.Nm kvm_write
.Nd read or write kernel virtual memory
.Sh SYNOPSIS
+.Fd #include <sys/types.h>
.Fd #include <kvm.h>
.Ft ssize_t
.Fn kvm_read "kvm_t *kd" "u_long addr" "void *buf" "size_t nbytes"
diff --git a/lib/libkvm/kvm_sparc.c b/lib/libkvm/kvm_sparc.c
index 5275068..a7b9594 100644
--- a/lib/libkvm/kvm_sparc.c
+++ b/lib/libkvm/kvm_sparc.c
@@ -40,7 +40,7 @@ static char sccsid[] = "@(#)kvm_sparc.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
/*
- * Sparc machine dependent routines for kvm. Hopefully, the forthcoming
+ * Sparc machine dependent routines for kvm. Hopefully, the forthcoming
* vm code will one day obsolete this module.
*/
@@ -107,7 +107,7 @@ _kvm_initvtop(kd)
*/
off = st.st_size - ctob(btoc(sizeof(vm->segmap)));
errno = 0;
- if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 ||
+ if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 ||
read(kd->pmfd, (char *)vm->segmap, sizeof(vm->segmap)) < 0) {
_kvm_err(kd, kd->program, "cannot read segment map");
return (-1);
@@ -118,7 +118,7 @@ _kvm_initvtop(kd)
off = st.st_size - ctob(btoc(sizeof(vm->pmeg)) +
btoc(sizeof(vm->segmap)));
errno = 0;
- if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 ||
+ if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 ||
read(kd->pmfd, (char *)vm->pmeg, sizeof(vm->pmeg)) < 0) {
_kvm_err(kd, kd->program, "cannot read PMEG table");
return (-1);
@@ -127,7 +127,7 @@ _kvm_initvtop(kd)
* Make pmap_stod be an identity map so we can bootstrap it in.
* We assume it's in the first contiguous chunk of physical memory.
*/
- for (i = 0; i < BTSIZE; ++i)
+ for (i = 0; i < BTSIZE; ++i)
vm->pmap_stod[i] = i << 4;
/*
@@ -142,7 +142,7 @@ _kvm_initvtop(kd)
_kvm_err(kd, kd->program, "pmap_stod: no such symbol");
return (-1);
}
- if (kvm_read(kd, (u_long)nlist[0].n_value,
+ if (kvm_read(kd, (u_long)nlist[0].n_value,
(char *)vm->pmap_stod, sizeof(vm->pmap_stod))
!= sizeof(vm->pmap_stod)) {
_kvm_err(kd, kd->program, "cannot read pmap_stod");
@@ -194,7 +194,7 @@ _kvm_uvatop(kd, p, va, pa)
frame = pte & PG_PFNUM;
else
frame = HWTOSW(kd->vmst->pmap_stod, pte & PG_PFNUM);
- *pa = (frame << PGSHIFT) | off;
+ *pa = (frame << PGSHIFT) | off;
return (NBPG - off);
}
invalid:
@@ -205,7 +205,7 @@ invalid:
/*
* Translate a kernel virtual address to a physical address using the
* mapping information in kd->vm. Returns the result in pa, and returns
- * the number of bytes that are contiguously available from this
+ * the number of bytes that are contiguously available from this
* physical address. This routine is used only for crashdumps.
*/
int
diff --git a/lib/libm/Makefile b/lib/libm/Makefile
index 2f4785f..7863229 100644
--- a/lib/libm/Makefile
+++ b/lib/libm/Makefile
@@ -1,4 +1,5 @@
-# @(#)Makefile 8.1 (Berkeley) 6/4/93
+# From: @(#)Makefile 8.1 (Berkeley) 6/4/93
+# $Id$
#
# ieee - for most IEEE machines, we hope.
# mc68881 - the, ahem, mc68881.
@@ -127,10 +128,15 @@ SRCS+= atan2.s cabs.s cbrt.s sqrt.s sincos.s tan.s argred.s support.s \
.endif
-MAN3+= acos.0 acosh.0 asin.0 asinh.0 atan.0 atan2.0 atanh.0 ceil.0 \
- cos.0 cosh.0 erf.0 exp.0 fabs.0 floor.0 fmod.0 hypot.0 ieee.0 \
- infnan.0 j0.0 lgamma.0 math.0 rint.0 sin.0 sinh.0 sqrt.0 \
- tan.0 tanh.0
+MAN3+= common_source/acos.3 common_source/acosh.3 common_source/asin.3 \
+ common_source/asinh.3 common_source/atan.3 common_source/atan2.3 \
+ common_source/atanh.3 common_source/ceil.3 common_source/cos.3 \
+ common_source/cosh.3 common_source/erf.3 common_source/exp.3 \
+ common_source/fabs.3 common_source/floor.3 common_source/fmod.3 \
+ common_source/hypot.3 common_source/ieee.3 common_source/infnan.3 \
+ common_source/j0.3 common_source/lgamma.3 common_source/math.3 \
+ common_source/rint.3 common_source/sin.3 common_source/sinh.3 \
+ common_source/sqrt.3 common_source/tan.3 common_source/tanh.3
MLINKS+=erf.3 erfc.3
MLINKS+=exp.3 expm1.3 exp.3 log.3 exp.3 log10.3 exp.3 log1p.3 exp.3 pow.3
@@ -153,10 +159,10 @@ depend: .depend
.s.o:
${AS} -o ${.TARGET} ${.IMPSRC}
@${LD} -x -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
.s.po:
sed -f ${.CURDIR}/${HARDWARE}/mcount.sed ${.IMPSRC} | \
${AS} -o ${.TARGET}
@${LD} -X -r ${.TARGET}
- @mv a.out ${.TARGET}
+ @mv -f a.out ${.TARGET}
diff --git a/lib/libm/common/atan2.c b/lib/libm/common/atan2.c
index 958a154..b847a1d 100644
--- a/lib/libm/common/atan2.c
+++ b/lib/libm/common/atan2.c
@@ -38,21 +38,21 @@ static char sccsid[] = "@(#)atan2.c 8.1 (Berkeley) 6/4/93";
/* ATAN2(Y,X)
* RETURN ARG (X+iY)
* DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
- * CODED IN C BY K.C. NG, 1/8/85;
+ * CODED IN C BY K.C. NG, 1/8/85;
* REVISED BY K.C. NG on 2/7/85, 2/13/85, 3/7/85, 3/30/85, 6/29/85.
*
* Required system supported functions :
* copysign(x,y)
* scalb(x,y)
* logb(x)
- *
+ *
* Method :
* 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
- * 2. Reduce x to positive by (if x and y are unexceptional):
+ * 2. Reduce x to positive by (if x and y are unexceptional):
* ARG (x+iy) = arctan(y/x) ... if x > 0,
* ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0,
- * 3. According to the integer k=4t+0.25 truncated , t=y/x, the argument
- * is further reduced to one of the following intervals and the
+ * 3. According to the integer k=4t+0.25 truncated , t=y/x, the argument
+ * is further reduced to one of the following intervals and the
* arctangent of y/x is evaluated by the corresponding formula:
*
* [0,7/16] atan(y/x) = t - t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
@@ -76,32 +76,32 @@ static char sccsid[] = "@(#)atan2.c 8.1 (Berkeley) 6/4/93";
* ARG( (anything but,0,NaN, and INF),+-INF ) is +-PI/2;
*
* Accuracy:
- * atan2(y,x) returns (PI/pi) * the exact ARG (x+iy) nearly rounded,
+ * atan2(y,x) returns (PI/pi) * the exact ARG (x+iy) nearly rounded,
* where
*
* in decimal:
- * pi = 3.141592653589793 23846264338327 .....
+ * pi = 3.141592653589793 23846264338327 .....
* 53 bits PI = 3.141592653589793 115997963 ..... ,
- * 56 bits PI = 3.141592653589793 227020265 ..... ,
+ * 56 bits PI = 3.141592653589793 227020265 ..... ,
*
* in hexadecimal:
* pi = 3.243F6A8885A308D313198A2E....
* 53 bits PI = 3.243F6A8885A30 = 2 * 1.921FB54442D18 error=.276ulps
* 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2 error=.206ulps
- *
+ *
* In a test run with 356,000 random argument on [-1,1] * [-1,1] on a
* VAX, the maximum observed error was 1.41 ulps (units of the last place)
* compared with (PI/pi)*(the exact ARG(x+iy)).
*
* Note:
* We use machine PI (the true pi rounded) in place of the actual
- * value of pi for all the trig and inverse trig functions. In general,
- * if trig is one of sin, cos, tan, then computed trig(y) returns the
- * exact trig(y*pi/PI) nearly rounded; correspondingly, computed arctrig
- * returns the exact arctrig(y)*PI/pi nearly rounded. These guarantee the
+ * value of pi for all the trig and inverse trig functions. In general,
+ * if trig is one of sin, cos, tan, then computed trig(y) returns the
+ * exact trig(y*pi/PI) nearly rounded; correspondingly, computed arctrig
+ * returns the exact arctrig(y)*PI/pi nearly rounded. These guarantee the
* trig functions have period PI, and trig(arctrig(x)) returns x for
* all critical values x.
- *
+ *
* Constants:
* The hexadecimal values are the intended ones for the following constants.
* The decimal values may be used, provided that the compiler will convert
@@ -174,7 +174,7 @@ ic(a11, 1.6438029044759730479E-2 , -6, 1.0D52174A1BB54)
double atan2(y,x)
double y,x;
-{
+{
static const double zero=0, one=1, small=1.0E-9, big=1.0E18;
double t,z,signy,signx,hi,lo;
int k,m;
@@ -185,8 +185,8 @@ double y,x;
#endif /* !defined(vax)&&!defined(tahoe) */
/* copy down the sign of y and x */
- signy = copysign(one,y) ;
- signx = copysign(one,x) ;
+ signy = copysign(one,y) ;
+ signx = copysign(one,x) ;
/* if x is 1.0, goto begin */
if(x==1) { y=copysign(y,one); t=y; if(finite(t)) goto begin;}
@@ -196,10 +196,10 @@ double y,x;
/* when x = 0 */
if(x==zero) return(copysign(PIo2,signy));
-
+
/* when x is INF */
if(!finite(x))
- if(!finite(y))
+ if(!finite(y))
return(copysign((signx==one)?PIo4:3*PIo4,signy));
else
return(copysign((signx==one)?zero:PI,signy));
@@ -208,43 +208,43 @@ double y,x;
if(!finite(y)) return(copysign(PIo2,signy));
/* compute y/x */
- x=copysign(x,one);
- y=copysign(y,one);
- if((m=(k=logb(y))-logb(x)) > 60) t=big+big;
+ x=copysign(x,one);
+ y=copysign(y,one);
+ if((m=(k=logb(y))-logb(x)) > 60) t=big+big;
else if(m < -80 ) t=y/x;
else { t = y/x ; y = scalb(y,-k); x=scalb(x,-k); }
/* begin argument reduction */
begin:
- if (t < 2.4375) {
+ if (t < 2.4375) {
/* truncate 4(t+1/16) to integer for branching */
k = 4 * (t+0.0625);
switch (k) {
/* t is in [0,7/16] */
- case 0:
+ case 0:
case 1:
- if (t < small)
+ if (t < small)
{ big + small ; /* raise inexact flag */
return (copysign((signx>zero)?t:PI-t,signy)); }
hi = zero; lo = zero; break;
/* t is in [7/16,11/16] */
- case 2:
+ case 2:
hi = athfhi; lo = athflo;
z = x+x;
t = ( (y+y) - x ) / ( z + y ); break;
/* t is in [11/16,19/16] */
- case 3:
+ case 3:
case 4:
hi = PIo4; lo = zero;
t = ( y - x ) / ( x + y ); break;
/* t is in [19/16,39/16] */
- default:
+ default:
hi = at1fhi; lo = at1flo;
z = y-x; y=y+y+y; t = x+x;
t = ( (z+z)-x ) / ( t + y ); break;
@@ -252,7 +252,7 @@ begin:
}
/* end of if (t < 2.4375) */
- else
+ else
{
hi = PIo2; lo = zero;
@@ -260,7 +260,7 @@ begin:
if (t <= big) t = - x / y;
/* t is in [big, INF] */
- else
+ else
{ big+small; /* raise inexact flag */
t = zero; }
}
diff --git a/lib/libm/common/sincos.c b/lib/libm/common/sincos.c
index ab88560..fc35618 100644
--- a/lib/libm/common/sincos.c
+++ b/lib/libm/common/sincos.c
@@ -67,7 +67,7 @@ double x;
}
double
-cos(x)
+cos(x)
double x;
{
double a,c,z,s = 1.0;
@@ -83,7 +83,7 @@ double x;
}
else { /* ... in [PI/4,3PI/4] */
a = PIo2-a;
- return a+a*sin__S(a*a); /* rtn. S(PI/2-|x|) */
+ return a+a*sin__S(a*a); /* rtn. S(PI/2-|x|) */
}
}
if (a < small) {
diff --git a/lib/libm/common/tan.c b/lib/libm/common/tan.c
index 61ed5c5..7b49bce 100644
--- a/lib/libm/common/tan.c
+++ b/lib/libm/common/tan.c
@@ -37,7 +37,7 @@ static char sccsid[] = "@(#)tan.c 8.1 (Berkeley) 6/4/93";
#include "trig.h"
double
-tan(x)
+tan(x)
double x;
{
double a,z,ss,cc,c;
diff --git a/lib/libm/common/trig.h b/lib/libm/common/trig.h
index 9e05b0e..e31fb4c 100644
--- a/lib/libm/common/trig.h
+++ b/lib/libm/common/trig.h
@@ -67,7 +67,7 @@ static const double
zero = 0,
one = 1,
negone = -1,
- half = 1.0/2.0,
+ half = 1.0/2.0,
small = 1E-10, /* 1+small**2 == 1; better values for small:
* small = 1.5E-9 for VAX D
* = 1.2E-8 for IEEE Double
@@ -77,27 +77,27 @@ static const double
/* sin__S(x*x) ... re-implemented as a macro
* DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
- * STATIC KERNEL FUNCTION OF SIN(X), COS(X), AND TAN(X)
- * CODED IN C BY K.C. NG, 1/21/85;
+ * STATIC KERNEL FUNCTION OF SIN(X), COS(X), AND TAN(X)
+ * CODED IN C BY K.C. NG, 1/21/85;
* REVISED BY K.C. NG on 8/13/85.
*
* sin(x*k) - x
* RETURN --------------- on [-PI/4,PI/4] , where k=pi/PI, PI is the rounded
- * x
+ * x
* value of pi in machine precision:
*
* Decimal:
- * pi = 3.141592653589793 23846264338327 .....
+ * pi = 3.141592653589793 23846264338327 .....
* 53 bits PI = 3.141592653589793 115997963 ..... ,
- * 56 bits PI = 3.141592653589793 227020265 ..... ,
+ * 56 bits PI = 3.141592653589793 227020265 ..... ,
*
* Hexadecimal:
* pi = 3.243F6A8885A308D313198A2E....
* 53 bits PI = 3.243F6A8885A30 = 2 * 1.921FB54442D18
- * 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2
+ * 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2
*
* Method:
- * 1. Let z=x*x. Create a polynomial approximation to
+ * 1. Let z=x*x. Create a polynomial approximation to
* (sin(k*x)-x)/x = z*(S0 + S1*z^1 + ... + S5*z^5).
* Then
* sin__S(x*x) = z*(S0 + S1*z^1 + ... + S5*z^5)
@@ -105,8 +105,8 @@ static const double
* The coefficient S's are obtained by a special Remez algorithm.
*
* Accuracy:
- * In the absence of rounding error, the approximation has absolute error
- * less than 2**(-61.11) for VAX D FORMAT, 2**(-57.45) for IEEE DOUBLE.
+ * In the absence of rounding error, the approximation has absolute error
+ * less than 2**(-61.11) for VAX D FORMAT, 2**(-57.45) for IEEE DOUBLE.
*
* Constants:
* The hexadecimal values are the intended ones for the following constants.
@@ -149,28 +149,28 @@ ic(S5, 1.5868926979889205164E-10 , -33, 1.5CF61DF672B13)
/* cos__C(x*x) ... re-implemented as a macro
* DOUBLE PRECISION (VAX D FORMAT 56 BITS, IEEE DOUBLE 53 BITS)
- * STATIC KERNEL FUNCTION OF SIN(X), COS(X), AND TAN(X)
- * CODED IN C BY K.C. NG, 1/21/85;
+ * STATIC KERNEL FUNCTION OF SIN(X), COS(X), AND TAN(X)
+ * CODED IN C BY K.C. NG, 1/21/85;
* REVISED BY K.C. NG on 8/13/85.
*
- * x*x
+ * x*x
* RETURN cos(k*x) - 1 + ----- on [-PI/4,PI/4], where k = pi/PI,
- * 2
+ * 2
* PI is the rounded value of pi in machine precision :
*
* Decimal:
- * pi = 3.141592653589793 23846264338327 .....
+ * pi = 3.141592653589793 23846264338327 .....
* 53 bits PI = 3.141592653589793 115997963 ..... ,
- * 56 bits PI = 3.141592653589793 227020265 ..... ,
+ * 56 bits PI = 3.141592653589793 227020265 ..... ,
*
* Hexadecimal:
* pi = 3.243F6A8885A308D313198A2E....
* 53 bits PI = 3.243F6A8885A30 = 2 * 1.921FB54442D18
- * 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2
+ * 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2
*
*
* Method:
- * 1. Let z=x*x. Create a polynomial approximation to
+ * 1. Let z=x*x. Create a polynomial approximation to
* cos(k*x)-1+z/2 = z*z*(C0 + C1*z^1 + ... + C5*z^5)
* then
* cos__C(z) = z*z*(C0 + C1*z^1 + ... + C5*z^5)
@@ -178,9 +178,9 @@ ic(S5, 1.5868926979889205164E-10 , -33, 1.5CF61DF672B13)
* The coefficient C's are obtained by a special Remez algorithm.
*
* Accuracy:
- * In the absence of rounding error, the approximation has absolute error
- * less than 2**(-64) for VAX D FORMAT, 2**(-58.3) for IEEE DOUBLE.
- *
+ * In the absence of rounding error, the approximation has absolute error
+ * less than 2**(-64) for VAX D FORMAT, 2**(-58.3) for IEEE DOUBLE.
+ *
*
* Constants:
* The hexadecimal values are the intended ones for the following constants.
diff --git a/lib/libm/common_source/acos.3 b/lib/libm/common_source/acos.3
index 6f1f386..4613957 100644
--- a/lib/libm/common_source/acos.3
+++ b/lib/libm/common_source/acos.3
@@ -71,16 +71,16 @@ to
.Dv EDOM
and a reserved operand fault is generated.
.Sh SEE ALSO
-.Xr sin 3 ,
-.Xr cos 3 ,
-.Xr tan 3 ,
.Xr asin 3 ,
.Xr atan 3 ,
.Xr atan2 3 ,
-.Xr sinh 3 ,
+.Xr cos 3 ,
.Xr cosh 3 ,
-.Xr tanh 3 ,
.Xr math 3 ,
+.Xr sin 3 ,
+.Xr sinh 3 ,
+.Xr tan 3 ,
+.Xr tanh 3
.Sh STANDARDS
The
.Fn acos
diff --git a/lib/libm/common_source/acosh.3 b/lib/libm/common_source/acosh.3
index 3023da5..3475162 100644
--- a/lib/libm/common_source/acosh.3
+++ b/lib/libm/common_source/acosh.3
@@ -72,8 +72,8 @@ causes a reserved operand fault.
.Xr asinh 3 ,
.Xr atanh 3 ,
.Xr exp 3 ,
-.Xr infnan 3
-.Xr math 3 ,
+.Xr infnan 3 ,
+.Xr math 3
.Sh HISTORY
The
.Fn acosh
diff --git a/lib/libm/common_source/acosh.c b/lib/libm/common_source/acosh.c
index bc16cc7..149e5de 100644
--- a/lib/libm/common_source/acosh.c
+++ b/lib/libm/common_source/acosh.c
@@ -48,10 +48,10 @@ static char sccsid[] = "@(#)acosh.c 8.1 (Berkeley) 6/4/93";
* log1p(x) ...return log(1+x)
*
* Method :
- * Based on
+ * Based on
* acosh(x) = log [ x + sqrt(x*x-1) ]
* we have
- * acosh(x) := log1p(x)+ln2, if (x > 1.0E20); else
+ * acosh(x) := log1p(x)+ln2, if (x > 1.0E20); else
* acosh(x) := log1p( sqrt(x-1) * (sqrt(x-1) + sqrt(x+1)) ) .
* These formulae avoid the over/underflow complication.
*
@@ -60,7 +60,7 @@ static char sccsid[] = "@(#)acosh.c 8.1 (Berkeley) 6/4/93";
* acosh(NaN) is NaN without signal.
*
* Accuracy:
- * acosh(x) returns the exact inverse hyperbolic cosine of x nearly
+ * acosh(x) returns the exact inverse hyperbolic cosine of x nearly
* rounded. In a test run with 512,000 random arguments on a VAX, the
* maximum observed error was 3.30 ulps (units of the last place) at
* x=1.0070493753568216 .
@@ -87,7 +87,7 @@ ic(ln2lo, 1.9082149292705877000E-10,-33, 1.A39EF35793C76)
double acosh(x)
double x;
-{
+{
double t,big=1.E20; /* big+1==big */
#if !defined(vax)&&!defined(tahoe)
@@ -95,7 +95,7 @@ double x;
#endif /* !defined(vax)&&!defined(tahoe) */
/* return log1p(x) + log(2) if x is large */
- if(x>big) {t=log1p(x)+ln2lo; return(t+ln2hi);}
+ if(x>big) {t=log1p(x)+ln2lo; return(t+ln2hi);}
t=sqrt(x-1.0);
return(log1p(t*(t+sqrt(x+1.0))));
diff --git a/lib/libm/common_source/asin.3 b/lib/libm/common_source/asin.3
index 9ca39ca..ebd4671 100644
--- a/lib/libm/common_source/asin.3
+++ b/lib/libm/common_source/asin.3
@@ -78,11 +78,11 @@ a reserved operand fault generated.
.Xr atan2 3 ,
.Xr cos 3 ,
.Xr cosh 3 ,
+.Xr math 3 ,
.Xr sin 3 ,
.Xr sinh 3 ,
.Xr tan 3 ,
-.Xr tanh 3 ,
-.Xr math 3 ,
+.Xr tanh 3
.Sh STANDARDS
The
.Fn asin
diff --git a/lib/libm/common_source/asincos.c b/lib/libm/common_source/asincos.c
index c746b16..12d0e14 100644
--- a/lib/libm/common_source/asincos.c
+++ b/lib/libm/common_source/asincos.c
@@ -45,12 +45,12 @@ static char sccsid[] = "@(#)asincos.c 8.1 (Berkeley) 6/4/93";
* sqrt(x)
*
* Required kernel function:
- * atan2(y,x)
+ * atan2(y,x)
*
- * Method :
- * asin(x) = atan2(x,sqrt(1-x*x)); for better accuracy, 1-x*x is
+ * Method :
+ * asin(x) = atan2(x,sqrt(1-x*x)); for better accuracy, 1-x*x is
* computed as follows
- * 1-x*x if x < 0.5,
+ * 1-x*x if x < 0.5,
* 2*(1-|x|)-(1-|x|)*(1-|x|) if x >= 0.5.
*
* Special cases:
@@ -59,22 +59,22 @@ static char sccsid[] = "@(#)asincos.c 8.1 (Berkeley) 6/4/93";
*
* Accuracy:
* 1) If atan2() uses machine PI, then
- *
+ *
* asin(x) returns (PI/pi) * (the exact arc sine of x) nearly rounded;
* and PI is the exact pi rounded to machine precision (see atan2 for
* details):
*
* in decimal:
- * pi = 3.141592653589793 23846264338327 .....
+ * pi = 3.141592653589793 23846264338327 .....
* 53 bits PI = 3.141592653589793 115997963 ..... ,
- * 56 bits PI = 3.141592653589793 227020265 ..... ,
+ * 56 bits PI = 3.141592653589793 227020265 ..... ,
*
* in hexadecimal:
* pi = 3.243F6A8885A308D313198A2E....
* 53 bits PI = 3.243F6A8885A30 = 2 * 1.921FB54442D18 error=.276ulps
* 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2 error=.206ulps
- *
- * In a test run with more than 200,000 random arguments on a VAX, the
+ *
+ * In a test run with more than 200,000 random arguments on a VAX, the
* maximum observed error in ulps (units in the last place) was
* 2.06 ulps. (comparing against (PI/pi)*(exact asin(x)));
*
@@ -82,7 +82,7 @@ static char sccsid[] = "@(#)asincos.c 8.1 (Berkeley) 6/4/93";
*
* asin(x) returns the exact asin(x) with error below about 2 ulps.
*
- * In a test run with more than 1,024,000 random arguments on a VAX, the
+ * In a test run with more than 1,024,000 random arguments on a VAX, the
* maximum observed error in ulps (units in the last place) was
* 1.99 ulps.
*/
@@ -97,7 +97,7 @@ double x;
s=copysign(x,one);
if(s <= 0.5)
return(atan2(x,sqrt(one-x*x)));
- else
+ else
{ t=one-s; s=t+t; return(atan2(x,sqrt(s-t*t))); }
}
@@ -112,9 +112,9 @@ double x;
* sqrt(x)
*
* Required kernel function:
- * atan2(y,x)
+ * atan2(y,x)
*
- * Method :
+ * Method :
* ________
* / 1 - x
* acos(x) = 2*atan2( / -------- , 1 ) .
@@ -126,22 +126,22 @@ double x;
*
* Accuracy:
* 1) If atan2() uses machine PI, then
- *
+ *
* acos(x) returns (PI/pi) * (the exact arc cosine of x) nearly rounded;
* and PI is the exact pi rounded to machine precision (see atan2 for
* details):
*
* in decimal:
- * pi = 3.141592653589793 23846264338327 .....
+ * pi = 3.141592653589793 23846264338327 .....
* 53 bits PI = 3.141592653589793 115997963 ..... ,
- * 56 bits PI = 3.141592653589793 227020265 ..... ,
+ * 56 bits PI = 3.141592653589793 227020265 ..... ,
*
* in hexadecimal:
* pi = 3.243F6A8885A308D313198A2E....
* 53 bits PI = 3.243F6A8885A30 = 2 * 1.921FB54442D18 error=.276ulps
* 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2 error=.206ulps
- *
- * In a test run with more than 200,000 random arguments on a VAX, the
+ *
+ * In a test run with more than 200,000 random arguments on a VAX, the
* maximum observed error in ulps (units in the last place) was
* 2.07 ulps. (comparing against (PI/pi)*(exact acos(x)));
*
@@ -149,7 +149,7 @@ double x;
*
* acos(x) returns the exact acos(x) with error below about 2 ulps.
*
- * In a test run with more than 1,024,000 random arguments on a VAX, the
+ * In a test run with more than 1,024,000 random arguments on a VAX, the
* maximum observed error in ulps (units in the last place) was
* 2.15 ulps.
*/
diff --git a/lib/libm/common_source/asinh.3 b/lib/libm/common_source/asinh.3
index 3958960..cd0b983 100644
--- a/lib/libm/common_source/asinh.3
+++ b/lib/libm/common_source/asinh.3
@@ -60,8 +60,8 @@ returns the inverse hyperbolic sine of
.Xr acosh 3 ,
.Xr atanh 3 ,
.Xr exp 3 ,
-.Xr infnan 3
-.Xr math 3 ,
+.Xr infnan 3 ,
+.Xr math 3
.Sh HISTORY
The
.Fn asinh
diff --git a/lib/libm/common_source/asinh.c b/lib/libm/common_source/asinh.c
index 5db8d2d..1804145 100644
--- a/lib/libm/common_source/asinh.c
+++ b/lib/libm/common_source/asinh.c
@@ -49,16 +49,16 @@ static char sccsid[] = "@(#)asinh.c 8.1 (Berkeley) 6/4/93";
* log1p(x) ...return log(1+x)
*
* Method :
- * Based on
+ * Based on
* asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
* we have
* asinh(x) := x if 1+x*x=1,
* := sign(x)*(log1p(x)+ln2)) if sqrt(1+x*x)=x, else
- * := sign(x)*log1p(|x| + |x|/(1/|x| + sqrt(1+(1/|x|)^2)) )
+ * := sign(x)*log1p(|x| + |x|/(1/|x| + sqrt(1+(1/|x|)^2)) )
*
* Accuracy:
* asinh(x) returns the exact inverse hyperbolic sine of x nearly rounded.
- * In a test run with 52,000 random arguments on a VAX, the maximum
+ * In a test run with 52,000 random arguments on a VAX, the maximum
* observed error was 1.58 ulps (units in the last place).
*
* Constants:
@@ -82,16 +82,16 @@ ic(ln2lo, 1.9082149292705877000E-10, -33, 1.A39EF35793C76)
double asinh(x)
double x;
-{
+{
double t,s;
const static double small=1.0E-10, /* fl(1+small*small) == 1 */
big =1.0E20, /* fl(1+big) == big */
- one =1.0 ;
+ one =1.0 ;
#if !defined(vax)&&!defined(tahoe)
if(x!=x) return(x); /* x is NaN */
#endif /* !defined(vax)&&!defined(tahoe) */
- if((t=copysign(x,one))>small)
+ if((t=copysign(x,one))>small)
if(t<big) {
s=one/t; return(copysign(log1p(t+t/(s+sqrt(one+s*s))),x)); }
else /* if |x| > big */
diff --git a/lib/libm/common_source/atan.3 b/lib/libm/common_source/atan.3
index 776978e..1119033 100644
--- a/lib/libm/common_source/atan.3
+++ b/lib/libm/common_source/atan.3
@@ -62,11 +62,11 @@ radians.
.Xr atan2 3 ,
.Xr cos 3 ,
.Xr cosh 3 ,
+.Xr math 3 ,
.Xr sin 3 ,
.Xr sinh 3 ,
.Xr tan 3 ,
-.Xr tanh 3 ,
-.Xr math 3 ,
+.Xr tanh 3
.Sh STANDARDS
The
.Fn atan
diff --git a/lib/libm/common_source/atan.c b/lib/libm/common_source/atan.c
index 272c7f1..f29c7d4 100644
--- a/lib/libm/common_source/atan.c
+++ b/lib/libm/common_source/atan.c
@@ -41,32 +41,32 @@ static char sccsid[] = "@(#)atan.c 8.1 (Berkeley) 6/4/93";
* CODED IN C BY K.C. NG, 4/16/85, REVISED ON 6/10/85.
*
* Required kernel function:
- * atan2(y,x)
+ * atan2(y,x)
*
- * Method:
- * atan(x) = atan2(x,1.0).
+ * Method:
+ * atan(x) = atan2(x,1.0).
*
* Special case:
* if x is NaN, return x itself.
*
* Accuracy:
* 1) If atan2() uses machine PI, then
- *
+ *
* atan(x) returns (PI/pi) * (the exact arc tangent of x) nearly rounded;
* and PI is the exact pi rounded to machine precision (see atan2 for
* details):
*
* in decimal:
- * pi = 3.141592653589793 23846264338327 .....
+ * pi = 3.141592653589793 23846264338327 .....
* 53 bits PI = 3.141592653589793 115997963 ..... ,
- * 56 bits PI = 3.141592653589793 227020265 ..... ,
+ * 56 bits PI = 3.141592653589793 227020265 ..... ,
*
* in hexadecimal:
* pi = 3.243F6A8885A308D313198A2E....
* 53 bits PI = 3.243F6A8885A30 = 2 * 1.921FB54442D18 error=.276ulps
* 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2 error=.206ulps
- *
- * In a test run with more than 200,000 random arguments on a VAX, the
+ *
+ * In a test run with more than 200,000 random arguments on a VAX, the
* maximum observed error in ulps (units in the last place) was
* 0.86 ulps. (comparing against (PI/pi)*(exact atan(x))).
*
@@ -74,7 +74,7 @@ static char sccsid[] = "@(#)atan.c 8.1 (Berkeley) 6/4/93";
*
* atan(x) returns the exact atan(x) with error below about 2 ulps.
*
- * In a test run with more than 1,024,000 random arguments on a VAX, the
+ * In a test run with more than 1,024,000 random arguments on a VAX, the
* maximum observed error in ulps (units in the last place) was
* 0.85 ulps.
*/
diff --git a/lib/libm/common_source/atan2.3 b/lib/libm/common_source/atan2.3
index a5eb7ac..3323e01 100644
--- a/lib/libm/common_source/atan2.3
+++ b/lib/libm/common_source/atan2.3
@@ -30,6 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)atan2.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
.\"
.Dd June 4, 1993
.Dt ATAN2 3
@@ -176,11 +177,11 @@ r := \(sr(x\(**x+y\(**y);\0\0if r = 0 then x := copysign(1,x);
.Xr atan 3 ,
.Xr cos 3 ,
.Xr cosh 3 ,
+.Xr math 3 ,
.Xr sin 3 ,
.Xr sinh 3 ,
.Xr tan 3 ,
-.Xr tanh 3 ,
-.Xr math 3 ,
+.Xr tanh 3
.Sh STANDARDS
The
.Fn atan2
diff --git a/lib/libm/common_source/atanh.3 b/lib/libm/common_source/atanh.3
index 6f08536..49d669f 100644
--- a/lib/libm/common_source/atanh.3
+++ b/lib/libm/common_source/atanh.3
@@ -74,8 +74,8 @@ a reserved operand fault is generated.
.Xr acosh 3 ,
.Xr asinh 3 ,
.Xr exp 3 ,
-.Xr infnan 3
-.Xr math 3 ,
+.Xr infnan 3 ,
+.Xr math 3
.Sh HISTORY
The
.Fn atanh
diff --git a/lib/libm/common_source/atanh.c b/lib/libm/common_source/atanh.c
index 89cb61c..e5cdadd 100644
--- a/lib/libm/common_source/atanh.c
+++ b/lib/libm/common_source/atanh.c
@@ -38,14 +38,14 @@ static char sccsid[] = "@(#)atanh.c 8.1 (Berkeley) 6/4/93";
/* ATANH(X)
* RETURN THE HYPERBOLIC ARC TANGENT OF X
* DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
- * CODED IN C BY K.C. NG, 1/8/85;
+ * CODED IN C BY K.C. NG, 1/8/85;
* REVISED BY K.C. NG on 2/7/85, 3/7/85, 8/18/85.
*
* Required kernel function:
* log1p(x) ...return log(1+x)
*
* Method :
- * Return
+ * Return
* 1 2x x
* atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
* 2 1 - x 1 - x
diff --git a/lib/libm/common_source/ceil.3 b/lib/libm/common_source/ceil.3
index 4bc02ba..080f30e 100644
--- a/lib/libm/common_source/ceil.3
+++ b/lib/libm/common_source/ceil.3
@@ -36,7 +36,7 @@
.Os
.Sh NAME
.Nm ceil
-.Nd smallest integral value not greater than x
+.Nd smallest integral value greather than or equal to x
.Sh SYNOPSIS
.Fd #include <math.h>
.Ft double
@@ -44,7 +44,7 @@
.Sh DESCRIPTION
The
.Fn ceil
-function computes the smallest integral value not less than
+function computes the smallest integral value greater than or equal to
.Fa x .
.Sh RETURN VALUES
The
@@ -55,9 +55,9 @@ expressed as a double.
.Xr abs 3 ,
.Xr fabs 3 ,
.Xr floor 3 ,
-.Xr rint 3 ,
.Xr ieee 3 ,
-.Xr math.3
+.Xr math 3 ,
+.Xr rint 3
.Sh STANDARDS
The
.Fn ceil
diff --git a/lib/libm/common_source/cos.3 b/lib/libm/common_source/cos.3
index d1051ed..d279d38 100644
--- a/lib/libm/common_source/cos.3
+++ b/lib/libm/common_source/cos.3
@@ -56,16 +56,16 @@ The
.Fn cos
function returns the cosine value.
.Sh SEE ALSO
-.Xr sin 3 ,
-.Xr tan 3 ,
-.Xr asin 3 ,
.Xr acos 3 ,
+.Xr asin 3 ,
.Xr atan 3 ,
.Xr atan2 3 ,
-.Xr sinh 3 ,
.Xr cosh 3 ,
-.Xr tanh 3 ,
.Xr math 3 ,
+.Xr sin 3 ,
+.Xr sinh 3 ,
+.Xr tan 3 ,
+.Xr tanh 3
.Sh STANDARDS
The
.Fn acos
diff --git a/lib/libm/common_source/cosh.3 b/lib/libm/common_source/cosh.3
index 4eabf55..f88c848 100644
--- a/lib/libm/common_source/cosh.3
+++ b/lib/libm/common_source/cosh.3
@@ -62,11 +62,11 @@ is set to
.Xr atan 3 ,
.Xr atan2 3 ,
.Xr cos 3 ,
+.Xr math 3 ,
.Xr sin 3 ,
.Xr sinh 3 ,
.Xr tan 3 ,
-.Xr tanh 3 ,
-.Xr math 3 ,
+.Xr tanh 3
.Sh STANDARDS
The
.Fn cosh
diff --git a/lib/libm/common_source/cosh.c b/lib/libm/common_source/cosh.c
index e2b3073..e8d3519 100644
--- a/lib/libm/common_source/cosh.c
+++ b/lib/libm/common_source/cosh.c
@@ -38,7 +38,7 @@ static char sccsid[] = "@(#)cosh.c 8.1 (Berkeley) 6/4/93";
/* COSH(X)
* RETURN THE HYPERBOLIC COSINE OF X
* DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
- * CODED IN C BY K.C. NG, 1/8/85;
+ * CODED IN C BY K.C. NG, 1/8/85;
* REVISED BY K.C. NG on 2/8/85, 2/23/85, 3/7/85, 3/29/85, 4/16/85.
*
* Required system supported functions :
@@ -46,20 +46,20 @@ static char sccsid[] = "@(#)cosh.c 8.1 (Berkeley) 6/4/93";
* scalb(x,N)
*
* Required kernel function:
- * exp(x)
+ * exp(x)
* exp__E(x,c) ...return exp(x+c)-1-x for |x|<0.3465
*
* Method :
- * 1. Replace x by |x|.
- * 2.
- * [ exp(x) - 1 ]^2
+ * 1. Replace x by |x|.
+ * 2.
+ * [ exp(x) - 1 ]^2
* 0 <= x <= 0.3465 : cosh(x) := 1 + -------------------
* 2*exp(x)
*
* exp(x) + 1/exp(x)
* 0.3465 <= x <= 22 : cosh(x) := -------------------
* 2
- * 22 <= x <= lnovfl : cosh(x) := exp(x)/2
+ * 22 <= x <= lnovfl : cosh(x) := exp(x)/2
* lnovfl <= x <= lnovfl+log(2)
* : cosh(x) := exp(x)/2 (avoid overflow)
* log(2)+lnovfl < x < INF: overflow to INF
@@ -106,7 +106,7 @@ static max = 1023 ;
double cosh(x)
double x;
-{
+{
static const double half=1.0/2.0,
one=1.0, small=1.0E-18; /* fl(1+small)==1 */
double t;
@@ -115,19 +115,19 @@ double x;
if(x!=x) return(x); /* x is NaN */
#endif /* !defined(vax)&&!defined(tahoe) */
if((x=copysign(x,one)) <= 22)
- if(x<0.3465)
+ if(x<0.3465)
if(x<small) return(one+x);
else {t=x+__exp__E(x,0.0);x=t+t; return(one+t*t/(2.0+x)); }
else /* for x lies in [0.3465,22] */
{ t=exp(x); return((t+one/t)*half); }
- if( lnovfl <= x && x <= (lnovfl+0.7))
- /* for x lies in [lnovfl, lnovfl+ln2], decrease x by ln(2^(max+1))
- * and return 2^max*exp(x) to avoid unnecessary overflow
+ if( lnovfl <= x && x <= (lnovfl+0.7))
+ /* for x lies in [lnovfl, lnovfl+ln2], decrease x by ln(2^(max+1))
+ * and return 2^max*exp(x) to avoid unnecessary overflow
*/
- return(scalb(exp((x-mln2hi)-mln2lo), max));
+ return(scalb(exp((x-mln2hi)-mln2lo), max));
- else
+ else
return(exp(x)*half); /* for large x, cosh(x)=exp(x)/2 */
}
diff --git a/lib/libm/common_source/erf.c b/lib/libm/common_source/erf.c
index 308f1a9..ba0c006 100644
--- a/lib/libm/common_source/erf.c
+++ b/lib/libm/common_source/erf.c
@@ -68,13 +68,13 @@ static char sccsid[] = "@(#)erf.c 8.1 (Berkeley) 6/4/93";
* erfc(x) = 1 - erf(x) if x<=0.25
* = 0.5 + ((0.5-x)-x*P) if x in [0.25,0.84375]
* where
- * 2 2 4 20
+ * 2 2 4 20
* P = P(x ) = (p0 + p1 * x + p2 * x + ... + p10 * x )
* is an approximation to (erf(x)-x)/x with precision
*
* -56.45
* | P - (erf(x)-x)/x | <= 2
- *
+ *
*
* Remark. The formula is derived by noting
* erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
@@ -96,7 +96,7 @@ static char sccsid[] = "@(#)erf.c 8.1 (Berkeley) 6/4/93";
* That is, we use rational approximation to approximate
* erf(1+s) - (c = (single)0.84506291151)
* Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
- * where
+ * where
* P1(s) = degree 6 poly in s
* Q1(s) = degree 6 poly in s
*
@@ -105,7 +105,7 @@ static char sccsid[] = "@(#)erf.c 8.1 (Berkeley) 6/4/93";
* erfc(x) = (1/x)exp(-x*x-(.5*log(pi) -.5z + R(z)/S(z))
*
* Where z = 1/(x*x), R is degree 9, and S is degree 3;
- *
+ *
* 5. For x in [4,28]
* erf(x) = 1.0 - tiny
* erfc(x) = (1/x)exp(-x*x-(.5*log(pi)+eps + zP(z))
@@ -139,7 +139,7 @@ static char sccsid[] = "@(#)erf.c 8.1 (Berkeley) 6/4/93";
*
* 7. Special cases:
* erf(0) = 0, erf(inf) = 1, erf(-inf) = -1,
- * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
+ * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
* erfc/erf(NaN) is NaN
*/
@@ -181,7 +181,7 @@ p8 = 1.640186161764254363152286358441771740838e-0006,
p9 = -1.571599331700515057841960987689515895479e-0007,
p10= 1.073087585213621540635426191486561494058e-0008;
/*
- * Coefficients for approximation to erf in [0.84375,1.25]
+ * Coefficients for approximation to erf in [0.84375,1.25]
*/
static double
pa0 = -2.362118560752659485957248365514511540287e-0003,
@@ -319,7 +319,7 @@ double erf(x)
return (z-one);
}
-double erfc(x)
+double erfc(x)
double x;
{
double R,S,P,Q,s,ax,y,z,r,fabs(),__exp__D();
@@ -352,7 +352,7 @@ double erfc(x)
P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
if (x>=0) {
- z = one-c; return z - P/Q;
+ z = one-c; return z - P/Q;
} else {
z = c+P/Q; return one+z;
}
diff --git a/lib/libm/common_source/exp.3 b/lib/libm/common_source/exp.3
index 1bdf060..be7677c 100644
--- a/lib/libm/common_source/exp.3
+++ b/lib/libm/common_source/exp.3
@@ -260,8 +260,8 @@ then \*(Na**0 = 1 too because x**0 = 1 for all finite
and infinite x, i.e., independently of x.
.El
.Sh SEE ALSO
-.Xr math 3 ,
-.Xr infnan 3
+.Xr infnan 3 ,
+.Xr math 3
.Sh HISTORY
A
.Fn exp ,
diff --git a/lib/libm/common_source/exp.c b/lib/libm/common_source/exp.c
index 9b4f045..fa6ea75 100644
--- a/lib/libm/common_source/exp.c
+++ b/lib/libm/common_source/exp.c
@@ -38,21 +38,21 @@ static char sccsid[] = "@(#)exp.c 8.1 (Berkeley) 6/4/93";
/* EXP(X)
* RETURN THE EXPONENTIAL OF X
* DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS)
- * CODED IN C BY K.C. NG, 1/19/85;
+ * CODED IN C BY K.C. NG, 1/19/85;
* REVISED BY K.C. NG on 2/6/85, 2/15/85, 3/7/85, 3/24/85, 4/16/85, 6/14/86.
*
* Required system supported functions:
- * scalb(x,n)
- * copysign(x,y)
+ * scalb(x,n)
+ * copysign(x,y)
* finite(x)
*
* Method:
- * 1. Argument Reduction: given the input x, find r and integer k such
+ * 1. Argument Reduction: given the input x, find r and integer k such
* that
- * x = k*ln2 + r, |r| <= 0.5*ln2 .
+ * x = k*ln2 + r, |r| <= 0.5*ln2 .
* r will be represented as r := z+c for better accuracy.
*
- * 2. Compute exp(r) by
+ * 2. Compute exp(r) by
*
* exp(r) = 1 + r + r*R1/(2-R1),
* where
@@ -143,7 +143,7 @@ double x;
}
/* end of x > lntiny */
- else
+ else
/* exp(-big#) underflows to zero */
if(finite(x)) return(scalb(1.0,-5000));
@@ -152,7 +152,7 @@ double x;
}
/* end of x < lnhuge */
- else
+ else
/* exp(INF) is INF, exp(+big#) overflows to INF */
return( finite(x) ? scalb(1.0,5000) : x);
}
@@ -188,7 +188,7 @@ double x, c;
}
/* end of x > lntiny */
- else
+ else
/* exp(-big#) underflows to zero */
if(finite(x)) return(scalb(1.0,-5000));
@@ -197,7 +197,7 @@ double x, c;
}
/* end of x < lnhuge */
- else
+ else
/* exp(INF) is INF, exp(+big#) overflows to INF */
return( finite(x) ? scalb(1.0,5000) : x);
}
diff --git a/lib/libm/common_source/exp__E.c b/lib/libm/common_source/exp__E.c
index ab97247..16ec4cbb 100644
--- a/lib/libm/common_source/exp__E.c
+++ b/lib/libm/common_source/exp__E.c
@@ -41,7 +41,7 @@ static char sccsid[] = "@(#)exp__E.c 8.1 (Berkeley) 6/4/93";
* exp__E RETURNS
*
* / exp(x+c) - 1 - x , 1E-19 < |x| < .3465736
- * exp__E(x,c) = |
+ * exp__E(x,c) = |
* \ 0 , |x| < 1E-19.
*
* DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS)
@@ -50,12 +50,12 @@ static char sccsid[] = "@(#)exp__E.c 8.1 (Berkeley) 6/4/93";
* REVISED BY K.C. NG on 3/16/85, 4/16/85.
*
* Required system supported function:
- * copysign(x,y)
+ * copysign(x,y)
*
* Method:
* 1. Rational approximation. Let r=x+c.
* Based on
- * 2 * sinh(r/2)
+ * 2 * sinh(r/2)
* exp(r) - 1 = ---------------------- ,
* cosh(r/2) - sinh(r/2)
* exp__E(r) is computed using
@@ -76,7 +76,7 @@ static char sccsid[] = "@(#)exp__E.c 8.1 (Berkeley) 6/4/93";
* Approximation error:
*
* | exp(x) - 1 | 2**(-57), (IEEE double)
- * | ------------ - (exp__E(x,0)+x)/x | <=
+ * | ------------ - (exp__E(x,0)+x)/x | <=
* | x | 2**(-69). (VAX D)
*
* Constants:
@@ -120,7 +120,7 @@ double x,c;
#else /* defined(vax)||defined(tahoe) */
q = z*( q1 +z* q2 );
#endif /* defined(vax)||defined(tahoe) */
- xp= x*p ;
+ xp= x*p ;
xh= x*half ;
w = xh-(q-xp) ;
p = p+p;
diff --git a/lib/libm/common_source/expm1.c b/lib/libm/common_source/expm1.c
index 760d2be..8a84f14 100644
--- a/lib/libm/common_source/expm1.c
+++ b/lib/libm/common_source/expm1.c
@@ -38,36 +38,36 @@ static char sccsid[] = "@(#)expm1.c 8.1 (Berkeley) 6/4/93";
/* EXPM1(X)
* RETURN THE EXPONENTIAL OF X MINUS ONE
* DOUBLE PRECISION (IEEE 53 BITS, VAX D FORMAT 56 BITS)
- * CODED IN C BY K.C. NG, 1/19/85;
+ * CODED IN C BY K.C. NG, 1/19/85;
* REVISED BY K.C. NG on 2/6/85, 3/7/85, 3/21/85, 4/16/85.
*
* Required system supported functions:
- * scalb(x,n)
- * copysign(x,y)
+ * scalb(x,n)
+ * copysign(x,y)
* finite(x)
*
* Kernel function:
* exp__E(x,c)
*
* Method:
- * 1. Argument Reduction: given the input x, find r and integer k such
+ * 1. Argument Reduction: given the input x, find r and integer k such
* that
- * x = k*ln2 + r, |r| <= 0.5*ln2 .
+ * x = k*ln2 + r, |r| <= 0.5*ln2 .
* r will be represented as r := z+c for better accuracy.
*
- * 2. Compute EXPM1(r)=exp(r)-1 by
+ * 2. Compute EXPM1(r)=exp(r)-1 by
*
* EXPM1(r=z+c) := z + exp__E(z,c)
*
* 3. EXPM1(x) = 2^k * ( EXPM1(r) + 1-2^-k ).
*
- * Remarks:
+ * Remarks:
* 1. When k=1 and z < -0.25, we use the following formula for
* better accuracy:
* EXPM1(x) = 2 * ( (z+0.5) + exp__E(z,c) )
* 2. To avoid rounding error in 1-2^-k where k is large, we use
* EXPM1(x) = 2^k * { [z+(exp__E(z,c)-2^-k )] + 1 }
- * when k>56.
+ * when k>56.
*
* Special cases:
* EXPM1(INF) is INF, EXPM1(NaN) is NaN;
@@ -108,7 +108,7 @@ ic(invln2, 1.4426950408889633870E0, 0, 1.71547652B82FE)
double expm1(x)
double x;
{
- const static double one=1.0, half=1.0/2.0;
+ const static double one=1.0, half=1.0/2.0;
double z,hi,lo,c;
int k;
#if defined(vax)||defined(tahoe)
@@ -126,13 +126,13 @@ double x;
/* argument reduction : x - k*ln2 */
k= invln2 *x+copysign(0.5,x); /* k=NINT(x/ln2) */
- hi=x-k*ln2hi ;
+ hi=x-k*ln2hi ;
z=hi-(lo=k*ln2lo);
c=(hi-z)-lo;
if(k==0) return(z+__exp__E(z,c));
if(k==1)
- if(z< -0.25)
+ if(z< -0.25)
{x=z+half;x +=__exp__E(z,c); return(x+x);}
else
{z+=__exp__E(z,c); x=half+z; return(x+x);}
@@ -143,17 +143,17 @@ double x;
{ x=one-scalb(one,-k); z += __exp__E(z,c);}
else if(k<100)
{ x = __exp__E(z,c)-scalb(one,-k); x+=z; z=one;}
- else
+ else
{ x = __exp__E(z,c)+z; z=one;}
- return (scalb(x+z,k));
+ return (scalb(x+z,k));
}
}
/* end of x > lnunfl */
- else
+ else
/* expm1(-big#) rounded to -1 (inexact) */
- if(finite(x))
+ if(finite(x))
{ ln2hi+ln2lo; return(-one);}
/* expm1(-INF) is -1 */
@@ -161,7 +161,7 @@ double x;
}
/* end of x < lnhuge */
- else
+ else
/* expm1(INF) is INF, expm1(+big#) overflows to INF */
return( finite(x) ? scalb(one,5000) : x);
}
diff --git a/lib/libm/common_source/fabs.3 b/lib/libm/common_source/fabs.3
index e4cf0f6..82704f1 100644
--- a/lib/libm/common_source/fabs.3
+++ b/lib/libm/common_source/fabs.3
@@ -56,9 +56,9 @@ function returns the absolute value of
.Xr abs 3 ,
.Xr ceil 3 ,
.Xr floor 3 ,
-.Xr rint 3 ,
.Xr ieee 3 ,
-.Xr math.3
+.Xr math 3 ,
+.Xr rint 3
.Sh STANDARDS
The
.Fn fabs
diff --git a/lib/libm/common_source/floor.3 b/lib/libm/common_source/floor.3
index 2df55f9..2aed79d 100644
--- a/lib/libm/common_source/floor.3
+++ b/lib/libm/common_source/floor.3
@@ -36,7 +36,7 @@
.Os
.Sh NAME
.Nm floor
-.Nd largest integral value not greater than x
+.Nd largest integral value less than or equal to x
.Sh SYNOPSIS
.Fd #include <math.h>
.Ft double
@@ -44,7 +44,7 @@
.Sh DESCRIPTION
The
.Fn floor
-function computes the largest integral value not greater than
+function computes the largest integral value less than or equal to
.Fa x .
.Sh RETURN VALUES
The
@@ -53,11 +53,11 @@ function returns the largest integral value
expressed as a double.
.Sh SEE ALSO
.Xr abs 3 ,
-.Xr ieee 3 ,
.Xr fabs 3 ,
.Xr floor 3 ,
-.Xr rint 3 ,
-.Xr math 3
+.Xr ieee 3 ,
+.Xr math 3 ,
+.Xr rint 3
.Sh STANDARDS
The
.Fn floor
diff --git a/lib/libm/common_source/ieee.3 b/lib/libm/common_source/ieee.3
index fd44617..432f7a0 100644
--- a/lib/libm/common_source/ieee.3
+++ b/lib/libm/common_source/ieee.3
@@ -192,8 +192,8 @@ to
.Dv ERANGE .
.Sh SEE ALSO
.Xr floor 3 ,
-.Xr math 3 ,
-.Xr infnan 3
+.Xr infnan 3 ,
+.Xr math 3
.Sh HISTORY
The
.Nm ieee
diff --git a/lib/libm/common_source/infnan.3 b/lib/libm/common_source/infnan.3
index 6a94bf6..6da38fd8 100644
--- a/lib/libm/common_source/infnan.3
+++ b/lib/libm/common_source/infnan.3
@@ -158,8 +158,8 @@ int iarg ;
}
.Ed
.Sh SEE ALSO
-.Xr math 3 ,
.Xr intro 2 ,
+.Xr math 3 ,
.Xr signal 3 .
.Pp
.Dv ERANGE
diff --git a/lib/libm/common_source/j0.3 b/lib/libm/common_source/j0.3
index cd4ac12..3a7d3fb 100644
--- a/lib/libm/common_source/j0.3
+++ b/lib/libm/common_source/j0.3
@@ -118,8 +118,8 @@ is set to
.Er EDOM
and a reserve operand fault is generated.
.Sh SEE ALSO
-.Xr math 3 ,
-.Xr infnan 3
+.Xr infnan 3 ,
+.Xr math 3
.Sh HISTORY
A set of these functions
function appeared in
diff --git a/lib/libm/common_source/j0.c b/lib/libm/common_source/j0.c
index a9b28b3..684fb4d 100644
--- a/lib/libm/common_source/j0.c
+++ b/lib/libm/common_source/j0.c
@@ -46,18 +46,18 @@ static char sccsid[] = "@(#)j0.c 8.2 (Berkeley) 11/30/93";
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
+ * software is freely granted, provided that this notice
* is preserved.
* ====================================================
*
* ******************* WARNING ********************
* This is an alpha version of SunPro's FDLIBM (Freely
- * Distributable Math Library) for IEEE double precision
+ * Distributable Math Library) for IEEE double precision
* arithmetic. FDLIBM is a basic math library written
- * in C that runs on machines that conform to IEEE
- * Standard 754/854. This alpha version is distributed
- * for testing purpose. Those who use this software
- * should report any bugs to
+ * in C that runs on machines that conform to IEEE
+ * Standard 754/854. This alpha version is distributed
+ * for testing purpose. Those who use this software
+ * should report any bugs to
*
* fdlibm-comments@sunpro.eng.sun.com
*
@@ -84,20 +84,20 @@ static char sccsid[] = "@(#)j0.c 8.2 (Berkeley) 11/30/93";
* (To avoid cancellation, use
* sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
* to compute the worse one.)
- *
+ *
* 3 Special cases
* j0(nan)= nan
* j0(0) = 1
* j0(inf) = 0
- *
+ *
* Method -- y0(x):
* 1. For x<2.
- * Since
+ * Since
* y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...)
* therefore y0(x)-2/pi*j0(x)*ln(x) is an even function.
* We use the following function to approximate y0,
* y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2
- * where
+ * where
* U(z) = u0 + u1*z + ... + u6*z^6
* V(z) = 1 + v1*z + ... + v4*z^4
* with absolute approximation error bounded by 2**-72.
@@ -121,7 +121,7 @@ static char sccsid[] = "@(#)j0.c 8.2 (Berkeley) 11/30/93";
static double pzero __P((double)), qzero __P((double));
-static double
+static double
huge = 1e300,
zero = 0.0,
one = 1.0,
@@ -138,7 +138,7 @@ s03 = 5.135465502073181376284426245689510134134e-0007,
s04 = 1.166140033337900097836930825478674320464e-0009;
double
-j0(x)
+j0(x)
double x;
{
double z, s,c,ss,cc,r,u,v;
@@ -201,7 +201,7 @@ v03 = 2.591508518404578033173189144579208685163e-0007,
v04 = 4.411103113326754838596529339004302243157e-0010;
double
-y0(x)
+y0(x)
double x;
{
double z, s, c, ss, cc, u, v;
@@ -345,7 +345,7 @@ static double pzero(x)
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
return one+ r/s;
}
-
+
/* For x >= 8, the asymptotic expansions of qzero is
* -1/8 s + 75/1024 s^3 - ..., where s = 1/x.
diff --git a/lib/libm/common_source/j1.c b/lib/libm/common_source/j1.c
index 71602aa..e8ca43a 100644
--- a/lib/libm/common_source/j1.c
+++ b/lib/libm/common_source/j1.c
@@ -46,18 +46,18 @@ static char sccsid[] = "@(#)j1.c 8.2 (Berkeley) 11/30/93";
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
+ * software is freely granted, provided that this notice
* is preserved.
* ====================================================
*
* ******************* WARNING ********************
* This is an alpha version of SunPro's FDLIBM (Freely
- * Distributable Math Library) for IEEE double precision
+ * Distributable Math Library) for IEEE double precision
* arithmetic. FDLIBM is a basic math library written
- * in C that runs on machines that conform to IEEE
- * Standard 754/854. This alpha version is distributed
- * for testing purpose. Those who use this software
- * should report any bugs to
+ * in C that runs on machines that conform to IEEE
+ * Standard 754/854. This alpha version is distributed
+ * for testing purpose. Those who use this software
+ * should report any bugs to
*
* fdlibm-comments@sunpro.eng.sun.com
*
@@ -85,16 +85,16 @@ static char sccsid[] = "@(#)j1.c 8.2 (Berkeley) 11/30/93";
* (To avoid cancellation, use
* sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
* to compute the worse one.)
- *
+ *
* 3 Special cases
* j1(nan)= nan
* j1(0) = 0
* j1(inf) = 0
- *
+ *
* Method -- y1(x):
- * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN
+ * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN
* 2. For x<2.
- * Since
+ * Since
* y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...)
* therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function.
* We use the following function to approximate y1,
@@ -122,7 +122,7 @@ static char sccsid[] = "@(#)j1.c 8.2 (Berkeley) 11/30/93";
static double pone(), qone();
-static double
+static double
huge = 1e300,
zero = 0.0,
one = 1.0,
@@ -142,7 +142,7 @@ s05 = 1.235422744261379203512624973117299248281e-0011;
#define two_129 6.80564733841876926e+038 /* 2^129 */
#define two_m54 5.55111512312578270e-017 /* 2^-54 */
-double j1(x)
+double j1(x)
double x;
{
double z, s,c,ss,cc,r,u,v,y;
@@ -205,7 +205,7 @@ static double v0[5] = {
1.665592462079920695971450872592458916421e-0011,
};
-double y1(x)
+double y1(x)
double x;
{
double z, s, c, ss, cc, u, v;
@@ -254,10 +254,10 @@ double y1(x)
z = invsqrtpi*(u*ss+v*cc)/sqrt(x);
}
return z;
- }
+ }
if (x <= two_m54) { /* x < 2**-54 */
return (-tpi/x);
- }
+ }
z = x*x;
u = u0[0]+z*(u0[1]+z*(u0[2]+z*(u0[3]+z*u0[4])));
v = one+z*(v0[0]+z*(v0[1]+z*(v0[2]+z*(v0[3]+z*v0[4]))));
@@ -351,7 +351,7 @@ static double pone(x)
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
return (one + r/s);
}
-
+
/* For x >= 8, the asymptotic expansions of qone is
* 3/8 s - 105/1024 s^3 - ..., where s = 1/x.
diff --git a/lib/libm/common_source/jn.c b/lib/libm/common_source/jn.c
index 85a5401..28d9687 100644
--- a/lib/libm/common_source/jn.c
+++ b/lib/libm/common_source/jn.c
@@ -46,18 +46,18 @@ static char sccsid[] = "@(#)jn.c 8.2 (Berkeley) 11/30/93";
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
+ * software is freely granted, provided that this notice
* is preserved.
* ====================================================
*
* ******************* WARNING ********************
* This is an alpha version of SunPro's FDLIBM (Freely
- * Distributable Math Library) for IEEE double precision
+ * Distributable Math Library) for IEEE double precision
* arithmetic. FDLIBM is a basic math library written
- * in C that runs on machines that conform to IEEE
- * Standard 754/854. This alpha version is distributed
- * for testing purpose. Those who use this software
- * should report any bugs to
+ * in C that runs on machines that conform to IEEE
+ * Standard 754/854. This alpha version is distributed
+ * for testing purpose. Those who use this software
+ * should report any bugs to
*
* fdlibm-comments@sunpro.eng.sun.com
*
@@ -69,7 +69,7 @@ static char sccsid[] = "@(#)jn.c 8.2 (Berkeley) 11/30/93";
* jn(int n, double x), yn(int n, double x)
* floating point Bessel's function of the 1st and 2nd kind
* of order n
- *
+ *
* Special cases:
* y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal;
* y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
@@ -88,7 +88,7 @@ static char sccsid[] = "@(#)jn.c 8.2 (Berkeley) 11/30/93";
* yn(n,x) is similar in all respects, except
* that forward recursion is used for all
* values of n>1.
- *
+ *
*/
#include <math.h>
@@ -120,7 +120,7 @@ double jn(n,x)
*/
/* if J(n,NaN) is NaN */
if (_IEEE && isnan(x)) return x+x;
- if (n<0){
+ if (n<0){
n = -n;
x = -x;
}
@@ -134,10 +134,10 @@ double jn(n,x)
/* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
if (_IEEE && x >= 8.148143905337944345e+090) {
/* x >= 2**302 */
- /* (x >> n**2)
+ /* (x >> n**2)
* Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
* Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
- * Let s=sin(x), c=cos(x),
+ * Let s=sin(x), c=cos(x),
* xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
*
* n sin(xn)*sqt2 cos(xn)*sqt2
@@ -154,7 +154,7 @@ double jn(n,x)
case 3: temp = cos(x)-sin(x); break;
}
b = invsqrtpi*temp/sqrt(x);
- } else {
+ } else {
a = j0(x);
b = j1(x);
for(i=1;i<n;i++){
@@ -165,7 +165,7 @@ double jn(n,x)
}
} else {
if (x < 1.86264514923095703125e-009) { /* x < 2**-29 */
- /* x is tiny, return the first Taylor expansion of J(n,x)
+ /* x is tiny, return the first Taylor expansion of J(n,x)
* J(n,x) = 1/n!*(x/2)^n - ...
*/
if (n > 33) /* underflow */
@@ -180,14 +180,14 @@ double jn(n,x)
}
} else {
/* use backward recurrence */
- /* x x^2 x^2
+ /* x x^2 x^2
* J(n,x)/J(n-1,x) = ---- ------ ------ .....
* 2n - 2(n+1) - 2(n+2)
*
- * 1 1 1
+ * 1 1 1
* (for large x) = ---- ------ ------ .....
* 2n 2(n+1) 2(n+2)
- * -- - ------ - ------ -
+ * -- - ------ - ------ -
* x x x
*
* Let w = 2n/x and h=2/x, then the above quotient
@@ -203,9 +203,9 @@ double jn(n,x)
* To determine how many terms needed, let
* Q(0) = w, Q(1) = w(w+h) - 1,
* Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
- * When Q(k) > 1e4 good for single
- * When Q(k) > 1e9 good for double
- * When Q(k) > 1e17 good for quadruple
+ * When Q(k) > 1e4 good for single
+ * When Q(k) > 1e9 good for double
+ * When Q(k) > 1e17 good for quadruple
*/
/* determine k */
double t,v;
@@ -254,7 +254,7 @@ double jn(n,x)
}
return ((sgn == 1) ? -b : b);
}
-double yn(n,x)
+double yn(n,x)
int n; double x;
{
int i, sign;
@@ -275,10 +275,10 @@ double yn(n,x)
if (n == 0) return(y0(x));
if (n == 1) return(sign*y1(x));
if(_IEEE && x >= 8.148143905337944345e+090) { /* x > 2**302 */
- /* (x >> n**2)
+ /* (x >> n**2)
* Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
* Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
- * Let s=sin(x), c=cos(x),
+ * Let s=sin(x), c=cos(x),
* xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
*
* n sin(xn)*sqt2 cos(xn)*sqt2
diff --git a/lib/libm/common_source/lgamma.3 b/lib/libm/common_source/lgamma.3
index 92f68ab..92f4ba6 100644
--- a/lib/libm/common_source/lgamma.3
+++ b/lib/libm/common_source/lgamma.3
@@ -105,8 +105,8 @@ For large non-integer negative values,
.Fn gamma
will underflow.
.Sh SEE ALSO
-.Xr math 3 ,
-.Xr infnan 3
+.Xr infnan 3 ,
+.Xr math 3
.Sh HISTORY
The
.Nm lgamma
diff --git a/lib/libm/common_source/log.c b/lib/libm/common_source/log.c
index ae18672..908b8544 100644
--- a/lib/libm/common_source/log.c
+++ b/lib/libm/common_source/log.c
@@ -391,7 +391,7 @@ log(x) double x;
return (x+x);
else
return (infnan(ERANGE));
-
+
/* Argument reduction: 1 <= g < 2; x/2^m = g; */
/* y = F*(1 + f/F) for |f| <= 2^-8 */
diff --git a/lib/libm/common_source/log10.c b/lib/libm/common_source/log10.c
index d2617cc..75205cd 100644
--- a/lib/libm/common_source/log10.c
+++ b/lib/libm/common_source/log10.c
@@ -38,9 +38,9 @@ static char sccsid[] = "@(#)log10.c 8.1 (Berkeley) 6/4/93";
/* LOG10(X)
* RETURN THE BASE 10 LOGARITHM OF x
* DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
- * CODED IN C BY K.C. NG, 1/20/85;
+ * CODED IN C BY K.C. NG, 1/20/85;
* REVISED BY K.C. NG on 1/23/85, 3/7/85, 4/16/85.
- *
+ *
* Required kernel function:
* log(x)
*
@@ -52,12 +52,12 @@ static char sccsid[] = "@(#)log10.c 8.1 (Berkeley) 6/4/93";
* Note:
* [log(10)] rounded to 56 bits has error .0895 ulps,
* [1/log(10)] rounded to 53 bits has error .198 ulps;
- * therefore, for better accuracy, in VAX D format, we divide
- * log(x) by log(10), but in IEEE Double format, we multiply
+ * therefore, for better accuracy, in VAX D format, we divide
+ * log(x) by log(10), but in IEEE Double format, we multiply
* log(x) by [1/log(10)].
*
* Special cases:
- * log10(x) is NaN with signal if x < 0;
+ * log10(x) is NaN with signal if x < 0;
* log10(+INF) is +INF with no signal; log10(0) is -INF with signal;
* log10(NaN) is that NaN with no signal.
*
diff --git a/lib/libm/common_source/log1p.c b/lib/libm/common_source/log1p.c
index cbf9fcd..0202667 100644
--- a/lib/libm/common_source/log1p.c
+++ b/lib/libm/common_source/log1p.c
@@ -35,24 +35,24 @@
static char sccsid[] = "@(#)log1p.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */
-/* LOG1P(x)
+/* LOG1P(x)
* RETURN THE LOGARITHM OF 1+x
* DOUBLE PRECISION (VAX D FORMAT 56 bits, IEEE DOUBLE 53 BITS)
- * CODED IN C BY K.C. NG, 1/19/85;
+ * CODED IN C BY K.C. NG, 1/19/85;
* REVISED BY K.C. NG on 2/6/85, 3/7/85, 3/24/85, 4/16/85.
- *
+ *
* Required system supported functions:
- * scalb(x,n)
+ * scalb(x,n)
* copysign(x,y)
- * logb(x)
+ * logb(x)
* finite(x)
*
* Required kernel function:
* log__L(z)
*
* Method :
- * 1. Argument Reduction: find k and f such that
- * 1+x = 2^k * (1+f),
+ * 1. Argument Reduction: find k and f such that
+ * 1+x = 2^k * (1+f),
* where sqrt(2)/2 < 1+f < sqrt(2) .
*
* 2. Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
@@ -65,11 +65,11 @@ static char sccsid[] = "@(#)log1p.c 8.1 (Berkeley) 6/4/93";
*
* See log__L() for the values of the coefficients.
*
- * 3. Finally, log(1+x) = k*ln2 + log(1+f).
+ * 3. Finally, log(1+x) = k*ln2 + log(1+f).
*
* Remarks 1. In step 3 n*ln2 will be stored in two floating point numbers
- * n*ln2hi + n*ln2lo, where ln2hi is chosen such that the last
- * 20 bits (for VAX D format), or the last 21 bits ( for IEEE
+ * n*ln2hi + n*ln2lo, where ln2hi is chosen such that the last
+ * 20 bits (for VAX D format), or the last 21 bits ( for IEEE
* double) is 0. This ensures n*ln2hi is exactly representable.
* 2. In step 1, f may not be representable. A correction term c
* for f is computed. It follows that the correction term for
@@ -83,7 +83,7 @@ static char sccsid[] = "@(#)log1p.c 8.1 (Berkeley) 6/4/93";
* only log1p(0)=0 is exact for finite argument.
*
* Accuracy:
- * log1p(x) returns the exact log(1+x) nearly rounded. In a test run
+ * log1p(x) returns the exact log(1+x) nearly rounded. In a test run
* with 1,536,000 random arguments on a VAX, the maximum observed
* error was .846 ulps (units in the last place).
*
@@ -114,7 +114,7 @@ ic(sqrt2, 1.4142135623730951455E0, 0, 1.6A09E667F3BCD)
double log1p(x)
double x;
{
- const static double zero=0.0, negone= -1.0, one=1.0,
+ const static double zero=0.0, negone= -1.0, one=1.0,
half=1.0/2.0, small=1.0E-20; /* 1+small == 1 */
double z,s,t,c;
int k;
@@ -129,7 +129,7 @@ double x;
/* argument reduction */
if(copysign(x,one)<small) return(x);
k=logb(one+x); z=scalb(x,-k); t=scalb(one,-k);
- if(z+t >= sqrt2 )
+ if(z+t >= sqrt2 )
{ k += 1 ; z *= half; t *= half; }
t += negone; x = z + t;
c = (t-x)+z ; /* correction term for x */
@@ -162,9 +162,9 @@ double x;
/* end of if (finite(x)) */
/* log(-INF) is NaN */
- else if(x<0)
+ else if(x<0)
return(zero/zero);
/* log(+INF) is INF */
- else return(x);
+ else return(x);
}
diff --git a/lib/libm/common_source/log__L.c b/lib/libm/common_source/log__L.c
index c00158f..207cb0d 100644
--- a/lib/libm/common_source/log__L.c
+++ b/lib/libm/common_source/log__L.c
@@ -39,14 +39,14 @@ static char sccsid[] = "@(#)log__L.c 8.1 (Berkeley) 6/4/93";
* LOG(1+X) - 2S X
* RETURN --------------- WHERE Z = S*S, S = ------- , 0 <= Z <= .0294...
* S 2 + X
- *
+ *
* DOUBLE PRECISION (VAX D FORMAT 56 bits or IEEE DOUBLE 53 BITS)
* KERNEL FUNCTION FOR LOG; TO BE USED IN LOG1P, LOG, AND POW FUNCTIONS
- * CODED IN C BY K.C. NG, 1/19/85;
+ * CODED IN C BY K.C. NG, 1/19/85;
* REVISED BY K.C. Ng, 2/3/85, 4/16/85.
*
* Method :
- * 1. Polynomial approximation: let s = x/(2+x).
+ * 1. Polynomial approximation: let s = x/(2+x).
* Based on log(1+x) = log(1+s) - log(1-s)
* = 2s + 2/3 s**3 + 2/5 s**5 + .....,
*
@@ -54,11 +54,11 @@ static char sccsid[] = "@(#)log__L.c 8.1 (Berkeley) 6/4/93";
*
* z*(L1 + z*(L2 + z*(... (L7 + z*L8)...)))
*
- * where z=s*s. (See the listing below for Lk's values.) The
- * coefficients are obtained by a special Remez algorithm.
+ * where z=s*s. (See the listing below for Lk's values.) The
+ * coefficients are obtained by a special Remez algorithm.
*
* Accuracy:
- * Assuming no rounding error, the maximum magnitude of the approximation
+ * Assuming no rounding error, the maximum magnitude of the approximation
* error (absolute) is 2**(-58.49) for IEEE double, and 2**(-63.63)
* for VAX D format.
*
diff --git a/lib/libm/common_source/pow.c b/lib/libm/common_source/pow.c
index 5121f30..9e92985 100644
--- a/lib/libm/common_source/pow.c
+++ b/lib/libm/common_source/pow.c
@@ -35,17 +35,17 @@
static char sccsid[] = "@(#)pow.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */
-/* POW(X,Y)
- * RETURN X**Y
+/* POW(X,Y)
+ * RETURN X**Y
* DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
- * CODED IN C BY K.C. NG, 1/8/85;
+ * CODED IN C BY K.C. NG, 1/8/85;
* REVISED BY K.C. NG on 7/10/85.
* KERNEL pow_P() REPLACED BY P. McILROY 7/22/92.
* Required system supported functions:
- * scalb(x,n)
- * logb(x)
- * copysign(x,y)
- * finite(x)
+ * scalb(x,n)
+ * logb(x)
+ * copysign(x,y)
+ * finite(x)
* drem(x,y)
*
* Required kernel functions:
@@ -56,7 +56,7 @@ static char sccsid[] = "@(#)pow.c 8.1 (Berkeley) 6/4/93";
* 1. Compute and return log(x) in three pieces:
* log(x) = n*ln2 + hi + lo,
* where n is an integer.
- * 2. Perform y*log(x) by simulating muti-precision arithmetic and
+ * 2. Perform y*log(x) by simulating muti-precision arithmetic and
* return the answer in three pieces:
* y*log(x) = m*ln2 + hi + lo,
* where m is an integer.
@@ -94,7 +94,7 @@ static char sccsid[] = "@(#)pow.c 8.1 (Berkeley) 6/4/93";
* pow(integer,integer)
* always returns the correct integer provided it is representable.
* In a test run with 100,000 random arguments with 0 < x, y < 20.0
- * on a VAX, the maximum observed error was 1.79 ulps (units in the
+ * on a VAX, the maximum observed error was 1.79 ulps (units in the
* last place).
*
* Constants :
@@ -123,7 +123,7 @@ const static double zero=0.0, one=1.0, two=2.0, negone= -1.0;
static double pow_P __P((double, double));
-double pow(x,y)
+double pow(x,y)
double x,y;
{
double t;
@@ -174,7 +174,8 @@ pow_P(x, y) double x, y;
#endif
{
struct Double s, t, __log__D();
- double __exp__D(), huge = 1e300, tiny = 1e-300;
+ double __exp__D();
+ volatile double huge = 1e300, tiny = 1e-300;
if (x == zero)
if (y > zero)
diff --git a/lib/libm/common_source/rint.3 b/lib/libm/common_source/rint.3
index 00cbf1c..868ebc9 100644
--- a/lib/libm/common_source/rint.3
+++ b/lib/libm/common_source/rint.3
@@ -103,8 +103,8 @@ and the presence or absence of an integer overflow are hard to
predict.
.Sh SEE ALSO
.Xr abs 3 ,
-.Xr fabs 3 ,
.Xr ceil 3 ,
+.Xr fabs 3 ,
.Xr floor 3 ,
.Xr ieee 3 ,
.Xr math 3
diff --git a/lib/libm/common_source/sin.3 b/lib/libm/common_source/sin.3
index c9bddd9..0eab465 100644
--- a/lib/libm/common_source/sin.3
+++ b/lib/libm/common_source/sin.3
@@ -61,10 +61,10 @@ function returns the sine value.
.Xr atan2 3 ,
.Xr cos 3 ,
.Xr cosh 3 ,
+.Xr math 3 ,
.Xr sinh 3 ,
.Xr tan 3 ,
-.Xr tanh 3 ,
-.Xr math 3 ,
+.Xr tanh 3
.Sh STANDARDS
The
.Fn sin
diff --git a/lib/libm/common_source/sinh.3 b/lib/libm/common_source/sinh.3
index c8b1b7f..26a1403 100644
--- a/lib/libm/common_source/sinh.3
+++ b/lib/libm/common_source/sinh.3
@@ -63,10 +63,10 @@ is set to
.Xr atan2 3 ,
.Xr cos 3 ,
.Xr cosh 3 ,
+.Xr math 3 ,
.Xr sin 3 ,
.Xr tan 3 ,
-.Xr tanh 3 ,
-.Xr math 3 ,
+.Xr tanh 3
.Sh STANDARDS
The
.Fn sinh
diff --git a/lib/libm/common_source/sinh.c b/lib/libm/common_source/sinh.c
index 0516849..075172c 100644
--- a/lib/libm/common_source/sinh.c
+++ b/lib/libm/common_source/sinh.c
@@ -38,7 +38,7 @@ static char sccsid[] = "@(#)sinh.c 8.1 (Berkeley) 6/4/93";
/* SINH(X)
* RETURN THE HYPERBOLIC SINE OF X
* DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
- * CODED IN C BY K.C. NG, 1/8/85;
+ * CODED IN C BY K.C. NG, 1/8/85;
* REVISED BY K.C. NG on 2/8/85, 3/7/85, 3/24/85, 4/16/85.
*
* Required system supported functions :
@@ -50,14 +50,14 @@ static char sccsid[] = "@(#)sinh.c 8.1 (Berkeley) 6/4/93";
*
* Method :
* 1. reduce x to non-negative by sinh(-x) = - sinh(x).
- * 2.
+ * 2.
*
* expm1(x) + expm1(x)/(expm1(x)+1)
* 0 <= x <= lnovfl : sinh(x) := --------------------------------
* 2
* lnovfl <= x <= lnovfl+ln2 : sinh(x) := expm1(x)/2 (avoid overflow)
* lnovfl+ln2 < x < INF : overflow to INF
- *
+ *
*
* Special cases:
* sinh(x) is x if x is +INF, -INF, or NaN.
@@ -112,7 +112,7 @@ double x;
{t=expm1(x); return(copysign((t+t/(one+t))*half,sign));}
else if(x <= lnovfl+0.7)
- /* subtract x by ln(2^(max+1)) and return 2^max*exp(x)
+ /* subtract x by ln(2^(max+1)) and return 2^max*exp(x)
to avoid unnecessary overflow */
return(copysign(scalb(one+expm1((x-mln2hi)-mln2lo),max),sign));
diff --git a/lib/libm/common_source/sqrt.3 b/lib/libm/common_source/sqrt.3
index a6d47d9..9c8c22b 100644
--- a/lib/libm/common_source/sqrt.3
+++ b/lib/libm/common_source/sqrt.3
@@ -106,8 +106,8 @@ in the
.Em P Ns lace
carried.
.Sh SEE ALSO
-.Xr math 3 ,
-.Xr infnan 3
+.Xr infnan 3 ,
+.Xr math 3
.Sh STANDARDS
The
.Nm sqrt
diff --git a/lib/libm/common_source/tan.3 b/lib/libm/common_source/tan.3
index 4e82ae3..b0d3767 100644
--- a/lib/libm/common_source/tan.3
+++ b/lib/libm/common_source/tan.3
@@ -62,10 +62,10 @@ function returns the tangent value.
.Xr atan2 3 ,
.Xr cos 3 ,
.Xr cosh 3 ,
+.Xr math 3 ,
.Xr sin 3 ,
.Xr sinh 3 ,
-.Xr tanh 3 ,
-.Xr math 3 ,
+.Xr tanh 3
.Sh STANDARDS
The
.Fn tan
diff --git a/lib/libm/common_source/tanh.3 b/lib/libm/common_source/tanh.3
index 7531728..2dc6bfc 100644
--- a/lib/libm/common_source/tanh.3
+++ b/lib/libm/common_source/tanh.3
@@ -59,10 +59,10 @@ function returns the hyperbolic tangent value.
.Xr atan2 3 ,
.Xr cos 3 ,
.Xr cosh 3 ,
+.Xr math 3 ,
.Xr sin 3 ,
.Xr sinh 3 ,
-.Xr tan 3 ,
-.Xr math 3 ,
+.Xr tan 3
.Sh STANDARDS
The
.Fn tanh
diff --git a/lib/libm/common_source/tanh.c b/lib/libm/common_source/tanh.c
index d4923b3..6813b55 100644
--- a/lib/libm/common_source/tanh.c
+++ b/lib/libm/common_source/tanh.c
@@ -38,7 +38,7 @@ static char sccsid[] = "@(#)tanh.c 8.1 (Berkeley) 6/4/93";
/* TANH(X)
* RETURN THE HYPERBOLIC TANGENT OF X
* DOUBLE PRECISION (VAX D FORMAT 56 BITS, IEEE DOUBLE 53 BITS)
- * CODED IN C BY K.C. NG, 1/8/85;
+ * CODED IN C BY K.C. NG, 1/8/85;
* REVISED BY K.C. NG on 2/8/85, 2/11/85, 3/7/85, 3/24/85.
*
* Required system supported functions :
@@ -85,7 +85,7 @@ double x;
sign=copysign(one,x);
x=copysign(x,one);
- if(x < 22.0)
+ if(x < 22.0)
if( x > one )
return(copysign(one-two/(expm1(x+x)+two),sign));
else if ( x > small )
diff --git a/lib/libm/ieee/cabs.c b/lib/libm/ieee/cabs.c
index c4a6fb0..5f1fc62 100644
--- a/lib/libm/ieee/cabs.c
+++ b/lib/libm/ieee/cabs.c
@@ -38,7 +38,7 @@ static char sccsid[] = "@(#)cabs.c 8.1 (Berkeley) 6/4/93";
/* HYPOT(X,Y)
* RETURN THE SQUARE ROOT OF X^2 + Y^2 WHERE Z=X+iY
* DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
- * CODED IN C BY K.C. NG, 11/28/84;
+ * CODED IN C BY K.C. NG, 11/28/84;
* REVISED BY K.C. NG, 7/12/85.
*
* Required system supported functions :
@@ -52,16 +52,16 @@ static char sccsid[] = "@(#)cabs.c 8.1 (Berkeley) 6/4/93";
* y if y > x (hence x is never smaller than y).
* 2. Hypot(x,y) is computed by:
* Case I, x/y > 2
- *
+ *
* y
* hypot = x + -----------------------------
* 2
* sqrt ( 1 + [x/y] ) + x/y
*
- * Case II, x/y <= 2
+ * Case II, x/y <= 2
* y
* hypot = x + --------------------------------------------------
- * 2
+ * 2
* [x/y] - 2
* (sqrt(2)+1) + (x-y)/y + -----------------------------
* 2
@@ -107,7 +107,7 @@ double
hypot(x,y)
double x, y;
{
- static const double zero=0, one=1,
+ static const double zero=0, one=1,
small=1.0E-18; /* fl(1+small)==1 */
static const ibig=30; /* fl(1+2**(2*ibig))==1 */
double t,r;
@@ -115,15 +115,15 @@ double x, y;
if(finite(x))
if(finite(y))
- {
+ {
x=copysign(x,one);
y=copysign(y,one);
- if(y > x)
+ if(y > x)
{ t=x; x=y; y=t; }
if(x == zero) return(zero);
if(y == zero) return(x);
exp= logb(x);
- if(exp-(int)logb(y) > ibig )
+ if(exp-(int)logb(y) > ibig )
/* raise inexact flag and return |x| */
{ one+small; return(x); }
@@ -144,7 +144,7 @@ double x, y;
else if(y==y) /* y is +-INF */
return(copysign(y,one));
- else
+ else
return(y); /* y is NaN and x is finite */
else if(x==x) /* x is +-INF */
@@ -199,16 +199,16 @@ double x, y;
if(finite(x))
if(finite(y))
- {
+ {
x=copysign(x,one);
y=copysign(y,one);
- if(y > x)
+ if(y > x)
{ temp=x; x=y; y=temp; }
if(x == zero) return(zero);
if(y == zero) return(x);
exp= logb(x);
x=scalb(x,-exp);
- if(exp-(int)logb(y) > ibig )
+ if(exp-(int)logb(y) > ibig )
/* raise inexact flag and return |x| */
{ one+small; return(scalb(x,exp)); }
else y=scalb(y,-exp);
@@ -217,7 +217,7 @@ double x, y;
else if(y==y) /* y is +-INF */
return(copysign(y,one));
- else
+ else
return(y); /* y is NaN and x is finite */
else if(x==x) /* x is +-INF */
diff --git a/lib/libm/ieee/cbrt.c b/lib/libm/ieee/cbrt.c
index fe5fb95..6d73779 100644
--- a/lib/libm/ieee/cbrt.c
+++ b/lib/libm/ieee/cbrt.c
@@ -50,8 +50,8 @@ static char sccsid[] = "@(#)cbrt.c 8.1 (Berkeley) 6/4/93";
* long interger at the address of a floating point number will be the
* leading 32 bits of that floating point number (i.e., sign, exponent,
* and the 20 most significant bits).
- * On a National machine, it has different ordering; therefore, this code
- * must be compiled with flag -DNATIONAL.
+ * On a National machine, it has different ordering; therefore, this code
+ * must be compiled with flag -DNATIONAL.
*/
#if !defined(vax)&&!defined(tahoe)
@@ -65,7 +65,7 @@ static const double
F= 45./28.,
G= 5./14.;
-double cbrt(x)
+double cbrt(x)
double x;
{
double r,s,t=0.0,w;
@@ -93,15 +93,15 @@ double x;
t*=x; pt[n0]=pt[n0]/3+B2;
}
else
- pt[n0]=px[n0]/3+B1;
+ pt[n0]=px[n0]/3+B1;
/* new cbrt to 23 bits, may be implemented in single precision */
r=t*t/x;
s=C+r*t;
- t*=G+F/(s+E+D/s);
+ t*=G+F/(s+E+D/s);
- /* chopped to 20 bits and make it larger than cbrt(x) */
+ /* chopped to 20 bits and make it larger than cbrt(x) */
pt[n1]=0; pt[n0]+=0x00000001;
diff --git a/lib/libm/ieee/support.c b/lib/libm/ieee/support.c
index e976839..0ae10bb 100644
--- a/lib/libm/ieee/support.c
+++ b/lib/libm/ieee/support.c
@@ -35,37 +35,37 @@
static char sccsid[] = "@(#)support.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */
-/*
- * Some IEEE standard 754 recommended functions and remainder and sqrt for
+/*
+ * Some IEEE standard 754 recommended functions and remainder and sqrt for
* supporting the C elementary functions.
******************************************************************************
* WARNING:
* These codes are developed (in double) to support the C elementary
* functions temporarily. They are not universal, and some of them are very
- * slow (in particular, drem and sqrt is extremely inefficient). Each
- * computer system should have its implementation of these functions using
+ * slow (in particular, drem and sqrt is extremely inefficient). Each
+ * computer system should have its implementation of these functions using
* its own assembler.
******************************************************************************
*
* IEEE 754 required operations:
- * drem(x,p)
+ * drem(x,p)
* returns x REM y = x - [x/y]*y , where [x/y] is the integer
* nearest x/y; in half way case, choose the even one.
- * sqrt(x)
- * returns the square root of x correctly rounded according to
+ * sqrt(x)
+ * returns the square root of x correctly rounded according to
* the rounding mod.
*
* IEEE 754 recommended functions:
- * (a) copysign(x,y)
- * returns x with the sign of y.
- * (b) scalb(x,N)
+ * (a) copysign(x,y)
+ * returns x with the sign of y.
+ * (b) scalb(x,N)
* returns x * (2**N), for integer values N.
- * (c) logb(x)
- * returns the unbiased exponent of x, a signed integer in
- * double precision, except that logb(0) is -INF, logb(INF)
+ * (c) logb(x)
+ * returns the unbiased exponent of x, a signed integer in
+ * double precision, except that logb(0) is -INF, logb(INF)
* is +INF, and logb(NAN) is that NAN.
- * (d) finite(x)
- * returns the value TRUE if -INF < x < +INF and returns
+ * (d) finite(x)
+ * returns the value TRUE if -INF < x < +INF and returns
* FALSE otherwise.
*
*
@@ -78,7 +78,7 @@ static char sccsid[] = "@(#)support.c 8.1 (Berkeley) 6/4/93";
#if defined(vax)||defined(tahoe) /* VAX D format */
#include <errno.h>
static const unsigned short msign=0x7fff , mexp =0x7f80 ;
- static const short prep1=57, gap=7, bias=129 ;
+ static const short prep1=57, gap=7, bias=129 ;
static const double novf=1.7E38, nunf=3.0E-39, zero=0.0 ;
#else /* defined(vax)||defined(tahoe) */
static const unsigned short msign=0x7fff, mexp =0x7ff0 ;
@@ -97,7 +97,7 @@ double x; int N;
unsigned short *px=(unsigned short *) &x;
#endif /* national */
- if( x == zero ) return(x);
+ if( x == zero ) return(x);
#if defined(vax)||defined(tahoe)
if( (k= *px & mexp ) != ~msign ) {
@@ -117,7 +117,7 @@ double x; int N;
if( k < (mexp>>gap) ) *px = (*px&~mexp) | (k<<gap);
else x=novf+novf; /* overflow */
else
- if( k > -prep1 )
+ if( k > -prep1 )
/* gradual underflow */
{*px=(*px&~mexp)|(short)(1<<gap); x *= scalb(1.0,k-1);}
else
@@ -147,7 +147,7 @@ double x,y;
}
double logb(x)
-double x;
+double x;
{
#ifdef national
@@ -164,8 +164,8 @@ double x;
return ( (k>>gap) - bias );
else if( x != zero)
return ( -1022.0 );
- else
- return(-(1.0/zero));
+ else
+ return(-(1.0/zero));
else if(x != x)
return(x);
else
@@ -174,7 +174,7 @@ double x;
}
finite(x)
-double x;
+double x;
{
#if defined(vax)||defined(tahoe)
return(1);
@@ -192,16 +192,16 @@ double x,p;
{
short sign;
double hp,dp,tmp;
- unsigned short k;
+ unsigned short k;
#ifdef national
unsigned short
- *px=(unsigned short *) &x +3,
+ *px=(unsigned short *) &x +3,
*pp=(unsigned short *) &p +3,
*pd=(unsigned short *) &dp +3,
*pt=(unsigned short *) &tmp+3;
#else /* national */
unsigned short
- *px=(unsigned short *) &x ,
+ *px=(unsigned short *) &x ,
*pp=(unsigned short *) &p ,
*pd=(unsigned short *) &dp ,
*pt=(unsigned short *) &tmp;
@@ -230,13 +230,13 @@ double x,p;
#endif /* defined(vax)||defined(tahoe) */
{ if (p != p) return p; else return x;}
- else if ( ((*pp & mexp)>>gap) <= 1 )
+ else if ( ((*pp & mexp)>>gap) <= 1 )
/* subnormal p, or almost subnormal p */
{ double b; b=scalb(1.0,(int)prep1);
p *= b; x = drem(x,p); x *= b; return(drem(x,p)/b);}
else if ( p >= novf/2)
{ p /= 2 ; x /= 2; return(drem(x,p)*2);}
- else
+ else
{
dp=p+p; hp=p/2;
sign= *px & ~msign ;
@@ -294,13 +294,13 @@ double x;
}
/* sqrt(INF) is INF */
- if(!finite(x)) return(x);
+ if(!finite(x)) return(x);
/* scale x to [1,4) */
n=logb(x);
x=scalb(x,-n);
if((m=logb(x))!=0) x=scalb(x,-m); /* subnormal number */
- m += n;
+ m += n;
n = m/2;
if((n+n)!=m) {x *= 2; m -=1; n=m/2;}
@@ -313,23 +313,23 @@ double x;
else
s *= 2;
}
-
+
/* generate the last bit and determine the final rounding */
- r/=2; x *= 4;
+ r/=2; x *= 4;
if(x==zero) goto end; 100+r; /* trigger inexact flag */
if(s<x) {
q+=r; x -=s; s += 2; s *= 2; x *= 4;
- t = (x-s)-5;
+ t = (x-s)-5;
b=1.0+3*r/4; if(b==1.0) goto end; /* b==1 : Round-to-zero */
b=1.0+r/4; if(b>1.0) t=1; /* b>1 : Round-to-(+INF) */
if(t>=0) q+=r; } /* else: Round-to-nearest */
- else {
- s *= 2; x *= 4;
- t = (x-s)-1;
+ else {
+ s *= 2; x *= 4;
+ t = (x-s)-1;
b=1.0+3*r/4; if(b==1.0) goto end;
b=1.0+r/4; if(b>1.0) t=1;
if(t>=0) q+=r; }
-
+
end: return(scalb(q,n));
}
@@ -342,13 +342,13 @@ end: return(scalb(q,n));
*
* Warning: this code should not get compiled in unless ALL of
* the following machine-dependent routines are supplied.
- *
+ *
* Required machine dependent functions (not on a VAX):
* swapINX(i): save inexact flag and reset it to "i"
* swapENI(e): save inexact enable and reset it to "e"
*/
-double drem(x,y)
+double drem(x,y)
double x,y;
{
@@ -363,8 +363,8 @@ double x,y;
double hy,y1,t,t1;
short k;
long n;
- int i,e;
- unsigned short xexp,yexp, *px =(unsigned short *) &x ,
+ int i,e;
+ unsigned short xexp,yexp, *px =(unsigned short *) &x ,
nx,nf, *py =(unsigned short *) &y ,
sign, *pt =(unsigned short *) &t ,
*pt1 =(unsigned short *) &t1 ;
@@ -381,7 +381,7 @@ double x,y;
/* save the inexact flag and inexact enable in i and e respectively
* and reset them to zero
*/
- i=swapINX(0); e=swapENI(0);
+ i=swapINX(0); e=swapENI(0);
/* subnormal number */
nx=0;
@@ -391,7 +391,7 @@ double x,y;
if( yexp <= m57 ) {py[n0]+=m57; nx+=m57; yexp+=m57;}
nf=nx;
- py[n0] &= 0x7fff;
+ py[n0] &= 0x7fff;
px[n0] &= 0x7fff;
/* mask off the least significant 27 bits of y */
@@ -408,7 +408,7 @@ loop:
if(k>0) /* if x/y >= 2**26, scale up y so that x/y < 2**26 */
{pt[n0]+=k;pt1[n0]+=k;}
n=x/t; x=(x-n*t1)-n*(t-t1);
- }
+ }
/* end while (x > y) */
if(nx!=0) {t=1.0; pt[n0]+=nx; x*=t; nx=0; goto loop;}
@@ -416,14 +416,14 @@ loop:
/* final adjustment */
hy=y/2.0;
- if(x>hy||((x==hy)&&n%2==1)) x-=y;
+ if(x>hy||((x==hy)&&n%2==1)) x-=y;
px[n0] ^= sign;
if(nf!=0) { t=1.0; pt[n0]-=nf; x*=t;}
/* restore inexact flag and inexact enable */
- swapINX(i); swapENI(e);
+ swapINX(i); swapENI(e);
- return(x);
+ return(x);
}
#endif
@@ -435,7 +435,7 @@ loop:
*
* Warning: this code should not get compiled in unless ALL of
* the following machine-dependent routines are supplied.
- *
+ *
* Required machine dependent functions:
* swapINX(i) ...return the status of INEXACT flag and reset it to "i"
* swapRM(r) ...return the current Rounding Mode and reset it to "r"
@@ -456,16 +456,16 @@ double x;
double const b54=134217728.*134217728.; /* b54=2**54 */
long mx,scalx;
long const mexp=0x7ff00000;
- int i,j,r,e,swapINX(),swapRM(),swapENI();
+ int i,j,r,e,swapINX(),swapRM(),swapENI();
unsigned long *py=(unsigned long *) &y ,
*pt=(unsigned long *) &t ,
*px=(unsigned long *) &x ;
#ifdef national /* ordering of word in a floating point number */
- const int n0=1, n1=0;
+ const int n0=1, n1=0;
#else
- const int n0=0, n1=1;
+ const int n0=0, n1=1;
#endif
-/* Rounding Mode: RN ...round-to-nearest
+/* Rounding Mode: RN ...round-to-nearest
* RZ ...round-towards 0
* RP ...round-towards +INF
* RM ...round-towards -INF
@@ -502,10 +502,10 @@ double x;
t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0;
/* triple to almost 56 sig. bits; now y approx. sqrt(x) to within 1 ulp */
- t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y;
+ t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y;
t=z/(t+x) ; pt[n0]+=0x00100000; y+=t;
-/* twiddle last bit to force y correctly rounded */
+/* twiddle last bit to force y correctly rounded */
swapRM(RZ); /* ...set Rounding Mode to round-toward-zero */
swapINX(0); /* ...clear INEXACT flag */
swapENI(e); /* ...restore inexact enable status */
diff --git a/lib/libmd/Makefile b/lib/libmd/Makefile
new file mode 100644
index 0000000..3969862
--- /dev/null
+++ b/lib/libmd/Makefile
@@ -0,0 +1,91 @@
+# $Id$
+
+LIB= md
+NOPIC= true
+SRCS= md2c.c md4c.c md5c.c md2hl.c md4hl.c md5hl.c
+MAN3+= md2.3 md4.3 md5.3
+MLINKS+=md2.3 MD2Init.3 md2.3 MD2Update.3 md2.3 MD2Final.3
+MLINKS+=md2.3 MD2End.3 md2.3 MD2File.3 md2.3 MD2Data.3
+MLINKS+=md4.3 MD4Init.3 md4.3 MD4Update.3 md4.3 MD4Final.3
+MLINKS+=md4.3 MD4End.3 md4.3 MD4File.3 md4.3 MD4Data.3
+MLINKS+=md5.3 MD5Init.3 md5.3 MD5Update.3 md5.3 MD5Final.3
+MLINKS+=md5.3 MD5End.3 md5.3 MD5File.3 md5.3 MD5Data.3
+CLEANFILES+= md[245]hl.c md[245].ref md[245].3 mddriver
+CFLAGS+= -I${.CURDIR}
+
+all: md2.3 md4.3 md5.3
+
+md2hl.c: mdXhl.c
+ sed -e 's/mdX/md2/g' -e 's/MDX/MD2/g' $> > $@
+
+md4hl.c: mdXhl.c
+ sed -e 's/mdX/md4/g' -e 's/MDX/MD4/g' $> > $@
+
+md5hl.c: mdXhl.c
+ sed -e 's/mdX/md5/g' -e 's/MDX/MD5/g' $> > $@
+
+md2.3: ${.CURDIR}/mdX.3
+ sed -e 's/mdX/md2/g' -e 's/MDX/MD2/g' $> > $@
+ cat ${.CURDIR}/md2.copyright >> $@
+
+md4.3: ${.CURDIR}/mdX.3
+ sed -e 's/mdX/md4/g' -e 's/MDX/MD4/g' $> > $@
+ cat ${.CURDIR}/md4.copyright >> $@
+
+md5.3: ${.CURDIR}/mdX.3
+ sed -e 's/mdX/md5/g' -e 's/MDX/MD5/g' $> > $@
+ cat ${.CURDIR}/md5.copyright >> $@
+
+md2.ref:
+ echo 'MD2 test suite:' > $@
+ @echo 'MD2 ("") = 8350e5a3e24c153df2275c9f80692773' >> $@
+ @echo 'MD2 ("a") = 32ec01ec4a6dac72c0ab96fb34c0b5d1' >> $@
+ @echo 'MD2 ("abc") = da853b0d3f88d99b30283a69e6ded6bb' >> $@
+ @echo 'MD2 ("message digest") = ab4f496bfb2a530b219ff33031fe06b0' >> $@
+ @echo 'MD2 ("abcdefghijklmnopqrstuvwxyz") = 4e8ddff3650292ab5a4108c3aa47940b' >> $@
+ @echo 'MD2 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = da33def2a42df13975352846c30338cd' >> $@
+ @echo 'MD2 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = d5976f79d83d3a0dc9806c3c66f3efd8' >> $@
+
+md4.ref:
+ echo 'MD4 test suite:' > $@
+ @echo 'MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0' >> $@
+ @echo 'MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24' >> $@
+ @echo 'MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d' >> $@
+ @echo 'MD4 ("message digest") = d9130a8164549fe818874806e1c7014b' >> $@
+ @echo 'MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9' >> $@
+ @echo 'MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 043f8582f241db351ce627e153e7f0e4' >> $@
+ @echo 'MD4 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536' >> $@
+
+md5.ref:
+ echo 'MD5 test suite:' > $@
+ @echo 'MD5 ("") = d41d8cd98f00b204e9800998ecf8427e' >> $@
+ @echo 'MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661' >> $@
+ @echo 'MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72' >> $@
+ @echo 'MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0' >> $@
+ @echo 'MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b' >> $@
+ @echo 'MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f' >> $@
+ @echo 'MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a' >> $@
+
+test: md2.ref md4.ref md5.ref
+ @${ECHO} if any of these test fail, the code produces wrong results
+ @${ECHO} and should NOT be used.
+ ${CC} -static ${CFLAGS} ${LDFLAGS} -DMD=2 -o mddriver ${.CURDIR}/mddriver.c -L. -lmd
+ ./mddriver | cmp md2.ref -
+ @${ECHO} MD2 passed test
+ ${CC} -static ${CFLAGS} ${LDFLAGS} -DMD=4 -o mddriver ${.CURDIR}/mddriver.c -L. -lmd
+ ./mddriver | cmp md4.ref -
+ @${ECHO} MD4 passed test
+ ${CC} -static ${CFLAGS} ${LDFLAGS} -DMD=5 -o mddriver ${.CURDIR}/mddriver.c -L. -lmd
+ ./mddriver | cmp md5.ref -
+ @${ECHO} MD5 passed test
+ -rm -f mddriver
+
+beforedepend: md2hl.c md4hl.c md5hl.c
+
+beforeinstall:
+.for i in md2.h md4.h md5.h
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/$i \
+ ${DESTDIR}/usr/include
+.endfor
+
+.include <bsd.lib.mk>
diff --git a/lib/libmd/md2.copyright b/lib/libmd/md2.copyright
new file mode 100644
index 0000000..5f04560
--- /dev/null
+++ b/lib/libmd/md2.copyright
@@ -0,0 +1,17 @@
+.\" $Id$
+Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+rights reserved.
+.Pp
+License to copy and use this software is granted for
+non-commercial Internet Privacy-Enhanced Mail provided that it is
+identified as the "RSA Data Security, Inc. MD2 Message Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+.Pp
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+.Pp
+These notices must be retained in any copies of any part of this
+documentation and/or software.
diff --git a/lib/libmd/md2.h b/lib/libmd/md2.h
new file mode 100644
index 0000000..ecdeaf7
--- /dev/null
+++ b/lib/libmd/md2.h
@@ -0,0 +1,40 @@
+/* MD2.H - header file for MD2C.C
+ * $Id$
+ */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+ rights reserved.
+
+ License to copy and use this software is granted for
+ non-commercial Internet Privacy-Enhanced Mail provided that it is
+ identified as the "RSA Data Security, Inc. MD2 Message Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+#ifndef _MD2_H_
+#define _MD2_H_
+
+typedef struct MD2Context {
+ unsigned char state[16]; /* state */
+ unsigned char checksum[16]; /* checksum */
+ unsigned int count; /* number of bytes, modulo 16 */
+ unsigned char buffer[16]; /* input buffer */
+} MD2_CTX;
+
+void MD2Init(MD2_CTX *);
+void MD2Update(MD2_CTX *, const unsigned char *, unsigned int);
+void MD2Final(unsigned char [16], MD2_CTX *);
+char * MD2End(MD2_CTX *, char *);
+char * MD2File(char *, char *);
+char * MD2Data(const unsigned char *, unsigned int, char *);
+
+#endif /* _MD2_H_ */
diff --git a/lib/libmd/md2c.c b/lib/libmd/md2c.c
new file mode 100644
index 0000000..ebf9edc
--- /dev/null
+++ b/lib/libmd/md2c.c
@@ -0,0 +1,199 @@
+/* MD2C.C - RSA Data Security, Inc., MD2 message-digest algorithm
+ * $Id$
+ */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+ rights reserved.
+
+ License to copy and use this software is granted for
+ non-commercial Internet Privacy-Enhanced Mail provided that it is
+ identified as the "RSA Data Security, Inc. MD2 Message Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+#include "md2.h"
+#include <string.h>
+#include <sys/types.h>
+
+
+typedef unsigned char *POINTER;
+typedef u_int16_t UINT2;
+typedef u_int32_t UINT4;
+
+#define PROTO_LIST(list) list
+
+static void MD2Transform PROTO_LIST
+ ((unsigned char [16], unsigned char [16], const unsigned char [16]));
+
+/* Permutation of 0..255 constructed from the digits of pi. It gives a
+ "random" nonlinear byte substitution operation.
+ */
+static unsigned char PI_SUBST[256] = {
+ 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+ 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+ 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+ 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+ 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+ 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+ 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+ 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+ 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+ 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+ 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+ 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+ 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+ 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+ 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+ 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+ 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+ 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+};
+
+static unsigned char *PADDING[] = {
+ (unsigned char *)"",
+ (unsigned char *)"\001",
+ (unsigned char *)"\002\002",
+ (unsigned char *)"\003\003\003",
+ (unsigned char *)"\004\004\004\004",
+ (unsigned char *)"\005\005\005\005\005",
+ (unsigned char *)"\006\006\006\006\006\006",
+ (unsigned char *)"\007\007\007\007\007\007\007",
+ (unsigned char *)"\010\010\010\010\010\010\010\010",
+ (unsigned char *)"\011\011\011\011\011\011\011\011\011",
+ (unsigned char *)"\012\012\012\012\012\012\012\012\012\012",
+ (unsigned char *)"\013\013\013\013\013\013\013\013\013\013\013",
+ (unsigned char *)"\014\014\014\014\014\014\014\014\014\014\014\014",
+ (unsigned char *)
+ "\015\015\015\015\015\015\015\015\015\015\015\015\015",
+ (unsigned char *)
+ "\016\016\016\016\016\016\016\016\016\016\016\016\016\016",
+ (unsigned char *)
+ "\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017",
+ (unsigned char *)
+ "\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020"
+};
+
+/* MD2 initialization. Begins an MD2 operation, writing a new context.
+ */
+void MD2Init (context)
+MD2_CTX *context; /* context */
+{
+ context->count = 0;
+ memset ((POINTER)context->state, 0, sizeof (context->state));
+ memset
+ ((POINTER)context->checksum, 0, sizeof (context->checksum));
+}
+
+/* MD2 block update operation. Continues an MD2 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+void MD2Update (context, input, inputLen)
+MD2_CTX *context; /* context */
+const unsigned char *input; /* input block */
+unsigned int inputLen; /* length of input block */
+{
+ unsigned int i, index, partLen;
+
+ /* Update number of bytes mod 16 */
+ index = context->count;
+ context->count = (index + inputLen) & 0xf;
+
+ partLen = 16 - index;
+
+ /* Transform as many times as possible.
+ */
+ if (inputLen >= partLen) {
+ memcpy
+ ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ MD2Transform (context->state, context->checksum, context->buffer);
+
+ for (i = partLen; i + 15 < inputLen; i += 16)
+ MD2Transform (context->state, context->checksum, &input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy
+ ((POINTER)&context->buffer[index], (POINTER)&input[i],
+ inputLen-i);
+}
+
+/* MD2 finalization. Ends an MD2 message-digest operation, writing the
+ message digest and zeroizing the context.
+ */
+void MD2Final (digest, context)
+unsigned char digest[16]; /* message digest */
+MD2_CTX *context; /* context */
+{
+ unsigned int index, padLen;
+
+ /* Pad out to multiple of 16.
+ */
+ index = context->count;
+ padLen = 16 - index;
+ MD2Update (context, PADDING[padLen], padLen);
+
+ /* Extend with checksum */
+ MD2Update (context, context->checksum, 16);
+
+ /* Store state in digest */
+ memcpy ((POINTER)digest, (POINTER)context->state, 16);
+
+ /* Zeroize sensitive information.
+ */
+ memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD2 basic transformation. Transforms state and updates checksum
+ based on block.
+ */
+static void MD2Transform (state, checksum, block)
+unsigned char state[16];
+unsigned char checksum[16];
+const unsigned char block[16];
+{
+ unsigned int i, j, t;
+ unsigned char x[48];
+
+ /* Form encryption block from state, block, state ^ block.
+ */
+ memcpy ((POINTER)x, (POINTER)state, 16);
+ memcpy ((POINTER)x+16, (POINTER)block, 16);
+ for (i = 0; i < 16; i++)
+ x[i+32] = state[i] ^ block[i];
+
+ /* Encrypt block (18 rounds).
+ */
+ t = 0;
+ for (i = 0; i < 18; i++) {
+ for (j = 0; j < 48; j++)
+ t = x[j] ^= PI_SUBST[t];
+ t = (t + i) & 0xff;
+ }
+
+ /* Save new state */
+ memcpy ((POINTER)state, (POINTER)x, 16);
+
+ /* Update checksum.
+ */
+ t = checksum[15];
+ for (i = 0; i < 16; i++)
+ t = checksum[i] ^= PI_SUBST[block[i] ^ t];
+
+ /* Zeroize sensitive information.
+ */
+ memset ((POINTER)x, 0, sizeof (x));
+}
diff --git a/lib/libmd/md4.copyright b/lib/libmd/md4.copyright
new file mode 100644
index 0000000..df93ad0
--- /dev/null
+++ b/lib/libmd/md4.copyright
@@ -0,0 +1,20 @@
+.\" $Id$
+Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+.Pp
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD4 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+.Pp
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+.Pp
+These notices must be retained in any copies of any part of this
+documentation and/or software.
diff --git a/lib/libmd/md4.h b/lib/libmd/md4.h
new file mode 100644
index 0000000..5481bbd
--- /dev/null
+++ b/lib/libmd/md4.h
@@ -0,0 +1,42 @@
+/* MD4.H - header file for MD4C.C
+ * $Id$
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD4 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+#ifndef _MD4_H_
+#define _MD4_H_
+/* MD4 context. */
+typedef struct MD4Context {
+ u_int32_t state[4]; /* state (ABCD) */
+ u_int32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} MD4_CTX;
+
+void MD4Init(MD4_CTX *);
+void MD4Update(MD4_CTX *, const unsigned char *, unsigned int);
+void MD4Final(unsigned char [16], MD4_CTX *);
+char * MD4End(MD4_CTX *, char *);
+char * MD4File(char *, char *);
+char * MD4Data(const unsigned char *, unsigned int, char *);
+
+#endif /* _MD4_H_ */
diff --git a/lib/libmd/md4c.c b/lib/libmd/md4c.c
new file mode 100644
index 0000000..a0eba4d
--- /dev/null
+++ b/lib/libmd/md4c.c
@@ -0,0 +1,279 @@
+/* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm
+ * $Id$
+ */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD4 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include "md4.h"
+
+typedef unsigned char *POINTER;
+typedef u_int16_t UINT2;
+typedef u_int32_t UINT4;
+
+#define PROTO_LIST(list) list
+
+/* Constants for MD4Transform routine.
+ */
+#define S11 3
+#define S12 7
+#define S13 11
+#define S14 19
+#define S21 3
+#define S22 5
+#define S23 9
+#define S24 13
+#define S31 3
+#define S32 9
+#define S33 11
+#define S34 15
+
+static void MD4Transform PROTO_LIST ((UINT4 [4], const unsigned char [64]));
+static void Encode PROTO_LIST
+ ((unsigned char *, UINT4 *, unsigned int));
+static void Decode PROTO_LIST
+ ((UINT4 *, const unsigned char *, unsigned int));
+
+static unsigned char PADDING[64] = {
+ 0x80, 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
+};
+
+/* F, G and H are basic MD4 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s) { \
+ (a) += F ((b), (c), (d)) + (x); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define GG(a, b, c, d, x, s) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define HH(a, b, c, d, x, s) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+
+/* MD4 initialization. Begins an MD4 operation, writing a new context.
+ */
+void MD4Init (context)
+MD4_CTX *context; /* context */
+{
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants.
+ */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/* MD4 block update operation. Continues an MD4 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+void MD4Update (context, input, inputLen)
+MD4_CTX *context; /* context */
+const unsigned char *input; /* input block */
+unsigned int inputLen; /* length of input block */
+{
+ unsigned int i, index, partLen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+ /* Update number of bits */
+ if ((context->count[0] += ((UINT4)inputLen << 3))
+ < ((UINT4)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((UINT4)inputLen >> 29);
+
+ partLen = 64 - index;
+ /* Transform as many times as possible.
+ */
+ if (inputLen >= partLen) {
+ memcpy
+ ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ MD4Transform (context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD4Transform (context->state, &input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy
+ ((POINTER)&context->buffer[index], (POINTER)&input[i],
+ inputLen-i);
+}
+
+/* MD4 finalization. Ends an MD4 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+void MD4Final (digest, context)
+unsigned char digest[16]; /* message digest */
+MD4_CTX *context; /* context */
+{
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ /* Save number of bits */
+ Encode (bits, context->count, 8);
+
+ /* Pad out to 56 mod 64.
+ */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ MD4Update (context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ MD4Update (context, bits, 8);
+ /* Store state in digest */
+ Encode (digest, context->state, 16);
+
+ /* Zeroize sensitive information.
+ */
+ memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD4 basic transformation. Transforms state based on block.
+ */
+static void MD4Transform (state, block)
+UINT4 state[4];
+const unsigned char block[64];
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode (x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11); /* 1 */
+ FF (d, a, b, c, x[ 1], S12); /* 2 */
+ FF (c, d, a, b, x[ 2], S13); /* 3 */
+ FF (b, c, d, a, x[ 3], S14); /* 4 */
+ FF (a, b, c, d, x[ 4], S11); /* 5 */
+ FF (d, a, b, c, x[ 5], S12); /* 6 */
+ FF (c, d, a, b, x[ 6], S13); /* 7 */
+ FF (b, c, d, a, x[ 7], S14); /* 8 */
+ FF (a, b, c, d, x[ 8], S11); /* 9 */
+ FF (d, a, b, c, x[ 9], S12); /* 10 */
+ FF (c, d, a, b, x[10], S13); /* 11 */
+ FF (b, c, d, a, x[11], S14); /* 12 */
+ FF (a, b, c, d, x[12], S11); /* 13 */
+ FF (d, a, b, c, x[13], S12); /* 14 */
+ FF (c, d, a, b, x[14], S13); /* 15 */
+ FF (b, c, d, a, x[15], S14); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 0], S21); /* 17 */
+ GG (d, a, b, c, x[ 4], S22); /* 18 */
+ GG (c, d, a, b, x[ 8], S23); /* 19 */
+ GG (b, c, d, a, x[12], S24); /* 20 */
+ GG (a, b, c, d, x[ 1], S21); /* 21 */
+ GG (d, a, b, c, x[ 5], S22); /* 22 */
+ GG (c, d, a, b, x[ 9], S23); /* 23 */
+ GG (b, c, d, a, x[13], S24); /* 24 */
+ GG (a, b, c, d, x[ 2], S21); /* 25 */
+ GG (d, a, b, c, x[ 6], S22); /* 26 */
+ GG (c, d, a, b, x[10], S23); /* 27 */
+ GG (b, c, d, a, x[14], S24); /* 28 */
+ GG (a, b, c, d, x[ 3], S21); /* 29 */
+ GG (d, a, b, c, x[ 7], S22); /* 30 */
+ GG (c, d, a, b, x[11], S23); /* 31 */
+ GG (b, c, d, a, x[15], S24); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 0], S31); /* 33 */
+ HH (d, a, b, c, x[ 8], S32); /* 34 */
+ HH (c, d, a, b, x[ 4], S33); /* 35 */
+ HH (b, c, d, a, x[12], S34); /* 36 */
+ HH (a, b, c, d, x[ 2], S31); /* 37 */
+ HH (d, a, b, c, x[10], S32); /* 38 */
+ HH (c, d, a, b, x[ 6], S33); /* 39 */
+ HH (b, c, d, a, x[14], S34); /* 40 */
+ HH (a, b, c, d, x[ 1], S31); /* 41 */
+ HH (d, a, b, c, x[ 9], S32); /* 42 */
+ HH (c, d, a, b, x[ 5], S33); /* 43 */
+ HH (b, c, d, a, x[13], S34); /* 44 */
+ HH (a, b, c, d, x[ 3], S31); /* 45 */
+ HH (d, a, b, c, x[11], S32); /* 46 */
+ HH (c, d, a, b, x[ 7], S33); /* 47 */
+ HH (b, c, d, a, x[15], S34); /* 48 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information.
+ */
+ memset ((POINTER)x, 0, sizeof (x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+ a multiple of 4.
+ */
+static void Encode (output, input, len)
+unsigned char *output;
+UINT4 *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+ a multiple of 4.
+ */
+static void Decode (output, input, len)
+
+UINT4 *output;
+const unsigned char *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
diff --git a/lib/libmd/md5.copyright b/lib/libmd/md5.copyright
new file mode 100644
index 0000000..c37746f
--- /dev/null
+++ b/lib/libmd/md5.copyright
@@ -0,0 +1,21 @@
+.\" $Id$
+Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+.Pp
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+.Pp
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+.Pp
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+.Pp
+These notices must be retained in any copies of any part of this
+documentation and/or software.
diff --git a/lib/libmd/md5.h b/lib/libmd/md5.h
new file mode 100644
index 0000000..803a88f
--- /dev/null
+++ b/lib/libmd/md5.h
@@ -0,0 +1,4 @@
+#ifndef _MD5_H_
+#define _MD5_H_
+#include <sys/md5.h>
+#endif /* _MD5_H_ */
diff --git a/lib/libmd/md5c.c b/lib/libmd/md5c.c
new file mode 100644
index 0000000..583d009
--- /dev/null
+++ b/lib/libmd/md5c.c
@@ -0,0 +1,331 @@
+/*
+ * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD5 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ *
+ * $Id$
+ *
+ * This code is the same as the code published by RSA Inc. It has been
+ * edited for clarity and style only.
+ */
+
+#include <sys/types.h>
+
+#ifdef KERNEL
+#include <sys/param.h>
+#include <sys/systm.h>
+#else
+#include <string.h>
+#endif
+
+#include <sys/md5.h>
+
+static void MD5Transform __P((u_int32_t [4], const unsigned char [64]));
+
+#ifdef KERNEL
+#define memset(x,y,z) bzero(x,z);
+#define memcpy(x,y,z) bcopy(y, x, z)
+#endif
+
+#ifdef i386
+#define Encode memcpy
+#define Decode memcpy
+#else /* i386 */
+
+/*
+ * Encodes input (u_int32_t) into output (unsigned char). Assumes len is
+ * a multiple of 4.
+ */
+
+static void
+Encode (output, input, len)
+ unsigned char *output;
+ u_int32_t *input;
+ unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+/*
+ * Decodes input (unsigned char) into output (u_int32_t). Assumes len is
+ * a multiple of 4.
+ */
+
+static void
+Decode (output, input, len)
+ u_int32_t *output;
+ const unsigned char *input;
+ unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((u_int32_t)input[j]) | (((u_int32_t)input[j+1]) << 8) |
+ (((u_int32_t)input[j+2]) << 16) | (((u_int32_t)input[j+3]) << 24);
+}
+#endif /* i386 */
+
+static unsigned char PADDING[64] = {
+ 0x80, 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
+};
+
+/* F, G, H and I are basic MD5 functions. */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits. */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/*
+ * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context. */
+
+void
+MD5Init (context)
+ MD5_CTX *context;
+{
+
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/*
+ * MD5 block update operation. Continues an MD5 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+
+void
+MD5Update (context, input, inputLen)
+ MD5_CTX *context;
+ const unsigned char *input;
+ unsigned int inputLen;
+{
+ unsigned int i, index, partLen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((u_int32_t)inputLen << 3))
+ < ((u_int32_t)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((u_int32_t)inputLen >> 29);
+
+ partLen = 64 - index;
+
+ /* Transform as many times as possible. */
+ if (inputLen >= partLen) {
+ memcpy((void *)&context->buffer[index], (void *)input,
+ partLen);
+ MD5Transform (context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD5Transform (context->state, &input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy ((void *)&context->buffer[index], (void *)&input[i],
+ inputLen-i);
+}
+
+/*
+ * MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+
+void
+MD5Final (digest, context)
+ unsigned char digest[16];
+ MD5_CTX *context;
+{
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ /* Save number of bits */
+ Encode (bits, context->count, 8);
+
+ /* Pad out to 56 mod 64. */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ MD5Update (context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ MD5Update (context, bits, 8);
+
+ /* Store state in digest */
+ Encode (digest, context->state, 16);
+
+ /* Zeroize sensitive information. */
+ memset ((void *)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block. */
+
+static void
+MD5Transform (state, block)
+ u_int32_t state[4];
+ const unsigned char block[64];
+{
+ u_int32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode (x, block, 64);
+
+ /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information. */
+ memset ((void *)x, 0, sizeof (x));
+}
diff --git a/lib/libmd/mdX.3 b/lib/libmd/mdX.3
new file mode 100644
index 0000000..d9539f6
--- /dev/null
+++ b/lib/libmd/mdX.3
@@ -0,0 +1,137 @@
+.\"
+.\" ----------------------------------------------------------------------------
+.\" "THE BEER-WARE LICENSE" (Revision 42):
+.\" <phk@login.dkuug.dk> 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
+.\" ----------------------------------------------------------------------------
+.\"
+.\" $Id: mdX.3,v 1.9 1997/02/22 15:07:22 peter Exp $
+.\"
+.Dd October 9, 1996
+.Dt MDX 3
+.Os FreeBSD 2
+.Sh NAME
+.Nm MDXInit ,
+.Nm MDXUpdate ,
+.Nm MDXFinal ,
+.Nm MDXEnd ,
+.Nm MDXFile ,
+.Nm MDXData
+.Nd calculate the RSA Data Security, Inc., ``MDX'' message digest
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <mdX.h>
+.Ft void
+.Fn MDXInit "MDX_CTX *context"
+.Ft void
+.Fn MDXUpdate "MDX_CTX *context" "const unsigned char *data" "unsigned int len"
+.Ft void
+.Fn MDXFinal "unsigned char digest[16]" "MDX_CTX *context"
+.Ft "char *"
+.Fn MDXEnd "MDX_CTX *context" "char *buf"
+.Ft "char *"
+.Fn MDXFile "char *filename" "char *buf"
+.Ft "char *"
+.Fn MDXData "const unsigned char *data" "unsigned int len" "char *buf"
+.Sh DESCRIPTION
+The MDX functions calculate a 128-bit cryptographic checksum (digest)
+for any number of input bytes. A cryptographic checksum is a one-way
+hash-function, that is, you cannot find (except by exhaustive search)
+the input corresponding to a particular output. This net result is
+a ``fingerprint'' of the input-data, which doesn't disclose the actual
+input.
+.Pp
+MD2 is the slowest, MD4 is the fastest and MD5 is somewhere in the middle.
+MD2 can only be used for Privacy-Enhanced Mail.
+MD4 has been criticized for being too weak, so MD5 was developed in
+response as ``MD4 with safety-belts''. When in doubt, use MD5.
+.Pp
+The
+.Fn MDXInit ,
+.Fn MDXUpdate ,
+and
+.Fn MDXFinal
+functions are the core functions. Allocate an MDX_CTX, initialize it with
+.Fn MDXInit ,
+run over the data with
+.Fn MDXUpdate ,
+and finally extract the result using
+.Fn MDXFinal .
+.Pp
+.Fn MDXEnd
+is a wrapper for
+.Fn MDXFinal
+which converts the return value to a 33-character
+(including the terminating '\e0')
+.Tn ASCII
+string which represents the 128 bits in hexadecimal.
+.Pp
+.Fn MDXFile
+calculates the digest of a file, and uses
+.Fn MDXEnd
+to return the result.
+If the file cannot be opened, a null pointer is returned.
+.Fn MDXData
+calculates the digest of a chunk of data in memory, and uses
+.Fn MDXEnd
+to return the result.
+.Pp
+When using
+.Fn MDXEnd ,
+.Fn MDXFile ,
+or
+.Fn MDXData ,
+the
+.Ar buf
+argument can be a null pointer, in which case the returned string
+is allocated with
+.Xr malloc 3
+and subsequently must be explicitly deallocated using
+.Xr free 3
+after use.
+If the
+.Ar buf
+argument is non-null it must point to at least 33 characters of buffer space.
+.Sh SEE ALSO
+.Xr md2 3 ,
+.Xr md4 3 ,
+.Xr md5 3
+.Rs
+.%A B. Kaliski
+.%T The MD2 Message-Digest Algorithm
+.%O RFC 1319
+.Re
+.Rs
+.%A R. Rivest
+.%T The MD4 Message-Digest Algorithm
+.%O RFC 1186
+.Re
+.Rs
+.%A R. Rivest
+.%T The MD5 Message-Digest Algorithm
+.%O RFC 1321
+.Re
+.Rs
+.%A RSA Laboratories
+.%T Frequently Asked Questions About today's Cryptography
+.Re
+.Sh AUTHOR
+The original MDX routines were developed by
+.Tn RSA
+Data Security, Inc., and published in the above references.
+This code is derived directly from these implementations by Poul-Henning Kamp
+.Aq Li phk@login.dkuug.dk
+.Pp
+Phk ristede runen.
+.Sh HISTORY
+These functions appeared in
+.Fx 2.0 .
+.Sh BUGS
+No method is known to exist which finds two files having the same hash value,
+nor to find a file with a specific hash value.
+There is on the other hand no guarantee that such a method doesn't exist.
+.Pp
+MD2 has only been licensed for use in Privacy Enhanced Mail.
+Use MD4 or MD5 if that isn't what you're doing.
+.Sh COPYRIGHT
diff --git a/lib/libmd/mdXhl.c b/lib/libmd/mdXhl.c
new file mode 100644
index 0000000..e0e9198
--- /dev/null
+++ b/lib/libmd/mdXhl.c
@@ -0,0 +1,71 @@
+/* mdXhl.c
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dkuug.dk> 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
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mdX.h"
+
+char *
+MDXEnd(MDX_CTX *ctx, char *buf)
+{
+ int i;
+ unsigned char digest[16];
+ static const char hex[]="0123456789abcdef";
+
+ if (!buf)
+ buf = malloc(33);
+ if (!buf)
+ return 0;
+ MDXFinal(digest,ctx);
+ for (i=0;i<16;i++) {
+ buf[i+i] = hex[digest[i] >> 4];
+ buf[i+i+1] = hex[digest[i] & 0x0f];
+ }
+ buf[i+i] = '\0';
+ return buf;
+}
+
+char *
+MDXFile (char *filename, char *buf)
+{
+ unsigned char buffer[BUFSIZ];
+ MDX_CTX ctx;
+ int f,i,j;
+
+ MDXInit(&ctx);
+ f = open(filename,O_RDONLY);
+ if (f < 0) return 0;
+ while ((i = read(f,buffer,sizeof buffer)) > 0) {
+ MDXUpdate(&ctx,buffer,i);
+ }
+ j = errno;
+ close(f);
+ errno = j;
+ if (i < 0) return 0;
+ return MDXEnd(&ctx, buf);
+}
+
+char *
+MDXData (const unsigned char *data, unsigned int len, char *buf)
+{
+ MDX_CTX ctx;
+
+ MDXInit(&ctx);
+ MDXUpdate(&ctx,data,len);
+ return MDXEnd(&ctx, buf);
+}
diff --git a/lib/libmd/mddriver.c b/lib/libmd/mddriver.c
new file mode 100644
index 0000000..633442b
--- /dev/null
+++ b/lib/libmd/mddriver.c
@@ -0,0 +1,67 @@
+/* MDDRIVER.C - test driver for MD2, MD4 and MD5
+ * $Id$
+ */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+ rights reserved.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+/* The following makes MD default to MD5 if it has not already been
+ defined with C compiler flags.
+ */
+#ifndef MD
+#define MD MD5
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#if MD == 2
+#include "md2.h"
+#define MDData MD2Data
+#endif
+#if MD == 4
+#include "md4.h"
+#define MDData MD4Data
+#endif
+#if MD == 5
+#include "md5.h"
+#define MDData MD5Data
+#endif
+
+/* Digests a string and prints the result.
+ */
+static void MDString (string)
+char *string;
+{
+ char buf[33];
+
+ printf ("MD%d (\"%s\") = %s\n",
+ MD, string, MDData(string,strlen(string),buf));
+}
+
+/* Digests a reference suite of strings and prints the results.
+ */
+main()
+{
+ printf ("MD%d test suite:\n", MD);
+
+ MDString ("");
+ MDString ("a");
+ MDString ("abc");
+ MDString ("message digest");
+ MDString ("abcdefghijklmnopqrstuvwxyz");
+ MDString
+ ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ MDString
+ ("1234567890123456789012345678901234567890\
+1234567890123456789012345678901234567890");
+}
diff --git a/lib/libmytinfo/EXAMPLES/terminfo.src b/lib/libmytinfo/EXAMPLES/terminfo.src
new file mode 100644
index 0000000..0fed13e
--- /dev/null
+++ b/lib/libmytinfo/EXAMPLES/terminfo.src
@@ -0,0 +1,104 @@
+#
+# terminfo.src
+#
+# By Ross Ridge
+# Public Domain
+# 92/02/01 07:30:32
+#
+# Some sample terminfo definitions
+#
+# @(#) mytinfo terminfo.src 3.2 92/02/01 public domain, By Ross Ridge
+#
+#
+dumb|dumb terminal, gn, co#80,
+#
+# Note not all ANSI terminals will support all of these capabilities.
+# This doesn't define any real terminal, and probably wouldn't work
+# with any real terminal either.
+#
+ansi-all|ANS X3.64-1979 terminal,
+ cr=^M, cud1=^J, ind=^J, nel=^M^J, bell=^G, cub1=^H,
+ cuu1=\EM, ff=^L, ht=^I,
+ .ind=\ED, .nel=\EE, hts=\EH, hd=\EK, hu=\EL, ri=\EM,
+ .ich1=\E[@, .ich=\E[%p1%d@, .cuu1=\E[A, cuu=\E[%p1%dA,
+ cud1=\E[B, .cud=\E[%p1%dB, cuf1=\E[C, cuf=\E[%p1%dC,
+ .cub1=\E[D, cub=\E[%p1%dD, .cnl=\E[%p1%dE, .cpl=\E[%p1%dF,
+ .hpa=\E[%i%p1%dG, cup=\E[%i%p1%d;%p2%dH, .cht=\E[%p1%dI,
+ ed=\E[J, el=\E[K, el1=\E[1K, il1=\E[L, il=\E[%p1%dL,
+ dl1=\E[M, dl=\E[%p1%dM, .ef=\E[N, .ea=\E[O,
+ dch1=\E[P, dch=\E[%p1%dP, .sem=\E[%p1%dQ,
+ .cpr=\E[%i%p1%d;%p2%dR, indn=\E[%p1%dS, .ind=\E[S,
+ rin=\E[%p1%dT, .ri=\E[T, .np=\E[%p1%dU, .pp=\E[%p1%dU,
+ .ctc=\E[%p1%dW, ech=\E[%p1%dX, .cvt=\E[%p1%dY,
+ cbt=\E[Z, hpa=\E[%i%p1%d`, .hpr=\E[%p1%da,
+ rep=%p1%c%?%p2%{1}%>%t\E[%p2%{1}%-%db%;,
+ .da=\E[c, vpa=\E[%i%p1%dd, .vpr=\E[%p1%e,
+ .hvp=\E[%i%p1%d;%p2%df, tbc=\E[3g,
+ mc=\E[0i, mc4=\E[4i, mc5=\E[5i,
+ sgr=\E[%?%p6%t;1%;%?%p5%p1%|%t;2%;%?%p2%t;4%;%?%p4%t;6%;%?%p3%p1%|%t;7%;%?%p7%t;8%;m,
+ smso=\E[1;7m, rmso=\E[m, smul=\E[4m, rmul=\E[m,
+ blink=\E[6m, bold=\E[1m, invis=\E[8m, rev=\E[7m,
+ sgr0=\E[m, .dsr=\E[%p1%dn, .daq=\E[%p1%do,
+ .sl=\E[%p1%d\s@, .sr=\E[%p1%d\sA, clear=\E[H\EJ, home=\E[H,
+ smir=\E[4h, rmir=\E[4l,
+ is2=\E[1Q\E[1;2;3;4;5;7;10;11;13;14;16;15;17;18;19;20l\E[6;12h\E[m,
+ rs2=\Ec\E[1Q\E[1;2;3;4;5;7;10;11;13;14;16;15;17;18;19;20l\E[6;12h\E[m\E[H\EJ,
+ansi-all-8|ANS X3.64-1979 terminal (8 bit),
+ cr=^M, cud1=^J, ind=^J, nel=^M^J, bell=^G, cub1=^H,
+ cuu1=\215, ff=^L, ht=^I,
+ .ind=\204, .nel=\205, hts=\207, hd=\213, hu=\214, ri=\215,
+ .ich1=\233@, .ich=\E%p1%d@, .cuu1=\233A, cuu=\233%p1%dA,
+ cud1=\233B, .cud=\233%p1%dB, cuf1=\233C, cuf=\233%p1%dC,
+ .cub1=\233D, cub=\233%p1%dD, .cnl=\233%p1%dE, .cpl=\233%p1%dF,
+ .hpa=\233%i%p1%dG, cup=\233%i%p1%d;%p2%dH, .cht=\233%p1%dI,
+ ed=\233J, el=\233K, el1=\2331K, il1=\233L, il=\233%p1%dL,
+ dl1=\233M, dl=\233%p1%dM, .ef=\233N, .ea=\233O,
+ dch1=\233P, dch=\233%p1%dP, .sem=\233%p1%dQ,
+ .cpr=\233%i%p1%d;%p2%dR, indn=\233%p1%dS, .ind=\233S,
+ rin=\233%p1%dT, .ri=\233T, .np=\233%p1%dU, .pp=\233%p1%dU,
+ .ctc=\233%p1%dW, ech=\233%p1%dX, .cvt=\233%p1%dY,
+ cbt=\233Z, hpa=\233%i%p1%d`, .hpr=\233%p1%da,
+ rep=%p1%c%?%p2%{1}%>%t\233%p2%{1}%-%db%;,
+ .da=\233c, vpa=\233%i%p1%dd, .vpr=\233%p1%e,
+ .hvp=\233%i%p1%d;%p2%df, tbc=\2333g,
+ mc=\2330i, mc4=\2334i, mc5=\2334i,
+ sgr=\233%?%p6%t;1%;%?%p5%p1%|%t;2%;%?%p2%t;4%;%?%p4%t;6%;%?%p3%p1%|%t;7%;%?%p7%t;8%;m,
+ smso=\2331;7m, rmso=\233m, smul=\2334m, rmul=\233m,
+ blink=\2336m, bold=\2331m, invis=\2338m, rev=\2337m,
+ sgr0=\233m, .dsr=\233%p1%dn, .daq=\233%p1%do,
+ .sl=\233%p1%d\s@, .sr=\233%p1%d\sA, clear=\233H\EJ, home=\233H,
+ smir=\2334h, rmir=\2334l,
+ is2=\2331Q\2331;2;3;4;5;7;10;11;13;14;16;15;17;18;19;20l\2336;12h\233m,
+ rs2=\Ec\2331Q\2331;2;3;4;5;7;10;11;13;14;16;15;17;18;19;20l\2336;12h\233m\233H\EJ,
+#
+# Not tested...
+#
+vt100|dec vt100,
+ xon, UWxc, msgr,
+ cols#80, lines#24, it#8, vt#3,
+ cr=\r, csr=^[[%i%p1%d;%p2%dr, tbc=^[[3g, clear=^[[;H^[[2J$<100>,
+ el=^[[K$<3>, ed=^[[J$<50>, cup=^[[%i%p1%d;%p2%dH$<5>, cud1=^[[B,
+ home=^[[H, cub1=^[[D, cuf1=^[[C$<2>, cuu1=^[[A$<2>, blink=^[[5m$<2>,
+ bold=^[[1m$<2>, rev=^[[7m$<2>, smso=^[[7m$<2>, smul=^[[4m$<2>,
+ sgr0=^[[m^N$<2>, rmso=^[[m$<2>, rmul=^[[m$<2>, hts=^[H, ht=^I,
+ is2=^[[1;24r^[[?1l^[[?3l^[[30h^[[?7h^[>, bell=^G,
+ kbs=\b, kcud1=^[[B, kf0=^[OP, kf1=^[OQ, kf2=^[OR, kf3=^[OS,
+ kcub1=^[[D, kcuf1=^[[C, kcuu1=^[[A, lf0=PF1, lf1=PF2,
+ lf2=PF3, lf3=PF4, nel=\r^[D, cud=^[[%p1%dB, cub=^[[%p1%dD,
+ cuf=^[[%p1%dC, cuu=^[[%p1%dA, rc=^[8, sc=^[7, ind=^[D, ri=^[M$<5>,
+ sgr=^[[0;%?%p4%t;5%;%?%p6%t;1%;%?%p3%p1%|%t;7%;%?%p2%t;4%;m%?%p1%t^N%e^O%;$<2>,
+ smacs=^O, rmacs=^N,
+vt100-am|vt100 with automatic margins,
+ am, xenl, @el, @ed,
+ use=vt100,
+vt102|dec vt102,
+ is=\E<\E[1;24r\E[?1l\E[?3l\E[?5l\E[?7h\E>,
+ il=\E[%p1%dL, dch=\E[%p1%dP, dl=\E[%p1%dM,
+ il1=\E[L, dch1=\E[P, dl1=\E[M,
+ mir, rmir=\E[4l, smir=\E[4h,
+ use=vt100,
+vt200|vt220|vt200-js|vt220-js|dec vt200 series with jump scroll,
+ clear=\E[H\E[J, rmso=\E[27m, rmul=\E[24m,
+ is2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H,
+ rs2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h,
+ use=vt102,
diff --git a/lib/libmytinfo/INSTALL b/lib/libmytinfo/INSTALL
new file mode 100644
index 0000000..3a0276d
--- /dev/null
+++ b/lib/libmytinfo/INSTALL
@@ -0,0 +1,211 @@
+Compiling this package requires a fair bit of knowledge about your system.
+There are no automatic configuration programmes or prepared configuration
+files for different type of systems. You will need to edit the Makefile
+to specify things like which compiler to use and any options it needs.
+The file config.h needs to be edited to reflect the system you are
+using and to enable and/or disable certain features.
+
+Defines in config.h
+===================
+
+USE_ANSIC
+
+Normally this will be defined automaticly if __STDC__ is defined, but
+if your compile isn't truly ANSI C compliant you may need to undefine this.
+
+USE_TERMIO
+
+Define this if your system uses the termio tty driver. System III and
+System V use termio.
+
+USE_SGTTY
+
+Define this if your system uses the "sgtty" tty driver. V7 Unix and BSD
+use sgtty.
+
+USE_WINSZ
+
+If you defined USE_SGTTY you can define this if your system supports
+SIGWINSZ and the accompaning ioctls. If this is defined the library
+will get number of columns and lines from the tty driver not the
+terminal description. BSD 4.3 supports SIGWINSZ. This will also work
+if USE_TERMIO is defined on some hybrid System V machines such as Release 4.
+
+Do not define both USE_TERMIO and USE_SGTTY. If your system supports both
+you'd probably be better of defining USE_TERMIO. If your system supports
+neither termio or sgtty you can leave USE_TERMIO and USE_SGTTY undefined,
+but this is only recommended for use with micomputers.
+
+USE_STRINGS
+
+If you define this then the header file <strings.h> will be included
+and BSD type string library assumed (index instead of strchr), otherwise
+<string.h> will included. If you have a BSD type system define this.
+If you have an ANSI C, System III, or System V type of system leave it
+undefined.
+
+USE_MYBSEARCH
+
+If your system's C library doesn't include bsearch, define this.
+Most System V systems have bsearch. However even your C library has this
+function you still may want to define USE_MYBSEARCH, see USE_SHORT_BSEARCH
+below. ("MYBSEARCH" is misnomer, I didn't write this routine.)
+
+USE_SHORT_BSEARCH
+
+If you define USE_MYBSEARCH you can define this so that the bsearch
+routine that library uses the type short instead of size_t (usually long)
+for it's arguments. This results a large speedup on 68000 based machines
+and possibly a significant speedup on others as well. However on some CPU's
+defining this will only make things slower.
+
+USE_MYSTRTOK
+
+If your system's C library doesn't include strtok, define this.
+Most ANSI C, System III, and System V systems have this.
+
+USE_MYQSORT
+
+If your system's C library doesn't include qsort, define this.
+All most all systems should have this function, if it doesn't complain
+to your vendor. The qsort routine comes from the GNU Emacs distribution.
+
+USE_MYMKDIR
+
+Define this if your system doesn't have the mkdir library function call.
+My routine simply calls the system command mkdir, you may have to
+edit mkdir.c if the pathname of that command isn't "/bin/mkdir".
+
+USE_MEMORY
+
+If your system has a <memory.h> header define this. If USE_MEMORY
+is not defined bcopy will used instead of memcpy.
+
+USE_SMALLMEM
+
+Use you can define use this to save some memory, but it doesn't
+save much at moment, and will only slow the library down.
+
+USE_FAKE_STDIO
+
+If you define this then the library won't use the real stdio but a
+fake one instead. This is for compatiblity with termcap and vi which
+don't use stdio.
+
+USE_DOPRNT
+
+If you don't have a vfprintf function, but you have a _doprnt function
+define this. If you don't have either than you can compile the library
+but not the support programmes. System V has vfprintf and most Unixes
+have a _doprnt (but probably not documented). BSD has released a freely
+distributable vfprintf for BSD Unixes.
+
+USE_UPBC_KLUDGE
+
+Define this if you want the library's tgoto to work like termcap's tgoto
+and avoid putting ^D, and \n into an output string by using the cursor up
+and backspace strings.
+
+USE_EXTERN_UPBC
+
+If you defined USE_UPBC_KLUDGE you can define this so tgoto will,
+like termcap's tgoto, get the cursor up and backspace strings from the
+externs UP and BC instead from the library's internal record.
+
+USE_LITOUT_KLUDGE
+
+Don't define this. It's another kludge for tgoto.
+
+If neither USE_UPBC_KLUDGE or USE_LITOUT_KLUDGE is defined then tgoto
+won't worry about putting ^D, and \n in a string.
+
+USE_PROTOTYPES
+
+Define this if your compiler supports ANSI C style prototypes.
+
+USE_STDLIB
+
+Define this if your system has an <stdlib.h> header.
+
+USE_STDARG
+
+Define this if your system has an <stdarg.h> header. If this isn't
+defined <varargs.h> will be included instead.
+
+USE_STDDEF
+
+Define this if your system has an <stddef.h> header. If this isn't
+defined <sys/types.h> will be included instead.
+
+typedef char *anyptr;
+
+You should change the typedef to a type that any pointer can be assigned
+to or from. ANSI C compilers can use "typedef void *anyptr", most
+other compilers should use "typedef char *anyptr".
+
+#define mysize_t unsigned
+
+"mysize_t" needs to defined as the type of the size of an object, or
+the type of the sizeof operator. Traditional usage is "unsigned", for
+ANSI C you should define mysize_t as "size_t".
+
+TERMCAPFILE
+
+Define this to a string containing the default termcap file(s) to look
+for terminal descriptions in. Multiple filenames should be seperated
+by spaces and environment variables can be specfied by prefixing them
+with dolar signs ($). eg:
+ #define TERMCAPFILE "$TERMCAPFILE $HOME/.termcap /etc/termcap"
+
+TERMINFOSRC
+
+Define this to a string containing the default terminfo source file to
+look for terminal descriptions in.
+
+TERMINFODIR
+
+Define this as the directory containing the default terminfo database,
+usually "/usr/lib/terminfo".
+
+Any of TERMCAPFILE, TERMINFOSRC or TERMINFODIR can be left undefined.
+
+
+defs.h
+======
+
+You may also need to edit defs.h and change the definitions of MAX_BUF,
+MAX_LINE, and MAX_NAME. Unless you are seriously starved for memory I
+don't recomend making them smaller.
+
+
+cap_list
+========
+
+You can add new capabilities to the file cap_list. You must provide
+a type, terminfo variable name, terminfo capname, and termcap name for
+all capabilities and you must make sure they are all unique.
+
+
+Making in the library
+=====================
+
+Once you've configured the package you can just type "make" and it
+will build the library and the "term.h" header. You can enter
+"make all" to make the library and the support programmes, tconv,
+cap2info, tic, clear, tput and tset. If you want a profiled library
+you can enter "make profiled". You can remove all the intermediate
+files with "make clean". "make spotless" will remove the target
+files as well.
+
+
+Installing the library
+======================
+
+As for installing it, that's up to you. Depending on how much you
+plan to use the libraries and whether or not you have termcap and/or
+terminfo already you can install them "standard" places (ie. /usr/lib,
+/usr/include, /usr/bin), in local directories, or just leave them in
+the source directory. However if you are compiling programmes that
+use terminfo and linking it with this library you must make sure that
+this library's term.h file is included in your programme and not the
+system supplied one.
diff --git a/lib/libmytinfo/Makefile b/lib/libmytinfo/Makefile
new file mode 100644
index 0000000..f5aa031
--- /dev/null
+++ b/lib/libmytinfo/Makefile
@@ -0,0 +1,58 @@
+# Makefile for libmytinfo
+# Use 'make update_term_h' manually after changing internal
+# mytinfo structures
+# $Id$
+
+LIB= mytinfo
+SRCS= addstr.c binorder.c buildpath.c caplist.c capsort.c compar.c\
+ fillterm.c findcap.c findterm.c getother.c gettbin.c\
+ gettcap.c gettinfo.c tcapconv.c tcapvars.c termcap.c\
+ terminfo.c tgoto.c tiget.c tmatch.c tparm.c tputs.c tty.c version.c
+CLEANFILES+= binorder.c caplist.c capsort.c mkbinorder mkcaplist \
+ mkcapsort mktermhead mkversion readcaps.o version.c
+
+CFLAGS+=-Wall -I${.CURDIR}
+
+CAPS= 1000
+
+# ${.CURDIR}/term.h: ${.CURDIR}/term.head ${.CURDIR}/term.tail
+update_term_h: ${.CURDIR}/term.head ${.CURDIR}/term.tail
+ cat ${.CURDIR}/term.head ${.CURDIR}/term.tail > ${.CURDIR}/term.h
+
+beforeinstall:
+ $(INSTALL) -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/term.h \
+ ${DESTDIR}/usr/include
+ ln -sf term.h ${DESTDIR}/usr/include/nterm.h
+
+capsort.c: mkcapsort
+ ./mkcapsort > capsort.c
+
+mkcapsort: mkcapsort.c caplist.o compar.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o mkcapsort ${.CURDIR}/mkcapsort.c caplist.o compar.o
+
+binorder.c: mkbinorder ${.CURDIR}/bin_order
+ ./mkbinorder ${.CURDIR}/bin_order > binorder.c
+
+mkbinorder: mkbinorder.c capsort.o caplist.o compar.o findcap.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o mkbinorder ${.CURDIR}/mkbinorder.c capsort.o \
+ caplist.o compar.o findcap.o
+
+version.c: mkversion
+ ./mkversion > version.c
+
+mkversion: mkversion.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o mkversion ${.CURDIR}/mkversion.c
+
+${.CURDIR}/term.head: mktermhead ${.CURDIR}/cap_list
+ ./mktermhead -n $(CAPS) ${.CURDIR}/cap_list > ${.CURDIR}/term.head
+
+caplist.c: mkcaplist ${.CURDIR}/cap_list
+ ./mkcaplist -n $(CAPS) ${.CURDIR}/cap_list > caplist.c
+
+mktermhead: mktermhead.c readcaps.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o mktermhead ${.CURDIR}/mktermhead.c readcaps.o
+
+mkcaplist: mkcaplist.c readcaps.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o mkcaplist ${.CURDIR}/mkcaplist.c readcaps.o
+
+.include <bsd.lib.mk>
diff --git a/lib/libmytinfo/README b/lib/libmytinfo/README
new file mode 100644
index 0000000..ea65c94
--- /dev/null
+++ b/lib/libmytinfo/README
@@ -0,0 +1,75 @@
+Mytinfo is Public Domain and comes with no guarantees.
+By Ross Ridge (ross@zooid.guild.org).
+
+Mytinfo is a single library that combines the functionality of the
+standard Unix termcap and terminfo libraries. It has the special
+ability of being able to fetch terminal descriptions from both
+termcap and terminfo databases regardless of which set of functions,
+termcap or terminfo, are used. It can even read terminal descriptions
+from terminfo source files.
+
+You should be able to compile this library on almost all versions of Unix.
+Much of it's development was done on '386 Xenix, but I've sucessfuly built
+mytinfo under BSD 4.3, HP-UX 2.1 (System III), SunOS 3.5, and Amix
+(System V R4). There hasn't been a large amount of testing of the support
+programmes that come with the library, but the library itself has been in
+use on a couple of public access Unix sites for over two years. It has
+successfully linked and run with many programmes such as rn, vi and nethack.
+
+Included in the package is tconv, an "all-in-one" programme that will
+compile terminfo sources to binary format and also translate termcap to
+either terminfo source or binary. tic and cap2info are just links
+to the tconv programme. I've also written replacement for tset,
+that uses the mytinfo library, in case tset doesn't come with your
+system or if you aren't too pleased with the one that did. Since this
+is the newest part of the package it probably still has a few bugs.
+You'll also find tput, as well two versions of clear, one that uses
+termcap and the other that uses terminfo.
+
+The environment variables TERMCAP and TERMINFO can have multiple
+filenames separated by a space, a feature not in terminfo and not in
+most termcaps. This is very handy for users that maintain their own
+private databases, as they don't have to have a copy the entire
+database. Eg:
+ TERMCAP="$HOME/.termcap /etc/termcap"
+ TERMINFO="$HOME/terminfo /usr/lib/terminfo"
+ export TERMCAP TERMINFO
+The library will also check compiled-in default locations for terminal
+descriptions. Like most termcaps, the TERMCAP variable can also
+contain the complete termcap terminal description, usually supplied
+from tset at login. The TERMINFO variable can also contain a complete
+terminfo description, but there is no programme like tset to supply it.
+
+Unlike termcap, this library can only use capabilities that it knows about.
+However it does knows about all the standard ones, and you can easily
+add your own to it's list. Included in the list are all terminfo
+capabilities to Release 4 of System V, obsolete termcap capabilities, a
+few caps used from the University of Waterloo (UW), a couple from GNU Emacs,
+and a few I made up myself. Two extensions to the standard termcap % codes
+are supported, GNU's %a, %m, %b, and %f, and UW's %-, %a, and %s.
+
+Termcap and terminfo source descriptions can be mixed in one file, but
+because of this termcap databases must be in a certain style. All
+continuation lines of a termcap entry must be indented from the left
+margin by white space. This shouldn't be a problem with most sites
+since this is the style that most termcap files are distributed, but local
+additions may not adhere to this style. Another possible problem is
+that termcap entries should end with a colon (:), but in most
+distributed termcaps there are entries that don't. If a one line
+termcap entry doesn't end with a colon, it will be ignored. A quick
+way to find these is "tconv -c /etc/termcap > /dev/null".
+
+See the file INSTALL for instructions on configuring and installing
+this library. The file README.doc lists the functions supported by the
+library, and gives short description of the tconv programme. tconv.1 is
+a simple man page for tconv. terminfo.src contains a few sample
+terminal descriptions in terminfo source format. TODO is a list of
+possible enhancements too the library, your comments and additions
+are welcome.
+
+Please let me know of any bugs you find, as well as any ideas you have
+for improvement.
+
+Ross Ridge
+
+ross@zooid.guild.org
diff --git a/lib/libmytinfo/README.doc b/lib/libmytinfo/README.doc
new file mode 100644
index 0000000..04e1409
--- /dev/null
+++ b/lib/libmytinfo/README.doc
@@ -0,0 +1,125 @@
+----------------------------------------------------------------------------
+tconv [-b] [-c [-OUGd]] [-i] [-B [-D dir]] [-I] [-k] [-t term] [file]
+tic [file]
+cap2info [-t term] [-OUGdk] [file]
+
+-c convert from termcap
+-i convert from terminfo source
+-b convert from terminfo binary
+-B convert to terminfo binary
+-I convert to terminfo source
+
+The following switches are available when converting from termcap:
+-d don't supply any defaults for missing capabilities
+-O include obsolete termcap capabilities
+-G include GNU capabilities
+-U include UW capabilities
+
+-k keep comments
+-D dir directory to put terminfo binaries in
+
+-t term name of terminal to translate
+file filename of termcap/terminfo database to use
+
+If a file is specifed and no terminal is given the entire file we be translated.
+If no terminal and no file is specified then the terminal name will be taken
+from the environment varible TERM. Unless compiling to a terminfo binary,
+output is to stdout.
+----------------------------------------------------------------------------
+
+char *tparm(char *str, ...); /* up to nine parameters */
+char *tgoto(char *str, int column, int row);
+
+tparm and tgoto support the following termcap and terminfo % codes:
+
+Terminfo % Codes
+
+ %% output a '%'
+ %[[:][-+# ][width][.precision]][doxXs]
+ output pop according to the printf format
+ %c output pop as a char
+ %'c' push character constant c.
+ %{n} push decimal constant n.
+ %p[1-9] push paramter [1-9]
+ %g[a-z] push variable [a-z]
+ %P[a-z] put pop in variable [a-z]
+ %l push the length of pop (a string)
+ %+ add pop to pop and push the result
+ %- subtract pop from pop and push the result
+ %* multiply pop and pop and push the result
+ %& bitwise and pop and pop and push the result
+ %| bitwise or pop and pop and push the result
+ %^ bitwise xor pop and pop and push the result
+ %~ push the bitwise not of pop
+ %= compare if pop and pop are equal and push the result
+ %> compare if pop is less than pop and push the result
+ %< compare if pop is greater than pop and push the result
+ %A logical and pop and pop and push the result
+ %O logical or pop and pop and push the result
+ %! push the logical not of pop
+ %? condition %t if_true [%e if_false] %;
+ if condtion evaulates as true then evaluate if_true,
+ else evaluate if_false. elseif's can be done:
+%? cond %t true [%e cond2 %t true2] ... [%e condN %t trueN] [%e false] %;
+ %i add one to parameters 1 and 2. (ANSI)
+
+Termcap Codes
+
+ %% output a %
+ %. output parameter as a character
+ %d output parameter as a decimal number
+ %2 output parameter in printf format %02d
+ %3 output parameter in printf format %03d
+ %+x add the character x to parameter and output it as a character
+(UW) %-x subtract parameter FROM the character x and output it as a char
+(UW) %ax add the character x to parameter
+(GNU) %a[+*-/=][cp]x
+ GNU arithmetic.
+(UW) %sx subtract parameter FROM the character x
+ %>xy if parameter > character x then add character y to parameter
+ %B convert to BCD (parameter = (parameter/10)*16 + parameter%16)
+ %D Delta Data encode (parameter = parameter - 2*(paramter%16))
+ %i increment the first two parameters by one
+ %n xor the first two parameters by 0140
+(GNU) %m xor the first two parameters by 0177
+ %r swap the first two parameters
+(GNU) %b backup to previous parameter
+(GNU) %f skip this parameter
+
+(GNU) used by GNU Emacs termcap libraries
+(UW) used by the University of Waterloo (MFCF) termcap libraries
+
+Note the two definitions of %a, the GNU defintion is used if the characters
+after the 'a' are valid for it, otherwise the UW definition is used.
+----------------------------------------------------------------------------
+
+int setupterm(char *term; int fd; int *err);
+int set_curterm(TERMINAL *new);
+int del_curterm(TERMINAL *old);
+char *tparm(char *str, ...); /* see above */
+int tputs(char *str, int count, int (*putc)());
+int putp(str);
+int tigetflag(char *cap);
+int tigetnum(char *cap);
+char *tigetstr(char *cap);
+int def_prog_mode();
+int def_shell_mode();
+int reset_prog_mode();
+int reset_shell_mode();
+char *boolnames[], *boolcodes[], *boolfnames[];
+char *numnames[], *numcodes[], *numfnames[];
+char *strnames[], *strcodes[], *strfnames[];
+
+These functions work just like the terminfo functions. Note restartterm(),
+vidputs(), vidattr(), and mvcur() are not available.
+----------------------------------------------------------------------------
+
+int tgetent(char *buf, char *term);
+int tgetflag(char *cap);
+int tgetnum(char *cap);
+char *tgetstr(char *cap, char **area);
+char *tgoto(char *cap, int column, int row);
+int tputs(char *str, int count, int (*putc)());
+
+These functions work just like termcap functions.
+----------------------------------------------------------------------------
diff --git a/lib/libmytinfo/TESTS/Makefile b/lib/libmytinfo/TESTS/Makefile
new file mode 100644
index 0000000..eeaa6d2
--- /dev/null
+++ b/lib/libmytinfo/TESTS/Makefile
@@ -0,0 +1,42 @@
+# Makefile for libmytinfo tests
+# $Id$
+
+LIB= mytinfo
+
+TESTS= ttest tputs.test tparm.test readcaps.test caps clear.tcap \
+ clear.tinfo tset tput
+
+CFLAGS+= -Wall -I${.CURDIR}/..
+
+CLEANFILES+= $(TESTS) quit.o
+
+all: $(TESTS)
+
+ttest: ttest.c quit.o
+ $(CC) $(CFLAGS) -o ttest $(LDFLAGS) ${.CURDIR}/ttest.c quit.o -l$(LIB)
+
+caps: caps.c quit.o
+ $(CC) $(CFLAGS) -o caps $(LDFLAGS) ${.CURDIR}/caps.c quit.o -l$(LIB)
+
+tputs.test: ${.CURDIR}/../tputs.c
+ $(CC) -o tputs.test $(LDFLAGS) $(CFLAGS) -DTEST ${.CURDIR}/../tputs.c -l$(LIB)
+
+tparm.test: ${.CURDIR}/../tparm.c
+ $(CC) -o tparm.test $(LDFLAGS) $(CFLAGS) -DTEST ${.CURDIR}/../tparm.c -l$(LIB)
+
+readcaps.test: ${.CURDIR}/../readcaps.c
+ $(CC) -o readcaps.test $(LDFLAGS) $(CFLAGS) -DTEST ${.CURDIR}/../readcaps.c -l$(LIB)
+
+clear.tcap: clear.c
+ $(CC) $(LDFLAGS) $(CFLAGS) -o clear.tcap ${.CURDIR}/clear.c -l$(LIB)
+
+clear.tinfo: clear.c
+ $(CC) $(LDFLAGS) $(CFLAGS) -DUSE_TERMINFO -o clear.tinfo ${.CURDIR}/clear.c -l$(LIB)
+
+tset: tset.c quit.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o tset ${.CURDIR}/tset.c quit.o -l$(LIB)
+
+tput: tput.c quit.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o tput ${.CURDIR}/tput.c quit.o -l$(LIB)
+
+.include <bsd.prog.mk>
diff --git a/lib/libmytinfo/TESTS/caps.c b/lib/libmytinfo/TESTS/caps.c
new file mode 100644
index 0000000..e90d26e
--- /dev/null
+++ b/lib/libmytinfo/TESTS/caps.c
@@ -0,0 +1,173 @@
+/*
+ * caps.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:29:45
+ *
+ * caps [-c | -t] [term]
+ *
+ * -c use termcap names instead of terminfo variable names
+ * -t use terminfo capnames instead of variables names
+ * term name of terminal to use
+ *
+ * prints out all the capabilities given the specified terminal. If no
+ * terminal is given, it is taken from the environment variable TERM.
+ *
+ */
+
+#define NOTLIB
+#include "defs.h"
+#include <term.h>
+
+const char SCCSid[] = "@(#) mytinfo caps.c 3.2 92/02/01 public domain, By Ross Ridge";
+
+/* output a string in a human readable format */
+void
+putstr(s)
+char *s; {
+ while(*s != '\0') {
+ switch(*s) {
+ case '\n': printf("\\n"); break;
+ case '\b': printf("\\b"); break;
+ case '\t': printf("\\t"); break;
+ case '\r': printf("\\r"); break;
+ case '\f': printf("\\f"); break;
+ case ' ': printf("\\s"); break;
+ case '\177': printf("^?"); break;
+ case '\200': printf("\\0"); break;
+ default:
+ if (*s > 0 && *s < 32)
+ printf("^%c", *s + 64);
+ else if (*s < 0)
+ printf("\\%03o", *s & 0xff);
+ else
+ putchar(*s);
+ break;
+ }
+ s++;
+ }
+}
+
+void
+do_cleanup(e)
+int e; {
+ fprintf(stderr, "usage: %s [-c | -t ] [terminal]\n", prg_name);
+ return;
+}
+
+int
+main(argc, argv)
+int argc;
+char **argv; {
+ int names = 0;
+ register int i;
+ int flag, num;
+ char *str;
+
+ prg_name = argv[0];
+ cleanup = do_cleanup;
+
+ if (argc > 3)
+ quit(-1, "argument count");
+
+ if (argc == 1)
+ setupterm(NULL, 2, (int *) 0);
+ else if (argc == 2) {
+ if (argv[1][0] != '-')
+ setupterm(argv[1], 2, (int *) 0);
+ else {
+ if (argv[1][1] == 'c')
+ names = 2;
+ else if (argv[1][1] == 't')
+ names = 1;
+ else
+ quit(-1, "unknown switch '%c'", argv[1][1]);
+ setupterm(NULL, 2, (int *) 0);
+ }
+ } else {
+ if (argv[1][0] != '-')
+ quit(-1, "bad switch");
+ if (argv[1][1] == 'c')
+ names = 2;
+ else if (argv[1][1] == 't')
+ names = 1;
+ else
+ quit(-1, "unknown switch '%c'", argv[1][1]);
+ setupterm(argv[2], 2, (int *) 0);
+
+ }
+
+ fflush(stderr);
+ fflush(stdout);
+ printf("\n");
+#ifdef _CUR_TERM
+ printf("%s: %s\n", cur_term->name, cur_term->name_all);
+ printf("pad: %d xon: %d termcap: %d\n",
+ cur_term->pad, cur_term->xon, cur_term->termcap);
+ printf("true_columns: %d true_lines: %d baudrate: %lu\n",
+ cur_term->true_columns, cur_term->true_lines,
+ (unsigned long) cur_term->baudrate);
+ printf("\n");
+#endif
+
+ printf("Booleans:\n");
+ for(i = 0; boolnames[i] != NULL; i++) {
+#ifdef _CUR_TERM
+ flag = cur_term->bools[i];
+#else
+ flag = tigetflag(boolnames[i]);
+#endif
+ if (flag != -1 && flag != 0) {
+ switch(names) {
+ case 0:
+ printf(" %s\n", boolfnames[i]);
+ break;
+ case 1:
+ printf(" %s\n", boolnames[i]);
+ break;
+ case 2:
+ printf(" %s\n", boolcodes[i]);
+ break;
+ }
+ }
+ }
+
+ printf("\nNumerics:\n");
+ for(i = 0; numnames[i] != NULL; i++) {
+ num = tigetnum(numnames[i]);
+ if (num != -2 && num != -1) {
+ switch(names) {
+ case 0:
+ printf(" %-32s: %d\n", numfnames[i], num);
+ break;
+ case 1:
+ printf(" %-5s: %d\n", numnames[i], num);
+ break;
+ case 2:
+ printf(" %-2s: %d\n", numcodes[i], num);
+ break;
+ }
+ }
+ }
+ printf("\nStrings:\n");
+ for(i = 0; strnames[i] != NULL; i++) {
+ str = tigetstr(strnames[i]);
+ if (str != (char *) -1 && str != (char *) 0) {
+ switch(names) {
+ case 0:
+ printf(" %-32s: ", strfnames[i]);
+ break;
+ case 1:
+ printf(" %-5s: ", strnames[i]);
+ break;
+ case 2:
+ printf(" %-2s: ", strcodes[i]);
+ break;
+ }
+ putstr(str);
+ putchar('\n');
+ }
+ }
+ return 0;
+}
diff --git a/lib/libmytinfo/TESTS/clear.c b/lib/libmytinfo/TESTS/clear.c
new file mode 100644
index 0000000..b603a52
--- /dev/null
+++ b/lib/libmytinfo/TESTS/clear.c
@@ -0,0 +1,156 @@
+/*
+ * clear.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:29:47
+ *
+ * clear
+ *
+ * clears the terminal's screen
+ *
+ */
+
+#include "defs.h"
+
+const char SCCSid[] = "@(#) mytinfo clear.c 3.2 92/02/01 public domain, By Ross Ridge";
+
+#ifndef USE_TERMINFO
+
+#ifdef USE_SGTTY
+#include <sgtty.h>
+#endif
+#ifdef USE_TERMIO
+#include <termio.h>
+#endif
+#ifdef USE_TERMIOS
+#include <termios.h>
+#endif
+#ifdef __FreeBSD__
+int tgetent __P((char *, char *));
+int tgetnum __P((char *));
+int tputs __P((char *, int, int (*)(char)));
+#endif
+
+char PC;
+short ospeed;
+
+int
+#ifdef USE_PROTOTYPES
+putch(char c)
+#else
+putch(c)
+int c;
+#endif
+{
+ return putchar(c);
+}
+
+int
+main(argc, argv)
+int argc;
+char **argv; {
+#ifdef USE_PROTOTYPES
+ char *tgetstr(char *, char **);
+#else
+ char *tgetstr();
+#endif
+ char *term;
+ char buf[MAX_BUF];
+ char CL[MAX_LINE];
+ char *s, *pc;
+
+#ifdef USE_SGTTY
+ struct sgttyb tty;
+
+ gtty(1, &tty);
+ ospeed = tty.sg_ospeed;
+#else
+#ifdef USE_TERMIO
+ struct termio tty;
+
+ ioctl(1, TCGETA, &tty);
+ ospeed = tty.c_cflag & CBAUD;
+#else
+#ifdef USE_TERMIOS
+ struct termios tty;
+
+ tcgetattr(1, &tty);
+ switch(cfgetospeed(&tty)) {
+ case B0: ospeed = 0; break;
+ case B50: ospeed = 1; break;
+ case B75: ospeed = 2; break;
+ case B110: ospeed = 3; break;
+ case B134: ospeed = 4; break;
+ case B150: ospeed = 5; break;
+ case B200: ospeed = 6; break;
+ case B300: ospeed = 7; break;
+ case B600: ospeed = 8; break;
+ case B1200: ospeed = 9; break;
+ case B1800: ospeed = 10; break;
+ case B2400: ospeed = 11; break;
+ case B4800: ospeed = 12; break;
+ case B9600: ospeed = 13; break;
+ case EXTA: ospeed = 14; break;
+ case EXTB: ospeed = 15; break;
+#ifdef B57600
+ case B57600: ospeed = 16; break;
+#endif
+#ifdef B115200
+ case B115200: ospeed = 17; break;
+#endif
+ }
+#else
+ ospeed = 0;
+#endif
+#endif
+#endif
+
+ term = getenv("TERM");
+ if (term == NULL)
+ exit(1);
+
+ if (tgetent(buf, term) != 1)
+ exit(1);
+
+ s = CL;
+ pc = tgetstr("pc", &s);
+ if (pc != NULL)
+ PC = *pc;
+
+ s = CL;
+ tgetstr("cl", &s);
+
+ if (CL != NULL) {
+ tputs(CL, tgetnum("li"), putch);
+ exit(1);
+ }
+
+ return 0;
+}
+
+#else /* USE_TERMINFO */
+
+#include <term.h>
+
+int
+#ifdef USE_PROTOTYPES
+putch(char c)
+#else
+putch(c)
+int c;
+#endif
+{
+ return putchar(c);
+}
+
+int
+main() {
+ setupterm((char *) 0, 1, (int *) 0);
+ if (clear_screen == (char *) 0)
+ exit(1);
+ tputs(clear_screen, lines > 0 ? lines : 1, putch);
+ return 0;
+}
+
+#endif /* USE_TERMINFO */
diff --git a/lib/libmytinfo/TESTS/quit.c b/lib/libmytinfo/TESTS/quit.c
new file mode 100644
index 0000000..f30fb50
--- /dev/null
+++ b/lib/libmytinfo/TESTS/quit.c
@@ -0,0 +1,72 @@
+/*
+ * quit.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:14
+ *
+ * quit with a diagnostic message printed on stderr
+ *
+ */
+
+#define NOTLIB
+#include "defs.h"
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo quit.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+char *prg_name;
+
+#if defined(USE_PROTOTYPES) && !defined(lint)
+void (*cleanup)(int);
+#else
+void (*cleanup)();
+#endif
+
+/* PRINTFLIKE2 */
+noreturn
+#ifdef USE_STDARG
+#ifdef USE_PROTOTYPES
+void
+quit(int e, char *fmt, ...)
+#else
+void quit(e, fmt)
+int e;
+char *fmt;
+#endif
+#else
+void quit(va_alist)
+va_dcl
+#endif
+{
+#ifndef USE_STDARG
+ int e;
+ char *fmt;
+#endif
+ va_list ap;
+
+#ifdef USE_STDARG
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+ e = va_arg(ap, int);
+ fmt = va_arg(ap, char *);
+#endif
+
+ (*cleanup)(e);
+
+ if (e != 0)
+ fprintf(stderr, "%s: ", prg_name);
+#ifdef USE_DOPRNT
+ _doprnt(fmt, ap, stderr);
+#else
+ vfprintf(stderr, fmt, ap);
+#endif
+ putc('\n', stderr);
+ if (e > 0 && e < sys_nerr) {
+ fprintf(stderr, "%d - %s\n", e, sys_errlist[e]);
+ }
+ fflush(stderr);
+ exit(e);
+}
diff --git a/lib/libmytinfo/TESTS/tput.c b/lib/libmytinfo/TESTS/tput.c
new file mode 100644
index 0000000..9c220b8
--- /dev/null
+++ b/lib/libmytinfo/TESTS/tput.c
@@ -0,0 +1,196 @@
+/*
+ * tput.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:39
+ *
+ */
+
+#define NOTLIB
+
+#include "defs.h"
+
+const char SCCSid[] = "@(#) mytinfo tput.c 3.2 92/02/01 public domain, By Ross Ridge";
+
+#define SINGLE
+#include <term.h>
+
+#include <ctype.h>
+
+#define PUTS(s) putp(s)
+#define PUTCHAR(c) putchar(c)
+#define FLUSH fflush(stdout)
+
+extern void (*cleanup)();
+
+static void
+clean(e)
+int e; {
+ return;
+}
+
+static void
+usage(e)
+int e; {
+ fprintf(stderr, "usage: %s [-T term] capname\n", prg_name);
+ return;
+}
+
+int
+main(argc, argv)
+int argc;
+char **argv; {
+ char *s;
+ int i, j, c;
+ int reset;
+ FILE *f;
+ char *term;
+
+ prg_name = argv[0];
+ s = strrchr(prg_name, '/');
+ if (s != NULL && *++s != '\0') {
+ prg_name = s;
+ }
+
+ term = getenv("TERM");
+
+ cleanup = usage;
+
+ if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'T') {
+ if (argv[1][2] == '\0' && argc > 3) {
+ term = argv[2];
+ argc--;
+ argv++;
+ } else {
+ term = argv[1] + 2;
+ }
+ argc--;
+ argv++;
+ }
+
+ if (argc != 2) {
+ quit(-1, "arg count");
+ }
+
+ cleanup = clean;
+
+ setupterm(term, 1, (int *)0);
+
+ reset = 0;
+ if (strcmp(argv[1], "reset") == 0) {
+ reset = 1;
+ }
+ if (reset || strcmp(argv[1], "init") == 0) {
+
+ if (init_prog != NULL) {
+ system(init_prog);
+ }
+ FLUSH;
+
+ if (reset && reset_1string != NULL) {
+ PUTS(reset_1string);
+ } else if (init_1string != NULL) {
+ PUTS(init_1string);
+ }
+ FLUSH;
+
+ if (reset && reset_2string != NULL) {
+ PUTS(reset_2string);
+ } else if (init_2string != NULL) {
+ PUTS(init_2string);
+ }
+ FLUSH;
+
+ if (set_lr_margin != NULL) {
+ PUTS(tparm(set_lr_margin, 0, columns - 1));
+ } else if (set_left_margin_parm != NULL
+ && set_right_margin_parm != NULL) {
+ PUTS(tparm(set_left_margin_parm, 0));
+ PUTS(tparm(set_right_margin_parm, columns - 1));
+ } else if (clear_margins != NULL && set_left_margin != NULL
+ && set_right_margin != NULL) {
+ PUTS(clear_margins);
+ if (carriage_return != NULL) {
+ PUTS(carriage_return);
+ } else {
+ PUTCHAR('\r');
+ }
+ PUTS(set_left_margin);
+ if (parm_right_cursor) {
+ PUTS(tparm(parm_right_cursor, columns - 1));
+ } else {
+ for(i = 0; i < columns - 1; i++) {
+ PUTCHAR(' ');
+ }
+ }
+ PUTS(set_right_margin);
+ if (carriage_return != NULL) {
+ PUTS(carriage_return);
+ } else {
+ PUTCHAR('\r');
+ }
+ }
+ FLUSH;
+
+ if (init_tabs != 8) {
+ if (clear_all_tabs != NULL && set_tab != NULL) {
+ for(i = 0; i < columns - 1; i += 8) {
+ if (parm_right_cursor) {
+ PUTS(tparm(parm_right_cursor,
+ 8));
+ } else {
+ for(j = 0; j < 8; j++) {
+ PUTCHAR(' ');
+ }
+ }
+ PUTS(set_tab);
+ }
+ FLUSH;
+ }
+ }
+
+ if (reset && reset_file != NULL) {
+ f = fopen(reset_file, "r");
+ if (f == NULL) {
+ quit(errno, "Can't open reset_file: '%s'",
+ reset_file);
+ }
+ while((c = fgetc(f)) != EOF) {
+ PUTCHAR(c);
+ }
+ fclose(f);
+ } else if (init_file != NULL) {
+ f = fopen(init_file, "r");
+ if (f == NULL) {
+ quit(errno, "Can't open init_file: '%s'",
+ init_file);
+ }
+ while((c = fgetc(f)) != EOF) {
+ PUTCHAR(c);
+ }
+ fclose(f);
+ }
+ FLUSH;
+
+ if (reset && reset_3string != NULL) {
+ PUTS(reset_3string);
+ } else if (init_2string != NULL) {
+ PUTS(init_3string);
+ }
+ FLUSH;
+ return 0;
+ }
+
+ s = tigetstr(argv[1]);
+
+ if (s == (char *) -1) {
+ quit(-1, "unknown capname '%s'", argv[1]);
+ } else if (s == NULL) {
+ return 0;
+ }
+
+ putp(s);
+
+ return 0;
+}
diff --git a/lib/libmytinfo/TESTS/tset.c b/lib/libmytinfo/TESTS/tset.c
new file mode 100644
index 0000000..3d1eb65
--- /dev/null
+++ b/lib/libmytinfo/TESTS/tset.c
@@ -0,0 +1,919 @@
+/*
+ * tset.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/19 18:53:12
+ *
+ */
+
+#define NOTLIB
+
+#include "defs.h"
+
+const char SCCSid[] = "@(#) mytinfo tset.c 3.3 92/02/19 public domain, By Ross Ridge";
+
+#define SINGLE
+#include <term.h>
+
+#include <ctype.h>
+
+#if defined(USE_TERMIO) || defined(USE_TERMIOS)
+
+#ifndef ICANON
+#ifdef USE_TERMIO
+#include <termio.h>
+#else
+#include <termios.h>
+#endif
+#endif
+
+#undef USE_SUSPEND
+#ifdef VSUSP
+#define USE_SUSPEND
+#endif
+
+#define USE_INTERRUPT
+
+#if defined(USE_TERMIO) && !defined(TCSETS)
+#undef USE_SUSPEND
+#endif
+
+#else /* USE_TERMIO */
+#ifdef USE_SGTTY
+
+#ifndef CBREAK
+#include <sgtty.h>
+#endif
+
+#undef USE_INTERRUPT
+#ifdef TIOCGETC
+#define USE_INTERRUPT
+#endif
+
+#undef USE_SUSPEND
+#ifdef TIOCGLTC
+#define USE_SUSPEND
+#endif
+
+#undef USE_NEWBSDTTY
+#ifdef TIOCSETD
+#ifdef NTTYDISC
+#define USE_NEWBSDTTY
+#endif
+#endif
+
+#else /* USE_SGTTY */
+
+#undef USE_SUSPEND
+#define USE_NOTTY
+
+#endif /* else USE_SGTTY */
+#endif /* else USE_TERMIO */
+
+#ifndef key_interrupt_char
+#undef USE_INTERRUPT
+#endif
+
+#ifndef key_suspend_char
+#undef USE_SUSPEND
+#endif
+
+char *term;
+int asked = 0;
+long baudrate;
+
+#ifndef USE_STDLIB
+#ifdef USE_PROTOTYPES
+long atol(char const *);
+#else
+long atol();
+#endif
+#endif
+
+#define OUTPUT_TERM 1
+#define OUTPUT_SHELL 2
+#define OUTPUT_TERMCAP 3
+
+#define PUTS(s) tputs(s, 1, putch)
+#define PUTCHAR(c) putc(c, stderr)
+#define FLUSH fflush(stderr)
+
+#ifdef USE_SMALLMEM
+extern unsigned short _baud_tbl[];
+#else
+extern long _baud_tbl[];
+#endif
+
+extern void (*cleanup)();
+
+static void
+clean(e)
+int e; {
+ return;
+}
+
+static int
+#ifdef USE_PROTOTYPES
+putch(char c)
+#else
+putch(c)
+int c;
+#endif
+{
+ return putc(c, stderr);
+}
+
+void
+set_term(name, query)
+char *name;
+int query; {
+ static char buf[MAX_LINE];
+ char *s, *t;
+
+ if (query) {
+ fprintf(stderr, "TERM = (%s) ", name);
+ fflush(stderr);
+ asked = 1;
+ if (fgets(buf, sizeof(buf), stdin) != NULL) {
+ s = buf;
+ while(*s != '\0' && isspace(*s))
+ s++;
+ t = s;
+ while(*s != '\0' && !isspace(*s))
+ s++;
+ *s = '\0';
+ if (*t != '\0') {
+ term = t;
+ return;
+ }
+ }
+ }
+ term = strcpy(buf, name);
+}
+
+int
+map_term(map, ask)
+char *map;
+int ask; {
+ char *type;
+ char test = 0;
+ char *baud = NULL;
+
+ type = map;
+#ifndef USE_NOTTY
+ while(*map && strchr(">@<!:?", *map) == NULL)
+ map++;
+ if (*map != '\0' && *map != ':' && *map != '?') {
+ if (*map == '!') {
+ switch(*++map) {
+ case '>': test = 'g'; break;
+ case '@': test = 'n'; break;
+ case '<': test = 'l'; break;
+ default:
+ quit(-1, "bad argument to 'm' switch");
+ }
+ } else
+ test = *map;
+ *map++ = '\0';
+ baud = map;
+ while(*map && *map != ':')
+ map++;
+ }
+
+#else
+ while(*map && *map != ':' && *map != '?')
+ map++;
+#endif
+
+ if (*map == ':')
+ *map++ = '\0';
+ if (*map == '?') {
+ ask = 1;
+ *map++ = '\0';
+ }
+ if (*map == '\0')
+ quit(-1, "bad argument to 'm' switch");
+
+ if (type[0] != '\0' && strcmp(type, term) != 0) {
+ return 0;
+ }
+
+#ifndef USE_NOTTY
+ switch(test) {
+ case '>':
+ if (baudrate <= atol(baud))
+ return 0;
+ break;
+ case '<':
+ if (baudrate >= atol(baud))
+ return 0;
+ break;
+ case '@':
+ if (baudrate != atol(baud))
+ return 0;
+ break;
+ case 'l':
+ if (baudrate < atol(baud))
+ return 0;
+ break;
+ case 'g':
+ if (baudrate > atol(baud))
+ return 0;
+ break;
+ case 'n':
+ if (baudrate == atol(baud))
+ return 0;
+ break;
+ }
+#endif
+
+ set_term(map, ask);
+ return 1;
+}
+
+int
+conv_char(s)
+char *s; {
+ if (s[0] == '^' && s[1] >= '@' && s[1] < '\177')
+ return s[1] & 31;
+ else if (s[0] == '^' && s[1] == '?')
+ return '\177';
+ else if (s[0] != '\0')
+ return s[0];
+ else
+ return -2;
+}
+
+char *
+expand_char(c)
+int c; {
+ static char buf[5];
+
+ if (c < 0 || c > 127) {
+ sprintf(buf, "\\%03o", c & 0177);
+ } else if (c == 127) {
+ return "DEL";
+ } else if (c < 32) {
+ buf[0] = '^';
+ buf[1] = c + 64;
+ buf[2] = '\0';
+ } else {
+ buf[0] = c;
+ buf[1] = '\0';
+ }
+
+ return buf;
+}
+
+#define START 1
+#define COPY 2
+#define ESCAPE 3
+
+void
+compress_buf(buf)
+char *buf; {
+ char *s, *d;
+ int state = START;
+
+ d = s = buf;
+
+ while(*s) {
+ switch(state) {
+ case START:
+ if (isspace(*s) || *s == ':') {
+ s++;
+ break;
+ }
+ state = COPY;
+ /* FALLTHROUGH */
+ case COPY:
+ switch(*s) {
+ case '^':
+ case '\\':
+ state = ESCAPE;
+ break;
+ case ':':
+ state = START;
+ break;
+ }
+ *d++ = *s++;
+ break;
+
+ case ESCAPE:
+ *d++ = *s++;
+ state = COPY;
+ break;
+ }
+ }
+}
+
+static void
+usage(e)
+int e; {
+#ifdef USE_ANSIC
+ fprintf(stderr, "usage: %s [-] [-"
+#define ARG(s) s
+#else
+ fprintf(stderr, "usage: %s [-] [-", prg_name);
+#define ARG(s) fputs(s, stderr);
+#endif
+ ARG("l")
+#ifndef USE_NOTTY
+#ifdef USE_NEWBSDTTY
+ ARG("n")
+#endif
+#endif
+ ARG("rsAI")
+#ifndef USE_NOTTY
+ ARG("Q")
+#endif
+ ARG("S")
+#ifndef USE_NOTTY
+ ARG("T")
+#endif
+ ARG("]")
+#ifndef USE_NOTTY
+ ARG(" [-e[c]] [-E[c]] [-k[c]]")
+#ifdef USE_INTERRUPT
+ ARG(" [-i[c]]")
+#endif
+#ifdef USE_SUSPEND
+ ARG(" [-z[c]]")
+#endif
+#endif
+ ARG("\n\t[-m ident")
+#ifndef USE_NOTTY
+ ARG("[[!][<@>]speed]")
+#endif
+ ARG(":[?]term] [term]\n")
+#ifdef USE_ANSIC
+ , prg_name);
+#endif
+
+#undef ARG
+
+ return;
+}
+
+int
+main(argc, argv)
+int argc;
+char **argv; {
+ char *s;
+ int i, j, r, c;
+ int ask = 0;
+#ifndef USE_NOTTY
+ int erase_char = -1;
+ int erase_if_bs = 0;
+ int kill_char = -1;
+#ifdef USE_INTERRUPT
+ int interrupt_char = -1;
+#endif
+#ifdef USE_SUSPEND
+ int suspend_char = -1;
+#endif
+#ifdef USE_NEWBSDTTY
+ int newbsdtty = 0;
+#endif
+#endif /* !USE_NOTTY */
+ int output_type = 0;
+ int no_term_init = 0;
+ int term_type_is = 0;
+ int no_set_to = 0;
+ int reset = 0;
+ int matched = 0;
+ int expand_tabs = -1;
+ int is_csh;
+#ifndef USE_NOTTTY
+#if defined(USE_TERMIOS) || defined(USE_TERMIO) && defined(TCSETS)
+ struct termios tty;
+#else
+#ifdef USE_TERMIO
+ struct termio tty;
+#else
+#ifdef USE_SGTTY
+ struct sgttyb tty;
+#ifdef USE_INTERRUPT
+ struct tchars tty2;
+#endif
+#ifdef USE_SUSPEND
+ struct ltchars tty3;
+#endif
+#endif /* USE_SGTTY */
+#endif /* else USE_TERMIO */
+#endif
+#endif /* !USE_NOTTY */
+ struct term_path *path;
+ char buf[MAX_BUF];
+ FILE *f;
+ int datatype;
+
+ prg_name = argv[0];
+ s = strrchr(prg_name, '/');
+ if (s != NULL && *++s != '\0') {
+ if (strcmp(s, "reset") == 0) {
+ reset = 1;
+ }
+ prg_name = s;
+ }
+
+ cleanup = clean;
+
+#ifndef USE_NOTTY
+#ifdef USE_TERMIOS
+ if (tcgetattr(2, &tty) == -1)
+ quit(errno, "tcgetattr failed");
+ baudrate = cfgetospeed(&tty);
+#else
+#ifdef USE_TERMIO
+#ifdef TCSETS
+ if (ioctl(2, TCGETS, &tty) == -1)
+#else
+ if (ioctl(2, TCGETA, &tty) == -1)
+#endif
+ {
+ quit(errno, "ioctl failed");
+ }
+ baudrate = _baud_tbl[tty.c_cflag & CBAUD];
+#else
+#ifdef USE_SGTTY
+ if (gtty(2, &tty) == -1) {
+ quit(errno, "gtty failed");
+ }
+ baudrate = _baud_tbl[tty.sg_ospeed];
+#ifdef USE_INTERRUPT
+ if (ioctl(2, TIOCGETC, &tty2) == -1) {
+ quit(errno, "ioctl failed");
+ }
+#endif
+#ifdef USE_SUSPEND
+ if (ioctl(2, TIOCGLTC, &tty3) == -1) {
+ quit(errno, "ioctl failed");
+ }
+#endif
+#endif /* USE_SGTTY */
+#endif /* else USE_TERMIO */
+#endif
+#endif /* !USE_NOTTY */
+
+ term = getenv("TERM");
+
+ cleanup = usage;
+
+ for(i = 1; i < argc; i++) {
+ if (argv[i][0] != '-') {
+ if (term == NULL) {
+ term = argv[i];
+ }
+ continue;
+ }
+ s = argv[i] + 1;
+ if (*s == '\0') {
+ output_type = OUTPUT_TERM;
+ continue;
+ }
+ while (*s != '\0') {
+ switch(*s++) {
+ case 'A':
+ ask = 1;
+ continue;
+#ifndef USE_NOTTY
+ case 'E':
+ erase_if_bs = 1;
+ /* FALLTHROUGH */
+ case 'e':
+ erase_char = conv_char(s);
+ break;
+ case 'k':
+ kill_char = conv_char(s);
+ break;
+#ifdef USE_INTERRUPT
+ case 'i':
+ interrupt_char = conv_char(s);
+ break;
+#endif
+#ifdef USE_SUSPEND
+ case 'z':
+ suspend_char = conv_char(s);
+ break;
+#endif
+ case 'T':
+ erase_char = kill_char
+#ifdef USE_INTERRUPT
+ = interrupt_char
+#endif
+#ifdef USE_SUSPEND
+ = suspend_char
+#endif
+ = -2;
+ continue;
+#ifdef USE_NEWBSDTTY
+ case 'n':
+ newbsdtty = 1;
+ continue;
+#endif
+ case 'Q':
+ no_set_to = 1;
+ continue;
+#endif /* !USE_NOTTY */
+ case 'l':
+ case 'I':
+ no_term_init = 1;
+ continue;
+ case 'r':
+ term_type_is = 1;
+ continue;
+ case 's':
+ output_type = OUTPUT_SHELL;
+ continue;
+ case 'S':
+ output_type = OUTPUT_TERMCAP;
+ continue;
+ case 'm':
+ if (*s == '\0') {
+ if (i == argc - 1) {
+ quit(-1, "'m' switch requires an argument.");
+ }
+ s = argv[++i];
+ }
+ if (!matched) {
+ matched = map_term(s, ask);
+ }
+ break;
+ default:
+ quit(-1, "unknown switch '%c'", s[-1]);
+ break;
+ }
+ break;
+ }
+ }
+
+ cleanup = clean;
+
+ path = _buildpath("$MYTERMINFO", 2,
+ "$TERMINFO", 2,
+ "$TERMCAP", 1,
+#ifdef TERMINFODIR
+ TERMINFODIR, 0,
+#endif
+#ifdef TERMCAPFILE
+ TERMCAPFILE, 0,
+#endif
+#ifdef TERMINFOSRC
+ TERMINFOSRC, 0,
+#endif
+ NULL, -1);
+
+ if (path == NULL) {
+ quit(-1, "malloc error");
+ }
+
+ do {
+ if (term == NULL) {
+ term = "unknown";
+ }
+
+ if (ask && !asked) {
+ set_term(term, 1);
+ }
+
+ datatype = _fillterm(term, path, buf);
+
+ switch(datatype) {
+ case -3:
+ quit(-1, "malloc error");
+ /* NOTREACHED */
+ case -2:
+ quit(-1, "database in bad format");
+ /* NOTREACHED */
+ case -1:
+ /* quit(-1, "database not found"); */
+ case 0:
+ if (ask || asked) {
+ fprintf(stderr, "terminal type '%s' unknown.\n",
+ term);
+ term = NULL;
+ ask = 1;
+ asked = 0;
+ } else {
+ quit(-1, "terminal type '%s' unknown.\n", term);
+ }
+ break;
+ case 1:
+ case 2:
+ case 3:
+ break;
+ default:
+ quit(-1, "oops...");
+ }
+ } while(term == NULL);
+
+ _delpath(path);
+
+ cur_term->baudrate = baudrate;
+
+ if (!no_term_init) {
+
+ if (init_prog != NULL) {
+ system(init_prog);
+ }
+ FLUSH;
+
+ if (reset && reset_1string != NULL) {
+ PUTS(reset_1string);
+ } else if (init_1string != NULL) {
+ PUTS(init_1string);
+ }
+ FLUSH;
+
+ if (reset && reset_2string != NULL) {
+ PUTS(reset_2string);
+ } else if (init_2string != NULL) {
+ PUTS(init_2string);
+ }
+ FLUSH;
+
+ if (set_lr_margin != NULL) {
+ PUTS(tparm(set_lr_margin, 0, columns - 1));
+ } else if (set_left_margin_parm != NULL
+ && set_right_margin_parm != NULL) {
+ PUTS(tparm(set_left_margin_parm, 0));
+ PUTS(tparm(set_right_margin_parm, columns - 1));
+ } else if (clear_margins != NULL && set_left_margin != NULL
+ && set_right_margin != NULL) {
+ PUTS(clear_margins);
+ if (carriage_return != NULL) {
+ PUTS(carriage_return);
+ } else {
+ PUTCHAR('\r');
+ }
+ PUTS(set_left_margin);
+ if (parm_right_cursor) {
+ PUTS(tparm(parm_right_cursor, columns - 1));
+ } else {
+ for(i = 0; i < columns - 1; i++) {
+ PUTCHAR(' ');
+ }
+ }
+ PUTS(set_right_margin);
+ if (carriage_return != NULL) {
+ PUTS(carriage_return);
+ } else {
+ PUTCHAR('\r');
+ }
+ }
+ FLUSH;
+
+ if (init_tabs != 8) {
+ if (clear_all_tabs != NULL && set_tab != NULL) {
+ if (carriage_return != NULL) {
+ PUTS(carriage_return);
+ } else {
+ PUTCHAR('\r');
+ }
+ PUTS(clear_all_tabs);
+ PUTS(set_tab);
+ for(i = 8; i < columns - 1; i += 8) {
+ if (parm_right_cursor) {
+ PUTS(tparm(parm_right_cursor,
+ 8));
+ } else {
+ for(j = 0; j < 8; j++) {
+ PUTCHAR(' ');
+ }
+ }
+ PUTS(set_tab);
+ }
+ if (carriage_return != NULL) {
+ PUTS(carriage_return);
+ } else {
+ PUTCHAR('\r');
+ }
+ expand_tabs = 0;
+ FLUSH;
+ } else {
+ expand_tabs = 1;
+ }
+ } else {
+ expand_tabs = 0;
+ }
+
+ if (reset && reset_file != NULL) {
+ f = fopen(reset_file, "r");
+ if (f == NULL) {
+ quit(errno, "Can't open reset_file: '%s'",
+ reset_file);
+ }
+ while((c = fgetc(f)) != EOF) {
+ PUTCHAR(c);
+ }
+ fclose(f);
+ } else if (init_file != NULL) {
+ f = fopen(init_file, "r");
+ if (f == NULL) {
+ quit(errno, "Can't open init_file: '%s'",
+ init_file);
+ }
+ while((c = fgetc(f)) != EOF) {
+ PUTCHAR(c);
+ }
+ fclose(f);
+ }
+ FLUSH;
+
+ if (reset && reset_3string != NULL) {
+ PUTS(reset_3string);
+ } else if (init_2string != NULL) {
+ PUTS(init_3string);
+ }
+ FLUSH;
+ }
+
+ if (term_type_is) {
+ fprintf(stderr, "Terminal type is %s\n", term);
+ }
+
+#ifndef USE_NOTTY
+#if defined(USE_TERMIO) || defined(USE_TERMIOS)
+
+#ifdef USE_TERMIO
+ if (expand_tabs == 0 && (tty.c_cflag & TABDLY) == TAB3) {
+ tty.c_cflag = tty.c_cflag & ~TABDLY;
+ } else if (expand_tabs == 1) {
+ tty.c_cflag = (tty.c_cflag & ~TABDLY) | TAB3;
+ }
+#else
+ if (!expand_tabs)
+ tty.c_oflag &= ~OXTABS;
+ else
+ tty.c_oflag |= OXTABS;
+#endif
+
+#define SETTO(v, m, t, c) (c != tty.c_cc[v] ? (tty.c_cc[v] = c, \
+ !no_set_to ? fprintf(stderr, "%s set to %s\n", t, \
+ expand_char(c)) : 0) : 0)
+
+#endif
+#ifdef USE_SGTTY
+
+#ifdef USE_NEWBSDTTY
+ if (newbsdtty) {
+ if (ioctl(2, TIOCSETD, NTTYDISC) == -1) {
+ quit(errno, "Can't switch tty to new line disc.");
+ }
+ }
+#endif
+
+ if (expand_tabs == 0) {
+ tty.sg_flags &= ~XTABS;
+ } else if (expand_tabs == 1) {
+ tty.sg_flags |= XTABS;
+ }
+
+#define SETTO(v, m, t, c) (c != m ? (m = c, \
+ !no_set_to ? fprintf(stderr, "%s set to %s\n", t, \
+ expand_char(c)) : 0) : 0)
+#endif
+
+ if (erase_char != -1
+ && (!erase_if_bs || backspaces_with_bs
+ || (cursor_left == NULL && cursor_left[0] != '\b'))) {
+ if (erase_char != -2) {
+ c = erase_char;
+ } else if (cursor_left == NULL || cursor_left[0] == '\0'
+ || cursor_left[1] != '\0') {
+ c = '\b';
+ } else {
+ c = cursor_left[0];
+ }
+ SETTO(VERASE, tty.sg_erase, "Erase", c);
+ }
+
+ if (kill_char != -1) {
+ if (kill_char != -2) {
+ c = kill_char;
+ } else if (key_kill_char == NULL || key_kill_char[0] == '\0'
+ || key_kill_char[1] != '\0') {
+ c = '\025';
+ } else {
+ c = key_kill_char[0];
+ }
+ SETTO(VKILL, tty.sg_kill, "Kill", c);
+ }
+
+
+#ifdef USE_INTERRUPT
+ if (interrupt_char != -1) {
+ if (interrupt_char != -2) {
+ c = interrupt_char;
+ } else if (key_interrupt_char == NULL
+ || key_interrupt_char[0] == '\0'
+ || key_interrupt_char[1] != '\0') {
+ c = '\177';
+ } else {
+ c = key_interrupt_char[0];
+ }
+ SETTO(VINTR, tty2.t_intrc, "Interrupt", c);
+ }
+#endif
+
+#ifdef USE_SUSPEND
+ if (suspend_char != -1) {
+ if (suspend_char != -2) {
+ c = suspend_char;
+ } else if (key_suspend_char == NULL
+ || key_suspend_char[0] == '\0'
+ || key_suspend_char[1] != '\0') {
+ c = '\032';
+ } else {
+ c = key_suspend_char[0];
+ }
+ SETTO(VSUSP, tty3.t_suspc, "Suspend", c);
+ }
+#endif
+
+#ifdef USE_TERMIOS
+ if (tcsetattr(2, TCSADRAIN, &tty) == -1)
+ quit(errno, "tcsetattr failed");
+#else
+#ifdef USE_TERMIO
+#ifdef TCSETS
+ if (ioctl(2, TCSETS, &tty) == -1)
+#else
+ if (ioctl(2, TCSETA, &tty) == -1)
+#endif
+ {
+ quit(errno, "ioctl failed");
+ }
+#else
+#ifdef USE_SGTTY
+ if (stty(2, &tty) == -1) {
+ quit(errno, "stty failed");
+ }
+#ifdef USE_INTERRUPT
+ if (ioctl(2, TIOCSETC, &tty2) == -1) {
+ quit(errno, "ioctl failed");
+ }
+#endif
+#ifdef USE_SUSPEND
+ if (ioctl(2, TIOCSLTC, &tty3) == -1) {
+ quit(errno, "ioctl failed");
+ }
+#endif
+#endif /* USE_SGTTY */
+#endif /* else USE_TERMIO */
+#endif
+#endif /* !USE_NOTTY */
+
+ s = getenv("SHELL");
+ r = strlen(s);
+
+ if (r >= 3 && strcmp("csh", s + r - 3) == 0) {
+ is_csh = 1;
+ } else {
+ is_csh = 0;
+ }
+
+ switch(output_type) {
+ case OUTPUT_TERM:
+ fprintf(stdout, "%s\n", term);
+ break;
+
+ case OUTPUT_TERMCAP:
+ if (is_csh) {
+ if (datatype == 1) {
+ compress_buf(buf);
+ fprintf(stdout, "%s %s", term, buf);
+ } else {
+ s = getenv("TERMCAP");
+ if (s == NULL || *s == '\0') {
+ s = ":";
+ }
+ fprintf(stdout, "%s %s", term, s);
+ }
+ break;
+ }
+ /* FALLTHROUGH */
+ case OUTPUT_SHELL:
+ if (is_csh) {
+ fprintf(stdout, "set noglob;\n");
+ fprintf(stdout, "setenv TERM '%s';\n", term);
+ if (datatype == 1) {
+ compress_buf(buf);
+ fprintf(stdout, "setenv TERMCAP '%s';\n", buf);
+ }
+ fprintf(stdout, "unset noglob;\n");
+ } else {
+ fprintf(stdout, "export TERM TERMCAP;\n");
+ fprintf(stdout, "TERM='%s';\n", term);
+ if (datatype == 1) {
+ compress_buf(buf);
+ fprintf(stdout, "TERMCAP='%s';\n", buf);
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
diff --git a/lib/libmytinfo/TESTS/ttest.c b/lib/libmytinfo/TESTS/ttest.c
new file mode 100644
index 0000000..d6cc36e
--- /dev/null
+++ b/lib/libmytinfo/TESTS/ttest.c
@@ -0,0 +1,297 @@
+/*
+ * ttest.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:47
+ *
+ */
+
+#define NOTLIB
+#include "defs.h"
+#include <term.h>
+
+const char SCCSid[] = "@(#) mytinfo ttest.c 3.2 92/02/01 public domain, By Ross Ridge";
+
+int
+cup(x,y)
+int x, y; {
+ if (columns < 2 || lines < 2)
+ return -1;
+ if (cursor_address != NULL)
+ putp(tparm(cursor_address, y, x));
+ else if (cursor_home != NULL && cursor_down != NULL
+ && cursor_right != NULL) {
+ putp(cursor_home);
+ if (parm_down_cursor != NULL)
+ putp(tparm(parm_down_cursor, y));
+ else
+ for(; y > 0; y--)
+ putp(cursor_down);
+ if (parm_right_cursor != NULL)
+ putp(tparm(parm_right_cursor, y));
+ else
+ for(; y > 0; y--)
+ putp(cursor_right);
+ } else if (cursor_to_ll != NULL && cursor_up != NULL
+ && cursor_right != NULL) {
+ putp(cursor_to_ll);
+ if (parm_up_cursor != NULL)
+ putp(tparm(parm_up_cursor, y));
+ else
+ for(y++; y < columns ; y++)
+ putp(cursor_up);
+ if (parm_right_cursor != NULL)
+ putp(tparm(parm_right_cursor, y));
+ else
+ for(; y > 0; y--)
+ putp(cursor_right);
+ } else
+ return 1;
+ return 0;
+}
+
+int
+clear() {
+ int r;
+ if (clear_screen != NULL)
+ putp(clear_screen);
+ else if (clr_eos != NULL) {
+ r = cup(0,0);
+ if (r != 0)
+ return r;
+ putp(clr_eos);
+ } else
+ return -2;
+ return 0;
+}
+
+void
+nl() {
+ if (newline != NULL)
+ putp(newline);
+ else if (carriage_return != NULL && cursor_down != NULL) {
+ putp(cursor_down);
+ putp(carriage_return);
+ } else
+ quit(-1, "can't do a newline");
+ return;
+}
+
+void
+putln(s)
+char *s; {
+ int i;
+
+ if (columns < 2 || auto_right_margin)
+ fputs(s, stdout);
+ else {
+ i = 0;
+ while(*s) {
+ putchar(*s);
+ s++;
+ if (++i == columns) {
+ nl();
+ i = 0;
+ }
+ }
+ }
+ nl();
+}
+
+void
+anykey() {
+ fputs("-- press any key --", stdout);
+ fflush(stdout);
+ getchar();
+ nl();
+}
+
+void
+do_cleanup(e)
+int e; {
+ fflush(stdout);
+ fflush(stderr);
+ reset_shell_mode();
+ fprintf(stderr, "\n");
+}
+
+#ifdef USE_SGTTY
+struct sgttyb new_tty;
+#else
+#ifdef USE_TERMIO
+struct termio new_tty;
+#else
+struct termios new_tty;
+#endif
+#endif
+
+int
+main(argc, argv)
+int argc;
+char **argv; {
+ register int i;
+
+ prg_name = argv[0];
+ cleanup = do_cleanup;
+
+ if (argc == 1)
+ setupterm(NULL, 1, (int *) 0);
+ else if (argc == 2)
+ setupterm(argv[1], 1, (int *) 0);
+ else {
+ fprintf(stderr, "usage: %s [terminal]\n", argv[0]);
+ return 1;
+ }
+ fflush(stderr);
+ fflush(stdout);
+#ifdef USE_SGTTY
+ ioctl(1, TIOCGETP, &new_tty);
+ new_tty.sg_flags &= ~(CRMOD | ECHO | XTABS);
+#ifdef CBREAK
+ new_tty.sg_flags |= CBREAK;
+#else
+ new_tty.sg_flags |= RAW;
+#endif
+ ioctl(1, TIOCSETP, &new_tty);
+#endif
+#ifdef USE_TERMIO
+ ioctl(1, TCGETA, &new_tty);
+#else
+#ifdef USE_TERMIOS
+ tcgetattr(1, &new_tty);
+#endif
+#endif
+#if defined(USE_TERMIO) || defined(USE_TERMIOS)
+ new_tty.c_lflag &= ~(ICANON | ECHO);
+ new_tty.c_oflag &= ~(OPOST);
+ new_tty.c_cc[VMIN] = 1;
+ new_tty.c_cc[VTIME] = 1;
+#endif
+#ifdef USE_TERMIO
+ ioctl(1, TCSETA, &new_tty);
+#else
+#ifdef USE_TERMIOS
+ tcsetattr(1, TCSADRAIN, &new_tty);
+#endif
+#endif
+ def_prog_mode();
+
+ clear();
+ printf("columns = %d", columns);
+ nl();
+ printf("lines = %d", lines);
+ if (columns < 2)
+ quit(-1, "columns must be > 1");
+ nl();
+ anykey();
+ nl();
+ if (auto_right_margin) {
+ putln("auto_right_margin = TRUE");
+ nl();
+ for(i = 0; i < columns; i++)
+ putchar('1');
+ for(i = 0; i < columns / 2; i++)
+ putchar('2');
+ nl();
+ } else {
+ putln("auto_right_margin = FALSE");
+ nl();
+ for(i = 0; i < columns + columns / 2; i++)
+ putchar('1');
+ nl();
+ for(i = 0; i < columns / 2; i++)
+ putchar('2');
+ nl();
+ }
+ nl();
+ putln("***a line of 1's followed by a line of 2's");
+ nl();
+ anykey();
+ nl();
+
+ if (over_strike) {
+ putln("over_strike = TRUE");
+ if (cursor_left != NULL) {
+ for(i = 0; i < columns / 4 + 1; i++) {
+ putchar('/');
+ putp(cursor_left);
+ putchar('\\');
+ }
+ } else if (carriage_return != NULL) {
+ for(i = 0; i < columns / 4 + 1; i++)
+ putchar('/');
+ putp(carriage_return);
+ for(i = 0; i < columns / 4 + 1; i++)
+ putchar('\\');
+ }
+ nl();
+ nl();
+ putln("*** X's made from \\'s overstriking /'s");
+ nl();
+ anykey();
+ nl();
+ }
+
+ if (cup(0,0) == 0) {
+ clear();
+ putln("cup test");
+ for(i = 1; i < columns; i++)
+ putp(tparm(cursor_address, 0, i));
+ for(i = 0; i < lines; i++)
+ putp(tparm(cursor_address, i, columns - 1));
+ for(i = columns; i--;)
+ putp(tparm(cursor_address, lines - 1, i));
+ for(i = lines; i--;)
+ putp(tparm(cursor_address, i, 0));
+ nl();
+ anykey();
+ }
+ clear();
+
+ putln("Attribute test");
+ nl();
+ if (enter_blink_mode != NULL) {
+ putp(enter_blink_mode);
+ printf("blink");
+ putp(exit_attribute_mode);
+ nl();
+ }
+ if (enter_bold_mode != NULL) {
+ putp(enter_bold_mode);
+ printf("bold");
+ putp(exit_attribute_mode);
+ nl();
+ }
+ if (enter_dim_mode != NULL) {
+ putp(enter_dim_mode);
+ printf("dim");
+ putp(exit_attribute_mode);
+ nl();
+ }
+ if (enter_reverse_mode != NULL) {
+ putp(enter_reverse_mode);
+ printf("reverse");
+ putp(exit_attribute_mode);
+ nl();
+ }
+ if (enter_standout_mode != NULL) {
+ putp(enter_standout_mode);
+ printf("standout");
+ putp(exit_standout_mode);
+ nl();
+ }
+ if (enter_underline_mode != NULL) {
+ putp(enter_underline_mode);
+ printf("underline");
+ putp(exit_underline_mode);
+ nl();
+ }
+ nl();
+ anykey();
+
+ clear();
+ reset_shell_mode();
+
+ return (0);
+}
diff --git a/lib/libmytinfo/addstr.c b/lib/libmytinfo/addstr.c
new file mode 100644
index 0000000..d3d7444
--- /dev/null
+++ b/lib/libmytinfo/addstr.c
@@ -0,0 +1,88 @@
+/*
+ * addstr.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:34:01
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#include <ctype.h>
+
+#ifdef USE_SCCS_IDS
+static char const SCCSid[] = "@(#) mytinfo addstr.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+/*
+ * I think this routine could be improved, as it is now it searches a
+ * linked list of strbufs for one that has enough room left for the
+ * string. The only thing else I can think of doing would be to
+ * expand a buffer by realloc and then fix the string pointers if it
+ * moves.
+ */
+
+static struct strbuf *strbuf = NULL;
+
+struct strbuf *
+_endstr() {
+ register struct strbuf *p;
+
+ p = strbuf;
+ strbuf = NULL;
+ return p;
+}
+
+char *
+_addstr(s)
+register char *s; {
+ register struct strbuf *p;
+ register int l;
+
+ if (s == NULL) {
+ strbuf = NULL;
+ return NULL;
+ }
+
+ if (strbuf == NULL) {
+ strbuf = (struct strbuf *) malloc(sizeof(struct strbuf));
+ if (strbuf == NULL)
+ return NULL;
+ strbuf->len = 0;
+ strbuf->next = NULL;
+ }
+ l = strlen(s) + 1;
+ if (l > MAX_CHUNK)
+ return NULL;
+ p = strbuf;
+ while (l + p->len > MAX_CHUNK) {
+ if (p->next == NULL) {
+ p->next = (struct strbuf *)
+ malloc(sizeof(struct strbuf));
+ p = p->next;
+ if (p == NULL)
+ return NULL;
+ p->len = 0;
+ p->next = NULL;
+ break;
+ }
+ p = p->next;
+ }
+ s = strcpy(p->buf + p->len, s);
+ p->len += l;
+ return s;
+}
+
+void
+_del_strs(p)
+TERMINAL *p; {
+ struct strbuf *q;
+
+ q = p->strbuf;
+ while(q != NULL) {
+ p->strbuf = q->next;
+ free((anyptr) q);
+ q = p->strbuf;
+ }
+}
diff --git a/lib/libmytinfo/bin_order b/lib/libmytinfo/bin_order
new file mode 100644
index 0000000..e00d342
--- /dev/null
+++ b/lib/libmytinfo/bin_order
@@ -0,0 +1,48 @@
+ bin_order
+
+ By Ross Ridge
+ Public Domain
+ 92/02/01 07:29:39
+
+ Order of entries in a terminfo binary
+
+ @(#) mytinfo bin_order 3.2 92/02/01 public domain, By Ross Ridge
+
+
+!
+bw am xsb xhp xenl eo gn hc km hs in da db mir msgr os eslok xt hz ul
+xon nxon mc5i chts nrrmc npc ndscr ccc bce hls xhpa crxm daisy xvpa sam
+cpix lpix
+
+#
+cols it lines lm xmc pb vt wsl nlab lh lw ma wnum colors pairs ncv bufsz
+spinv spinh maddr mjump mcs mls npins orc orl orhi orvi cps widcs btns
+bitwin bitype
+
+$
+cbt bel cr csr tbc clear el ed hpa cmdch cup cud1 home civis cub1 mrcup cnorm
+cuf1 ll cuu1 cvvis dch1 dl1 dsl hd smacs blink bold smcup smdc dim smir invis
+prot rev smso smul ech rmacs sgr0 rmcup rmdc rmir rmso rmul flash ff fsl is1
+is2 is3 if ich1 il1 ip kbs ktbc kclr kctab kdch1 kdl1 kcud1 krmir kel ked
+kf0 kf1 kf10 kf2 kf3 kf4 kf5 kf6 kf7 kf8 kf9 khome kich1 kil1 kcub1 kll
+knp kpp kcuf1 kind kri khts kcuu1 rmkx smkx lf0 lf1 lf10 lf2 lf3 lf4 lf5
+lf6 lf7 lf8 lf9 rmm smm nel pad dch dl cud ich indn il cub cuf rin cuu pfkey
+pfloc pfx mc0 mc4 mc5 rep rs1 rs2 rs3 rf rc vpa sc ind ri sgr hts wind ht
+tsl uc hu iprog ka1 ka3 kb2 kc1 kc3 mc5p rmp acsc pln kcbt smxon rmxon
+smam rmam xonc xoffc enacs smln rmln kbeg kcan kclo kcmd kcpy kcrt kend
+kent kext kfnd khlp kmrk kmsg kmov knxt kopn kopt kprv kprt krdo kref
+krfr krpl krst kres ksav kspd kund kBEG kCAN kCMD kCPY kCRT kDC kDL kslt
+kEND kEOL kEXT kFND kHLP kHOM kIC kLFT kMSG kMOV kNXT kOPT kPRV kPRT kRDO
+kRPL kRIT kRES kSAV kSPD kUND rfi kf11 kf12 kf13 kf14 kf15 kf16 kf17 kf18
+kf19 kf20 kf21 kf22 kf23 kf24 kf25 kf26 kf27 kf28 kf29 kf30 kf31 kf32
+kf33 kf34 kf35 kf36 kf37 kf38 kf39 kf40 kf41 kf42 kf43 kf44 kf45 kf46 kf47
+kf48 kf49 kf50 kf51 kf52 kf53 kf54 kf55 kf56 kf57 kf58 kf59 kf60 kf61 kf62
+kf63 el1 mgc smgl smgr fln sclk dclk rmclk cwin wingo hup dial qdial tone
+pulse hook pause wait u0 u1 u2 u3 u4 u5 u6 u7 u8 u9 op oc initc initp scp
+setf setb cpi lpi chr cvr defc swidm sdrfq sitm slm smicm snlq snrmq sshm
+ssubm ssupm sum rwidm ritm rlm rmicm rshm rsubm rsupm rum mhpa mcud1 mcub1
+mcuf1 mvpa mcuu1 porder mcud mcub mcuf mcuu scs smgb smgbp smglp smgrp smgt
+smgtp sbim scsd rbim rcsd subcs supcs docr zerom csnm kmous minfo reqmp
+getm setaf setab pfxl devt csin s0ds s1ds s2ds s3ds smglr smgtb birep binel
+bicr colornm defbi endbi setcolor slines dispc smpch rmpch smsc rmsc pctrm
+scesc scesa
diff --git a/lib/libmytinfo/bsearch.c b/lib/libmytinfo/bsearch.c
new file mode 100644
index 0000000..aa4eabf
--- /dev/null
+++ b/lib/libmytinfo/bsearch.c
@@ -0,0 +1,97 @@
+/*
+ * bsearch.c
+ *
+ * This is something I found on watmath. I've made some minor changes for use
+ * in this package.
+ *
+ * 92/06/04 11:35:15
+ */
+
+#if 0
+#ifndef lint
+static char *RCSid = "$OHeader: /usr/mfcf/src/accounts/libuw/RCS/bsearch.c,v 1.1 88/06/11 20:41:48 root Exp $";
+#endif
+#endif
+
+#include "defs.h"
+
+#ifdef USE_MYBSEARCH
+
+#ifdef USE_SCCS_IDS
+static char const SCCSid[] = "@(#) mytinfo bsearch.c 3.4 92/06/04 public domain, By Ross Ridge";
+#endif
+
+#ifdef USE_SHORT_BSEARCH
+#define fast_int short
+#else
+#define fast_int mysize_t
+#endif
+
+/*
+ * bsearch - find an element of a sorted vector
+ *
+ * found = bsearch(key, array, dimension, width, compare)
+ * returns a pointer to the specified element in the array,
+ * or (char*)0 if the element can't be found.
+ * key
+ * pointer to the element to be searched for in the array
+ * array
+ * address of an array of elements
+ * dimension
+ * number of elements in the array
+ * width
+ * sizeof(type) of each element
+ * compare
+ * pointer to a function taking (char *) pointers to two elements
+ * and returning <0, 0, or >0 as the first element comes before,
+ * at, or after the second element. A compare function is provided
+ * for comparing strings.
+*/
+#if 0
+/*
+ * $OLog: bsearch.c,v $
+ * Revision 1.1 88/06/11 20:41:48 root
+ * Initial revision
+ *
+*/
+#endif
+
+ static anyptr
+bsearch(key, array, dimension, iwidth, compare)
+ anyptr key;
+ anyptr array;
+ int dimension;
+ mysize_t iwidth;
+ compar_fn compare;
+{
+ register fast_int start; /* offset to start of current interval */
+ register fast_int end; /* offset to end+1 of current interval */
+ register fast_int middle; /* offset to middle of current interval */
+ auto int status;
+ register fast_int width;
+
+ width = iwidth / sizeof(char);
+
+ start = 0;
+ middle = 0;
+ end = dimension;
+
+ while (start < end) {
+
+ middle = (start + end) / 2;
+
+ status = (*compare)(key, ((char *)array + middle*width));
+
+ if (status < 0)
+ end = middle;
+
+ else if (status > 0)
+ start = middle + 1;
+
+ else return (anyptr)(((char *)array) + middle*width);
+ }
+
+ return 0;
+}
+
+#endif /* USE_MYBSEARCH */
diff --git a/lib/libmytinfo/buildpath.c b/lib/libmytinfo/buildpath.c
new file mode 100644
index 0000000..cecba42
--- /dev/null
+++ b/lib/libmytinfo/buildpath.c
@@ -0,0 +1,203 @@
+/*
+ * buildpath.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:29:42
+ *
+ * _buildpath builds a list of file names and terminal descriprions extracted
+ * from its arguments. It returns a pointer to a structure that is used by
+ * other routines as the list of file names to search for terminal
+ * descriptions. It is passed a variable number of arguments consisting
+ * of file name and type pairs. The file name can actually be a list of
+ * file names seperated by spaces and any environment variables specified
+ * by a dollar sign ($) followed by its name are substituted in. A type
+ * of 1 indicates that the file name may actually be termcap description
+ * and a type of 2 indicates it may be a terminfo description. A type of 0
+ * indicates that the file name can only be a file name (or list of them).
+ *
+ */
+
+#include "defs.h"
+
+#include <ctype.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo buildpath.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+/* more memory is allocated for file names every HUNK file names */
+#define HUNK 32
+
+/* characters that seperate file names in a list */
+#define SEPERATORS " :"
+
+static struct term_path *path = NULL; /* the list of files */
+static int files = 0; /* # of files in the list */
+static int size = 0; /* # of files there is space for */
+
+/* add a file name, type pair to the list */
+static int
+addfile(file, type)
+char *file;
+int type; {
+ int l;
+ char *s;
+
+ if (file == NULL) {
+ if (type != -1)
+ return -1;
+ } else if (file[0] == '\0')
+ return -1;
+
+#ifdef DEBUG
+ if (file != NULL)
+ printf("addfile: %s\n", file);
+#endif
+
+ if (files >= size) {
+ size += HUNK;
+ if (path == NULL)
+ path = (struct term_path *)
+ malloc(size * sizeof(struct term_path));
+ else
+ path = (struct term_path *)
+ realloc((anyptr) path,
+ size * sizeof(struct term_path));
+ if (path == NULL)
+ return 0;
+ }
+ if (file == NULL) {
+ path[files].file = file;
+ } else {
+ l = strlen(file) + 1;
+ s = (char *) malloc(l * sizeof(char));
+ if (s == NULL)
+ return 0;
+ path[files].file = strcpy(s, file);
+ }
+ path[files].type = type;
+
+ return ++files;
+}
+
+/* deallocate space used by the path list */
+void
+_delpath(ppath)
+struct term_path *ppath; {
+ struct term_path *p;
+
+ p = ppath;
+ while(p->file != NULL) {
+ free((anyptr)p->file);
+ p++;
+ }
+
+ free((anyptr)ppath);
+}
+
+/* build a list of paths. see above */
+#ifdef lint
+/*VARARGS2*/
+struct term_path *
+_buildpath(file, type)
+char *file;
+int type;
+#else
+#ifdef USE_STDARG
+#ifdef USE_PROTOTYPES
+struct term_path *_buildpath(char *file, int type, ...)
+#else
+struct term_path *_buildpath(file, type)
+char *file;
+int type;
+#endif /* USE_PROTOTYPES */
+#else /* USE_STDARG */
+struct term_path *_buildpath(va_alist)
+va_dcl
+#endif /* USE_STDARG */
+#endif /* lint */
+{
+#ifndef lint
+#ifndef USE_STDARG
+ char *file;
+ int type;
+#endif
+#endif
+ va_list ap;
+ register char *s, *d, *e;
+ char *p;
+ char line[MAX_BUF+1];
+ char name[MAX_NAME+1];
+ int i,j;
+
+ size = 0;
+ files = 0;
+ path = NULL;
+
+#ifdef lint
+ ap = NULL;
+#else
+#ifdef USE_STDARG
+ va_start(ap, type);
+#else
+ va_start(ap);
+ file = va_arg(ap, char *);
+ type = va_arg(ap, int);
+#endif
+#endif
+
+ while (type >= 0 && type <= 2) {
+ s = file;
+ d = line;
+ i = 0;
+ while(*s != '\0') {
+ if (*s == '$') {
+ s++;
+ j = 0;
+ while(*s != '\0' && (*s == '_' || isalnum(*s)))
+ if (j < MAX_NAME) {
+ name[j] = *s++;
+ j++;
+ } else
+ break;
+ name[j] = '\0';
+ e = getenv(name);
+ if (e != NULL) {
+ while(*e != '\0') {
+ if (i < MAX_BUF) {
+ *d++ = *e++;
+ i++;
+ } else
+ break;
+ }
+ } else if (*s == '/')
+ s++;
+ } else {
+ if (i < MAX_BUF) {
+ *d++ = *s++;
+ i++;
+ } else
+ break;
+ }
+ }
+ *d = '\0';
+ if (type == 0 || line[0] == '/') {
+ p = line;
+ while ((s = strsep(&p, SEPERATORS)) != NULL && *s == '\0')
+ ;
+ while(s != NULL) {
+ if (addfile(s, 0) == 0)
+ return NULL;
+ while ((s = strsep(&p, SEPERATORS)) != NULL && *s == '\0')
+ ;
+ }
+ } else
+ if (addfile(line, type) == 0)
+ return NULL;
+ file = va_arg(ap, char *);
+ type = va_arg(ap, int);
+ }
+ addfile(NULL, -1);
+ return path;
+}
diff --git a/lib/libmytinfo/cap_list b/lib/libmytinfo/cap_list
new file mode 100644
index 0000000..8acf973
--- /dev/null
+++ b/lib/libmytinfo/cap_list
@@ -0,0 +1,529 @@
+ cap_list
+
+ By Ross Ridge
+ Public Domain
+ 92/02/01 07:29:44
+
+ @(#) mytinfo cap_list 3.2 92/02/01 public domain, By Ross Ridge
+
+types: ! = boolean, # = number, $ = string, $G = string with parameters,
+ $K = string that never is outputed (with tputs).
+
+type variable capname termcap
+
+Standard terminfo capabilities:
+
+! auto_left_margin bw bw
+! auto_right_margin am am
+! ceol_standout_glitch xhp xs
+! dest_tabs_magic_smso xt xt
+! eat_newline_glitch xenl xn
+! erase_overstrike eo eo
+! generic_type gn gn
+! hard_copy hc hc
+! hard_cursor chts HC
+! has_meta_key km km
+! has_status_line hs hs
+! insert_null_glitch in in
+! memory_above da da
+! memory_below db db
+! move_insert_mode mir mi
+! move_standout_mode msgr ms
+! needs_xon_xoff nxon nx
+! no_esc_ctlc xsb xb
+! no_pad_char npc NP
+! non_rev_rmcup nrrmc NR
+! over_strike os os
+! prtr_silent mc5i 5i
+! status_line_esc_ok eslok es
+! tilde_glitch hz hz
+! transparent_underline ul ul
+! xon_xoff xon xo
+# columns cols co
+# init_tabs it it
+# label_height lh lh
+# label_width lw lw
+# lines lines li
+# lines_of_memory lm lm
+# magic_cookie_glitch xmc sg
+# num_labels nlab Nl
+# padding_baud_rate pb pb
+# virtual_terminal vt vt
+# width_status_line wsl ws
+$K acs_chars acsc ac
+$ back_tab cbt bt
+$ bell bel bl
+$ carriage_return cr cr
+$G change_scroll_region csr cs
+$ char_padding rmp rP
+$ clear_all_tabs tbc ct
+$ clear_margins mgc MC
+$ clear_screen clear cl
+$ clr_bol el1 cb
+$ clr_eol el ce
+$ clr_eos ed cd
+$G column_address hpa ch
+$K command_character cmdch CC
+$G cursor_address cup cm
+$ cursor_down cud1 do
+$ cursor_home home ho
+$ cursor_invisible civis vi
+$ cursor_left cub1 le
+$G cursor_mem_address mrcup CM
+$ cursor_normal cnorm ve
+$ cursor_right cuf1 nd
+$ cursor_to_ll ll ll
+$ cursor_up cuu1 up
+$ cursor_visible cvvis vs
+$ delete_character dch1 dc
+$ delete_line dl1 dl
+$ dis_status_line dsl ds
+$ down_half_line hd hd
+$ ena_acs enacs eA
+$ enter_alt_charset_mode smacs as
+$ enter_am_mode smam SA
+$ enter_blink_mode blink mb
+$ enter_bold_mode bold md
+$ enter_ca_mode smcup ti
+$ enter_delete_mode smdc dm
+$ enter_dim_mode dim mh
+$ enter_insert_mode smir im
+$ enter_protected_mode prot mp
+$ enter_reverse_mode rev mr
+$ enter_secure_mode invis mk
+$ enter_standout_mode smso so
+$ enter_underline_mode smul us
+$ enter_xon_mode smxon SX
+$G erase_chars ech ec
+$ exit_alt_charset_mode rmacs ae
+$ exit_am_mode rmam RA
+$ exit_attribute_mode sgr0 me
+$ exit_ca_mode rmcup te
+$ exit_delete_mode rmdc ed
+$ exit_insert_mode rmir ei
+$ exit_standout_mode rmso se
+$ exit_underline_mode rmul ue
+$ exit_xon_mode rmxon RX
+$ flash_screen flash vb
+$ form_feed ff ff
+$ from_status_line fsl fs
+$ init_1string is1 i1
+$ init_2string is2 is
+$ init_3string is3 i3
+$K init_file if if
+$K init_prog iprog iP
+$ insert_character ich1 ic
+$ insert_line il1 al
+$ insert_padding ip ip
+$K key_a1 ka1 K1
+$K key_a3 ka3 K3
+$K key_b2 kb2 K2
+$K key_backspace kbs kb
+$K key_beg kbeg @1
+$K key_btab kcbt kB
+$K key_c1 kc1 K4
+$K key_c3 kc3 K5
+$K key_cancel kcan @2
+$K key_catab ktbc ka
+$K key_clear kclr kC
+$K key_close kclo @3
+$K key_command kcmd @4
+$K key_copy kcpy @5
+$K key_create kcrt @6
+$K key_ctab kctab kt
+$K key_dc kdch1 kD
+$K key_dl kdl1 kL
+$K key_down kcud1 kd
+$K key_eic krmir kM
+$K key_end kend @7
+$K key_enter kent @8
+$K key_eol kel kE
+$K key_eos ked kS
+$K key_exit kext @9
+$K key_f0 kf0 k0
+$K key_f1 kf1 k1
+$K key_f10 kf10 k;
+$K key_f11 kf11 F1
+$K key_f12 kf12 F2
+$K key_f13 kf13 F3
+$K key_f14 kf14 F4
+$K key_f15 kf15 F5
+$K key_f16 kf16 F6
+$K key_f17 kf17 F7
+$K key_f18 kf18 F8
+$K key_f19 kf19 F9
+$K key_f2 kf2 k2
+$K key_f20 kf20 FA
+$K key_f21 kf21 FB
+$K key_f22 kf22 FC
+$K key_f23 kf23 FD
+$K key_f24 kf24 FE
+$K key_f25 kf25 FF
+$K key_f26 kf26 FG
+$K key_f27 kf27 FH
+$K key_f28 kf28 FI
+$K key_f29 kf29 FJ
+$K key_f3 kf3 k3
+$K key_f30 kf30 FK
+$K key_f31 kf31 FL
+$K key_f32 kf32 FM
+$K key_f33 kf33 FN
+$K key_f34 kf34 FO
+$K key_f35 kf35 FP
+$K key_f36 kf36 FQ
+$K key_f37 kf37 FR
+$K key_f38 kf38 FS
+$K key_f39 kf39 FT
+$K key_f4 kf4 k4
+$K key_f40 kf40 FU
+$K key_f41 kf41 FV
+$K key_f42 kf42 FW
+$K key_f43 kf43 FX
+$K key_f44 kf44 FY
+$K key_f45 kf45 FZ
+$K key_f46 kf46 Fa
+$K key_f47 kf47 Fb
+$K key_f48 kf48 Fc
+$K key_f49 kf49 Fd
+$K key_f5 kf5 k5
+$K key_f50 kf50 Fe
+$K key_f51 kf51 Ff
+$K key_f52 kf52 Fg
+$K key_f53 kf53 Fh
+$K key_f54 kf54 Fi
+$K key_f55 kf55 Fj
+$K key_f56 kf56 Fk
+$K key_f57 kf57 Fl
+$K key_f58 kf58 Fm
+$K key_f59 kf59 Fn
+$K key_f6 kf6 k6
+$K key_f60 kf60 Fo
+$K key_f61 kf61 Fp
+$K key_f62 kf62 Fq
+$K key_f63 kf63 Fr
+$K key_f7 kf7 k7
+$K key_f8 kf8 k8
+$K key_f9 kf9 k9
+$K key_find kfnd @0
+$K key_help khlp %1
+$K key_home khome kh
+$K key_ic kich1 kI
+$K key_il kil1 kA
+$K key_left kcub1 kl
+$K key_ll kll kH
+$K key_mark kmrk %2
+$K key_message kmsg %3
+$K key_move kmov %4
+$K key_next knxt %5
+$K key_npage knp kN
+$K key_open kopn %6
+$K key_options kopt %7
+$K key_ppage kpp kP
+$K key_previous kprv %8
+$K key_print kprt %9
+$K key_redo krdo %0
+$K key_reference kref &1
+$K key_refresh krfr &2
+$K key_replace krpl &3
+$K key_restart krst &4
+$K key_resume kres &5
+$K key_right kcuf1 kr
+$K key_save ksav &6
+$K key_sbeg kBEG &9
+$K key_scancel kCAN &0
+$K key_scommand kCMD *1
+$K key_scopy kCPY *2
+$K key_screate kCRT *3
+$K key_sdc kDC *4
+$K key_sdl kDL *5
+$K key_select kslt *6
+$K key_send kEND *7
+$K key_seol kEOL *8
+$K key_sexit kEXT *9
+$K key_sf kind kF
+$K key_sfind kFND *0
+$K key_shelp kHLP #1
+$K key_shome kHOM #2
+$K key_sic kIC #3
+$K key_sleft kLFT #4
+$K key_smessage kMSG %a
+$K key_smove kMOV %b
+$K key_snext kNXT %c
+$K key_soptions kOPT %d
+$K key_sprevious kPRV %e
+$K key_sprint kPRT %f
+$K key_sr kri kR
+$K key_sredo kRDO %g
+$K key_sreplace kRPL %h
+$K key_sright kRIT %i
+$K key_srsume kRES %j
+$K key_ssave kSAV !1
+$K key_ssuspend kSPD !2
+$K key_stab khts kT
+$K key_sundo kUND !3
+$K key_suspend kspd &7
+$K key_undo kund &8
+$K key_up kcuu1 ku
+$ keypad_local rmkx ke
+$ keypad_xmit smkx ks
+$K lab_f0 lf0 l0
+$K lab_f1 lf1 l1
+$K lab_f10 lf10 la
+$K lab_f2 lf2 l2
+$K lab_f3 lf3 l3
+$K lab_f4 lf4 l4
+$K lab_f5 lf5 l5
+$K lab_f6 lf6 l6
+$K lab_f7 lf7 l7
+$K lab_f8 lf8 l8
+$K lab_f9 lf9 l9
+$ label_off rmln LF
+$ label_on smln LO
+$ meta_off rmm mo
+$ meta_on smm mm
+$ newline nel nw
+$K pad_char pad pc
+$G parm_dch dch DC
+$G parm_delete_line dl DL
+$G parm_down_cursor cud DO
+$G parm_ich ich IC
+$G parm_index indn SF
+$G parm_insert_line il AL
+$G parm_left_cursor cub LE
+$G parm_right_cursor cuf RI
+$G parm_rindex rin SR
+$G parm_up_cursor cuu UP
+$G pkey_key pfkey pk
+$G pkey_local pfloc pl
+$G pkey_xmit pfx px
+$G plab_norm pln pn
+$ print_screen mc0 ps
+$G prtr_non mc5p pO
+$ prtr_off mc4 pf
+$ prtr_on mc5 po
+$G repeat_char rep rp
+$ req_for_input rfi RF
+$ reset_1string rs1 r1
+$ reset_2string rs2 r2
+$ reset_3string rs3 r3
+$K reset_file rf rf
+$ restore_cursor rc rc
+$G row_address vpa cv
+$ save_cursor sc sc
+$ scroll_forward ind sf
+$ scroll_reverse ri sr
+$G set_attributes sgr sa
+$ set_left_margin smgl ML
+$ set_right_margin smgr MR
+$ set_tab hts st
+$G set_window wind wi
+$ tab ht ta
+$G to_status_line tsl ts
+$ underline_char uc uc
+$ up_half_line hu hu
+$ xoff_character xoffc XF
+$ xon_character xonc XN
+
+Release 3.2 and 4 capabilities (AMIX)
+(some of the string attributes are guesses...)
+
+! back_color_erase bce ut
+! can_change ccc cc
+! col_addr_glitch xhpa YA
+! cpi_changes_res cpix YF
+! cr_cancels_micro_mode crxm YB
+! has_print_wheel daisy YC
+! hue_lightness_saturation hls hl
+! lpi_changes_res lpix YG
+! non_dest_scroll_region ndscr ND
+! row_addr_glitch xvpa YD
+! semi_auto_right_margin sam YE
+# bit_image_entwining bitwin Yo
+# bit_image_type bitype Yp
+# buffer_capacity bufsz Ya
+# buttons btns BT
+# dot_horz_spacing spinh Yc
+# dot_vert_spacing spinv Yb
+# max_attributes ma ma
+# max_colors colors Co
+# max_micro_address maddr Yd
+# max_micro_jump mjump Ye
+# max_pairs pairs pa
+# maximum_windows wnum MW
+# micro_char_size mcs Yf
+# micro_line_size mls Yg
+# no_color_video ncv NC
+# number_of_pins npins Yh
+# output_res_char orc Yi
+# output_res_horz_inch orhi Yk
+# output_res_line orl Yj
+# output_res_vert_inch orvi Yl
+# print_rate cps Ym
+# wide_char_size widcs Yn
+$ alt_scancode_esc scesa S8
+$G bit_image_carriage_return bicr Yv
+$G bit_image_newline binel Zz
+$G bit_image_repeat birep Xy
+$G change_char_pitch cpi ZA
+$G change_line_pitch lpi ZB
+$G change_res_horz chr ZC
+$G change_res_vert cvr ZD
+$G char_set_names csnm Zy
+$ code_set_init csin ci
+$G color_names colornm Yw
+$G create_window cwin CW
+$G define_bit_image_region defbi Yx
+$G define_char defc ZE
+$ device_type devt dv
+$G dial_phone dial DI
+$ display_clock dclk DK
+$ display_pc_char dispc S1
+$ end_bit_image_region endbi Yy
+$ enter_doublewide_mode swidm ZF
+$ enter_draft_quality sdrfq ZG
+$ enter_italics_mode sitm ZH
+$ enter_leftward_mode slm ZI
+$ enter_micro_mode smicm ZJ
+$ enter_near_letter_quality snlq ZK
+$ enter_normal_quality snrmq ZL
+$ enter_pc_charset_mode smpch S2
+$ enter_scancode_mode smsc S4
+$ enter_shadow_mode sshm ZM
+$ enter_subscript_mode ssubm ZN
+$ enter_superscript_mode ssupm ZO
+$ enter_upward_mode sum ZP
+$ exit_doublewide_mode rwidm ZQ
+$ exit_italics_mode ritm ZR
+$ exit_leftward_mode rlm ZS
+$ exit_micro_mode rmicm ZT
+$ exit_pc_charset_mode rmpch S3
+$ exit_scancode_mode rmsc S5
+$ exit_shadow_mode rshm ZU
+$ exit_subscript_mode rsubm ZV
+$ exit_superscript_mode rsupm ZW
+$ exit_upward_mode rum ZX
+$ fixed_pause pause PA
+$ flash_hook hook fh
+$ get_mouse getm Gm
+$G goto_window wingo WG
+$ hangup hup HU
+$G initialize_color initc Ic
+$G initialize_pair initp Ip
+$ key_mouse kmous Km
+$ label_format fln Lf
+$G micro_column_address mhpa ZY
+$ micro_down mcud1 ZZ
+$ micro_left mcub1 Za
+$ micro_right mcuf1 Zb
+$G micro_row_address mvpa Zc
+$ micro_up mcuu1 Zd
+$ mouse_info minfo Mi
+$K order_of_pins porder Ze
+$ orig_colors oc oc
+$ orig_pair op op
+$G parm_down_micro mcud Zf
+$G parm_left_micro mcub Zg
+$G parm_right_micro mcuf Zh
+$G parm_up_micro mcuu Zi
+$ pc_term_options pctrm S6
+$G pkey_plab pfxl xl
+$ pulse pulse PU
+$ quick_dial qdial QD
+$ remove_clock rmclk RC
+$ req_mouse_pos reqmp RQ
+$ scancode_escape scesc S7
+$G select_char_set scs Zj
+$ set0_des_seq s0ds s0
+$ set1_des_seq s1ds s1
+$ set2_des_seq s2ds s2
+$ set3_des_seq s3ds s3
+$G set_a_background setab AB
+$G set_a_foreground setaf AF
+$G set_background setb Sb
+$ set_bottom_margin smgb Zk
+$G set_bottom_margin_parm smgbp Zl
+$G set_clock sclk SC
+$G set_color_band setcolor Yz
+$G set_color_pair scp sp
+$G set_foreground setf Sf
+$G set_left_margin_parm smglp Zm
+$G set_lr_margin smglr ML
+$G set_page_length slines YZ
+$G set_right_margin_parm smgrp Zn
+$G set_tb_margin smgtb MT
+$ set_top_margin smgt Zo
+$G set_top_margin_parm smgtp Zp
+$G start_bit_image sbim Zq
+$G start_char_set_def scsd Zr
+$ stop_bit_image rbim Zs
+$G stop_char_set_def rcsd Zt
+$K subscript_characters subcs Zu
+$K superscript_characters supcs Zv
+$K these_cause_cr docr Zw
+$ tone tone TO
+$ user0 u0 u0
+$ user1 u1 u1
+$ user2 u2 u2
+$ user3 u3 u3
+$ user4 u4 u4
+$ user5 u5 u5
+$ user6 u6 u6
+$ user7 u7 u7
+$ user8 u8 u8
+$ user9 u9 u9
+$ wait_tone wait WA
+$ zero_motion zerom Zx
+
+"Obsolete" termcap capabilities (variable and terminfo names are mine)
+
+$ backspace_if_not_bs OTbc bc
+! backspaces_with_bs OTbs bs
+# backspace_delay OTdB dB
+# carriage_return_delay OTdC dC
+# form_feed_delay OTdF dF
+# new_line_delay OTdN dN
+# horizontal_tab_delay OTdT dT
+# vertical_tab_delay OTdV dV
+! even_parity OTEP EP
+! half_duplex OTHD HD
+# number_of_function_keys OTkn kn
+$K other_non_function_keys OTko ko
+! lower_case_only OTLC LC
+$K arrow_key_map OTma ma
+$ memory_lock_above OTml ml
+$ memory_unlock OTmu mu
+! no_correctly_working_cr OTnc nc
+! linefeed_is_newline OTNL NL
+$ linefeed_if_not_lf OTnl nl
+! crt_without_scrolling OTns ns
+! odd_parity OTOP OP
+! has_hardware_tabs OTpt pt
+! uppercase_only OTUC UC
+! return_does_clr_eol OTxr xr
+! tek_4025_insert_line OTxx xx
+# magic_cookie_glitch_ul OTug ug
+
+Caps used by the University of Waterloo (variable and terminfo names are mine)
+
+$K key_interrupt_char UWki ki
+$K key_kill_char UWkk kk
+$K key_suspend_char UWkz kz
+! initialization_messy UWxc xc
+! index_at_bottom_does_cr UWxl xl
+
+! rind_only_at_top OTxq xq
+
+Different names for existing terminfo caps used by GNU Emacs:
+! GNU_has_meta_key GNUMT MT
+# GNU_tab_width GNUtw tw
+
+Non standard capabilities:
+
+$ scroll_left sl1 Sl
+$ scroll_right sr1 Sr
+$G parm_scroll_left sl SL
+$G parm_scroll_right sr SI
+
+Dummy (must be present and last):
+
+$K _get_other use tc
diff --git a/lib/libmytinfo/compar.c b/lib/libmytinfo/compar.c
new file mode 100644
index 0000000..f8998d3
--- /dev/null
+++ b/lib/libmytinfo/compar.c
@@ -0,0 +1,40 @@
+/*
+ * compar.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/06/04 11:36:24
+ *
+ */
+
+#include "defs.h"
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo compar.c 3.3 92/06/04 public domain, By Ross Ridge";
+#endif
+
+/* compare two elements a sorted list of pointers to strings */
+int
+_compar(a, b)
+#ifdef USE_ANSIC
+void const *a;
+void const *b; {
+#else
+anyptr a, b; {
+#endif
+ register char *aa = **(char ***)a;
+ register char *bb = **(char ***)b;
+
+ /* An optimization trick from C News, compare the first
+ * two chars of the string here to avoid a the overhead of a
+ * call to strcmp.
+ */
+
+#ifdef __GNUC__
+ return ((*aa - *bb) ? : strcmp(aa, bb));
+#else
+ if (*aa != *bb)
+ return *aa - *bb;
+ return strcmp(aa, bb);
+#endif
+}
diff --git a/lib/libmytinfo/config.h b/lib/libmytinfo/config.h
new file mode 100644
index 0000000..87afa05
--- /dev/null
+++ b/lib/libmytinfo/config.h
@@ -0,0 +1,89 @@
+/*
+ * config.h
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/19 18:56:28
+ *
+ * @(#) mytinfo config.h 3.3 92/02/19 public domain, By Ross Ridge
+ *
+ * Read the file INSTALL for more information on configuring mytinfo
+ *
+ */
+
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+#ifdef __STDC__
+#define USE_ANSIC /* undefine this if your compiler lies */
+#endif
+
+#define USE_TERMIOS /* use POSIX termios */
+#undef USE_TERMIO /* use termio (SysIII, SysV) */
+#undef USE_SGTTY /* use sgtty (v7, BSD) */
+#define USE_WINSZ /* get window size from the tty driver */
+#undef USE_STRINGS /* include <strings.h> instead of <string.h> */
+#undef USE_MYBSEARCH /* your library doesn't have bsearch */
+#undef USE_MYSTRTOK /* your library doesn't have strtok */
+#undef USE_MYQSORT /* your library doesn't have qsort */
+#undef USE_MYMKDIR /* your library doesn't have mkdir */
+#define USE_MEMORY /* you have an <memory.h> header */
+#undef USE_FAKE_STDIO /* don't use real stdio */
+#undef USE_DOPRNT /* no vfprintf, use _doprnt */
+#undef USE_TERMINFO /* look in terminfo dirs for entry */
+#define USE_TERMCAP /* look in termcap dirs for entry */
+
+#undef USE_SHORT_BSEARCH /* speeds up MYBSEARCH on most machines */
+
+#undef USE_SMALLMEM /* save some memory */
+
+#undef USE_UPBC_KLUDGE /* do tgoto like real togo */
+#undef USE_EXTERN_UPBC /* get cuu1 and cub1 from externs UP and BC */
+#undef USE_LITOUT_KLUDGE /* an alternate tgoto kludge, not recommened */
+
+
+#ifndef USE_ANSIC
+
+#undef USE_PROTOTYPES /* use ANSI C prototypes */
+#undef USE_STDLIB /* you have a <stdlib.h> */
+#undef USE_STDARG /* you have a <stdarg.h> */
+#undef USE_STDDEF /* you have a <stddef.h> */
+
+#define const
+#define volatile
+#define noreturn /* a function that doesn't return */
+
+typedef char *anyptr; /* a type that any pointer can be assigned to */
+
+#define mysize_t unsigned /* size_t, the size of an object */
+
+#else /* USE_ANSIC */
+
+#define USE_PROTOTYPES
+#define USE_STDLIB
+#define USE_STDARG
+#define USE_STDDEF
+
+typedef void *anyptr;
+
+#define mysize_t size_t
+
+#ifdef __GNUC__
+#define noreturn volatile
+#else
+#define noreturn
+#endif
+
+#endif /* USE_ANSIC */
+
+#ifdef __FreeBSD__
+#define TERMCAPFILE "$TERMCAPFILE $HOME/.termcap /usr/share/misc/termcap"
+#else
+#define TERMCAPFILE "$TERMCAPFILE $HOME/.termcap /etc/termcap"
+#endif
+
+#define TERMINFOSRC "/usr/lib/terminfo/terminfo.src"
+
+#define TERMINFODIR "/usr/lib/terminfo"
+
+#endif
diff --git a/lib/libmytinfo/defs.h b/lib/libmytinfo/defs.h
new file mode 100644
index 0000000..7b8e8d9
--- /dev/null
+++ b/lib/libmytinfo/defs.h
@@ -0,0 +1,195 @@
+/*
+ * defs.h
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/06/04 11:37:02
+ *
+ * @(#) mytinfo defs.h 3.3 92/06/04 public domain, By Ross Ridge
+ */
+
+#ifndef _DEFS_H_
+#define _DEFS_H_
+
+#ifdef TEST
+#undef NOTLIB
+#define NOTLIB
+#endif
+
+#include "config.h"
+
+#ifdef NOTLIB
+#undef USE_FAKE_STDIO
+#endif
+
+#ifdef USE_STDDEF
+#include <stddef.h>
+#else
+#include <sys/types.h>
+#endif
+
+#ifdef USE_STDLIB
+#include <stdlib.h>
+#else
+#ifdef USE_PROTOTYPES
+anyptr malloc(mysize_t);
+anyptr realloc(anyptr, mysize_t);
+char *getenv(char const *);
+#else
+anyptr malloc();
+anyptr realloc();
+char *getenv();
+#endif
+#endif
+
+#ifdef USE_STDARG
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifndef _VA_LIST
+#define _VA_LIST
+#endif
+
+#ifdef USE_FAKE_STDIO
+#include "fake_stdio.h"
+#define sprintf _fake_sprintf
+#ifdef USE_PROTOTYPES
+int sprintf(char *, char *, ...);
+#else
+int sprintf();
+#endif
+#else /* USE_FAKE_STDIO */
+#if 0
+#include <stdio.h>
+#else
+#undef NULL
+#include <stdio.h>
+#endif
+#endif /* !USE_FAKE_STDIO */
+
+#ifdef USE_STRINGS
+#include <strings.h>
+#define strchr(s, c) index(s, c)
+#define strrchr(s, c) rindex(s, c)
+#ifndef USE_MYSTRTOK
+#ifdef USE_PROTOTYPES
+char *strtok(char *, char *);
+#else
+char *strtok();
+#endif
+#endif
+#else
+#include <string.h>
+#endif
+
+#ifdef USE_MEMORY
+#include <memory.h>
+#else
+#define memcpy(b, a, n) bcopy(a, b, n)
+#endif
+
+#include <errno.h>
+
+#define MAX_BUF 4096
+#define MAX_LINE 640
+#define MAX_NAME 128
+
+#define MAX_CHUNK MAX_LINE
+
+#define MAX_DEPTH 32
+
+#define MAX_VARNAME 32
+#define MAX_TINFONAME 5
+#define MAX_TCAPNAME 2
+
+struct caplist {
+ char type;
+ char flag;
+ char var[MAX_VARNAME + 1];
+ char tinfo[MAX_TINFONAME + 1];
+ char tcap[MAX_TCAPNAME + 1];
+};
+
+struct term_path {
+ char *file;
+ int type; /* 0 = file, 1 = TERMCAP env, 2 = TERMINFO env */
+};
+
+struct _terminal;
+
+#ifdef USE_PROTOTYPES
+
+int _gettcap(char *, struct _terminal *, struct term_path *);
+int _gettinfo(char *, struct _terminal *, struct term_path *);
+int _fillterm(char *, struct term_path *, char *);
+int _findterm(char *, struct term_path *, char *);
+int _init_tty(void), _lit_output(void), _check_tty(void);
+void _figure_termcap(void);
+int _tmatch(char *, char *);
+void _norm_output(void);
+int readcaps(FILE *, struct caplist *, int);
+noreturn void quit(int, char *, ...);
+#ifdef lint
+extern void (*cleanup)();
+#else
+extern void (*cleanup)(int);
+#endif
+struct term_path *_buildpath(char *, int, ...);
+void _delpath(struct term_path *);
+char *_addstr(char *);
+struct strbuf *_endstr(void);
+void _del_strs(struct _terminal *);
+void _tcapconv(void);
+void _tcapdefault(void);
+int _getother(char *, struct term_path *, struct _terminal *);
+int _gettbin(char *, struct _terminal *);
+int _findboolcode(char *), _findnumcode(char *), _findstrcode(char *);
+int _findboolname(char *), _findnumname(char *), _findstrname(char *);
+int _findboolfname(char *), _findnumfname(char *), _findstrfname(char *);
+
+#ifdef USE_ANSIC
+int _compar(void const *, void const *);
+typedef int (*compar_fn)(void const *, void const *);
+#else
+int _compar(anyptr, anyptr);
+typedef int (*compar_fn)(anyptr, anyptr);
+#endif
+
+#else /* USE_PROTOTYPES */
+
+int _gettcap(), _gettinfo(), _fillterm(), _findterm(), _init_tty();
+int _lit_output(), _check_tty();
+void _figure_termcap();
+int _tmatch();
+void _norm_output();
+int readcaps();
+noreturn void /* GOTO */ quit(/*FORMAT2*/);
+extern void (*cleanup)();
+struct term_path *_buildpath();
+void _delpath();
+char *_addstr();
+struct strbuf *_endstr();
+void _del_strs();
+void _tcapconv();
+void _tcapdefault();
+int _getother();
+int _gettbin();
+int _findboolcode(), _findnumcode(), _findstrcode();
+int _findboolname(), _findnumname(), _findstrname();
+int _findboolfname(), _findnumfname(), _findstrfname();
+int _compar();
+typedef int (*compar_fn)();
+
+#endif /* USE_PROTOTYPES */
+
+extern char _strflags[];
+
+extern char _mytinfo_version[];
+
+/* for quit.c */
+extern int sys_nerr;
+extern char *prg_name;
+
+#endif /* _DEFS_H_ */
diff --git a/lib/libmytinfo/fillterm.c b/lib/libmytinfo/fillterm.c
new file mode 100644
index 0000000..8e120c9
--- /dev/null
+++ b/lib/libmytinfo/fillterm.c
@@ -0,0 +1,81 @@
+/*
+ * fillterm.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:29:54
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo fillterm.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+TERMINAL _term_buf;
+TERMINAL *cur_term;
+
+int
+_fillterm(name, path, buf)
+char *name, *buf;
+struct term_path *path; {
+ register int i, r;
+
+ r = -1;
+
+ for(i = NUM_OF_BOOLS; i;)
+ _term_buf.bools[--i] = -1;
+ for(i = NUM_OF_NUMS; i;)
+ _term_buf.nums[--i] = -2;
+ for(i = NUM_OF_STRS; i;)
+ _term_buf.strs[--i] = (char *) -1;
+
+ _term_buf.name_all = NULL;
+
+ r = _findterm(name, path, buf);
+ switch(r) {
+ case 1:
+ if (_gettcap(buf, &_term_buf, path) != 0)
+ return -3;
+ _tcapconv();
+ _tcapdefault();
+ break;
+ case 2:
+ if (_gettinfo(buf, &_term_buf, path) != 0)
+ return -3;
+ break;
+ case 3:
+ if (_gettbin(buf, &_term_buf) != 0)
+ return -3;
+ break;
+ default:
+ return r;
+ }
+
+ if ((_term_buf.name = _addstr(name)) == NULL)
+ return -3;
+
+ for(i = NUM_OF_BOOLS; i;)
+ if (_term_buf.bools[--i] == -1)
+ _term_buf.bools[i] = 0;
+ for(i = NUM_OF_NUMS; i;)
+ if (_term_buf.nums[--i] == -2)
+ _term_buf.nums[i] = -1;
+ for(i = NUM_OF_STRS; i;)
+ if (_term_buf.strs[--i] == (char *) -1)
+ _term_buf.strs[i] = NULL;
+
+ _term_buf.fd = 1;
+ _term_buf.pad = 1;
+ _term_buf.baudrate = 0;
+ _term_buf.strbuf = _endstr();
+
+ cur_term = (TERMINAL *) malloc(sizeof(_term_buf));
+ if (cur_term == NULL)
+ return -3;
+ memcpy((anyptr)cur_term, (anyptr)&_term_buf, sizeof(_term_buf));
+
+ return r;
+}
diff --git a/lib/libmytinfo/findcap.c b/lib/libmytinfo/findcap.c
new file mode 100644
index 0000000..81ede3f
--- /dev/null
+++ b/lib/libmytinfo/findcap.c
@@ -0,0 +1,149 @@
+/*
+ * findcap.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:29:55
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#include "bsearch.c"
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo findcap.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+extern char **_sboolcodes[], **_snumcodes[], **_sstrcodes[];
+extern char **_sboolnames[], **_snumnames[], **_sstrnames[];
+extern char **_sboolfnames[], **_snumfnames[], **_sstrfnames[];
+
+static char **p2p2c;
+
+int
+_findboolcode(s)
+char *s; {
+ char ***match;
+
+ p2p2c = &s;
+
+ match = (char ***) bsearch((anyptr) &p2p2c, (anyptr) _sboolcodes,
+ NUM_OF_BOOLS, sizeof(p2p2c), _compar);
+ if (match == NULL)
+ return -1;
+ return *match - boolcodes;
+}
+
+int
+_findboolname(s)
+char *s; {
+ char ***match;
+
+ p2p2c = &s;
+
+ match = (char ***) bsearch((anyptr) &p2p2c, (anyptr) _sboolnames,
+ NUM_OF_BOOLS, sizeof(p2p2c), _compar);
+ if (match == NULL)
+ return -1;
+ return *match - boolnames;
+}
+
+int
+_findboolfname(s)
+char *s; {
+ char ***match;
+
+ p2p2c = &s;
+
+ match = (char ***) bsearch((anyptr) &p2p2c, (anyptr) _sboolfnames,
+ NUM_OF_BOOLS, sizeof(p2p2c), _compar);
+ if (match == NULL)
+ return -1;
+ return *match - boolfnames;
+}
+
+int
+_findnumcode(s)
+char *s; {
+ char ***match;
+
+ p2p2c = &s;
+
+ match = (char ***) bsearch((anyptr) &p2p2c, (anyptr) _snumcodes,
+ NUM_OF_NUMS, sizeof(p2p2c), _compar);
+ if (match == NULL)
+ return -1;
+ return *match - numcodes;
+}
+
+int
+_findnumname(s)
+char *s; {
+ char ***match;
+
+ p2p2c = &s;
+
+ match = (char ***) bsearch((anyptr) &p2p2c, (anyptr) _snumnames,
+ NUM_OF_NUMS, sizeof(p2p2c), _compar);
+ if (match == NULL)
+ return -1;
+ return *match - numnames;
+}
+
+int
+_findnumfname(s)
+char *s; {
+ char ***match;
+
+ p2p2c = &s;
+
+ match = (char ***) bsearch((anyptr) &p2p2c, (anyptr) _snumfnames,
+ NUM_OF_NUMS, sizeof(p2p2c), _compar);
+ if (match == NULL)
+ return -1;
+ return *match - numfnames;
+}
+
+int
+_findstrcode(s)
+char *s; {
+ char ***match;
+
+ p2p2c = &s;
+
+ match = (char ***) bsearch((anyptr) &p2p2c, (anyptr) _sstrcodes,
+ NUM_OF_STRS, sizeof(p2p2c), _compar);
+ if (match == NULL)
+ return -1;
+ return *match - strcodes;
+}
+
+int
+_findstrname(s)
+char *s; {
+ char ***match;
+
+ p2p2c = &s;
+
+ match = (char ***) bsearch((anyptr) &p2p2c, (anyptr) _sstrnames,
+ NUM_OF_STRS, sizeof(p2p2c), _compar);
+ if (match == NULL)
+ return -1;
+ return *match - strnames;
+}
+
+int
+_findstrfname(s)
+char *s; {
+ char ***match;
+
+ p2p2c = &s;
+
+ match = (char ***) bsearch((anyptr) &p2p2c, (anyptr) _sstrfnames,
+ NUM_OF_STRS, sizeof(p2p2c), _compar);
+ if (match == NULL)
+ return -1;
+ return *match - strfnames;
+}
diff --git a/lib/libmytinfo/findterm.c b/lib/libmytinfo/findterm.c
new file mode 100644
index 0000000..1fe5a9b
--- /dev/null
+++ b/lib/libmytinfo/findterm.c
@@ -0,0 +1,286 @@
+/* findterm.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:29:56
+ *
+ */
+
+#include "defs.h"
+
+#include <ctype.h>
+#include <fcntl.h>
+#ifdef USE_STDDEF
+#include <sys/types.h>
+#endif
+#include <sys/stat.h>
+#ifdef __FreeBSD__
+#include <unistd.h>
+#endif
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo findterm.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+static int linecnt;
+
+static int
+getln(f, buf, len)
+FILE *f;
+register char *buf;
+int len; {
+ register int c, i = 0;
+
+ while((c = getc(f)) == '#') {
+ linecnt++;
+ while((c = getc(f)) != '\n')
+ if (c == EOF)
+ return -1;
+ }
+
+ while(c != '\n') {
+ if (c == EOF)
+ return -1;
+ if (i < len) {
+ i++;
+ *buf++ = c;
+ }
+ c = getc(f);
+ }
+
+ while(isspace(*(buf-1))) {
+ buf--;
+ i--;
+ }
+
+ *buf = '\0';
+ return i;
+}
+
+static int
+_findterm2(name, file, buf)
+char *name, *buf;
+char *file; {
+ char line[MAX_LINE];
+ FILE *f;
+ register char *sp, *dp;
+ int c;
+ int l;
+ int cont;
+ int fd;
+ struct stat st;
+
+ linecnt = 0;
+
+#ifdef DEBUG
+ printf("open: %s\n", file);
+#endif
+ fd = open(file, O_RDONLY);
+ if (fd == -1)
+ return -1;
+ if (fstat(fd, &st) == -1) {
+ close(fd);
+ return -1;
+ }
+ if ((st.st_mode & 0170000) == 0040000) {
+ sprintf(buf, "%s/%c/%s", file, name[0], name);
+ close(fd);
+ fd = open(buf, O_RDONLY);
+ if (fd == -1)
+ return -1;
+ if (read(fd, buf, MAX_BUF) < 12
+ || buf[0] != 032 || buf[1] != 1) {
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return 3;
+ }
+ f = fdopen(fd, "r");
+ if (f == NULL) {
+ close(fd);
+ return -1;
+ }
+
+ while ((l = getln(f, buf, MAX_LINE)) != -1) {
+ linecnt++;
+ if (!isspace(buf[0]) && l != 0) {
+ sp = buf + l - 1;
+ cont = 0;
+ switch(*sp) {
+ case '\\':
+ cont = 1;
+ *sp = '\0';
+ /* FALLTHROUGH */
+ case ':':
+ sp = buf;
+ dp = line;
+ while (*sp != ':') {
+ if (*sp == '\0' && cont &&
+ (l = getln(f, buf, MAX_LINE))
+ != -1) {
+ linecnt++;
+ sp = buf;
+ if (l > 0 && buf[l-1] == '\\')
+ cont = 1;
+ else
+ cont = 0;
+ continue;
+ }
+ if (*sp == '\0') {
+#ifdef DEBUG
+ printf("bad line (%d)\n",
+ linecnt);
+ fclose(f);
+ return -2;
+#else
+ goto err;
+#endif
+ }
+ *dp++ = *sp++;
+ }
+ *dp = '\0';
+ if (!_tmatch(line, name))
+ break;
+ if (!cont) {
+ fclose(f);
+ return 1;
+ }
+ l = strlen(buf);
+ dp = buf + l;
+ while((c = getc(f)) != EOF && l < MAX_BUF) {
+ if (c == '\n')
+ break;
+ if (c == '\\') {
+ c = getc(f);
+ if (c == EOF)
+ break;
+ if (c == '\n') {
+ c = getc(f);
+ if (c == EOF)
+ break;
+ if (c == '#') {
+ while((c = getc(f)) != EOF && c != '\n');
+ if (c == EOF)
+ break;
+ continue;
+ }
+ *dp++ = c;
+ continue;
+ }
+ *dp++ = '\\';
+ *dp++ = c;
+ continue;
+ }
+ *dp++ = c;
+ }
+ *dp = '\0';
+ fclose(f);
+ return 1;
+ case ',':
+ sp = buf;
+ dp = line;
+ while(*sp != ',')
+ *dp++ = *sp++;
+ *dp = '\0';
+ if (!_tmatch(line, name))
+ break;
+ dp = buf + l;
+ while ((c = getc(f)) != EOF && l < MAX_BUF) {
+ if (c == '\n') {
+ c = getc(f);
+ if (isspace(c))
+ continue;
+ if (c == '\n') {
+ ungetc(c, f);
+ continue;
+ }
+ if (c == '#') {
+ while((c = getc(f)) != EOF)
+ if (c == '\n')
+ break;
+ if (c == EOF)
+ break;
+ ungetc(c, f);
+ continue;
+ }
+ break;
+ }
+ *dp++ = c;
+ l++;
+ }
+ *dp = '\0';
+ fclose(f);
+ return 2;
+ default:
+ err:
+#ifdef DEBUG
+ printf("strange line (%d)\n", linecnt);
+#endif
+ break;
+ }
+ }
+ }
+ fclose(f);
+ return 0;
+}
+
+int
+_findterm(name, path, buf)
+char *name;
+struct term_path *path;
+char *buf; {
+ register char *s, *d;
+ int r = 0;
+ while(path->file != NULL) {
+ switch(path->type) {
+ case 0:
+ r = _findterm2(name, path->file, buf);
+ break;
+ case 1:
+ if (path->file[0] == '/') {
+ r = _findterm2(name, path->file, buf);
+ } else {
+ s = path->file;
+ d = buf;
+ while(*s != '\0' && *s != ':')
+ *d++ = *s++;
+ *d = '\0';
+ if (_tmatch(buf, name)) {
+ while(*s != '\0')
+ *d++ = *s++;
+ return 1;
+ }
+ r = 0;
+ }
+ break;
+ case 2:
+ if (path->file[0] == '/') {
+ r = _findterm2(name, path->file, buf);
+ } else {
+ s = path->file;
+ d = buf;
+ while(*s != '\0' && *s != ',')
+ *d++ = *s++;
+ *d = '\0';
+ if (_tmatch(buf, name)) {
+ while(*s != '\0')
+ *d++ = *s++;
+ return 2;
+ }
+ r = 0;
+ }
+ break;
+ default:
+ r = 0;
+ break;
+ }
+ if (r == 1 || r == 2 || r == 3) {
+#ifdef DEBUG
+ printf("found in %s\n", path->file);
+#endif
+ break;
+ }
+ path++;
+ }
+ return r;
+}
diff --git a/lib/libmytinfo/getother.c b/lib/libmytinfo/getother.c
new file mode 100644
index 0000000..2542f66
--- /dev/null
+++ b/lib/libmytinfo/getother.c
@@ -0,0 +1,49 @@
+/*
+ * getother.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:29:58
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo getother.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+int
+_getother(name, path, ct)
+char *name;
+struct term_path *path;
+TERMINAL *ct; {
+ static int depth = 0;
+ int r;
+ char buf[MAX_BUF];
+
+ if (depth >= MAX_DEPTH)
+ return 1; /* infinite loop */
+
+#ifdef DEBUG
+ printf("\ngetother: %s\n", name);
+#endif
+
+ switch(_findterm(name, path, buf)) {
+ case -3:
+ return 1;
+ case 1:
+ depth++;
+ r = _gettcap(buf, ct, path);
+ break;
+ case 2:
+ depth++;
+ r = _gettinfo(buf, ct, path);
+ break;
+ default:
+ return 0;
+ }
+ depth--;
+ return r;
+}
diff --git a/lib/libmytinfo/gettbin.c b/lib/libmytinfo/gettbin.c
new file mode 100644
index 0000000..678a7d8
--- /dev/null
+++ b/lib/libmytinfo/gettbin.c
@@ -0,0 +1,127 @@
+/*
+ * gettbin.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:29:59
+ *
+ * Get a terminfo binary entry
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo gettbin.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+extern int _boolorder[], _numorder[], _strorder[];
+
+#ifdef TRUE_BYTE_ORDERING
+/* 8 bit char, 16 bit short, lsb first, twos complement */
+#define convshort(s) (*(short *)(s))
+
+#else
+
+#ifdef TWOS_COPLEMENT
+/* 8 bit char, 16 bit short, lsb last, twos complement */
+#define convshort(s) ((short)(((s[0] & 0377) << 8) | (s[1] & 0377)))
+
+#else
+
+/* anything else... */
+
+static short
+convshort(s)
+char *s; {
+ register int a,b;
+
+ a = (int) s[0] & 0377;
+ b = (int) s[1] & 0377;
+
+ if (a == 0377 && b == 0377)
+ return -1;
+ if (a == 0376 && b == 0377)
+ return -2;
+
+ return a + b * 256;
+}
+#endif
+#endif
+
+int
+_gettbin(buf, cur)
+char *buf;
+TERMINAL *cur; {
+ register char *s;
+ int i;
+ int sz_names, sz_bools, sz_nums, sz_offs, sz_strs;
+ int n_bools, n_nums, n_strs;
+ char *strtbl;
+
+ buf[MAX_BUF-1] = '\0';
+ s = buf;
+
+ if (convshort(s) != 0432)
+ return 1;
+ sz_names = convshort(s + 2);
+ sz_bools = convshort(s + 4);
+ n_nums = convshort(s + 6);
+ n_strs = convshort(s + 8);
+ sz_strs = convshort(s + 10);
+
+ n_bools = sz_bools;
+ sz_nums = n_nums * 2;
+ sz_offs = n_strs * 2;
+
+ if ((sz_names + sz_bools) & 1)
+ sz_bools++;
+
+ if (12 + sz_names + sz_bools + sz_nums + sz_offs + sz_strs >= MAX_BUF)
+ return 1;
+
+ s += 12;
+ if ((cur->name_all = _addstr(s)) == NULL)
+ return 1;
+ s += sz_names;
+ while(--s >= buf + 12) {
+ if (*s == '|') {
+ if ((cur->name_long = _addstr(s + 1)) == NULL)
+ return 1;
+ break;
+ }
+ }
+
+ s = buf + 12 + sz_names;
+ for(i = 0; i < n_bools && _boolorder[i] != -1; i++, s++) {
+ if (cur->bools[_boolorder[i]] == -1 && *s == 1)
+ cur->bools[_boolorder[i]] = 1;
+ }
+
+ s = buf + 12 + sz_names + sz_bools;
+ for(i = 0; i < n_nums && _numorder[i] != -1; i++, s += 2) {
+ if (convshort(s) == -2)
+ cur->nums[_numorder[i]] = -1;
+ else if (cur->nums[_numorder[i]] == -2 && convshort(s) != -1)
+ cur->nums[_numorder[i]] = convshort(s);
+ }
+
+ s = buf + 12 + sz_names + sz_bools + sz_nums;
+ strtbl = s + sz_offs;
+ for(i = 0; i < n_strs && _strorder[i] != -1; i++, s += 2) {
+ if (convshort(s) == -2)
+ cur->strs[_strorder[i]] = NULL;
+ else if (cur->strs[_strorder[i]] == (char *) -1
+ && convshort(s) != -1) {
+#ifdef DEBUG
+ printf("$%s ", strnames[_strorder[i]]);
+#endif
+ if ((cur->strs[_strorder[i]]
+ = _addstr(strtbl + convshort(s))) == NULL)
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/libmytinfo/gettcap.c b/lib/libmytinfo/gettcap.c
new file mode 100644
index 0000000..1424b88
--- /dev/null
+++ b/lib/libmytinfo/gettcap.c
@@ -0,0 +1,276 @@
+/*
+ * gettcap.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:00
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#include <ctype.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo gettcap.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+int
+_gettcap(sp, cur, path)
+register char *sp;
+TERMINAL *cur;
+struct term_path *path; {
+ static char name[MAX_NAME];
+ static char entry[MAX_LINE];
+ register char *dp;
+ register TERMINAL *ct = cur;
+ int i, pad, fract, mul = 0, ind;
+ char c, flag;
+
+ dp = entry;
+ while(*sp != ':' && *sp != '\0')
+ *dp++ = *sp++;
+ if (ct->name_all == NULL) {
+ *dp = '\0';
+ if ((ct->name_all = _addstr(entry)) == NULL)
+ return 1;
+ while(dp > entry && *--dp != '|');
+ ct->name_long = ct->name_all + (dp - entry) + 1;
+ }
+
+ while(*sp != '\0') {
+ while(*sp == ':')
+ sp++;
+ while(isspace(*sp))
+ sp++;
+ if (*sp == ':')
+ continue;
+ if (*sp == '\0')
+ break;
+ dp = name;
+ while (*sp != ':' && *sp != '#' && *sp != '=' &&
+ !isspace(*sp) && *sp != '\0')
+ *dp++ = *sp++;
+ *dp = '\0';
+#ifdef DEBUG
+ printf(" %s", name);
+#endif
+ switch(*sp) {
+ case '=':
+#ifdef DEBUG
+ putchar('$');
+#endif
+ ind = _findstrcode(name);
+ if (ind != -1)
+ flag = _strflags[ind];
+ else
+ flag = 'K';
+ dp = entry;
+ fract = pad = 0;
+ sp++;
+ if (isdigit(*sp) && flag != 'K') {
+ pad = *sp++ - '0';
+ while(isdigit(*sp))
+ pad = pad * 10 + (*sp++ - '0');
+ if (*sp == '.' && isdigit(sp[1])) {
+ sp++;
+ fract = (*sp++ - '0');
+ }
+ if (*sp == '*') {
+ mul = 1;
+ sp++;
+ } else
+ mul = 0;
+
+ }
+ while(*sp != '\0' && *sp != ':') {
+ switch(*sp) {
+ case '\\':
+ switch(*++sp) {
+ case 'e':
+ case 'E': *dp++ = '\033'; break;
+ case 'l': *dp++ = '\012'; break;
+ case 'n': *dp++ = '\n'; break;
+ case 'r': *dp++ = '\r'; break;
+ case 't': *dp++ = '\t'; break;
+ case 'b': *dp++ = '\b'; break;
+ case 'f': *dp++ = '\f'; break;
+ case 's': *dp++ = ' '; break;
+
+ case '^':
+ case '\\':
+ case ',':
+ case ':':
+ *dp++ = *sp;
+ break;
+
+ case '0':
+ if (!isdigit(*(sp + 1))) {
+ *dp++ = '\200';
+ break;
+ }
+ ;/* FALLTHROUGH */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ c = *sp - '0';
+ if (sp[1] >= '0'
+ && sp[1] <= '8')
+ c = c * 8
+ + (*++sp - '0');
+ if (sp[1] >= '0'
+ && sp[1] <= '8')
+ c = c * 8
+ + (*++sp - '0');
+ switch((char)c) {
+ case 0:
+ if (flag == 'K')
+ *dp++ = '\200';
+ else {
+ *dp++ = '\\';
+ *dp++ = '0';
+ *dp++ = '0';
+ *dp++ = '0';
+ }
+ break;
+ case '$':
+ case '\'':
+ case '\\':
+ if (flag != 'K')
+ *dp++ = '\\';
+ /* FALLTHROUGH */
+ default:
+ if (flag == 'G'
+ && c == '%')
+ *dp++ = '\\';
+ *dp++ = c;
+ break;
+ }
+ break;
+ default:
+ *dp++ = '\\';
+ *dp++ = *sp;
+ break;
+ }
+ sp++;
+ break;
+ case '^':
+ if (*++sp >= 'A' && *sp <= '_') {
+ *dp++ = *sp++ - '@';
+ } else if (*sp >= 'a' && *sp <= 'z') {
+ *dp++ = *sp++ - 'a' + 1;
+ } else if (*sp == '@') {
+ if (flag == 'K')
+ *dp++ = '\200';
+ else {
+ *dp++ = '\\';
+ *dp++ = '0';
+ *dp++ = '0';
+ *dp++ = '0';
+ }
+ sp++;
+ } else if (*sp == '?') {
+ *dp++ = '\177';
+ sp++;
+ } else
+ *dp++ = '^';
+ break;
+ case '$':
+ if (flag != 'K')
+ *dp++ = '\\';
+ /* FALLTHROUGH */
+ default:
+ *dp++ = *sp++;
+ break;
+ }
+ }
+ if (pad != 0 || fract != 0) {
+ if (fract == 0)
+ sprintf(dp, "$<%d", pad);
+ else
+ sprintf(dp, "$<%d.%d", pad, fract);
+ dp += strlen(dp);
+ if (mul)
+ *dp++ = '*';
+ *dp++ = '>';
+ }
+ *dp++ = '\0';
+ if(name[0] == 't' && name[1] == 'c' && name[2] == '\0'){
+ if (_getother(entry, path, ct))
+ return 1;
+ break;
+ }
+ if (ind == -1)
+ break;
+ if (ct->strs[ind] != (char *) -1)
+ break;
+ if ((ct->strs[ind] = _addstr(entry)) == NULL)
+ return 1;
+ break;
+ case '#':
+#ifdef DEBUG
+ putchar('#');
+#endif
+ i = atoi(++sp);
+ while(*sp != '\0' && *sp++ != ':');
+ ind = _findnumcode(name);
+ if (ind == -1)
+ break;
+ if (ct->nums[ind] != -2)
+ break;
+ ct->nums[ind] = i;
+ break;
+ default:
+ while(*sp != '\0' && *sp++ != ':');
+ if (*(dp - 1) == '@') {
+#ifdef DEBUG
+ putchar('@');
+#endif
+ *(dp - 1) = '\0';
+ ind = _findboolcode(name);
+ if (ind != -1) {
+#ifdef DEBUG
+ putchar('!');
+#endif
+ if (ct->bools[ind] == -1)
+ ct->bools[ind] = 0;
+ break;
+ }
+ ind = _findnumcode(name);
+ if (ind != -1) {
+#ifdef DEBUG
+ putchar('#');
+#endif
+ if (ct->nums[ind] == -2)
+ ct->nums[ind] = -1;
+ break;
+ }
+ ind = _findstrcode(name);
+ if (ind != -1) {
+#ifdef DEBUG
+ putchar('$');
+#endif
+ if (ct->strs[ind] == (char *) -1)
+ ct->strs[ind] = NULL;
+ break;
+ }
+ break;
+ }
+#ifdef DEBUG
+ putchar('!');
+#endif
+ ind = _findboolcode(name);
+ if (ind == -1)
+ break;
+ if (ct->bools[ind] != -1)
+ break;
+ ct->bools[ind] = 1;
+ }
+ }
+ return 0;
+}
diff --git a/lib/libmytinfo/gettinfo.c b/lib/libmytinfo/gettinfo.c
new file mode 100644
index 0000000..7b7b445
--- /dev/null
+++ b/lib/libmytinfo/gettinfo.c
@@ -0,0 +1,303 @@
+/*
+ * gettinfo.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:02
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#include <ctype.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo gettinfo.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+int _gettinfo(sp, cur, path)
+register char *sp;
+struct term_path *path;
+TERMINAL *cur; {
+ static char name[MAX_NAME];
+ static char entry[MAX_LINE];
+ register char *dp;
+ register TERMINAL *ct = cur;
+ int ind, i, base;
+ char c, flag;
+
+ dp = entry;
+ while(*sp != ',' && *sp != '\0')
+ *dp++ = *sp++;
+ if (ct->name_all == NULL) {
+ *dp = '\0';
+ if ((ct->name_all = _addstr(entry)) == NULL)
+ return 1;
+ while(dp > entry && *--dp != '|');
+ ct->name_long = ct->name_all + (dp - entry) + 1;
+ }
+
+ while(*sp != '\0') {
+ while(*sp == ',')
+ sp++;
+ while(isspace(*sp))
+ sp++;
+ if (*sp == ',')
+ continue;
+ if (*sp == '\0')
+ break;
+ dp = name;
+ while (*sp != ',' && *sp != '#' && *sp != '=' && !isspace(*sp) && *sp != '\0')
+ *dp++ = *sp++;
+ *dp = '\0';
+#ifdef DEBUG
+ printf(" %s", name);
+#endif
+ switch(*sp) {
+ case '=':
+#ifdef DEBUG
+ putchar('$');
+#endif
+ dp = entry;
+ sp++;
+ ind = _findstrname(name);
+ if (ind != -1)
+ flag = _strflags[ind];
+ else {
+ ind = _findstrfname(name);
+ if (ind != -1)
+ flag = _strflags[ind];
+ else
+ flag = 'K';
+ }
+ while(*sp != '\0' && *sp != ',') {
+ switch(*sp) {
+ case '%':
+ *dp++ = *sp++;
+ if (*sp == '^' && flag == 'G')
+ *dp++ = *sp++;
+ break;
+ case '\\':
+ switch(*++sp) {
+ case 'e':
+ case 'E': *dp++ = '\033'; break;
+ case 'l': *dp++ = '\012'; break;
+ case 'n': *dp++ = '\n'; break;
+ case 'r': *dp++ = '\r'; break;
+ case 't': *dp++ = '\t'; break;
+ case 'b': *dp++ = '\b'; break;
+ case 'f': *dp++ = '\f'; break;
+ case 's': *dp++ = ' '; break;
+
+ case '^':
+ case '\\':
+ case ',':
+ case ':':
+ *dp++ = *sp; break;
+
+ case '0':
+ if (!isdigit(*(sp + 1))) {
+ *dp++ = '\200';
+ break;
+ }
+ /* FALLTHROUGH */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ c = *sp - '0';
+ if (isdigit(sp[1]))
+ c = c * 8 + (*++sp-'0');
+ if (isdigit(sp[1]))
+ c = c * 8 + (*++sp-'0');
+ switch((char)c) {
+ case 0:
+ if (flag == 'K')
+ *dp++ = '\200';
+ else {
+ *dp++ = '\\';
+ *dp++ = '0';
+ *dp++ = '0';
+ *dp++ = '0';
+ }
+ break;
+ case '$':
+ case '\'':
+ case '\\':
+ if (flag != 'K')
+ *dp++ = '\\';
+ /* FALLTHROUGH */
+ default:
+ if (flag == 'G'
+ && c == '%')
+ *dp++ = '\\';
+ *dp++ = c;
+ break;
+ }
+ break;
+ default:
+ *dp++ = '\\';
+ *dp++ = *sp;
+ break;
+ }
+ sp++;
+ break;
+ case '^':
+ if (*++sp >= 'A' && *sp <= '_') {
+ *dp++ = *sp++ - '@';
+ } else if (*sp >= 'a' && *sp <= 'z') {
+ *dp++ = *sp++ - 'a' + 1;
+ } else if (*sp == '@') {
+ if (flag == 'K')
+ *dp++ = '\200';
+ else {
+ *dp++ = '\\';
+ *dp++ = '0';
+ *dp++ = '0';
+ *dp++ = '0';
+ }
+ sp++;
+ } else
+ *dp++ = '^';
+ break;
+ default:
+ *dp++ = *sp++;
+ break;
+ }
+ }
+ *dp++ = '\0';
+ if (strcmp(name, "use") == 0) {
+ if (_getother(entry, path, ct))
+ return 1;
+ break;
+ }
+ if (ind == -1)
+ break;
+ if (ct->strs[ind] != (char *) -1)
+ break;
+ if ((ct->strs[ind] = _addstr(entry)) == NULL)
+ return 1;
+ break;
+ case '#':
+#ifdef DEBUG
+ putchar('#');
+#endif
+#if 0
+ i = atoi(++sp);
+#else
+ sp++;
+ if (*sp == '0') {
+ sp++;
+ if (*sp == 'x' || *sp == 'X') {
+ sp++;
+ base = 16;
+ } else
+ base = 8;
+ } else
+ base = 10;
+ i = 0;
+ while(1) {
+ if (isdigit(*sp))
+ i = i * base + *sp - '0';
+ else if (base == 16 && isxdigit(*sp))
+ i = i * base + tolower(*sp) - 'a' + 10;
+ else
+ break;
+ sp++;
+ }
+#endif
+ while(*sp != '\0' && *sp != ',')
+ sp++;
+
+ ind = _findnumname(name);
+ if (ind != -1) {
+ if (ct->nums[ind] != -2)
+ break;
+ ct->nums[ind] = i;
+ } else {
+ ind = _findnumfname(name);
+ if (ind != -1) {
+ if (ct->nums[ind] != -2)
+ break;
+ ct->nums[ind] = i;
+ }
+ }
+ break;
+ default:
+ while(*sp != '\0' && *sp++ != ',');
+ if (*(dp - 1) == '@') {
+#ifdef DEBUG
+ putchar('@');
+#endif
+ *(dp - 1) = '\0';
+ ind = _findboolname(name);
+ if (ind != -1) {
+#ifdef DEBUG
+ putchar('!');
+#endif
+ ct->bools[ind] = 0;
+ break;
+ }
+ ind = _findnumname(name);
+ if (ind != -1) {
+#ifdef DEBUG
+ putchar('#');
+#endif
+ ct->nums[ind] = -1;
+ break;
+ }
+ ind = _findstrname(name);
+ if (ind != -1) {
+#ifdef DEBUG
+ putchar('$');
+#endif
+ ct->strs[ind] = NULL;
+ break;
+ }
+ ind = _findboolfname(name);
+ if (ind != -1) {
+#ifdef DEBUG
+ putchar('!');
+#endif
+ ct->bools[ind] = 0;
+ break;
+ }
+ ind = _findnumfname(name);
+ if (ind != -1) {
+#ifdef DEBUG
+ putchar('#');
+#endif
+ ct->nums[ind] = -1;
+ break;
+ }
+ ind = _findstrfname(name);
+ if (ind != -1) {
+#ifdef DEBUG
+ putchar('$');
+#endif
+ ct->strs[ind] = NULL;
+ break;
+ }
+ break;
+ }
+#ifdef DEBUG
+ putchar('!');
+#endif
+ ind = _findboolname(name);
+ if (ind == -1) {
+ ind = _findboolfname(name);
+ if (ind == -1)
+ break;
+ }
+ if (ct->bools[ind] != -1)
+ break;
+ ct->bools[ind] = 1;
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/lib/libmytinfo/mkbinorder.c b/lib/libmytinfo/mkbinorder.c
new file mode 100644
index 0000000..0bcc474
--- /dev/null
+++ b/lib/libmytinfo/mkbinorder.c
@@ -0,0 +1,116 @@
+/*
+ * mkbinorder.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:04
+ *
+ */
+
+#define NOTLIB
+#include "defs.h"
+#include <term.h>
+
+const char SCCSid[] = "@(#) mytinfo mkbinorder.c 3.2 92/02/01 public domain, By Ross Ridge";
+
+char cap[MAX_NAME];
+char *p2c = cap;
+char **p2p2c = &p2c;
+
+int
+main(argc, argv)
+int argc;
+char **argv; {
+ int r;
+ int ind;
+ FILE *f;
+
+ if (argc == 1)
+ f = stdin;
+ else if (argc == 2) {
+ f = fopen(argv[1], "r");
+ if (f == NULL) {
+ fprintf(stderr, "can't open %s\n", argv[1]);
+ exit(1);
+ }
+ } else {
+ fprintf(stderr, "argument count\n");
+ exit(1);
+ }
+
+ do {
+ r = fscanf(f, "%s", cap);
+ } while(r == 1 && strcmp(cap, "!") != 0);
+ if (r != 1) {
+ fprintf(stderr, "expected '!'\n");
+ exit(1);
+ }
+
+ puts("/*");
+ puts(" * binorder.c");
+ puts(" *");
+ puts(" * This file was generated automatically");
+ puts(" *");
+ puts(" */\n");
+
+ puts("int _boolorder[] = {");
+
+ while(1) {
+ r = fscanf(f, "%s", cap);
+ cap[MAX_TINFONAME] = '\0';
+ if (r != 1) {
+ fprintf(stderr, "unexpected EOF\n");
+ exit(1);
+ }
+ if (strcmp(cap, "#") == 0)
+ break;
+ ind = _findboolname(cap);
+ if (ind == -1) {
+ fprintf(stderr, "unknown bool name '%s'\n", cap);
+ continue;
+ }
+ printf("\t%d,\n", ind);
+ }
+ puts("\t-1");
+ puts("};\n");
+
+ puts("int _numorder[] = {");
+
+ while(1) {
+ r = fscanf(f, "%s", cap);
+ cap[MAX_TINFONAME] = '\0';
+ if (r != 1) {
+ fprintf(stderr, "unexpected EOF\n");
+ exit(1);
+ }
+ if (strcmp(cap, "$") == 0)
+ break;
+ ind = _findnumname(cap);
+ if (ind == -1) {
+ fprintf(stderr, "unknown num name '%s'\n", cap);
+ continue;
+ }
+ printf("\t%d,\n", ind);
+ }
+ puts("\t-1");
+ puts("};\n");
+
+ puts("int _strorder[] = {");
+
+ while(1) {
+ r = fscanf(f, "%s", cap);
+ cap[MAX_TINFONAME] = '\0';
+ if (r != 1)
+ break;
+ ind = _findstrname(cap);
+ if (ind == -1) {
+ fprintf(stderr, "unknown str name '%s'\n", cap);
+ continue;
+ }
+ printf("\t%d,\n", ind);
+ }
+ puts("\t-1");
+ puts("};\n");
+
+ return 0;
+}
diff --git a/lib/libmytinfo/mkcaplist.c b/lib/libmytinfo/mkcaplist.c
new file mode 100644
index 0000000..2fedf2d
--- /dev/null
+++ b/lib/libmytinfo/mkcaplist.c
@@ -0,0 +1,166 @@
+/*
+ * mkcaplist.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:05
+ *
+ * mkcaplist [-n caps] [file]
+ *
+ * makes caplist.c from the cap_list file
+ *
+ */
+
+#define NOTLIB
+#include "defs.h"
+
+const char SCCSid[] = "@(#) mytinfo mkcaplist.c 3.2 92/02/01 public domain, By Ross Ridge";
+
+#define DEFAULT_CAPS 1000
+
+struct caplist *list;
+
+int
+main(argc, argv)
+int argc;
+char **argv; {
+ FILE *f;
+ int caps = DEFAULT_CAPS;
+ int n;
+ register int i;
+
+ if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'n') {
+ caps = atoi(argv[2]);
+ argv += 2;
+ argc -= 2;
+ }
+
+ if (argc == 1) {
+ f = stdin;
+ } else if (argc == 2) {
+ f = fopen(argv[1], "r");
+ if (f == NULL) {
+ fprintf(stderr, "%s: can't open '%s'\n", argv[0],
+ argv[1]);
+ return 1;
+ }
+ } else {
+ fprintf(stderr, "%s: too many arguments\n", argv[0]);
+ fprintf(stderr, "usage: %s [-n caps] [file]\n", argv[0]);
+ return 1;
+ }
+
+ list = (struct caplist *) malloc(caps * sizeof(struct caplist));
+ if (list == NULL) {
+ fprintf(stderr, "%s: malloc failed.\n", argv[0]);
+ return 1;
+ }
+
+ n = readcaps(f, list, caps);
+ if (n > caps) {
+ fprintf(stderr, "%s: too many caps, use -n.\n", argv[0]);
+ return 1;
+ }
+ if (n == 0) {
+ fprintf(stderr, "%s: no caps in file.\n", argv[0]);
+ return 1;
+ }
+ if (n == -1) {
+ fprintf(stderr, "%s: bad caps line.\n", argv[0]);
+ return 1;
+ }
+ if (n == -2) {
+ fprintf(stderr, "%s: unexpected EOF.\n", argv[0]);
+ return 1;
+ }
+
+ puts("/*");
+ puts(" * caplist.c ");
+ puts(" *");
+ puts(" * This file was generated automatically.");
+ puts(" *");
+ puts(" */");
+ putchar('\n');
+
+ puts("char *boolnames[] = {");
+ for (i = 0; i < n; i++)
+ if (list[i].type == '!')
+ printf("\t\"%s\",\n", list[i].tinfo);
+ puts("\t(char *)0");
+ puts("};");
+ putchar('\n');
+
+ puts("char *boolcodes[] = {");
+ for (i = 0; i < n; i++)
+ if (list[i].type == '!')
+ printf("\t\"%s\",\n", list[i].tcap);
+ puts("\t(char *)0");
+ puts("};");
+ putchar('\n');
+
+ puts("char *boolfnames[] = {");
+ for (i = 0; i < n; i++)
+ if (list[i].type == '!')
+ printf("\t\"%s\",\n", list[i].var);
+ puts("\t(char *)0");
+ puts("};");
+ putchar('\n');
+
+ puts("char *numnames[] = {");
+ for (i = 0; i < n; i++)
+ if (list[i].type == '#')
+ printf("\t\"%s\",\n", list[i].tinfo);
+ puts("\t(char *)0");
+ puts("};");
+ putchar('\n');
+
+ puts("char *numcodes[] = {");
+ for (i = 0; i < n; i++)
+ if (list[i].type == '#')
+ printf("\t\"%s\",\n", list[i].tcap);
+ puts("\t(char *)0");
+ puts("};");
+ putchar('\n');
+
+ puts("char *numfnames[] = {");
+ for (i = 0; i < n; i++)
+ if (list[i].type == '#')
+ printf("\t\"%s\",\n", list[i].var);
+ puts("\t(char *)0");
+ puts("};");
+ putchar('\n');
+
+ puts("char *strnames[] = {");
+ for (i = 0; i < n; i++)
+ if (list[i].type == '$')
+ printf("\t\"%s\",\n", list[i].tinfo);
+ puts("\t(char *)0");
+ puts("};");
+ putchar('\n');
+
+ puts("char *strcodes[] = {");
+ for (i = 0; i < n; i++)
+ if (list[i].type == '$')
+ printf("\t\"%s\",\n", list[i].tcap);
+ puts("\t(char *)0");
+ puts("};");
+ putchar('\n');
+
+ puts("char *strfnames[] = {");
+ for (i = 0; i < n; i++)
+ if (list[i].type == '$')
+ printf("\t\"%s\",\n", list[i].var);
+ puts("\t(char *)0");
+ puts("};");
+ putchar('\n');
+
+ puts("char _strflags[] = {");
+ for (i = 0; i < n; i++)
+ if (list[i].type == '$')
+ printf("\t'%c',\n", list[i].flag);
+ puts("\t'\\0'");
+ puts("};");
+ putchar('\n');
+
+ return 0;
+}
diff --git a/lib/libmytinfo/mkcapsort.c b/lib/libmytinfo/mkcapsort.c
new file mode 100644
index 0000000..9079dcf
--- /dev/null
+++ b/lib/libmytinfo/mkcapsort.c
@@ -0,0 +1,134 @@
+/*
+ * mkcapsort.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/06/04 11:38:02
+ *
+ * mkcapsort
+ *
+ * make the sorted lists of pointers to strins
+ *
+ */
+
+#define NOTLIB
+#include "defs.h"
+#include <term.h>
+
+#ifdef USE_MYQSORT
+#include "qsort.c"
+#endif
+
+const char SCCSid[] = "@(#) mytinfo mkcapsort.c 3.3 92/06/04 public domain, By Ross Ridge";
+
+char **sboolnames[NUM_OF_BOOLS], **sboolcodes[NUM_OF_BOOLS], **sboolfnames[NUM_OF_BOOLS];
+char **snumnames[NUM_OF_NUMS], **snumcodes[NUM_OF_NUMS], **snumfnames[NUM_OF_NUMS];
+char **sstrnames[NUM_OF_STRS], **sstrcodes[NUM_OF_STRS], **sstrfnames[NUM_OF_STRS];
+
+
+int
+main() {
+ register int i;
+
+ i = NUM_OF_BOOLS;
+ while(i) {
+ i--;
+ sboolnames[i] = &boolnames[i];
+ sboolcodes[i] = &boolcodes[i];
+ sboolfnames[i] = &boolfnames[i];
+ }
+
+ i = NUM_OF_NUMS;
+ while(i) {
+ i--;
+ snumnames[i] = &numnames[i];
+ snumcodes[i] = &numcodes[i];
+ snumfnames[i] = &numfnames[i];
+ }
+
+ i = NUM_OF_STRS;
+ while(i) {
+ i--;
+ sstrnames[i] = &strnames[i];
+ sstrcodes[i] = &strcodes[i];
+ sstrfnames[i] = &strfnames[i];
+ }
+
+ qsort((anyptr) sboolnames, NUM_OF_BOOLS, sizeof(*sboolnames), _compar);
+ qsort((anyptr) sboolcodes, NUM_OF_BOOLS, sizeof(*sboolcodes), _compar);
+ qsort((anyptr) sboolfnames, NUM_OF_BOOLS, sizeof(*sboolfnames),_compar);
+ qsort((anyptr) snumnames, NUM_OF_NUMS, sizeof(*snumnames), _compar);
+ qsort((anyptr) snumcodes, NUM_OF_NUMS, sizeof(*snumcodes), _compar);
+ qsort((anyptr) snumfnames, NUM_OF_NUMS, sizeof(*snumfnames), _compar);
+ qsort((anyptr) sstrnames, NUM_OF_STRS, sizeof(*sstrnames), _compar);
+ qsort((anyptr) sstrcodes, NUM_OF_STRS, sizeof(*sstrcodes), _compar);
+ qsort((anyptr) sstrfnames, NUM_OF_STRS, sizeof(*sstrfnames), _compar);
+
+ printf("/*\n");
+ printf(" * capsort.c\n");
+ printf(" *\n");
+ printf(" * This file was generated automatically.\n");
+ printf(" *\n");
+ printf(" */\n\n");
+
+ puts("extern char *boolnames[], *boolcodes[], *boolfnames[];");
+ puts("extern char *numnames[], *numcodes[], *numfnames[];");
+ puts("extern char *strnames[], *strcodes[], *strfnames[];");
+ putchar('\n');
+
+ printf("char **_sboolnames[] = {\n");
+ for(i = 0; i < NUM_OF_BOOLS; i++)
+ printf("\tboolnames + %d,\n", sboolnames[i] - boolnames);
+ printf(" (char **) 0\n");
+ printf("};\n\n");
+
+ printf("char **_sboolcodes[] = {\n");
+ for(i = 0; i < NUM_OF_BOOLS; i++)
+ printf("\tboolcodes + %d,\n", sboolcodes[i] - boolcodes);
+ printf(" (char **) 0\n");
+ printf("};\n\n");
+
+ printf("char **_sboolfnames[] = {\n");
+ for(i = 0; i < NUM_OF_BOOLS; i++)
+ printf("\tboolfnames + %d,\n", sboolfnames[i] - boolfnames);
+ printf(" (char **) 0\n");
+ printf("};\n\n");
+
+ printf("char **_snumnames[] = {\n");
+ for(i = 0; i < NUM_OF_NUMS; i++)
+ printf("\tnumnames + %d,\n", snumnames[i] - numnames);
+ printf(" (char **) 0\n");
+ printf("};\n\n");
+
+ printf("char **_snumcodes[] = {\n");
+ for(i = 0; i < NUM_OF_NUMS; i++)
+ printf("\tnumcodes + %d,\n", snumcodes[i] - numcodes);
+ printf(" (char **) 0\n");
+ printf("};\n\n");
+
+ printf("char **_snumfnames[] = {\n");
+ for(i = 0; i < NUM_OF_NUMS; i++)
+ printf("\tnumfnames + %d,\n", snumfnames[i] - numfnames);
+ printf(" (char **) 0\n");
+ printf("};\n\n");
+
+ printf("char **_sstrnames[] = {\n");
+ for(i = 0; i < NUM_OF_STRS; i++)
+ printf("\tstrnames + %d,\n", sstrnames[i] - strnames);
+ printf(" (char **) 0\n");
+ printf("};\n\n");
+
+ printf("char **_sstrcodes[] = {\n");
+ for(i = 0; i < NUM_OF_STRS; i++)
+ printf("\tstrcodes + %d,\n", sstrcodes[i] - strcodes);
+ printf(" (char **) 0\n");
+ printf("};\n\n");
+
+ printf("char **_sstrfnames[] = {\n");
+ for(i = 0; i < NUM_OF_STRS; i++)
+ printf("\tstrfnames + %d,\n", sstrfnames[i] - strfnames);
+ printf(" (char **) 0\n");
+ printf("};\n\n");
+
+ return 0;
+}
diff --git a/lib/libmytinfo/mktermhead.c b/lib/libmytinfo/mktermhead.c
new file mode 100644
index 0000000..bacf051
--- /dev/null
+++ b/lib/libmytinfo/mktermhead.c
@@ -0,0 +1,160 @@
+/*
+ * mktermhead.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/06/04 11:38:57
+ *
+ * mktermhead [-n caps] file
+ *
+ * generates term.head
+ *
+ */
+
+#define NOTLIB
+#include "defs.h"
+
+const char SCCSid[] = "@(#) mytinfo mktermhead.c 3.3 92/06/04 public domain, By Ross Ridge";
+
+#define DEFAULT_CAPS 1000
+
+
+int
+main(argc, argv)
+int argc;
+char **argv; {
+ FILE *f;
+ int caps = DEFAULT_CAPS;
+ int n;
+ register int i;
+ int nb, ns, nn;
+ struct caplist *list;
+
+ if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'n') {
+ caps = atoi(argv[2]);
+ argv += 2;
+ argc -= 2;
+ }
+
+ if (argc == 1) {
+ f = stdin;
+ } else if (argc == 2) {
+ f = fopen(argv[1], "r");
+ if (f == NULL) {
+ fprintf(stderr, "%s: can't open '%s'\n", argv[0],
+ argv[1]);
+ return 1;
+ }
+ } else {
+ fprintf(stderr, "%s: too many arguments\n", argv[0]);
+ fprintf(stderr, "usage: %s [-n caps] [file]\n", argv[0]);
+ return 1;
+ }
+
+ list = (struct caplist *) malloc(caps * sizeof(struct caplist));
+ if (list == NULL) {
+ fprintf(stderr, "%s: malloc failed.\n", argv[0]);
+ return 1;
+ }
+
+ n = readcaps(f, list, caps);
+ if (n > caps) {
+ fprintf(stderr, "%s: too many caps, use -n.\n", argv[0]);
+ return 1;
+ }
+ switch(n) {
+ case 0:
+ fprintf(stderr, "%s: no caps in file.\n", argv[0]);
+ return 1;
+ case -1:
+ fprintf(stderr, "%s: bad caps line.\n", argv[0]);
+ return 1;
+ case -2:
+ fprintf(stderr, "%s: unexpected EOF.\n", argv[0]);
+ return 1;
+ }
+
+ puts("/*");
+ puts(" * term.h ");
+ puts(" *");
+ puts(" * This file was generated automatically.");
+ puts(" *");
+ puts(" */");
+ putchar('\n');
+ puts("#ifndef _TERM_H_");
+ puts("#define _TERM_H_");
+ putchar('\n');
+ nb = 0;
+ for (i = 0; i < n; i++) {
+ if (list[i].type == '!') {
+ printf("#define %-*s (_CUR_TERM.bools[%d])\n",
+ MAX_VARNAME, list[i].var, nb);
+ nb++;
+ }
+ }
+
+ nn = 0;
+ for (i = 0; i < n; i++) {
+ if (list[i].type == '#') {
+ printf("#define %-*s (_CUR_TERM.nums[%d])\n",
+ MAX_VARNAME, list[i].var, nn);
+ nn++;
+ }
+ }
+
+ ns = 0;
+ for (i = 0; i < n; i++) {
+ if (list[i].type == '$') {
+ printf("#define %-*s (_CUR_TERM.strs[%d])\n",
+ MAX_VARNAME, list[i].var, ns);
+ ns++;
+ }
+ }
+
+ putchar('\n');
+
+ printf ("#define NUM_OF_BOOLS\t%d\n", nb);
+ printf ("#define NUM_OF_NUMS\t%d\n", nn);
+ printf ("#define NUM_OF_STRS\t%d\n", ns);
+
+ putchar('\n');
+ puts("#ifndef OVERRIDE");
+ puts("#undef _USE_SGTTY");
+#ifdef USE_SGTTY
+ puts("#define _USE_SGTTY");
+#endif
+ puts("#undef _USE_TERMIO");
+#ifdef USE_TERMIO
+ puts("#define _USE_TERMIO");
+#endif
+ puts("#undef _USE_TERMIOS");
+#ifdef USE_TERMIOS
+ puts("#define _USE_TERMIOS");
+#endif
+ puts("#undef _USE_SMALLMEM");
+#ifdef USE_SMALLMEM
+ puts("#define _USE_SMALLMEM");
+#endif
+ puts("#undef _USE_PROTOTYPES");
+#ifdef USE_PROTOTYPES
+ puts("#define _USE_PROTOTYPES");
+#endif
+ puts("#undef _USE_WINSZ");
+#ifdef USE_WINSZ
+ puts("#define _USE_WINSZ");
+#endif
+ puts("#undef _USE_TERMINFO");
+#ifdef USE_TERMINFO
+ puts("#define _USE_TERMINFO");
+#endif
+ puts("#undef _USE_TERMCAP");
+#ifdef USE_TERMCAP
+ puts("#define _USE_TERMCAP");
+#endif
+ puts("#undef _MAX_CHUNK");
+ printf("#define _MAX_CHUNK %d\n", MAX_CHUNK);
+ puts("#endif /* OVERRIDE */");
+ putchar('\n');
+
+ return 0;
+}
diff --git a/lib/libmytinfo/mkversion.c b/lib/libmytinfo/mkversion.c
new file mode 100644
index 0000000..9fbc12e
--- /dev/null
+++ b/lib/libmytinfo/mkversion.c
@@ -0,0 +1,35 @@
+/*
+ * mkversion.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:09
+ *
+ * generates version.c
+ *
+ */
+
+#define NOTLIB
+#include "defs.h"
+
+#include "version.h"
+
+const char SCCSid[] = "@(#) mytinfo mkversion.c 3.2 92/02/01 public domain, By Ross Ridge";
+
+int
+main(argc, argv)
+int argc;
+char **argv; {
+ puts("/*");
+ puts(" * version.c ");
+ puts(" *");
+ puts(" * This file was generated automatically.");
+ puts(" *");
+ puts(" */");
+ putchar('\n');
+
+ printf("char _mytinfo_version[] = \"@(#) mytinfo: Release %d, Patchlevel %d (ache).\";\n",
+ RELEASE, PATCHLEVEL);
+
+ return 0;
+}
diff --git a/lib/libmytinfo/readcaps.c b/lib/libmytinfo/readcaps.c
new file mode 100644
index 0000000..b78bdc1
--- /dev/null
+++ b/lib/libmytinfo/readcaps.c
@@ -0,0 +1,151 @@
+/*
+ * readcaps.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:15
+ *
+ * Read in the cap_list file
+ *
+ */
+
+#define NOTLIB
+#include "defs.h"
+
+#include <ctype.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo readcaps.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+#ifdef __GNUC__
+__inline__
+#endif
+static int
+skipline(f)
+register FILE *f; {
+ register int c;
+
+ do {
+ c = getc(f);
+ if (c == EOF)
+ return EOF;
+#ifdef TEST
+ putchar(c);
+#endif
+ } while (c != '\n');
+
+ return 0;
+}
+
+#ifdef __GNUC__
+__inline__
+#endif
+static int
+getfield(f, s, len)
+register FILE *f;
+register char *s;
+int len; {
+ register int c;
+ int i;
+#ifdef TEST
+ char *start = s;
+#endif
+
+ do {
+ c = getc(f);
+ if (c == EOF)
+ return EOF;
+ } while (c != '\n' && isspace(c));
+ if (c == '\n')
+ return 0;
+
+ i = 0;
+ while(!isspace(c)) {
+ if (i++ < len)
+ *s++ = c;
+ c = getc(f);
+ if (c == EOF)
+ return EOF;
+
+ }
+ *s = '\0';
+#ifdef TEST
+ printf(" %s", start);
+#endif
+ return c;
+}
+
+int
+readcaps(f, buf, max)
+FILE *f;
+register struct caplist *buf;
+int max; {
+ int type;
+ register int count;
+ int c;
+ static char dummy;
+
+ count = 0;
+ type = getc(f);
+ while(type != EOF) {
+ if (type == '$' || type == '!' || type == '#') {
+ if (count >= max)
+ return count + 1;
+#ifdef TEST
+ putchar(type);
+#endif
+ buf[count].type = type;
+
+ if (type == '$') {
+ c = getc(f);
+ if (c == EOF)
+ break;
+ if (c == 'G')
+ buf[count].flag = 'G';
+ else if (c == 'K')
+ buf[count].flag = 'K';
+ else
+ buf[count].flag = ' ';
+ }
+
+ c = getfield(f, buf[count].var, MAX_VARNAME);
+ if (c == EOF || c == '\n' || c == 0)
+ return -1;
+ c = getfield(f, buf[count].tinfo, MAX_TINFONAME);
+ if (c == EOF || c == '\n' || c == 0)
+ return -1;
+ c = getfield(f, buf[count].tcap, MAX_TCAPNAME);
+ if (c == EOF || c == 0)
+ return -1;
+ if (c != '\n')
+ if (getfield(f, &dummy, 1) != 0)
+ return -1;
+ count++;
+#ifdef TEST
+ putchar('\n');
+#endif
+ } else {
+#ifdef TEST
+ putchar(type);
+#endif
+ if (type != '\n' && skipline(f) == EOF)
+ return -1;
+ }
+ type = getc(f);
+ }
+ return count;
+}
+
+#ifdef TEST
+struct caplist list[1000];
+
+int
+main() {
+ int ret;
+
+ ret = readcaps(stdin, list, 1000);
+ printf("ret = %d\n", ret);
+ return 0;
+}
+#endif
diff --git a/lib/libmytinfo/tcapconv.c b/lib/libmytinfo/tcapconv.c
new file mode 100644
index 0000000..3cd4d36
--- /dev/null
+++ b/lib/libmytinfo/tcapconv.c
@@ -0,0 +1,194 @@
+/*
+ * tcapconv.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:20
+ *
+ */
+
+#include "defs.h"
+#define SINGLE
+#include <term.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo tcapconv.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+extern char **_sstrcodes[], **_sstrnames[];
+
+static char *C_CR = "\r";
+static char *C_LF = "\n";
+static char *C_BS = "\b";
+/* static char *C_FF = "\f"; */
+static char *C_HT = "\t";
+/* static char *C_VT = "\013"; */
+/* static char *C_NL = "\r\n"; */
+
+#define DEF(s) ((s) != (char *) -1 && (s) != NULL)
+#define NOTSET(s) ((s) == (char *) -1)
+
+/*
+ * This routine fills in caps that either had defaults under termcap or
+ * can be manufactured from obsolete termcap capabilities.
+ */
+
+void
+_tcapdefault() {
+ char buf[MAX_LINE * 2 + 2];
+ int set_scroll_forward_to_lf;
+
+ if (NOTSET(carriage_return)) {
+ if (carriage_return_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_CR, carriage_return_delay);
+ carriage_return = _addstr(buf);
+ } else
+ carriage_return = _addstr(C_CR);
+ }
+ if (NOTSET(cursor_left)) {
+ if (backspace_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_BS, backspace_delay);
+ cursor_left = _addstr(buf);
+ } else if (backspaces_with_bs == 1)
+ cursor_left = _addstr(C_BS);
+ else if (DEF(backspace_if_not_bs))
+ cursor_left = _addstr(backspace_if_not_bs);
+ }
+/* vi doesn't use "do", but it does seems to use nl (or '\n') instead */
+ if (NOTSET(cursor_down)) {
+ if (DEF(linefeed_if_not_lf))
+ cursor_down = _addstr(linefeed_if_not_lf);
+ else if (linefeed_is_newline != 1) {
+ if (new_line_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_LF, new_line_delay);
+ cursor_down = _addstr(buf);
+ } else
+ cursor_down = _addstr(C_LF);
+ }
+ }
+ set_scroll_forward_to_lf = 0;
+ if (NOTSET(scroll_forward) && crt_without_scrolling != 1) {
+ set_scroll_forward_to_lf = 1;
+ if (DEF(linefeed_if_not_lf))
+ scroll_forward = _addstr(linefeed_if_not_lf);
+ else if (linefeed_is_newline != 1) {
+ if (new_line_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_LF, new_line_delay);
+ scroll_forward = _addstr(buf);
+ } else
+ scroll_forward = _addstr(C_LF);
+ }
+ }
+ if (NOTSET(newline)) {
+ if (linefeed_is_newline == 1) {
+ if (new_line_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_LF, new_line_delay);
+ newline = _addstr(buf);
+ } else
+ newline = _addstr(C_LF);
+ } else if (DEF(carriage_return) && carriage_return_delay <= 0) {
+ if (set_scroll_forward_to_lf) {
+ strncpy(buf, carriage_return, MAX_LINE-2);
+ buf[MAX_LINE-1] = '\0';
+ strncat(buf, scroll_forward, MAX_LINE-strlen(buf)-1);
+ } else if (DEF(linefeed_if_not_lf)) {
+ strncpy(buf, carriage_return, MAX_LINE-2);
+ buf[MAX_LINE-1] = '\0';
+ strncat(buf, linefeed_if_not_lf, MAX_LINE-strlen(buf)-1);
+ }
+ else if (new_line_delay > 0)
+ sprintf(buf, "%s%s$<%d>", carriage_return, C_LF, new_line_delay);
+ else {
+ strncpy(buf, carriage_return, MAX_LINE-2);
+ buf[MAX_LINE-1] = '\0';
+ strncat(buf, C_LF, MAX_LINE-strlen(buf)-1);
+ }
+ buf[MAX_LINE-1] = '\0';
+ newline = _addstr(buf);
+ }
+ }
+
+/*
+ * We wait until know to decide if we've got a working cr because even
+ * one that doesn't work can be used for newline. Unfortunately the
+ * space allocated for it is wasted.
+ */
+ if (return_does_clr_eol == 1 || no_correctly_working_cr == 1)
+ carriage_return = NULL;
+
+/*
+ * supposedly most termcap entries have ta now and '\t' is no longer a
+ * default, but it doesn't seem to be true...
+ */
+ if (NOTSET(tab)) {
+ if (horizontal_tab_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_HT, horizontal_tab_delay);
+ tab = _addstr(buf);
+ } else
+ tab = _addstr(C_HT);
+ }
+#if 0
+/* probably not needed and might confuse some programmes */
+ if (NOTSET(form_feed)) {
+ if (form_feed_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_FF, form_feed_delay);
+ form_feed = _addstr(buf);
+ } else
+ form_feed = _addstr(C_FF);
+ }
+#endif
+ if (init_tabs == -1 && has_hardware_tabs == 1)
+ init_tabs = 8;
+
+ if (NOTSET(key_backspace))
+ key_backspace = _addstr(C_BS);
+ if (NOTSET(key_left))
+ key_left = _addstr(C_BS);
+ if (NOTSET(key_down))
+ key_down = _addstr(C_LF);
+}
+
+void
+_tcapconv() {
+ char buf[MAX_LINE+1];
+
+ if (GNU_tab_width > 0 && init_tabs == -1)
+ init_tabs = GNU_tab_width;
+
+ if (GNU_has_meta_key == 1 && has_meta_key == -1)
+ has_meta_key = 1;
+
+/*
+ * this is some what a kludge, but should work unless someone breaks
+ * conventions.
+ */
+ if (DEF(other_non_function_keys)) {
+ register char *s;
+ static char *o;
+ static char name[MAX_NAME] = "k";
+ char *str;
+ int ind;
+
+ s = strcpy(buf, other_non_function_keys);
+ while(*s != '\0') {
+ o = s;
+ while(*s != ',' && *s != '\0')
+ s++;
+ if (*s != '\0')
+ *s++ = '\0';
+ ind = _findstrcode(o);
+ if (ind == -1)
+ continue;
+ str = _term_buf.strs[ind];
+ if (!DEF(str))
+ continue;
+ strncpy(name + 1, strnames[ind], MAX_NAME - 2);
+ ind = _findstrname(name);
+ if (ind == -1)
+ continue;
+ if (!NOTSET(_term_buf.strs[ind]))
+ continue;
+ _term_buf.strs[ind] = _addstr(str);
+ }
+ }
+}
diff --git a/lib/libmytinfo/tcapvars.c b/lib/libmytinfo/tcapvars.c
new file mode 100644
index 0000000..52e339c
--- /dev/null
+++ b/lib/libmytinfo/tcapvars.c
@@ -0,0 +1,36 @@
+/*
+ * tcapvars.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:21
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo tcapvars.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+char PC;
+short ospeed;
+char *UP, *BC;
+
+void
+_figure_termcap() {
+#if defined(USE_SGTTY) || defined(USE_TERMIO) || defined(USE_TERMIOS)
+#ifdef USE_TERMIOS
+ extern speed_t _baud_tbl[];
+#else
+#ifdef USE_SMALLMEM
+ extern unsigned short _baud_tbl[];
+#else
+ extern long _baud_tbl[];
+#endif
+#endif
+ cur_term->padch = PC;
+ cur_term->baudrate = _baud_tbl[ospeed];
+#endif
+}
diff --git a/lib/libmytinfo/term.h b/lib/libmytinfo/term.h
new file mode 100644
index 0000000..f2b3a4d
--- /dev/null
+++ b/lib/libmytinfo/term.h
@@ -0,0 +1,664 @@
+/*
+ * term.h
+ *
+ * This file was generated automatically.
+ *
+ */
+
+#ifndef _TERM_H_
+#define _TERM_H_
+
+#define auto_left_margin (_CUR_TERM.bools[0])
+#define auto_right_margin (_CUR_TERM.bools[1])
+#define ceol_standout_glitch (_CUR_TERM.bools[2])
+#define dest_tabs_magic_smso (_CUR_TERM.bools[3])
+#define eat_newline_glitch (_CUR_TERM.bools[4])
+#define erase_overstrike (_CUR_TERM.bools[5])
+#define generic_type (_CUR_TERM.bools[6])
+#define hard_copy (_CUR_TERM.bools[7])
+#define hard_cursor (_CUR_TERM.bools[8])
+#define has_meta_key (_CUR_TERM.bools[9])
+#define has_status_line (_CUR_TERM.bools[10])
+#define insert_null_glitch (_CUR_TERM.bools[11])
+#define memory_above (_CUR_TERM.bools[12])
+#define memory_below (_CUR_TERM.bools[13])
+#define move_insert_mode (_CUR_TERM.bools[14])
+#define move_standout_mode (_CUR_TERM.bools[15])
+#define needs_xon_xoff (_CUR_TERM.bools[16])
+#define no_esc_ctlc (_CUR_TERM.bools[17])
+#define no_pad_char (_CUR_TERM.bools[18])
+#define non_rev_rmcup (_CUR_TERM.bools[19])
+#define over_strike (_CUR_TERM.bools[20])
+#define prtr_silent (_CUR_TERM.bools[21])
+#define status_line_esc_ok (_CUR_TERM.bools[22])
+#define tilde_glitch (_CUR_TERM.bools[23])
+#define transparent_underline (_CUR_TERM.bools[24])
+#define xon_xoff (_CUR_TERM.bools[25])
+#define back_color_erase (_CUR_TERM.bools[26])
+#define can_change (_CUR_TERM.bools[27])
+#define col_addr_glitch (_CUR_TERM.bools[28])
+#define cpi_changes_res (_CUR_TERM.bools[29])
+#define cr_cancels_micro_mode (_CUR_TERM.bools[30])
+#define has_print_wheel (_CUR_TERM.bools[31])
+#define hue_lightness_saturation (_CUR_TERM.bools[32])
+#define lpi_changes_res (_CUR_TERM.bools[33])
+#define non_dest_scroll_region (_CUR_TERM.bools[34])
+#define row_addr_glitch (_CUR_TERM.bools[35])
+#define semi_auto_right_margin (_CUR_TERM.bools[36])
+#define backspaces_with_bs (_CUR_TERM.bools[37])
+#define even_parity (_CUR_TERM.bools[38])
+#define half_duplex (_CUR_TERM.bools[39])
+#define lower_case_only (_CUR_TERM.bools[40])
+#define no_correctly_working_cr (_CUR_TERM.bools[41])
+#define linefeed_is_newline (_CUR_TERM.bools[42])
+#define crt_without_scrolling (_CUR_TERM.bools[43])
+#define odd_parity (_CUR_TERM.bools[44])
+#define has_hardware_tabs (_CUR_TERM.bools[45])
+#define uppercase_only (_CUR_TERM.bools[46])
+#define return_does_clr_eol (_CUR_TERM.bools[47])
+#define tek_4025_insert_line (_CUR_TERM.bools[48])
+#define initialization_messy (_CUR_TERM.bools[49])
+#define index_at_bottom_does_cr (_CUR_TERM.bools[50])
+#define rind_only_at_top (_CUR_TERM.bools[51])
+#define GNU_has_meta_key (_CUR_TERM.bools[52])
+#define columns (_CUR_TERM.nums[0])
+#define init_tabs (_CUR_TERM.nums[1])
+#define label_height (_CUR_TERM.nums[2])
+#define label_width (_CUR_TERM.nums[3])
+#define lines (_CUR_TERM.nums[4])
+#define lines_of_memory (_CUR_TERM.nums[5])
+#define magic_cookie_glitch (_CUR_TERM.nums[6])
+#define num_labels (_CUR_TERM.nums[7])
+#define padding_baud_rate (_CUR_TERM.nums[8])
+#define virtual_terminal (_CUR_TERM.nums[9])
+#define width_status_line (_CUR_TERM.nums[10])
+#define bit_image_entwining (_CUR_TERM.nums[11])
+#define bit_image_type (_CUR_TERM.nums[12])
+#define buffer_capacity (_CUR_TERM.nums[13])
+#define buttons (_CUR_TERM.nums[14])
+#define dot_horz_spacing (_CUR_TERM.nums[15])
+#define dot_vert_spacing (_CUR_TERM.nums[16])
+#define max_attributes (_CUR_TERM.nums[17])
+#define max_colors (_CUR_TERM.nums[18])
+#define max_micro_address (_CUR_TERM.nums[19])
+#define max_micro_jump (_CUR_TERM.nums[20])
+#define max_pairs (_CUR_TERM.nums[21])
+#define maximum_windows (_CUR_TERM.nums[22])
+#define micro_char_size (_CUR_TERM.nums[23])
+#define micro_line_size (_CUR_TERM.nums[24])
+#define no_color_video (_CUR_TERM.nums[25])
+#define number_of_pins (_CUR_TERM.nums[26])
+#define output_res_char (_CUR_TERM.nums[27])
+#define output_res_horz_inch (_CUR_TERM.nums[28])
+#define output_res_line (_CUR_TERM.nums[29])
+#define output_res_vert_inch (_CUR_TERM.nums[30])
+#define print_rate (_CUR_TERM.nums[31])
+#define wide_char_size (_CUR_TERM.nums[32])
+#define backspace_delay (_CUR_TERM.nums[33])
+#define carriage_return_delay (_CUR_TERM.nums[34])
+#define form_feed_delay (_CUR_TERM.nums[35])
+#define new_line_delay (_CUR_TERM.nums[36])
+#define horizontal_tab_delay (_CUR_TERM.nums[37])
+#define vertical_tab_delay (_CUR_TERM.nums[38])
+#define number_of_function_keys (_CUR_TERM.nums[39])
+#define magic_cookie_glitch_ul (_CUR_TERM.nums[40])
+#define GNU_tab_width (_CUR_TERM.nums[41])
+#define acs_chars (_CUR_TERM.strs[0])
+#define back_tab (_CUR_TERM.strs[1])
+#define bell (_CUR_TERM.strs[2])
+#define carriage_return (_CUR_TERM.strs[3])
+#define change_scroll_region (_CUR_TERM.strs[4])
+#define char_padding (_CUR_TERM.strs[5])
+#define clear_all_tabs (_CUR_TERM.strs[6])
+#define clear_margins (_CUR_TERM.strs[7])
+#define clear_screen (_CUR_TERM.strs[8])
+#define clr_bol (_CUR_TERM.strs[9])
+#define clr_eol (_CUR_TERM.strs[10])
+#define clr_eos (_CUR_TERM.strs[11])
+#define column_address (_CUR_TERM.strs[12])
+#define command_character (_CUR_TERM.strs[13])
+#define cursor_address (_CUR_TERM.strs[14])
+#define cursor_down (_CUR_TERM.strs[15])
+#define cursor_home (_CUR_TERM.strs[16])
+#define cursor_invisible (_CUR_TERM.strs[17])
+#define cursor_left (_CUR_TERM.strs[18])
+#define cursor_mem_address (_CUR_TERM.strs[19])
+#define cursor_normal (_CUR_TERM.strs[20])
+#define cursor_right (_CUR_TERM.strs[21])
+#define cursor_to_ll (_CUR_TERM.strs[22])
+#define cursor_up (_CUR_TERM.strs[23])
+#define cursor_visible (_CUR_TERM.strs[24])
+#define delete_character (_CUR_TERM.strs[25])
+#define delete_line (_CUR_TERM.strs[26])
+#define dis_status_line (_CUR_TERM.strs[27])
+#define down_half_line (_CUR_TERM.strs[28])
+#define ena_acs (_CUR_TERM.strs[29])
+#define enter_alt_charset_mode (_CUR_TERM.strs[30])
+#define enter_am_mode (_CUR_TERM.strs[31])
+#define enter_blink_mode (_CUR_TERM.strs[32])
+#define enter_bold_mode (_CUR_TERM.strs[33])
+#define enter_ca_mode (_CUR_TERM.strs[34])
+#define enter_delete_mode (_CUR_TERM.strs[35])
+#define enter_dim_mode (_CUR_TERM.strs[36])
+#define enter_insert_mode (_CUR_TERM.strs[37])
+#define enter_protected_mode (_CUR_TERM.strs[38])
+#define enter_reverse_mode (_CUR_TERM.strs[39])
+#define enter_secure_mode (_CUR_TERM.strs[40])
+#define enter_standout_mode (_CUR_TERM.strs[41])
+#define enter_underline_mode (_CUR_TERM.strs[42])
+#define enter_xon_mode (_CUR_TERM.strs[43])
+#define erase_chars (_CUR_TERM.strs[44])
+#define exit_alt_charset_mode (_CUR_TERM.strs[45])
+#define exit_am_mode (_CUR_TERM.strs[46])
+#define exit_attribute_mode (_CUR_TERM.strs[47])
+#define exit_ca_mode (_CUR_TERM.strs[48])
+#define exit_delete_mode (_CUR_TERM.strs[49])
+#define exit_insert_mode (_CUR_TERM.strs[50])
+#define exit_standout_mode (_CUR_TERM.strs[51])
+#define exit_underline_mode (_CUR_TERM.strs[52])
+#define exit_xon_mode (_CUR_TERM.strs[53])
+#define flash_screen (_CUR_TERM.strs[54])
+#define form_feed (_CUR_TERM.strs[55])
+#define from_status_line (_CUR_TERM.strs[56])
+#define init_1string (_CUR_TERM.strs[57])
+#define init_2string (_CUR_TERM.strs[58])
+#define init_3string (_CUR_TERM.strs[59])
+#define init_file (_CUR_TERM.strs[60])
+#define init_prog (_CUR_TERM.strs[61])
+#define insert_character (_CUR_TERM.strs[62])
+#define insert_line (_CUR_TERM.strs[63])
+#define insert_padding (_CUR_TERM.strs[64])
+#define key_a1 (_CUR_TERM.strs[65])
+#define key_a3 (_CUR_TERM.strs[66])
+#define key_b2 (_CUR_TERM.strs[67])
+#define key_backspace (_CUR_TERM.strs[68])
+#define key_beg (_CUR_TERM.strs[69])
+#define key_btab (_CUR_TERM.strs[70])
+#define key_c1 (_CUR_TERM.strs[71])
+#define key_c3 (_CUR_TERM.strs[72])
+#define key_cancel (_CUR_TERM.strs[73])
+#define key_catab (_CUR_TERM.strs[74])
+#define key_clear (_CUR_TERM.strs[75])
+#define key_close (_CUR_TERM.strs[76])
+#define key_command (_CUR_TERM.strs[77])
+#define key_copy (_CUR_TERM.strs[78])
+#define key_create (_CUR_TERM.strs[79])
+#define key_ctab (_CUR_TERM.strs[80])
+#define key_dc (_CUR_TERM.strs[81])
+#define key_dl (_CUR_TERM.strs[82])
+#define key_down (_CUR_TERM.strs[83])
+#define key_eic (_CUR_TERM.strs[84])
+#define key_end (_CUR_TERM.strs[85])
+#define key_enter (_CUR_TERM.strs[86])
+#define key_eol (_CUR_TERM.strs[87])
+#define key_eos (_CUR_TERM.strs[88])
+#define key_exit (_CUR_TERM.strs[89])
+#define key_f0 (_CUR_TERM.strs[90])
+#define key_f1 (_CUR_TERM.strs[91])
+#define key_f10 (_CUR_TERM.strs[92])
+#define key_f11 (_CUR_TERM.strs[93])
+#define key_f12 (_CUR_TERM.strs[94])
+#define key_f13 (_CUR_TERM.strs[95])
+#define key_f14 (_CUR_TERM.strs[96])
+#define key_f15 (_CUR_TERM.strs[97])
+#define key_f16 (_CUR_TERM.strs[98])
+#define key_f17 (_CUR_TERM.strs[99])
+#define key_f18 (_CUR_TERM.strs[100])
+#define key_f19 (_CUR_TERM.strs[101])
+#define key_f2 (_CUR_TERM.strs[102])
+#define key_f20 (_CUR_TERM.strs[103])
+#define key_f21 (_CUR_TERM.strs[104])
+#define key_f22 (_CUR_TERM.strs[105])
+#define key_f23 (_CUR_TERM.strs[106])
+#define key_f24 (_CUR_TERM.strs[107])
+#define key_f25 (_CUR_TERM.strs[108])
+#define key_f26 (_CUR_TERM.strs[109])
+#define key_f27 (_CUR_TERM.strs[110])
+#define key_f28 (_CUR_TERM.strs[111])
+#define key_f29 (_CUR_TERM.strs[112])
+#define key_f3 (_CUR_TERM.strs[113])
+#define key_f30 (_CUR_TERM.strs[114])
+#define key_f31 (_CUR_TERM.strs[115])
+#define key_f32 (_CUR_TERM.strs[116])
+#define key_f33 (_CUR_TERM.strs[117])
+#define key_f34 (_CUR_TERM.strs[118])
+#define key_f35 (_CUR_TERM.strs[119])
+#define key_f36 (_CUR_TERM.strs[120])
+#define key_f37 (_CUR_TERM.strs[121])
+#define key_f38 (_CUR_TERM.strs[122])
+#define key_f39 (_CUR_TERM.strs[123])
+#define key_f4 (_CUR_TERM.strs[124])
+#define key_f40 (_CUR_TERM.strs[125])
+#define key_f41 (_CUR_TERM.strs[126])
+#define key_f42 (_CUR_TERM.strs[127])
+#define key_f43 (_CUR_TERM.strs[128])
+#define key_f44 (_CUR_TERM.strs[129])
+#define key_f45 (_CUR_TERM.strs[130])
+#define key_f46 (_CUR_TERM.strs[131])
+#define key_f47 (_CUR_TERM.strs[132])
+#define key_f48 (_CUR_TERM.strs[133])
+#define key_f49 (_CUR_TERM.strs[134])
+#define key_f5 (_CUR_TERM.strs[135])
+#define key_f50 (_CUR_TERM.strs[136])
+#define key_f51 (_CUR_TERM.strs[137])
+#define key_f52 (_CUR_TERM.strs[138])
+#define key_f53 (_CUR_TERM.strs[139])
+#define key_f54 (_CUR_TERM.strs[140])
+#define key_f55 (_CUR_TERM.strs[141])
+#define key_f56 (_CUR_TERM.strs[142])
+#define key_f57 (_CUR_TERM.strs[143])
+#define key_f58 (_CUR_TERM.strs[144])
+#define key_f59 (_CUR_TERM.strs[145])
+#define key_f6 (_CUR_TERM.strs[146])
+#define key_f60 (_CUR_TERM.strs[147])
+#define key_f61 (_CUR_TERM.strs[148])
+#define key_f62 (_CUR_TERM.strs[149])
+#define key_f63 (_CUR_TERM.strs[150])
+#define key_f7 (_CUR_TERM.strs[151])
+#define key_f8 (_CUR_TERM.strs[152])
+#define key_f9 (_CUR_TERM.strs[153])
+#define key_find (_CUR_TERM.strs[154])
+#define key_help (_CUR_TERM.strs[155])
+#define key_home (_CUR_TERM.strs[156])
+#define key_ic (_CUR_TERM.strs[157])
+#define key_il (_CUR_TERM.strs[158])
+#define key_left (_CUR_TERM.strs[159])
+#define key_ll (_CUR_TERM.strs[160])
+#define key_mark (_CUR_TERM.strs[161])
+#define key_message (_CUR_TERM.strs[162])
+#define key_move (_CUR_TERM.strs[163])
+#define key_next (_CUR_TERM.strs[164])
+#define key_npage (_CUR_TERM.strs[165])
+#define key_open (_CUR_TERM.strs[166])
+#define key_options (_CUR_TERM.strs[167])
+#define key_ppage (_CUR_TERM.strs[168])
+#define key_previous (_CUR_TERM.strs[169])
+#define key_print (_CUR_TERM.strs[170])
+#define key_redo (_CUR_TERM.strs[171])
+#define key_reference (_CUR_TERM.strs[172])
+#define key_refresh (_CUR_TERM.strs[173])
+#define key_replace (_CUR_TERM.strs[174])
+#define key_restart (_CUR_TERM.strs[175])
+#define key_resume (_CUR_TERM.strs[176])
+#define key_right (_CUR_TERM.strs[177])
+#define key_save (_CUR_TERM.strs[178])
+#define key_sbeg (_CUR_TERM.strs[179])
+#define key_scancel (_CUR_TERM.strs[180])
+#define key_scommand (_CUR_TERM.strs[181])
+#define key_scopy (_CUR_TERM.strs[182])
+#define key_screate (_CUR_TERM.strs[183])
+#define key_sdc (_CUR_TERM.strs[184])
+#define key_sdl (_CUR_TERM.strs[185])
+#define key_select (_CUR_TERM.strs[186])
+#define key_send (_CUR_TERM.strs[187])
+#define key_seol (_CUR_TERM.strs[188])
+#define key_sexit (_CUR_TERM.strs[189])
+#define key_sf (_CUR_TERM.strs[190])
+#define key_sfind (_CUR_TERM.strs[191])
+#define key_shelp (_CUR_TERM.strs[192])
+#define key_shome (_CUR_TERM.strs[193])
+#define key_sic (_CUR_TERM.strs[194])
+#define key_sleft (_CUR_TERM.strs[195])
+#define key_smessage (_CUR_TERM.strs[196])
+#define key_smove (_CUR_TERM.strs[197])
+#define key_snext (_CUR_TERM.strs[198])
+#define key_soptions (_CUR_TERM.strs[199])
+#define key_sprevious (_CUR_TERM.strs[200])
+#define key_sprint (_CUR_TERM.strs[201])
+#define key_sr (_CUR_TERM.strs[202])
+#define key_sredo (_CUR_TERM.strs[203])
+#define key_sreplace (_CUR_TERM.strs[204])
+#define key_sright (_CUR_TERM.strs[205])
+#define key_srsume (_CUR_TERM.strs[206])
+#define key_ssave (_CUR_TERM.strs[207])
+#define key_ssuspend (_CUR_TERM.strs[208])
+#define key_stab (_CUR_TERM.strs[209])
+#define key_sundo (_CUR_TERM.strs[210])
+#define key_suspend (_CUR_TERM.strs[211])
+#define key_undo (_CUR_TERM.strs[212])
+#define key_up (_CUR_TERM.strs[213])
+#define keypad_local (_CUR_TERM.strs[214])
+#define keypad_xmit (_CUR_TERM.strs[215])
+#define lab_f0 (_CUR_TERM.strs[216])
+#define lab_f1 (_CUR_TERM.strs[217])
+#define lab_f10 (_CUR_TERM.strs[218])
+#define lab_f2 (_CUR_TERM.strs[219])
+#define lab_f3 (_CUR_TERM.strs[220])
+#define lab_f4 (_CUR_TERM.strs[221])
+#define lab_f5 (_CUR_TERM.strs[222])
+#define lab_f6 (_CUR_TERM.strs[223])
+#define lab_f7 (_CUR_TERM.strs[224])
+#define lab_f8 (_CUR_TERM.strs[225])
+#define lab_f9 (_CUR_TERM.strs[226])
+#define label_off (_CUR_TERM.strs[227])
+#define label_on (_CUR_TERM.strs[228])
+#define meta_off (_CUR_TERM.strs[229])
+#define meta_on (_CUR_TERM.strs[230])
+#define newline (_CUR_TERM.strs[231])
+#define pad_char (_CUR_TERM.strs[232])
+#define parm_dch (_CUR_TERM.strs[233])
+#define parm_delete_line (_CUR_TERM.strs[234])
+#define parm_down_cursor (_CUR_TERM.strs[235])
+#define parm_ich (_CUR_TERM.strs[236])
+#define parm_index (_CUR_TERM.strs[237])
+#define parm_insert_line (_CUR_TERM.strs[238])
+#define parm_left_cursor (_CUR_TERM.strs[239])
+#define parm_right_cursor (_CUR_TERM.strs[240])
+#define parm_rindex (_CUR_TERM.strs[241])
+#define parm_up_cursor (_CUR_TERM.strs[242])
+#define pkey_key (_CUR_TERM.strs[243])
+#define pkey_local (_CUR_TERM.strs[244])
+#define pkey_xmit (_CUR_TERM.strs[245])
+#define plab_norm (_CUR_TERM.strs[246])
+#define print_screen (_CUR_TERM.strs[247])
+#define prtr_non (_CUR_TERM.strs[248])
+#define prtr_off (_CUR_TERM.strs[249])
+#define prtr_on (_CUR_TERM.strs[250])
+#define repeat_char (_CUR_TERM.strs[251])
+#define req_for_input (_CUR_TERM.strs[252])
+#define reset_1string (_CUR_TERM.strs[253])
+#define reset_2string (_CUR_TERM.strs[254])
+#define reset_3string (_CUR_TERM.strs[255])
+#define reset_file (_CUR_TERM.strs[256])
+#define restore_cursor (_CUR_TERM.strs[257])
+#define row_address (_CUR_TERM.strs[258])
+#define save_cursor (_CUR_TERM.strs[259])
+#define scroll_forward (_CUR_TERM.strs[260])
+#define scroll_reverse (_CUR_TERM.strs[261])
+#define set_attributes (_CUR_TERM.strs[262])
+#define set_left_margin (_CUR_TERM.strs[263])
+#define set_right_margin (_CUR_TERM.strs[264])
+#define set_tab (_CUR_TERM.strs[265])
+#define set_window (_CUR_TERM.strs[266])
+#define tab (_CUR_TERM.strs[267])
+#define to_status_line (_CUR_TERM.strs[268])
+#define underline_char (_CUR_TERM.strs[269])
+#define up_half_line (_CUR_TERM.strs[270])
+#define xoff_character (_CUR_TERM.strs[271])
+#define xon_character (_CUR_TERM.strs[272])
+#define alt_scancode_esc (_CUR_TERM.strs[273])
+#define bit_image_carriage_return (_CUR_TERM.strs[274])
+#define bit_image_newline (_CUR_TERM.strs[275])
+#define bit_image_repeat (_CUR_TERM.strs[276])
+#define change_char_pitch (_CUR_TERM.strs[277])
+#define change_line_pitch (_CUR_TERM.strs[278])
+#define change_res_horz (_CUR_TERM.strs[279])
+#define change_res_vert (_CUR_TERM.strs[280])
+#define char_set_names (_CUR_TERM.strs[281])
+#define code_set_init (_CUR_TERM.strs[282])
+#define color_names (_CUR_TERM.strs[283])
+#define create_window (_CUR_TERM.strs[284])
+#define define_bit_image_region (_CUR_TERM.strs[285])
+#define define_char (_CUR_TERM.strs[286])
+#define device_type (_CUR_TERM.strs[287])
+#define dial_phone (_CUR_TERM.strs[288])
+#define display_clock (_CUR_TERM.strs[289])
+#define display_pc_char (_CUR_TERM.strs[290])
+#define end_bit_image_region (_CUR_TERM.strs[291])
+#define enter_doublewide_mode (_CUR_TERM.strs[292])
+#define enter_draft_quality (_CUR_TERM.strs[293])
+#define enter_italics_mode (_CUR_TERM.strs[294])
+#define enter_leftward_mode (_CUR_TERM.strs[295])
+#define enter_micro_mode (_CUR_TERM.strs[296])
+#define enter_near_letter_quality (_CUR_TERM.strs[297])
+#define enter_normal_quality (_CUR_TERM.strs[298])
+#define enter_pc_charset_mode (_CUR_TERM.strs[299])
+#define enter_scancode_mode (_CUR_TERM.strs[300])
+#define enter_shadow_mode (_CUR_TERM.strs[301])
+#define enter_subscript_mode (_CUR_TERM.strs[302])
+#define enter_superscript_mode (_CUR_TERM.strs[303])
+#define enter_upward_mode (_CUR_TERM.strs[304])
+#define exit_doublewide_mode (_CUR_TERM.strs[305])
+#define exit_italics_mode (_CUR_TERM.strs[306])
+#define exit_leftward_mode (_CUR_TERM.strs[307])
+#define exit_micro_mode (_CUR_TERM.strs[308])
+#define exit_pc_charset_mode (_CUR_TERM.strs[309])
+#define exit_scancode_mode (_CUR_TERM.strs[310])
+#define exit_shadow_mode (_CUR_TERM.strs[311])
+#define exit_subscript_mode (_CUR_TERM.strs[312])
+#define exit_superscript_mode (_CUR_TERM.strs[313])
+#define exit_upward_mode (_CUR_TERM.strs[314])
+#define fixed_pause (_CUR_TERM.strs[315])
+#define flash_hook (_CUR_TERM.strs[316])
+#define get_mouse (_CUR_TERM.strs[317])
+#define goto_window (_CUR_TERM.strs[318])
+#define hangup (_CUR_TERM.strs[319])
+#define initialize_color (_CUR_TERM.strs[320])
+#define initialize_pair (_CUR_TERM.strs[321])
+#define key_mouse (_CUR_TERM.strs[322])
+#define label_format (_CUR_TERM.strs[323])
+#define micro_column_address (_CUR_TERM.strs[324])
+#define micro_down (_CUR_TERM.strs[325])
+#define micro_left (_CUR_TERM.strs[326])
+#define micro_right (_CUR_TERM.strs[327])
+#define micro_row_address (_CUR_TERM.strs[328])
+#define micro_up (_CUR_TERM.strs[329])
+#define mouse_info (_CUR_TERM.strs[330])
+#define order_of_pins (_CUR_TERM.strs[331])
+#define orig_colors (_CUR_TERM.strs[332])
+#define orig_pair (_CUR_TERM.strs[333])
+#define parm_down_micro (_CUR_TERM.strs[334])
+#define parm_left_micro (_CUR_TERM.strs[335])
+#define parm_right_micro (_CUR_TERM.strs[336])
+#define parm_up_micro (_CUR_TERM.strs[337])
+#define pc_term_options (_CUR_TERM.strs[338])
+#define pkey_plab (_CUR_TERM.strs[339])
+#define pulse (_CUR_TERM.strs[340])
+#define quick_dial (_CUR_TERM.strs[341])
+#define remove_clock (_CUR_TERM.strs[342])
+#define req_mouse_pos (_CUR_TERM.strs[343])
+#define scancode_escape (_CUR_TERM.strs[344])
+#define select_char_set (_CUR_TERM.strs[345])
+#define set0_des_seq (_CUR_TERM.strs[346])
+#define set1_des_seq (_CUR_TERM.strs[347])
+#define set2_des_seq (_CUR_TERM.strs[348])
+#define set3_des_seq (_CUR_TERM.strs[349])
+#define set_a_background (_CUR_TERM.strs[350])
+#define set_a_foreground (_CUR_TERM.strs[351])
+#define set_background (_CUR_TERM.strs[352])
+#define set_bottom_margin (_CUR_TERM.strs[353])
+#define set_bottom_margin_parm (_CUR_TERM.strs[354])
+#define set_clock (_CUR_TERM.strs[355])
+#define set_color_band (_CUR_TERM.strs[356])
+#define set_color_pair (_CUR_TERM.strs[357])
+#define set_foreground (_CUR_TERM.strs[358])
+#define set_left_margin_parm (_CUR_TERM.strs[359])
+#define set_lr_margin (_CUR_TERM.strs[360])
+#define set_page_length (_CUR_TERM.strs[361])
+#define set_right_margin_parm (_CUR_TERM.strs[362])
+#define set_tb_margin (_CUR_TERM.strs[363])
+#define set_top_margin (_CUR_TERM.strs[364])
+#define set_top_margin_parm (_CUR_TERM.strs[365])
+#define start_bit_image (_CUR_TERM.strs[366])
+#define start_char_set_def (_CUR_TERM.strs[367])
+#define stop_bit_image (_CUR_TERM.strs[368])
+#define stop_char_set_def (_CUR_TERM.strs[369])
+#define subscript_characters (_CUR_TERM.strs[370])
+#define superscript_characters (_CUR_TERM.strs[371])
+#define these_cause_cr (_CUR_TERM.strs[372])
+#define tone (_CUR_TERM.strs[373])
+#define user0 (_CUR_TERM.strs[374])
+#define user1 (_CUR_TERM.strs[375])
+#define user2 (_CUR_TERM.strs[376])
+#define user3 (_CUR_TERM.strs[377])
+#define user4 (_CUR_TERM.strs[378])
+#define user5 (_CUR_TERM.strs[379])
+#define user6 (_CUR_TERM.strs[380])
+#define user7 (_CUR_TERM.strs[381])
+#define user8 (_CUR_TERM.strs[382])
+#define user9 (_CUR_TERM.strs[383])
+#define wait_tone (_CUR_TERM.strs[384])
+#define zero_motion (_CUR_TERM.strs[385])
+#define backspace_if_not_bs (_CUR_TERM.strs[386])
+#define other_non_function_keys (_CUR_TERM.strs[387])
+#define arrow_key_map (_CUR_TERM.strs[388])
+#define memory_lock_above (_CUR_TERM.strs[389])
+#define memory_unlock (_CUR_TERM.strs[390])
+#define linefeed_if_not_lf (_CUR_TERM.strs[391])
+#define key_interrupt_char (_CUR_TERM.strs[392])
+#define key_kill_char (_CUR_TERM.strs[393])
+#define key_suspend_char (_CUR_TERM.strs[394])
+#define scroll_left (_CUR_TERM.strs[395])
+#define scroll_right (_CUR_TERM.strs[396])
+#define parm_scroll_left (_CUR_TERM.strs[397])
+#define parm_scroll_right (_CUR_TERM.strs[398])
+#define _get_other (_CUR_TERM.strs[399])
+
+#define NUM_OF_BOOLS 53
+#define NUM_OF_NUMS 42
+#define NUM_OF_STRS 400
+
+#ifndef OVERRIDE
+#undef _USE_SGTTY
+#undef _USE_TERMIO
+#undef _USE_TERMIOS
+#define _USE_TERMIOS
+#undef _USE_SMALLMEM
+#undef _USE_PROTOTYPES
+#define _USE_PROTOTYPES
+#undef _USE_WINSZ
+#define _USE_WINSZ
+#undef _USE_TERMINFO
+#undef _USE_TERMCAP
+#define _USE_TERMCAP
+#undef _MAX_CHUNK
+#define _MAX_CHUNK 640
+#endif /* OVERRIDE */
+
+/*
+ * 92/02/01 07:30:28
+ * @(#) mytinfo term.tail 3.2 92/02/01 public domain, By Ross Ridge
+ *
+ */
+
+#if defined(_USE_TERMIO) || defined(_USE_TERMIOS)
+#ifndef ICANON
+#ifdef _USE_TERMIO
+#include <termio.h>
+#else
+#include <termios.h>
+#endif
+#endif
+#if defined(_USE_WINSZ) && defined(__FreeBSD__)
+#include <sys/ioctl.h>
+#endif
+#if defined(_USE_WINSZ) && defined(xenix)
+#include <sys/stream.h>
+#include <sys/ptem.h>
+#endif
+#endif
+
+#ifdef _USE_SGTTY
+#ifndef CBREAK
+#include <sgtty.h>
+#endif
+#endif
+
+typedef struct _terminal {
+ int fd;
+#ifdef _USE_SMALLMEM
+#ifdef _USE_TERMIOS
+ speed_t baudrate;
+#else
+ unsigned short baudrate;
+#endif
+ unsigned pad:1, xon:1, termcap:1;
+#else
+ int pad;
+ int xon;
+ int termcap;
+#ifdef _USE_TERMIOS
+ speed_t baudrate;
+#else
+ long baudrate;
+#endif
+#endif
+ char padch;
+ short true_lines, true_columns;
+ struct strbuf {
+ struct strbuf *next;
+#ifdef _USE_SMALLMEM
+ short len;
+#else
+ int len;
+#endif
+ char buf[_MAX_CHUNK];
+ } *strbuf;
+ char *name, *name_long, *name_all;
+#ifdef _USE_SGTTY
+ struct sgtty_str {
+ struct sgttyb v6;
+#ifdef TIOCGETC
+ struct tchars v7;
+#endif
+#ifdef TIOCLGET
+ int bsd;
+#endif
+#ifdef TIOCGLTC
+ struct ltchars bsd_new;
+#endif
+ } prog_mode, shell_mode;
+#else /* _USE_SGTTY */
+#ifdef _USE_TERMIOS
+ struct termios prog_mode, shell_mode;
+#else
+#ifdef _USE_TERMIO
+ struct termio prog_mode, shell_mode;
+#endif
+#endif
+#endif /* else _USE_SGTTY */
+#ifdef _USE_WINSZ
+#ifdef TIOCGWINSZ
+ struct winsize prog_winsz, shell_winsz;
+#endif
+#endif
+ char bools[NUM_OF_BOOLS];
+ short nums[NUM_OF_NUMS];
+ char *strs[NUM_OF_STRS];
+} TERMINAL;
+
+#ifndef _CUR_TERM
+#ifdef SINGLE
+#define _CUR_TERM _term_buf
+#else
+#define _CUR_TERM (*cur_term)
+#endif
+#endif
+
+extern TERMINAL *cur_term;
+extern TERMINAL _term_buf;
+
+#ifndef __P
+#if defined(_USE_PROTOTYPES) && (defined(__STDC__) || defined(__cplusplus))
+#define __P(protos) protos /* full-blown ANSI C */
+#else
+#define __P(protos) () /* traditional C preprocessor */
+#endif
+#endif
+
+extern char *tparm __P((const char *, ...));
+extern int setupterm __P((char *, int, int *)), set_curterm __P((TERMINAL *));
+extern int del_curterm __P((TERMINAL *)), tputs __P((const char *, int, int (*)(int)));
+extern int putp __P((char *));
+extern int tigetflag __P((char *)), tigetnum __P((char *));
+extern char *tigetstr __P((char *));
+extern int def_prog_mode __P((void)), def_shell_mode __P((void));
+extern int reset_prog_mode __P((void)), reset_shell_mode __P((void));
+
+extern char *boolnames[], *boolcodes[], *boolfnames[];
+extern char *numnames[], *numcodes[], *numfnames[];
+extern char *strnames[], *strcodes[], *strfnames[];
+
+#ifndef OK
+#undef ERR
+#define OK (0)
+#define ERR (-1)
+#endif
+
+/* Compatibility */
+#define Filedes fd
+#define Ottyb shell_mode
+#define Nttyb prog_mode
+#define TTY struct termios
+
+#endif /* _TERM_H_ */
diff --git a/lib/libmytinfo/term.head b/lib/libmytinfo/term.head
new file mode 100644
index 0000000..4001038
--- /dev/null
+++ b/lib/libmytinfo/term.head
@@ -0,0 +1,527 @@
+/*
+ * term.h
+ *
+ * This file was generated automatically.
+ *
+ */
+
+#ifndef _TERM_H_
+#define _TERM_H_
+
+#define auto_left_margin (_CUR_TERM.bools[0])
+#define auto_right_margin (_CUR_TERM.bools[1])
+#define ceol_standout_glitch (_CUR_TERM.bools[2])
+#define dest_tabs_magic_smso (_CUR_TERM.bools[3])
+#define eat_newline_glitch (_CUR_TERM.bools[4])
+#define erase_overstrike (_CUR_TERM.bools[5])
+#define generic_type (_CUR_TERM.bools[6])
+#define hard_copy (_CUR_TERM.bools[7])
+#define hard_cursor (_CUR_TERM.bools[8])
+#define has_meta_key (_CUR_TERM.bools[9])
+#define has_status_line (_CUR_TERM.bools[10])
+#define insert_null_glitch (_CUR_TERM.bools[11])
+#define memory_above (_CUR_TERM.bools[12])
+#define memory_below (_CUR_TERM.bools[13])
+#define move_insert_mode (_CUR_TERM.bools[14])
+#define move_standout_mode (_CUR_TERM.bools[15])
+#define needs_xon_xoff (_CUR_TERM.bools[16])
+#define no_esc_ctlc (_CUR_TERM.bools[17])
+#define no_pad_char (_CUR_TERM.bools[18])
+#define non_rev_rmcup (_CUR_TERM.bools[19])
+#define over_strike (_CUR_TERM.bools[20])
+#define prtr_silent (_CUR_TERM.bools[21])
+#define status_line_esc_ok (_CUR_TERM.bools[22])
+#define tilde_glitch (_CUR_TERM.bools[23])
+#define transparent_underline (_CUR_TERM.bools[24])
+#define xon_xoff (_CUR_TERM.bools[25])
+#define back_color_erase (_CUR_TERM.bools[26])
+#define can_change (_CUR_TERM.bools[27])
+#define col_addr_glitch (_CUR_TERM.bools[28])
+#define cpi_changes_res (_CUR_TERM.bools[29])
+#define cr_cancels_micro_mode (_CUR_TERM.bools[30])
+#define has_print_wheel (_CUR_TERM.bools[31])
+#define hue_lightness_saturation (_CUR_TERM.bools[32])
+#define lpi_changes_res (_CUR_TERM.bools[33])
+#define non_dest_scroll_region (_CUR_TERM.bools[34])
+#define row_addr_glitch (_CUR_TERM.bools[35])
+#define semi_auto_right_margin (_CUR_TERM.bools[36])
+#define backspaces_with_bs (_CUR_TERM.bools[37])
+#define even_parity (_CUR_TERM.bools[38])
+#define half_duplex (_CUR_TERM.bools[39])
+#define lower_case_only (_CUR_TERM.bools[40])
+#define no_correctly_working_cr (_CUR_TERM.bools[41])
+#define linefeed_is_newline (_CUR_TERM.bools[42])
+#define crt_without_scrolling (_CUR_TERM.bools[43])
+#define odd_parity (_CUR_TERM.bools[44])
+#define has_hardware_tabs (_CUR_TERM.bools[45])
+#define uppercase_only (_CUR_TERM.bools[46])
+#define return_does_clr_eol (_CUR_TERM.bools[47])
+#define tek_4025_insert_line (_CUR_TERM.bools[48])
+#define initialization_messy (_CUR_TERM.bools[49])
+#define index_at_bottom_does_cr (_CUR_TERM.bools[50])
+#define rind_only_at_top (_CUR_TERM.bools[51])
+#define GNU_has_meta_key (_CUR_TERM.bools[52])
+#define columns (_CUR_TERM.nums[0])
+#define init_tabs (_CUR_TERM.nums[1])
+#define label_height (_CUR_TERM.nums[2])
+#define label_width (_CUR_TERM.nums[3])
+#define lines (_CUR_TERM.nums[4])
+#define lines_of_memory (_CUR_TERM.nums[5])
+#define magic_cookie_glitch (_CUR_TERM.nums[6])
+#define num_labels (_CUR_TERM.nums[7])
+#define padding_baud_rate (_CUR_TERM.nums[8])
+#define virtual_terminal (_CUR_TERM.nums[9])
+#define width_status_line (_CUR_TERM.nums[10])
+#define bit_image_entwining (_CUR_TERM.nums[11])
+#define bit_image_type (_CUR_TERM.nums[12])
+#define buffer_capacity (_CUR_TERM.nums[13])
+#define buttons (_CUR_TERM.nums[14])
+#define dot_horz_spacing (_CUR_TERM.nums[15])
+#define dot_vert_spacing (_CUR_TERM.nums[16])
+#define max_attributes (_CUR_TERM.nums[17])
+#define max_colors (_CUR_TERM.nums[18])
+#define max_micro_address (_CUR_TERM.nums[19])
+#define max_micro_jump (_CUR_TERM.nums[20])
+#define max_pairs (_CUR_TERM.nums[21])
+#define maximum_windows (_CUR_TERM.nums[22])
+#define micro_char_size (_CUR_TERM.nums[23])
+#define micro_line_size (_CUR_TERM.nums[24])
+#define no_color_video (_CUR_TERM.nums[25])
+#define number_of_pins (_CUR_TERM.nums[26])
+#define output_res_char (_CUR_TERM.nums[27])
+#define output_res_horz_inch (_CUR_TERM.nums[28])
+#define output_res_line (_CUR_TERM.nums[29])
+#define output_res_vert_inch (_CUR_TERM.nums[30])
+#define print_rate (_CUR_TERM.nums[31])
+#define wide_char_size (_CUR_TERM.nums[32])
+#define backspace_delay (_CUR_TERM.nums[33])
+#define carriage_return_delay (_CUR_TERM.nums[34])
+#define form_feed_delay (_CUR_TERM.nums[35])
+#define new_line_delay (_CUR_TERM.nums[36])
+#define horizontal_tab_delay (_CUR_TERM.nums[37])
+#define vertical_tab_delay (_CUR_TERM.nums[38])
+#define number_of_function_keys (_CUR_TERM.nums[39])
+#define magic_cookie_glitch_ul (_CUR_TERM.nums[40])
+#define GNU_tab_width (_CUR_TERM.nums[41])
+#define acs_chars (_CUR_TERM.strs[0])
+#define back_tab (_CUR_TERM.strs[1])
+#define bell (_CUR_TERM.strs[2])
+#define carriage_return (_CUR_TERM.strs[3])
+#define change_scroll_region (_CUR_TERM.strs[4])
+#define char_padding (_CUR_TERM.strs[5])
+#define clear_all_tabs (_CUR_TERM.strs[6])
+#define clear_margins (_CUR_TERM.strs[7])
+#define clear_screen (_CUR_TERM.strs[8])
+#define clr_bol (_CUR_TERM.strs[9])
+#define clr_eol (_CUR_TERM.strs[10])
+#define clr_eos (_CUR_TERM.strs[11])
+#define column_address (_CUR_TERM.strs[12])
+#define command_character (_CUR_TERM.strs[13])
+#define cursor_address (_CUR_TERM.strs[14])
+#define cursor_down (_CUR_TERM.strs[15])
+#define cursor_home (_CUR_TERM.strs[16])
+#define cursor_invisible (_CUR_TERM.strs[17])
+#define cursor_left (_CUR_TERM.strs[18])
+#define cursor_mem_address (_CUR_TERM.strs[19])
+#define cursor_normal (_CUR_TERM.strs[20])
+#define cursor_right (_CUR_TERM.strs[21])
+#define cursor_to_ll (_CUR_TERM.strs[22])
+#define cursor_up (_CUR_TERM.strs[23])
+#define cursor_visible (_CUR_TERM.strs[24])
+#define delete_character (_CUR_TERM.strs[25])
+#define delete_line (_CUR_TERM.strs[26])
+#define dis_status_line (_CUR_TERM.strs[27])
+#define down_half_line (_CUR_TERM.strs[28])
+#define ena_acs (_CUR_TERM.strs[29])
+#define enter_alt_charset_mode (_CUR_TERM.strs[30])
+#define enter_am_mode (_CUR_TERM.strs[31])
+#define enter_blink_mode (_CUR_TERM.strs[32])
+#define enter_bold_mode (_CUR_TERM.strs[33])
+#define enter_ca_mode (_CUR_TERM.strs[34])
+#define enter_delete_mode (_CUR_TERM.strs[35])
+#define enter_dim_mode (_CUR_TERM.strs[36])
+#define enter_insert_mode (_CUR_TERM.strs[37])
+#define enter_protected_mode (_CUR_TERM.strs[38])
+#define enter_reverse_mode (_CUR_TERM.strs[39])
+#define enter_secure_mode (_CUR_TERM.strs[40])
+#define enter_standout_mode (_CUR_TERM.strs[41])
+#define enter_underline_mode (_CUR_TERM.strs[42])
+#define enter_xon_mode (_CUR_TERM.strs[43])
+#define erase_chars (_CUR_TERM.strs[44])
+#define exit_alt_charset_mode (_CUR_TERM.strs[45])
+#define exit_am_mode (_CUR_TERM.strs[46])
+#define exit_attribute_mode (_CUR_TERM.strs[47])
+#define exit_ca_mode (_CUR_TERM.strs[48])
+#define exit_delete_mode (_CUR_TERM.strs[49])
+#define exit_insert_mode (_CUR_TERM.strs[50])
+#define exit_standout_mode (_CUR_TERM.strs[51])
+#define exit_underline_mode (_CUR_TERM.strs[52])
+#define exit_xon_mode (_CUR_TERM.strs[53])
+#define flash_screen (_CUR_TERM.strs[54])
+#define form_feed (_CUR_TERM.strs[55])
+#define from_status_line (_CUR_TERM.strs[56])
+#define init_1string (_CUR_TERM.strs[57])
+#define init_2string (_CUR_TERM.strs[58])
+#define init_3string (_CUR_TERM.strs[59])
+#define init_file (_CUR_TERM.strs[60])
+#define init_prog (_CUR_TERM.strs[61])
+#define insert_character (_CUR_TERM.strs[62])
+#define insert_line (_CUR_TERM.strs[63])
+#define insert_padding (_CUR_TERM.strs[64])
+#define key_a1 (_CUR_TERM.strs[65])
+#define key_a3 (_CUR_TERM.strs[66])
+#define key_b2 (_CUR_TERM.strs[67])
+#define key_backspace (_CUR_TERM.strs[68])
+#define key_beg (_CUR_TERM.strs[69])
+#define key_btab (_CUR_TERM.strs[70])
+#define key_c1 (_CUR_TERM.strs[71])
+#define key_c3 (_CUR_TERM.strs[72])
+#define key_cancel (_CUR_TERM.strs[73])
+#define key_catab (_CUR_TERM.strs[74])
+#define key_clear (_CUR_TERM.strs[75])
+#define key_close (_CUR_TERM.strs[76])
+#define key_command (_CUR_TERM.strs[77])
+#define key_copy (_CUR_TERM.strs[78])
+#define key_create (_CUR_TERM.strs[79])
+#define key_ctab (_CUR_TERM.strs[80])
+#define key_dc (_CUR_TERM.strs[81])
+#define key_dl (_CUR_TERM.strs[82])
+#define key_down (_CUR_TERM.strs[83])
+#define key_eic (_CUR_TERM.strs[84])
+#define key_end (_CUR_TERM.strs[85])
+#define key_enter (_CUR_TERM.strs[86])
+#define key_eol (_CUR_TERM.strs[87])
+#define key_eos (_CUR_TERM.strs[88])
+#define key_exit (_CUR_TERM.strs[89])
+#define key_f0 (_CUR_TERM.strs[90])
+#define key_f1 (_CUR_TERM.strs[91])
+#define key_f10 (_CUR_TERM.strs[92])
+#define key_f11 (_CUR_TERM.strs[93])
+#define key_f12 (_CUR_TERM.strs[94])
+#define key_f13 (_CUR_TERM.strs[95])
+#define key_f14 (_CUR_TERM.strs[96])
+#define key_f15 (_CUR_TERM.strs[97])
+#define key_f16 (_CUR_TERM.strs[98])
+#define key_f17 (_CUR_TERM.strs[99])
+#define key_f18 (_CUR_TERM.strs[100])
+#define key_f19 (_CUR_TERM.strs[101])
+#define key_f2 (_CUR_TERM.strs[102])
+#define key_f20 (_CUR_TERM.strs[103])
+#define key_f21 (_CUR_TERM.strs[104])
+#define key_f22 (_CUR_TERM.strs[105])
+#define key_f23 (_CUR_TERM.strs[106])
+#define key_f24 (_CUR_TERM.strs[107])
+#define key_f25 (_CUR_TERM.strs[108])
+#define key_f26 (_CUR_TERM.strs[109])
+#define key_f27 (_CUR_TERM.strs[110])
+#define key_f28 (_CUR_TERM.strs[111])
+#define key_f29 (_CUR_TERM.strs[112])
+#define key_f3 (_CUR_TERM.strs[113])
+#define key_f30 (_CUR_TERM.strs[114])
+#define key_f31 (_CUR_TERM.strs[115])
+#define key_f32 (_CUR_TERM.strs[116])
+#define key_f33 (_CUR_TERM.strs[117])
+#define key_f34 (_CUR_TERM.strs[118])
+#define key_f35 (_CUR_TERM.strs[119])
+#define key_f36 (_CUR_TERM.strs[120])
+#define key_f37 (_CUR_TERM.strs[121])
+#define key_f38 (_CUR_TERM.strs[122])
+#define key_f39 (_CUR_TERM.strs[123])
+#define key_f4 (_CUR_TERM.strs[124])
+#define key_f40 (_CUR_TERM.strs[125])
+#define key_f41 (_CUR_TERM.strs[126])
+#define key_f42 (_CUR_TERM.strs[127])
+#define key_f43 (_CUR_TERM.strs[128])
+#define key_f44 (_CUR_TERM.strs[129])
+#define key_f45 (_CUR_TERM.strs[130])
+#define key_f46 (_CUR_TERM.strs[131])
+#define key_f47 (_CUR_TERM.strs[132])
+#define key_f48 (_CUR_TERM.strs[133])
+#define key_f49 (_CUR_TERM.strs[134])
+#define key_f5 (_CUR_TERM.strs[135])
+#define key_f50 (_CUR_TERM.strs[136])
+#define key_f51 (_CUR_TERM.strs[137])
+#define key_f52 (_CUR_TERM.strs[138])
+#define key_f53 (_CUR_TERM.strs[139])
+#define key_f54 (_CUR_TERM.strs[140])
+#define key_f55 (_CUR_TERM.strs[141])
+#define key_f56 (_CUR_TERM.strs[142])
+#define key_f57 (_CUR_TERM.strs[143])
+#define key_f58 (_CUR_TERM.strs[144])
+#define key_f59 (_CUR_TERM.strs[145])
+#define key_f6 (_CUR_TERM.strs[146])
+#define key_f60 (_CUR_TERM.strs[147])
+#define key_f61 (_CUR_TERM.strs[148])
+#define key_f62 (_CUR_TERM.strs[149])
+#define key_f63 (_CUR_TERM.strs[150])
+#define key_f7 (_CUR_TERM.strs[151])
+#define key_f8 (_CUR_TERM.strs[152])
+#define key_f9 (_CUR_TERM.strs[153])
+#define key_find (_CUR_TERM.strs[154])
+#define key_help (_CUR_TERM.strs[155])
+#define key_home (_CUR_TERM.strs[156])
+#define key_ic (_CUR_TERM.strs[157])
+#define key_il (_CUR_TERM.strs[158])
+#define key_left (_CUR_TERM.strs[159])
+#define key_ll (_CUR_TERM.strs[160])
+#define key_mark (_CUR_TERM.strs[161])
+#define key_message (_CUR_TERM.strs[162])
+#define key_move (_CUR_TERM.strs[163])
+#define key_next (_CUR_TERM.strs[164])
+#define key_npage (_CUR_TERM.strs[165])
+#define key_open (_CUR_TERM.strs[166])
+#define key_options (_CUR_TERM.strs[167])
+#define key_ppage (_CUR_TERM.strs[168])
+#define key_previous (_CUR_TERM.strs[169])
+#define key_print (_CUR_TERM.strs[170])
+#define key_redo (_CUR_TERM.strs[171])
+#define key_reference (_CUR_TERM.strs[172])
+#define key_refresh (_CUR_TERM.strs[173])
+#define key_replace (_CUR_TERM.strs[174])
+#define key_restart (_CUR_TERM.strs[175])
+#define key_resume (_CUR_TERM.strs[176])
+#define key_right (_CUR_TERM.strs[177])
+#define key_save (_CUR_TERM.strs[178])
+#define key_sbeg (_CUR_TERM.strs[179])
+#define key_scancel (_CUR_TERM.strs[180])
+#define key_scommand (_CUR_TERM.strs[181])
+#define key_scopy (_CUR_TERM.strs[182])
+#define key_screate (_CUR_TERM.strs[183])
+#define key_sdc (_CUR_TERM.strs[184])
+#define key_sdl (_CUR_TERM.strs[185])
+#define key_select (_CUR_TERM.strs[186])
+#define key_send (_CUR_TERM.strs[187])
+#define key_seol (_CUR_TERM.strs[188])
+#define key_sexit (_CUR_TERM.strs[189])
+#define key_sf (_CUR_TERM.strs[190])
+#define key_sfind (_CUR_TERM.strs[191])
+#define key_shelp (_CUR_TERM.strs[192])
+#define key_shome (_CUR_TERM.strs[193])
+#define key_sic (_CUR_TERM.strs[194])
+#define key_sleft (_CUR_TERM.strs[195])
+#define key_smessage (_CUR_TERM.strs[196])
+#define key_smove (_CUR_TERM.strs[197])
+#define key_snext (_CUR_TERM.strs[198])
+#define key_soptions (_CUR_TERM.strs[199])
+#define key_sprevious (_CUR_TERM.strs[200])
+#define key_sprint (_CUR_TERM.strs[201])
+#define key_sr (_CUR_TERM.strs[202])
+#define key_sredo (_CUR_TERM.strs[203])
+#define key_sreplace (_CUR_TERM.strs[204])
+#define key_sright (_CUR_TERM.strs[205])
+#define key_srsume (_CUR_TERM.strs[206])
+#define key_ssave (_CUR_TERM.strs[207])
+#define key_ssuspend (_CUR_TERM.strs[208])
+#define key_stab (_CUR_TERM.strs[209])
+#define key_sundo (_CUR_TERM.strs[210])
+#define key_suspend (_CUR_TERM.strs[211])
+#define key_undo (_CUR_TERM.strs[212])
+#define key_up (_CUR_TERM.strs[213])
+#define keypad_local (_CUR_TERM.strs[214])
+#define keypad_xmit (_CUR_TERM.strs[215])
+#define lab_f0 (_CUR_TERM.strs[216])
+#define lab_f1 (_CUR_TERM.strs[217])
+#define lab_f10 (_CUR_TERM.strs[218])
+#define lab_f2 (_CUR_TERM.strs[219])
+#define lab_f3 (_CUR_TERM.strs[220])
+#define lab_f4 (_CUR_TERM.strs[221])
+#define lab_f5 (_CUR_TERM.strs[222])
+#define lab_f6 (_CUR_TERM.strs[223])
+#define lab_f7 (_CUR_TERM.strs[224])
+#define lab_f8 (_CUR_TERM.strs[225])
+#define lab_f9 (_CUR_TERM.strs[226])
+#define label_off (_CUR_TERM.strs[227])
+#define label_on (_CUR_TERM.strs[228])
+#define meta_off (_CUR_TERM.strs[229])
+#define meta_on (_CUR_TERM.strs[230])
+#define newline (_CUR_TERM.strs[231])
+#define pad_char (_CUR_TERM.strs[232])
+#define parm_dch (_CUR_TERM.strs[233])
+#define parm_delete_line (_CUR_TERM.strs[234])
+#define parm_down_cursor (_CUR_TERM.strs[235])
+#define parm_ich (_CUR_TERM.strs[236])
+#define parm_index (_CUR_TERM.strs[237])
+#define parm_insert_line (_CUR_TERM.strs[238])
+#define parm_left_cursor (_CUR_TERM.strs[239])
+#define parm_right_cursor (_CUR_TERM.strs[240])
+#define parm_rindex (_CUR_TERM.strs[241])
+#define parm_up_cursor (_CUR_TERM.strs[242])
+#define pkey_key (_CUR_TERM.strs[243])
+#define pkey_local (_CUR_TERM.strs[244])
+#define pkey_xmit (_CUR_TERM.strs[245])
+#define plab_norm (_CUR_TERM.strs[246])
+#define print_screen (_CUR_TERM.strs[247])
+#define prtr_non (_CUR_TERM.strs[248])
+#define prtr_off (_CUR_TERM.strs[249])
+#define prtr_on (_CUR_TERM.strs[250])
+#define repeat_char (_CUR_TERM.strs[251])
+#define req_for_input (_CUR_TERM.strs[252])
+#define reset_1string (_CUR_TERM.strs[253])
+#define reset_2string (_CUR_TERM.strs[254])
+#define reset_3string (_CUR_TERM.strs[255])
+#define reset_file (_CUR_TERM.strs[256])
+#define restore_cursor (_CUR_TERM.strs[257])
+#define row_address (_CUR_TERM.strs[258])
+#define save_cursor (_CUR_TERM.strs[259])
+#define scroll_forward (_CUR_TERM.strs[260])
+#define scroll_reverse (_CUR_TERM.strs[261])
+#define set_attributes (_CUR_TERM.strs[262])
+#define set_left_margin (_CUR_TERM.strs[263])
+#define set_right_margin (_CUR_TERM.strs[264])
+#define set_tab (_CUR_TERM.strs[265])
+#define set_window (_CUR_TERM.strs[266])
+#define tab (_CUR_TERM.strs[267])
+#define to_status_line (_CUR_TERM.strs[268])
+#define underline_char (_CUR_TERM.strs[269])
+#define up_half_line (_CUR_TERM.strs[270])
+#define xoff_character (_CUR_TERM.strs[271])
+#define xon_character (_CUR_TERM.strs[272])
+#define alt_scancode_esc (_CUR_TERM.strs[273])
+#define bit_image_carriage_return (_CUR_TERM.strs[274])
+#define bit_image_newline (_CUR_TERM.strs[275])
+#define bit_image_repeat (_CUR_TERM.strs[276])
+#define change_char_pitch (_CUR_TERM.strs[277])
+#define change_line_pitch (_CUR_TERM.strs[278])
+#define change_res_horz (_CUR_TERM.strs[279])
+#define change_res_vert (_CUR_TERM.strs[280])
+#define char_set_names (_CUR_TERM.strs[281])
+#define code_set_init (_CUR_TERM.strs[282])
+#define color_names (_CUR_TERM.strs[283])
+#define create_window (_CUR_TERM.strs[284])
+#define define_bit_image_region (_CUR_TERM.strs[285])
+#define define_char (_CUR_TERM.strs[286])
+#define device_type (_CUR_TERM.strs[287])
+#define dial_phone (_CUR_TERM.strs[288])
+#define display_clock (_CUR_TERM.strs[289])
+#define display_pc_char (_CUR_TERM.strs[290])
+#define end_bit_image_region (_CUR_TERM.strs[291])
+#define enter_doublewide_mode (_CUR_TERM.strs[292])
+#define enter_draft_quality (_CUR_TERM.strs[293])
+#define enter_italics_mode (_CUR_TERM.strs[294])
+#define enter_leftward_mode (_CUR_TERM.strs[295])
+#define enter_micro_mode (_CUR_TERM.strs[296])
+#define enter_near_letter_quality (_CUR_TERM.strs[297])
+#define enter_normal_quality (_CUR_TERM.strs[298])
+#define enter_pc_charset_mode (_CUR_TERM.strs[299])
+#define enter_scancode_mode (_CUR_TERM.strs[300])
+#define enter_shadow_mode (_CUR_TERM.strs[301])
+#define enter_subscript_mode (_CUR_TERM.strs[302])
+#define enter_superscript_mode (_CUR_TERM.strs[303])
+#define enter_upward_mode (_CUR_TERM.strs[304])
+#define exit_doublewide_mode (_CUR_TERM.strs[305])
+#define exit_italics_mode (_CUR_TERM.strs[306])
+#define exit_leftward_mode (_CUR_TERM.strs[307])
+#define exit_micro_mode (_CUR_TERM.strs[308])
+#define exit_pc_charset_mode (_CUR_TERM.strs[309])
+#define exit_scancode_mode (_CUR_TERM.strs[310])
+#define exit_shadow_mode (_CUR_TERM.strs[311])
+#define exit_subscript_mode (_CUR_TERM.strs[312])
+#define exit_superscript_mode (_CUR_TERM.strs[313])
+#define exit_upward_mode (_CUR_TERM.strs[314])
+#define fixed_pause (_CUR_TERM.strs[315])
+#define flash_hook (_CUR_TERM.strs[316])
+#define get_mouse (_CUR_TERM.strs[317])
+#define goto_window (_CUR_TERM.strs[318])
+#define hangup (_CUR_TERM.strs[319])
+#define initialize_color (_CUR_TERM.strs[320])
+#define initialize_pair (_CUR_TERM.strs[321])
+#define key_mouse (_CUR_TERM.strs[322])
+#define label_format (_CUR_TERM.strs[323])
+#define micro_column_address (_CUR_TERM.strs[324])
+#define micro_down (_CUR_TERM.strs[325])
+#define micro_left (_CUR_TERM.strs[326])
+#define micro_right (_CUR_TERM.strs[327])
+#define micro_row_address (_CUR_TERM.strs[328])
+#define micro_up (_CUR_TERM.strs[329])
+#define mouse_info (_CUR_TERM.strs[330])
+#define order_of_pins (_CUR_TERM.strs[331])
+#define orig_colors (_CUR_TERM.strs[332])
+#define orig_pair (_CUR_TERM.strs[333])
+#define parm_down_micro (_CUR_TERM.strs[334])
+#define parm_left_micro (_CUR_TERM.strs[335])
+#define parm_right_micro (_CUR_TERM.strs[336])
+#define parm_up_micro (_CUR_TERM.strs[337])
+#define pc_term_options (_CUR_TERM.strs[338])
+#define pkey_plab (_CUR_TERM.strs[339])
+#define pulse (_CUR_TERM.strs[340])
+#define quick_dial (_CUR_TERM.strs[341])
+#define remove_clock (_CUR_TERM.strs[342])
+#define req_mouse_pos (_CUR_TERM.strs[343])
+#define scancode_escape (_CUR_TERM.strs[344])
+#define select_char_set (_CUR_TERM.strs[345])
+#define set0_des_seq (_CUR_TERM.strs[346])
+#define set1_des_seq (_CUR_TERM.strs[347])
+#define set2_des_seq (_CUR_TERM.strs[348])
+#define set3_des_seq (_CUR_TERM.strs[349])
+#define set_a_background (_CUR_TERM.strs[350])
+#define set_a_foreground (_CUR_TERM.strs[351])
+#define set_background (_CUR_TERM.strs[352])
+#define set_bottom_margin (_CUR_TERM.strs[353])
+#define set_bottom_margin_parm (_CUR_TERM.strs[354])
+#define set_clock (_CUR_TERM.strs[355])
+#define set_color_band (_CUR_TERM.strs[356])
+#define set_color_pair (_CUR_TERM.strs[357])
+#define set_foreground (_CUR_TERM.strs[358])
+#define set_left_margin_parm (_CUR_TERM.strs[359])
+#define set_lr_margin (_CUR_TERM.strs[360])
+#define set_page_length (_CUR_TERM.strs[361])
+#define set_right_margin_parm (_CUR_TERM.strs[362])
+#define set_tb_margin (_CUR_TERM.strs[363])
+#define set_top_margin (_CUR_TERM.strs[364])
+#define set_top_margin_parm (_CUR_TERM.strs[365])
+#define start_bit_image (_CUR_TERM.strs[366])
+#define start_char_set_def (_CUR_TERM.strs[367])
+#define stop_bit_image (_CUR_TERM.strs[368])
+#define stop_char_set_def (_CUR_TERM.strs[369])
+#define subscript_characters (_CUR_TERM.strs[370])
+#define superscript_characters (_CUR_TERM.strs[371])
+#define these_cause_cr (_CUR_TERM.strs[372])
+#define tone (_CUR_TERM.strs[373])
+#define user0 (_CUR_TERM.strs[374])
+#define user1 (_CUR_TERM.strs[375])
+#define user2 (_CUR_TERM.strs[376])
+#define user3 (_CUR_TERM.strs[377])
+#define user4 (_CUR_TERM.strs[378])
+#define user5 (_CUR_TERM.strs[379])
+#define user6 (_CUR_TERM.strs[380])
+#define user7 (_CUR_TERM.strs[381])
+#define user8 (_CUR_TERM.strs[382])
+#define user9 (_CUR_TERM.strs[383])
+#define wait_tone (_CUR_TERM.strs[384])
+#define zero_motion (_CUR_TERM.strs[385])
+#define backspace_if_not_bs (_CUR_TERM.strs[386])
+#define other_non_function_keys (_CUR_TERM.strs[387])
+#define arrow_key_map (_CUR_TERM.strs[388])
+#define memory_lock_above (_CUR_TERM.strs[389])
+#define memory_unlock (_CUR_TERM.strs[390])
+#define linefeed_if_not_lf (_CUR_TERM.strs[391])
+#define key_interrupt_char (_CUR_TERM.strs[392])
+#define key_kill_char (_CUR_TERM.strs[393])
+#define key_suspend_char (_CUR_TERM.strs[394])
+#define scroll_left (_CUR_TERM.strs[395])
+#define scroll_right (_CUR_TERM.strs[396])
+#define parm_scroll_left (_CUR_TERM.strs[397])
+#define parm_scroll_right (_CUR_TERM.strs[398])
+#define _get_other (_CUR_TERM.strs[399])
+
+#define NUM_OF_BOOLS 53
+#define NUM_OF_NUMS 42
+#define NUM_OF_STRS 400
+
+#ifndef OVERRIDE
+#undef _USE_SGTTY
+#undef _USE_TERMIO
+#undef _USE_TERMIOS
+#define _USE_TERMIOS
+#undef _USE_SMALLMEM
+#undef _USE_PROTOTYPES
+#define _USE_PROTOTYPES
+#undef _USE_WINSZ
+#define _USE_WINSZ
+#undef _USE_TERMINFO
+#undef _USE_TERMCAP
+#define _USE_TERMCAP
+#undef _MAX_CHUNK
+#define _MAX_CHUNK 640
+#endif /* OVERRIDE */
+
diff --git a/lib/libmytinfo/term.tail b/lib/libmytinfo/term.tail
new file mode 100644
index 0000000..dd5b6ad
--- /dev/null
+++ b/lib/libmytinfo/term.tail
@@ -0,0 +1,137 @@
+/*
+ * 92/02/01 07:30:28
+ * @(#) mytinfo term.tail 3.2 92/02/01 public domain, By Ross Ridge
+ *
+ */
+
+#if defined(_USE_TERMIO) || defined(_USE_TERMIOS)
+#ifndef ICANON
+#ifdef _USE_TERMIO
+#include <termio.h>
+#else
+#include <termios.h>
+#endif
+#endif
+#if defined(_USE_WINSZ) && defined(__FreeBSD__)
+#include <sys/ioctl.h>
+#endif
+#if defined(_USE_WINSZ) && defined(xenix)
+#include <sys/stream.h>
+#include <sys/ptem.h>
+#endif
+#endif
+
+#ifdef _USE_SGTTY
+#ifndef CBREAK
+#include <sgtty.h>
+#endif
+#endif
+
+typedef struct _terminal {
+ int fd;
+#ifdef _USE_SMALLMEM
+#ifdef _USE_TERMIOS
+ speed_t baudrate;
+#else
+ unsigned short baudrate;
+#endif
+ unsigned pad:1, xon:1, termcap:1;
+#else
+ int pad;
+ int xon;
+ int termcap;
+#ifdef _USE_TERMIOS
+ speed_t baudrate;
+#else
+ long baudrate;
+#endif
+#endif
+ char padch;
+ short true_lines, true_columns;
+ struct strbuf {
+ struct strbuf *next;
+#ifdef _USE_SMALLMEM
+ short len;
+#else
+ int len;
+#endif
+ char buf[_MAX_CHUNK];
+ } *strbuf;
+ char *name, *name_long, *name_all;
+#ifdef _USE_SGTTY
+ struct sgtty_str {
+ struct sgttyb v6;
+#ifdef TIOCGETC
+ struct tchars v7;
+#endif
+#ifdef TIOCLGET
+ int bsd;
+#endif
+#ifdef TIOCGLTC
+ struct ltchars bsd_new;
+#endif
+ } prog_mode, shell_mode;
+#else /* _USE_SGTTY */
+#ifdef _USE_TERMIOS
+ struct termios prog_mode, shell_mode;
+#else
+#ifdef _USE_TERMIO
+ struct termio prog_mode, shell_mode;
+#endif
+#endif
+#endif /* else _USE_SGTTY */
+#ifdef _USE_WINSZ
+#ifdef TIOCGWINSZ
+ struct winsize prog_winsz, shell_winsz;
+#endif
+#endif
+ char bools[NUM_OF_BOOLS];
+ short nums[NUM_OF_NUMS];
+ char *strs[NUM_OF_STRS];
+} TERMINAL;
+
+#ifndef _CUR_TERM
+#ifdef SINGLE
+#define _CUR_TERM _term_buf
+#else
+#define _CUR_TERM (*cur_term)
+#endif
+#endif
+
+extern TERMINAL *cur_term;
+extern TERMINAL _term_buf;
+
+#ifndef __P
+#if defined(_USE_PROTOTYPES) && (defined(__STDC__) || defined(__cplusplus))
+#define __P(protos) protos /* full-blown ANSI C */
+#else
+#define __P(protos) () /* traditional C preprocessor */
+#endif
+#endif
+
+extern char *tparm __P((const char *, ...));
+extern int setupterm __P((char *, int, int *)), set_curterm __P((TERMINAL *));
+extern int del_curterm __P((TERMINAL *)), tputs __P((const char *, int, int (*)(int)));
+extern int putp __P((char *));
+extern int tigetflag __P((char *)), tigetnum __P((char *));
+extern char *tigetstr __P((char *));
+extern int def_prog_mode __P((void)), def_shell_mode __P((void));
+extern int reset_prog_mode __P((void)), reset_shell_mode __P((void));
+
+extern char *boolnames[], *boolcodes[], *boolfnames[];
+extern char *numnames[], *numcodes[], *numfnames[];
+extern char *strnames[], *strcodes[], *strfnames[];
+
+#ifndef OK
+#undef ERR
+#define OK (0)
+#define ERR (-1)
+#endif
+
+/* Compatibility */
+#define Filedes fd
+#define Ottyb shell_mode
+#define Nttyb prog_mode
+#define TTY struct termios
+
+#endif /* _TERM_H_ */
diff --git a/lib/libmytinfo/termcap.c b/lib/libmytinfo/termcap.c
new file mode 100644
index 0000000..f914c0b
--- /dev/null
+++ b/lib/libmytinfo/termcap.c
@@ -0,0 +1,165 @@
+/*
+ * termcap.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/06/01 07:43:08
+ *
+ * termcap compatibility functions
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+#ifdef __FreeBSD__
+#include <unistd.h>
+#endif
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo termcap.c 3.3 92/06/01 public domain, By Ross Ridge";
+#endif
+
+extern char _mytinfo_version[];
+/* not static */
+char *_force_pick1 = _mytinfo_version;
+
+int
+tgetent(buf, term)
+char *term, *buf; {
+ char *s;
+ struct term_path *path;
+ int r = -1;
+ int fd;
+
+ if (term == NULL)
+ term = getenv("TERM");
+ if (term == NULL)
+ return 0;
+
+ path = _buildpath(
+#ifdef USE_TERMINFO
+ "$MYTERMINFO", 2,
+ "$TERMINFO", 2,
+#ifdef TERMINFODIR
+ TERMINFODIR, 0,
+#endif
+#ifdef TERMINFOSRC
+ TERMINFOSRC, 0,
+#endif
+#endif
+#ifdef USE_TERMCAP
+ "$TERMCAP", 1,
+#ifdef TERMCAPFILE
+ TERMCAPFILE, 0,
+#endif
+#endif
+ NULL, -1);
+
+ if (path == NULL)
+ return -1;
+
+#if 1
+ {
+ char buf1[MAX_BUF];
+ r = _fillterm(term, path, buf1);
+ }
+#else
+ r = _fillterm(term, path, buf);
+#endif
+
+ _delpath(path);
+
+ switch(r) {
+ case -3:
+ case -2:
+ case -1:
+ return -1;
+ case 0:
+ return 0;
+ case 1:
+ case 2:
+ case 3:
+ if (isatty(1))
+ fd = 1;
+ else if (isatty(2))
+ fd = 2;
+ else if (isatty(3)) /* V10 /dev/tty ?? */
+ fd = 3;
+ else if (isatty(0))
+ fd = 0;
+ else
+ fd = 1;
+
+ cur_term->fd = fd;
+ _term_buf.fd = fd;
+
+ if (_init_tty() == ERR)
+ return 0;
+ if ((s = getenv("LINES")) != NULL && atoi(s) > 0)
+ lines = atoi(s);
+ if ((s = getenv("COLUMNS")) != NULL && atoi(s) > 0)
+ columns = atoi(s);
+ cur_term->termcap = 1;
+ return 1;
+ default:
+ return -1;
+ }
+}
+
+static char cap2[3];
+
+int
+tgetnum(cap)
+char *cap; {
+ int ind;
+
+ cap2[0] = cap[0];
+ cap2[1] = cap[1];
+ cap2[2] = '\0';
+
+ ind = _findnumcode(cap2);
+ if (ind == -1)
+ return -1;
+ return cur_term->nums[ind];
+}
+
+int
+tgetflag(cap)
+char *cap; {
+ int ind;
+
+ cap2[0] = cap[0];
+ cap2[1] = cap[1];
+ cap2[2] = '\0';
+
+ ind = _findboolcode(cap2);
+ if (ind == -1)
+ return 0;
+ return cur_term->bools[ind];
+}
+
+char *
+tgetstr(cap, area)
+char *cap;
+char **area; {
+ register char *sp, *dp;
+ int ind;
+
+ cap2[0] = cap[0];
+ cap2[1] = cap[1];
+ cap2[2] = '\0';
+
+ ind = _findstrcode(cap2);
+ if (ind == -1)
+ return NULL;
+ sp = cur_term->strs[ind];
+ if (area == NULL || sp == NULL)
+ return sp;
+ dp = *area;
+ while (*sp != '\0')
+ *dp++ = *sp++;
+ *dp++ = '\0';
+ sp = *area;
+ *area = dp;
+ return sp;
+}
diff --git a/lib/libmytinfo/terminfo.c b/lib/libmytinfo/terminfo.c
new file mode 100644
index 0000000..0568588
--- /dev/null
+++ b/lib/libmytinfo/terminfo.c
@@ -0,0 +1,132 @@
+/*
+ * terminfo.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:30
+ *
+ * terminfo compatible libary functions
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo terminfo.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+extern char _mytinfo_version[];
+/* not static */
+char *_force_pick2 = _mytinfo_version;
+
+#ifdef USE_FAKE_STDIO
+
+#ifdef __GNUC__
+__inline__
+#endif
+static int
+printerr(msg)
+char *msg; {
+ return write(2, msg, strlen(msg));
+}
+
+#define RETERR(e, msg) { (err == NULL ? (printerr(msg), exit(1)) \
+ : (*err = e)); return ERR; }
+
+#else
+
+#define RETERR(e, msg) { (err == NULL ? (fprintf(stderr, "setupterm(\"%s\",%d,NULL): %s", term, fd, msg), exit(1)) \
+ : (*err = e)); return ERR; }
+
+#endif
+
+int
+setupterm(term, fd, err)
+char *term;
+int fd;
+int *err; {
+ struct term_path *path;
+ char *s;
+ int r = -1;
+ char buf[MAX_BUF];
+
+
+ if (term == NULL)
+ term = getenv("TERM");
+ if (term == NULL)
+ RETERR(0, "TERM not set\n")
+
+ path = _buildpath(
+#ifdef USE_TERMINFO
+ "$MYTERMINFO", 2,
+ "$TERMINFO", 2,
+#ifdef TERMINFODIR
+ TERMINFODIR, 0,
+#endif
+#ifdef TERMINFOSRC
+ TERMINFOSRC, 0,
+#endif
+#endif
+#ifdef USE_TERMCAP
+ "$TERMCAP", 1,
+#ifdef TERMCAPFILE
+ TERMCAPFILE, 0,
+#endif
+#endif
+ NULL, -1);
+
+ if (path == NULL)
+ RETERR(0, "malloc error\n");
+
+ r = _fillterm(term, path, buf);
+
+ _delpath(path);
+
+ switch(r) {
+ case -3:
+ RETERR(0, "malloc error\n");
+ case -2:
+ RETERR(-1, "bad format\n");
+ case -1:
+ RETERR(-1, "database not found\n");
+ case 0:
+ RETERR(0, "terminal not found\n");
+ case 1:
+ case 2:
+ case 3:
+ cur_term->fd = fd;
+ _term_buf.fd = fd;
+ if (_init_tty() == ERR)
+ RETERR(0, "problem initializing tty\n");
+ if ((s = getenv("LINES")) != NULL && atoi(s) > 0)
+ lines = atoi(s);
+ if ((s = getenv("COLUMNS")) != NULL && atoi(s) > 0)
+ columns = atoi(s);
+ if (err != NULL)
+ *err = 1;
+ return OK;
+ default:
+ RETERR(0, "oops...\n");
+ }
+}
+
+int
+set_curterm(p)
+TERMINAL *p; {
+ cur_term = p;
+ if (_init_tty() == ERR)
+ return ERR;
+ if (_check_tty() == ERR)
+ return ERR;
+ return OK;
+}
+
+int
+del_curterm(p)
+TERMINAL *p; {
+ _del_strs(p);
+ free((anyptr) p);
+
+ return OK;
+}
diff --git a/lib/libmytinfo/tgoto.c b/lib/libmytinfo/tgoto.c
new file mode 100644
index 0000000..1bc735b
--- /dev/null
+++ b/lib/libmytinfo/tgoto.c
@@ -0,0 +1,148 @@
+/*
+ * tgoto.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:33
+ *
+ * A few kludged attempts to worry outputing ^D's and NL's...
+ * My advice is to get a decent terminal.
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo tgoto.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+#ifdef USE_LITOUT_KLUDGE
+
+/*
+ * This kludge works by telling tputs to switch the tty driver to
+ * "literal output" when printing the string so we don't have worry
+ * about newlines and EOTs. The problem is that ioctls used to
+ * switch modes might flush buffers and cause other problems.
+ */
+
+
+char *
+tgoto(str, x, y)
+char *str;
+int x,y; {
+ register char *sp;
+
+ static char buf[MAX_LINE] = {'\\', '@'};
+
+ sp = str = tparm(str, y, x);
+
+ while (*sp != '\0') {
+ if (*sp == '\004' || *sp == '\n') {
+ strncpy(buf + 2, str, MAX_LINE - 2);
+ buf[MAX_LINE - 2] = '\0';
+ return buf;
+ }
+ sp++;
+ }
+ return sp;
+}
+#else
+
+#ifdef USE_UPBC_KLUDGE
+
+#ifdef USE_EXTERN_UPBC
+extern char *BC, *UP;
+#else
+#define BC cursor_left
+#define UP cursor_right
+#endif
+
+#ifdef __GNUC__
+__inline__
+#endif
+static int
+checkit(s)
+register char *s; {
+ while(*s != '\0') {
+ if (*s == '\004' || *s == '\n')
+ return 1;
+ s++;
+ }
+ return 0;
+}
+
+/*
+ * Major kludge, basically we just change the parmeters until we get
+ * a string that doesn't contain a newline or EOT.
+ */
+
+char *
+tgoto(str, x, y)
+char *str;
+int x,y; {
+ static char buf[MAX_LINE];
+ register char *orig, *s;
+ int l;
+
+ orig = tparm(str, y, x);
+
+ if (!checkit(orig))
+ return orig;
+
+ s = tparm(str, y + 1, x);
+
+ if (!checkit(s)) {
+ if (BC == NULL)
+ return s;
+ l = strlen(s);
+ strncpy(buf, s, MAX_LINE - 1);
+ if (l < MAX_LINE - 1)
+ strncpy(buf + l, BC, MAX_LINE - 1 - l);
+ return s;
+ }
+
+ s = tparm(str, y, x + 1);
+
+ if (!checkit(s)) {
+ if (UP == NULL)
+ return s;
+ l = strlen(s);
+ strncpy(buf, s, MAX_LINE - 1);
+ if (l < MAX_LINE - 1)
+ strncpy(buf + l, UP, MAX_LINE - 1 - l);
+ return s;
+ }
+
+ s = tparm(str, y + 1, x + 1);
+
+ if (!checkit(s)) {
+ if (UP == NULL || BC == NULL)
+ return s;
+ l = strlen(s);
+ strncpy(buf, s, MAX_LINE - 1);
+ if (l < MAX_LINE - 1)
+ strncpy(buf + l, UP, MAX_LINE - 1 - l);
+ l += strlen(UP);
+ if (l < MAX_LINE - 1)
+ strncpy(buf + l, BC, MAX_LINE - 1 - l);
+ return s;
+ }
+
+ return orig;
+}
+
+#else
+
+/* the simple tgoto, don't worry about any of this newline/EOT crap */
+
+char *
+tgoto(str, x, y)
+char *str;
+int x,y; {
+ return tparm(str, y, x);
+}
+
+#endif
+
+#endif
diff --git a/lib/libmytinfo/tiget.c b/lib/libmytinfo/tiget.c
new file mode 100644
index 0000000..e312422
--- /dev/null
+++ b/lib/libmytinfo/tiget.c
@@ -0,0 +1,51 @@
+/*
+ * tiget.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:34
+ *
+ * The various tiget terminfo functions.
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo tiget.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+int
+tigetnum(cap)
+char *cap; {
+ int ind;
+
+ ind = _findnumname(cap);
+ if (ind == -1)
+ return -2;
+ return cur_term->nums[ind];
+}
+
+int
+tigetflag(cap)
+char *cap; {
+ int ind;
+
+ ind = _findboolname(cap);
+ if (ind == -1)
+ return -1;
+ return cur_term->bools[ind];
+}
+
+char *
+tigetstr(cap)
+char *cap; {
+ int ind;
+
+ ind = _findstrname(cap);
+ if (ind == -1)
+ return (char *) -1;
+ return cur_term->strs[ind];
+}
+
+
diff --git a/lib/libmytinfo/tmatch.c b/lib/libmytinfo/tmatch.c
new file mode 100644
index 0000000..afccda7
--- /dev/null
+++ b/lib/libmytinfo/tmatch.c
@@ -0,0 +1,37 @@
+/*
+ * tmatch.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:35
+ *
+ * See if a terminal name matches a list of terminal names from a
+ * terminal description
+ *
+ */
+
+#include "defs.h"
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo tmatch.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+int
+_tmatch(line, name)
+char *line, *name; {
+ char term[MAX_LINE];
+ char *sp, *dp;
+
+ sp = line;
+ while (*sp != '\0') {
+ dp = term;
+ while (*sp != '\0' && *sp != '|')
+ *dp++ = *sp++;
+ *dp = '\0';
+ if (strcmp(term, name) == 0)
+ return 1;
+ if (*sp == '|')
+ sp++;
+ }
+ return 0;
+}
diff --git a/lib/libmytinfo/tparm.c b/lib/libmytinfo/tparm.c
new file mode 100644
index 0000000..0cc2c89
--- /dev/null
+++ b/lib/libmytinfo/tparm.c
@@ -0,0 +1,807 @@
+/*
+ * tparm.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:36
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#include <ctype.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo tparm.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+#ifndef MAX_PUSHED
+#define MAX_PUSHED 32
+#endif
+
+#define ARG 1
+#define NUM 2
+
+#define INTEGER 1
+#define STRING 2
+
+typedef struct stack_str {
+ int type;
+ int argnum;
+ int value;
+} stack;
+
+static stack S[MAX_PUSHED];
+static stack vars['z'-'a'+1];
+static int pos = 0;
+
+static struct arg_str {
+ int type;
+ int integer;
+ char *string;
+} arg_list[10];
+
+static int argcnt;
+
+static va_list tparm_args;
+
+static int
+pusharg(arg)
+int arg; {
+ if (pos == MAX_PUSHED)
+ return 1;
+ S[pos].type = ARG;
+ S[pos++].argnum = arg;
+ return 0;
+}
+
+static int
+pushnum(num)
+int num; {
+ if (pos == MAX_PUSHED)
+ return 1;
+ S[pos].type = NUM;
+ S[pos++].value = num;
+ return 0;
+}
+
+/* VARARGS2 */
+static int
+getarg(argnum, type, p)
+int argnum, type;
+anyptr p; {
+ while (argcnt < argnum) {
+ arg_list[argcnt].type = INTEGER;
+ arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
+ }
+ if (argcnt > argnum) {
+ if (arg_list[argnum].type != type)
+ return 1;
+ else if (type == STRING)
+ *(char **)p = arg_list[argnum].string;
+ else
+ *(int *)p = arg_list[argnum].integer;
+ } else {
+ arg_list[argcnt].type = type;
+ if (type == STRING)
+ *(char **)p = arg_list[argcnt++].string
+ = (char *) va_arg(tparm_args, char *);
+ else
+ *(int *)p = arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
+ }
+ return 0;
+}
+
+
+static int
+popstring(str)
+char **str; {
+ if (pos-- == 0)
+ return 1;
+ if (S[pos].type != ARG)
+ return 1;
+ return(getarg(S[pos].argnum, STRING, (anyptr) str));
+}
+
+static int
+popnum(num)
+int *num; {
+ if (pos-- == 0)
+ return 1;
+ switch (S[pos].type) {
+ case ARG:
+ return (getarg(S[pos].argnum, INTEGER, (anyptr) num));
+ case NUM:
+ *num = S[pos].value;
+ return 0;
+ }
+ return 1;
+}
+
+static int
+cvtchar(sp, c)
+register char *sp, *c; {
+ switch(*sp) {
+ case '\\':
+ switch(*++sp) {
+ case '\'':
+ case '$':
+ case '\\':
+ case '%':
+ *c = *sp;
+ return 2;
+ case '\0':
+ *c = '\\';
+ return 1;
+ case '0':
+ if (sp[1] == '0' && sp[2] == '0') {
+ *c = '\0';
+ return 4;
+ }
+ *c = '\200'; /* '\0' ???? */
+ return 2;
+ default:
+ *c = *sp;
+ return 2;
+ }
+ default:
+ *c = *sp;
+ return 1;
+ }
+}
+
+static int termcap;
+
+/* sigh... this has got to be the ugliest code I've ever written.
+ Trying to handle everything has its cost, I guess.
+
+ It actually isn't to hard to figure out if a given % code is supposed
+ to be interpeted with its termcap or terminfo meaning since almost
+ all terminfo codes are invalid unless something has been pushed on
+ the stack and termcap strings will never push things on the stack
+ (%p isn't used by termcap). So where we have a choice we make the
+ decision by wether or not somthing has been pushed on the stack.
+ The static variable termcap keeps track of this; it starts out set
+ to 1 and is incremented as each argument processed by a termcap % code,
+ however if something is pushed on the stack it's set to 0 and the
+ rest of the % codes are interpeted as terminfo % codes. Another way
+ of putting it is that if termcap equals one we haven't decided either
+ way yet, if it equals zero we're looking for terminfo codes, and if
+ its greater than 1 we're looking for termcap codes.
+
+ Terminfo % codes:
+
+ %% output a '%'
+ %[[:][-+# ][width][.precision]][doxXs]
+ output pop according to the printf format
+ %c output pop as a char
+ %'c' push character constant c.
+ %{n} push decimal constant n.
+ %p[1-9] push paramter [1-9]
+ %g[a-z] push variable [a-z]
+ %P[a-z] put pop in variable [a-z]
+ %l push the length of pop (a string)
+ %+ add pop to pop and push the result
+ %- subtract pop from pop and push the result
+ %* multiply pop and pop and push the result
+ %& bitwise and pop and pop and push the result
+ %| bitwise or pop and pop and push the result
+ %^ bitwise xor pop and pop and push the result
+ %~ push the bitwise not of pop
+ %= compare if pop and pop are equal and push the result
+ %> compare if pop is less than pop and push the result
+ %< compare if pop is greater than pop and push the result
+ %A logical and pop and pop and push the result
+ %O logical or pop and pop and push the result
+ %! push the logical not of pop
+ %? condition %t if_true [%e if_false] %;
+ if condtion evaulates as true then evaluate if_true,
+ else evaluate if_false. elseif's can be done:
+%? cond %t true [%e cond2 %t true2] ... [%e condN %t trueN] [%e false] %;
+ %i add one to parameters 1 and 2. (ANSI)
+
+ Termcap Codes:
+
+ %% output a %
+ %. output parameter as a character
+ %d output parameter as a decimal number
+ %2 output parameter in printf format %02d
+ %3 output parameter in printf format %03d
+ %+x add the character x to parameter and output it as a character
+(UW) %-x subtract parameter FROM the character x and output it as a char
+(UW) %ax add the character x to parameter
+(GNU) %a[+*-/=][cp]x
+ GNU arithmetic.
+(UW) %sx subtract parameter FROM the character x
+ %>xy if parameter > character x then add character y to parameter
+ %B convert to BCD (parameter = (parameter/10)*16 + parameter%16)
+ %D Delta Data encode (parameter = parameter - 2*(paramter%16))
+ %i increment the first two parameters by one
+ %n xor the first two parameters by 0140
+(GNU) %m xor the first two parameters by 0177
+ %r swap the first two parameters
+(GNU) %b backup to previous parameter
+(GNU) %f skip this parameter
+
+ Note the two definitions of %a, the GNU defintion is used if the characters
+ after the 'a' are valid, otherwise the UW definition is used.
+
+ (GNU) used by GNU Emacs termcap libraries
+ (UW) used by the University of Waterloo (MFCF) termcap libraries
+
+*/
+
+#ifdef lint
+/* VARARGS1 */
+char *
+tparm(str)
+char *str; {
+#else /* lint */
+#ifdef USE_STDARG
+#ifdef USE_PROTOTYPES
+char *tparm(const char *str, ...) {
+#else /* USE_PROTOTYPES */
+char *tparm(str)
+char *str; {
+#endif /* USE_PROTOTYPES */
+#else /* USE_STDARG */
+char *tparm(va_alist)
+va_dcl {
+ char *str;
+#endif
+#endif
+ static char OOPS[] = "OOPS";
+ static char buf[MAX_LINE];
+ register char *dp;
+ register char *fmt;
+ const char *sp;
+ char conv_char;
+ char scan_for;
+ int scan_depth = 0, if_depth;
+ static int i, j;
+ static char *s, c;
+ char fmt_buf[MAX_LINE];
+ char sbuf[MAX_LINE];
+
+#ifdef USE_STDARG
+ va_start(tparm_args, str);
+#else
+ va_start(tparm_args);
+ str = (char *) va_arg(tparm_args, char *);
+#endif
+
+ sp = str;
+ dp = buf;
+ scan_for = 0;
+ if_depth = 0;
+ argcnt = 0;
+ pos = 0;
+ termcap = 1;
+ while(*sp != '\0') {
+ switch(*sp) {
+ case '\\':
+ if (scan_for) {
+ if (*++sp != '\0')
+ sp++;
+ break;
+ }
+ *dp++ = *sp++;
+ if (*sp != '\0')
+ *dp++ = *sp++;
+ break;
+ case '%':
+ sp++;
+ if (scan_for) {
+ if (*sp == scan_for && if_depth == scan_depth) {
+ if (scan_for == ';')
+ if_depth--;
+ scan_for = 0;
+ } else if (*sp == '?')
+ if_depth++;
+ else if (*sp == ';') {
+ if (if_depth == 0)
+ return OOPS;
+ else
+ if_depth--;
+ }
+ sp++;
+ break;
+ }
+ fmt = NULL;
+ switch(*sp) {
+ case '%':
+ *dp++ = *sp++;
+ break;
+ case '+':
+ if (!termcap) {
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i += j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ }
+ ;/* FALLTHROUGH */
+ case 'C':
+ if (*sp == 'C') {
+ if (getarg(termcap - 1, INTEGER, &i))
+ return OOPS;
+ if (i >= 96) {
+ i /= 96;
+ if (i == '$')
+ *dp++ = '\\';
+ *dp++ = i;
+ }
+ }
+ fmt = "%c";
+ /* FALLTHROUGH */
+ case 'a':
+ if (!termcap)
+ return OOPS;
+ if (getarg(termcap - 1, INTEGER, (anyptr) &i))
+ return OOPS;
+ if (*++sp == '\0')
+ return OOPS;
+ if ((sp[1] == 'p' || sp[1] == 'c')
+ && sp[2] != '\0' && fmt == NULL) {
+ /* GNU aritmitic parameter, what they
+ realy need is terminfo. */
+ int val, lc;
+ if (sp[1] == 'p'
+ && getarg(termcap - 1 + sp[2] - '@',
+ INTEGER, (anyptr) &val))
+ return OOPS;
+ if (sp[1] == 'c') {
+ lc = cvtchar(sp + 2, &c) + 2;
+ /* Mask out 8th bit so \200 can be
+ used for \0 as per GNU doc's */
+ val = c & 0177;
+ } else
+ lc = 2;
+ switch(sp[0]) {
+ case '=':
+ break;
+ case '+':
+ val = i + val;
+ break;
+ case '-':
+ val = i - val;
+ break;
+ case '*':
+ val = i * val;
+ break;
+ case '/':
+ val = i / val;
+ break;
+ default:
+ /* Not really GNU's %a after all... */
+ lc = cvtchar(sp, &c);
+ val = c + i;
+ break;
+ }
+ arg_list[termcap - 1].integer = val;
+ sp += lc;
+ break;
+ }
+ sp += cvtchar(sp, &c);
+ arg_list[termcap - 1].integer = c + i;
+ if (fmt == NULL)
+ break;
+ sp--;
+ /* FALLTHROUGH */
+ case '-':
+ if (!termcap) {
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i -= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ }
+ fmt = "%c";
+ /* FALLTHROUGH */
+ case 's':
+ if (termcap && (fmt == NULL || *sp == '-')) {
+ if (getarg(termcap - 1, INTEGER, &i))
+ return OOPS;
+ if (*++sp == '\0')
+ return OOPS;
+ sp += cvtchar(sp, &c);
+ arg_list[termcap - 1].integer = c - i;
+ if (fmt == NULL)
+ break;
+ sp--;
+ }
+ if (!termcap)
+ return OOPS;
+ ;/* FALLTHROUGH */
+ case '.':
+ if (termcap && fmt == NULL)
+ fmt = "%c";
+ ;/* FALLTHROUGH */
+ case 'd':
+ if (termcap && fmt == NULL)
+ fmt = "%d";
+ ;/* FALLTHROUGH */
+ case '2':
+ if (termcap && fmt == NULL)
+ fmt = "%02d";
+ ;/* FALLTHROUGH */
+ case '3':
+ if (termcap && fmt == NULL)
+ fmt = "%03d";
+ ;/* FALLTHROUGH */
+ case ':': case ' ': case '#': case 'u':
+ case 'x': case 'X': case 'o': case 'c':
+ case '0': case '1': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ if (fmt == NULL) {
+ if (termcap)
+ return OOPS;
+ if (*sp == ':')
+ sp++;
+ fmt = fmt_buf;
+ *fmt++ = '%';
+ while(*sp != 's' && *sp != 'x' && *sp != 'X' && *sp != 'd' && *sp != 'o' && *sp != 'c' && *sp != 'u') {
+ if (*sp == '\0')
+ return OOPS;
+ *fmt++ = *sp++;
+ }
+ *fmt++ = *sp;
+ *fmt = '\0';
+ fmt = fmt_buf;
+ }
+ conv_char = fmt[strlen(fmt) - 1];
+ if (conv_char == 's') {
+ if (popstring(&s))
+ return OOPS;
+ sprintf(sbuf, fmt, s);
+ } else {
+ if (termcap) {
+ if (getarg(termcap++ - 1,
+ INTEGER, &i))
+ return OOPS;
+ } else
+ if (popnum(&i))
+ return OOPS;
+ if (i == 0 && conv_char == 'c')
+ strcpy(sbuf, "\000");
+ else
+ sprintf(sbuf, fmt, i);
+ }
+ sp++;
+ fmt = sbuf;
+ while(*fmt != '\0') {
+ if (*fmt == '$')
+ *dp++ = '\\';
+ *dp++ = *fmt++;
+ }
+ break;
+ case 'r':
+ if (!termcap || getarg(1, INTEGER, &i))
+ return OOPS;
+ arg_list[1].integer = arg_list[0].integer;
+ arg_list[0].integer = i;
+ sp++;
+ break;
+ case 'i':
+ if (getarg(1, INTEGER, &i)
+ || arg_list[0].type != INTEGER)
+ return OOPS;
+ arg_list[1].integer++;
+ arg_list[0].integer++;
+ sp++;
+ break;
+ case 'n':
+ if (!termcap || getarg(1, INTEGER, &i))
+ return OOPS;
+ arg_list[0].integer ^= 0140;
+ arg_list[1].integer ^= 0140;
+ sp++;
+ break;
+ case '>':
+ if (!termcap) {
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i = (i > j);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ }
+ if (getarg(termcap-1, INTEGER, &i))
+ return OOPS;
+ sp += cvtchar(sp, &c);
+ if (i > c) {
+ sp += cvtchar(sp, &c);
+ arg_list[termcap-1].integer += c;
+ } else
+ sp += cvtchar(sp, &c);
+ sp++;
+ break;
+ case 'B':
+ if (!termcap || getarg(termcap-1, INTEGER, &i))
+ return OOPS;
+ arg_list[termcap-1].integer = 16*(i/10)+i%10;
+ sp++;
+ break;
+ case 'D':
+ if (!termcap || getarg(termcap-1, INTEGER, &i))
+ return OOPS;
+ arg_list[termcap-1].integer = i - 2 * (i % 16);
+ sp++;
+ break;
+ case 'p':
+ if (termcap > 1)
+ return OOPS;
+ if (*++sp == '\0')
+ return OOPS;
+ if (*sp == '0')
+ i = 9;
+ else
+ i = *sp - '1';
+ if (i < 0 || i > 9)
+ return OOPS;
+ if (pusharg(i))
+ return OOPS;
+ termcap = 0;
+ sp++;
+ break;
+ case 'P':
+ if (termcap || *++sp == '\0')
+ return OOPS;
+ i = *sp++ - 'a';
+ if (i < 0 || i > 25)
+ return OOPS;
+ if (pos-- == 0)
+ return OOPS;
+ switch(vars[i].type = S[pos].type) {
+ case ARG:
+ vars[i].argnum = S[pos].argnum;
+ break;
+ case NUM:
+ vars[i].value = S[pos].value;
+ break;
+ }
+ break;
+ case 'g':
+ if (termcap || *++sp == '\0')
+ return OOPS;
+ i = *sp++ - 'a';
+ if (i < 0 || i > 25)
+ return OOPS;
+ switch(vars[i].type) {
+ case ARG:
+ if (pusharg(vars[i].argnum))
+ return OOPS;
+ break;
+ case NUM:
+ if (pushnum(vars[i].value))
+ return OOPS;
+ break;
+ }
+ break;
+ case '\'':
+ if (termcap > 1)
+ return OOPS;
+ if (*++sp == '\0')
+ return OOPS;
+ sp += cvtchar(sp, &c);
+ if (pushnum(c) || *sp++ != '\'')
+ return OOPS;
+ termcap = 0;
+ break;
+ case '{':
+ if (termcap > 1)
+ return OOPS;
+ i = 0;
+ sp++;
+ while(isdigit(*sp))
+ i = 10 * i + *sp++ - '0';
+ if (*sp++ != '}' || pushnum(i))
+ return OOPS;
+ termcap = 0;
+ break;
+ case 'l':
+ if (termcap || popstring(&s))
+ return OOPS;
+ i = strlen(s);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '*':
+ if (termcap || popnum(&j) || popnum(&i))
+ return OOPS;
+ i *= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '/':
+ if (termcap || popnum(&j) || popnum(&i))
+ return OOPS;
+ i /= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case 'm':
+ if (termcap) {
+ if (getarg(1, INTEGER, &i))
+ return OOPS;
+ arg_list[0].integer ^= 0177;
+ arg_list[1].integer ^= 0177;
+ sp++;
+ break;
+ }
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i %= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '&':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i &= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '|':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i |= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '^':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i ^= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '=':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i = (i == j);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '<':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i = (i < j);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case 'A':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i = (i && j);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case 'O':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i = (i || j);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '!':
+ if (popnum(&i))
+ return OOPS;
+ i = !i;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '~':
+ if (popnum(&i))
+ return OOPS;
+ i = ~i;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '?':
+ if (termcap > 1)
+ return OOPS;
+ termcap = 0;
+ if_depth++;
+ sp++;
+ break;
+ case 't':
+ if (popnum(&i) || if_depth == 0)
+ return OOPS;
+ if (!i) {
+ scan_for = 'e';
+ scan_depth = if_depth;
+ }
+ sp++;
+ break;
+ case 'e':
+ if (if_depth == 0)
+ return OOPS;
+ scan_for = ';';
+ scan_depth = if_depth;
+ sp++;
+ break;
+ case ';':
+ if (if_depth-- == 0)
+ return OOPS;
+ sp++;
+ break;
+ case 'b':
+ if (--termcap < 1)
+ return OOPS;
+ sp++;
+ break;
+ case 'f':
+ if (!termcap++)
+ return OOPS;
+ sp++;
+ break;
+ }
+ break;
+ default:
+ if (scan_for)
+ sp++;
+ else
+ *dp++ = *sp++;
+ break;
+ }
+ }
+ va_end(tparm_args);
+ *dp = '\0';
+ return buf;
+}
+
+#ifdef TEST
+
+void
+putch(c)
+char c; {
+ if (c < 0) {
+ printf("\\%03o", c);
+ } else if (c < 32) {
+ printf("^%c", c + '@');
+ } else if (c == 127) {
+ printf("^?");
+ } else {
+ putchar(c);
+ }
+}
+
+char line[MAX_LINE];
+
+int
+main(argc, argv)
+int argc;
+char **argv; {
+ register char *sp;
+ putchar('\n');
+
+ while(fgets(line, sizeof(line), stdin) != NULL) {
+ line[strlen(line)-1] = '\0';
+ sp = tparm(line, 1, -2, 30, 0, "bob was here");
+ while(*sp)
+ putch(*sp++);
+ putchar('\n');
+ }
+ return 0;
+}
+#endif
diff --git a/lib/libmytinfo/tputs.c b/lib/libmytinfo/tputs.c
new file mode 100644
index 0000000..840b3c8
--- /dev/null
+++ b/lib/libmytinfo/tputs.c
@@ -0,0 +1,266 @@
+/*
+ * tputs.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/06/04 11:41:15
+ *
+ * Output a terminal capability string with any needed padding
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#include <ctype.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo tputs.c 3.3 92/06/04 public domain, By Ross Ridge";
+#endif
+
+#ifdef TEST
+#define def_prog_mode() (OK)
+#define _norm_output() ((void)(0))
+#define _lit_output() (1)
+#endif
+
+/*
+ * BITSPERCHAR (as actually transmitted over a serial line) is usually 10
+ * (not 8). 1 stop bit, 1 start bit, 7 data bits, and one parity bit.
+ */
+
+#define BITSPERCHAR 10
+
+#ifdef USE_FAKE_STDIO
+#undef putchar
+#endif
+
+#ifdef USE_PROTOTYPES
+#define PUTCHAR(c) (outc == (int (*)(int)) NULL ? (putchar(c)):(*outc)(c))
+#else
+#define PUTCHAR(c) (outc == (int (*)()) NULL ? (putchar(c)):(*outc)(c))
+#endif
+
+int
+tputs(sp, count, outc)
+register const char *sp;
+int count;
+#ifdef USE_PROTOTYPES
+register int (*outc)(int);
+#else
+register int (*outc)();
+#endif
+{
+ register int l;
+ register long cnt;
+ int must_pad, multiply_pad;
+ int forced_lit = 0;
+
+ /* some programmes expect this behaviour from tputs */
+ if (sp == NULL) {
+#ifdef DEBUG
+ fprintf(stderr, "tputs: NULL\n");
+#endif
+ return 0;
+ }
+
+ if (cur_term->termcap) {
+ _figure_termcap();
+ }
+
+ while(*sp != '\0') {
+ switch(*sp) {
+ case '\\':
+ switch(*++sp) {
+ case 'n': PUTCHAR('\n'); sp++; break;
+ case 'b': PUTCHAR('\b'); sp++; break;
+ case 't': PUTCHAR('\t'); sp++; break;
+ case 'r': PUTCHAR('\r'); sp++; break;
+ case 'f': PUTCHAR('\f'); sp++; break;
+ case 'l': PUTCHAR('\012'); sp++; break;
+ case 's': PUTCHAR(' '); sp++; break;
+ case 'e': case 'E': PUTCHAR('\033'); sp++; break;
+
+ case '^':
+ case '\\':
+ case ',':
+ case ':':
+ case '\'':
+ case '$':
+ PUTCHAR(*sp++);
+ break;
+
+ case '0':
+ if (*(sp + 1) < '0' || *(sp + 1) > '7') {
+ PUTCHAR('\200'); /* I'd prefer \0 */
+ sp++;
+ break;
+ }
+ ;/* FALLTHROUGH */
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7':
+ l = *sp++ - '0';
+ if (*sp >= '0' && *sp <= '7') {
+ l = l * 8 + (*sp++ - '0');
+ if (*sp >= '0' && *sp <= '7')
+ l = l * 8 + (*sp++ - '0');
+ }
+ PUTCHAR(l);
+ break;
+
+ case '\0':
+ PUTCHAR('\\');
+ break;
+
+ case '@':
+ if (!forced_lit)
+ forced_lit = _lit_output();
+ sp++;
+ break;
+
+ default:
+ PUTCHAR('\\');
+ PUTCHAR(*sp++);
+ break;
+ }
+ break;
+ case '^':
+ if (*++sp == '\0')
+ break;
+ l = *sp - '@';
+ if (l > 31)
+ l -= 32;
+ if (l < 0 || l > 31) {
+ PUTCHAR('^');
+ PUTCHAR(*sp++);
+ } else {
+ PUTCHAR(l);
+ sp++;
+ }
+ break;
+ case '$':
+ if (*++sp != '<') {
+ PUTCHAR('$');
+ break;
+ }
+ must_pad = 0;
+ multiply_pad = 0;
+ l = 0;
+ sp++;
+ while (isdigit(*sp))
+ l = l * 10 + (*sp++ - '0');
+ l *= 10;
+ if (*sp == '.') {
+ sp++;
+ if (isdigit(*sp))
+ l += *sp++ - '0';
+ }
+ if (*sp == '/') {
+ must_pad = 1;
+ if (*++sp == '*') {
+ multiply_pad = 1;
+ sp++;
+ }
+ } else if (*sp == '*') {
+ multiply_pad = 1;
+ if (*++sp == '/') {
+ must_pad = 1;
+ sp++;
+ }
+ }
+ if (*sp != '>') {
+ PUTCHAR('p');
+ PUTCHAR('a');
+ PUTCHAR('d');
+ PUTCHAR('?');
+ break;
+ }
+ sp++;
+#ifdef TEST
+ printf("\nl = %d", l);
+#endif
+ if (cur_term->pad || must_pad) {
+ cnt = ((long) l * cur_term->baudrate
+ * (multiply_pad ? count : 1)
+ + (10000L * BITSPERCHAR / 2L))
+ / (10000L * BITSPERCHAR);
+#ifdef TEST
+ printf("; cnt = %ld\n", cnt);
+#endif
+ while(cnt--)
+ PUTCHAR(cur_term->padch);
+ }
+#ifdef TEST
+ printf("\n");
+#endif
+ break;
+ default:
+ PUTCHAR(*sp++);
+ }
+ }
+ if (forced_lit)
+ _norm_output();
+ return OK;
+}
+
+int
+putp(str)
+char *str; {
+#ifdef USE_PROTOTYPES
+ return(tputs(str, 1,(int (*)(int)) NULL));
+#else
+ return(tputs(str, 1,(int (*)()) NULL));
+#endif
+}
+
+#ifdef TEST
+
+TERMINAL test_term, *cur_term = &test_term;
+
+int
+#ifdef USE_PROTOTYPES
+putch(char c)
+#else
+putch(c)
+char c;
+#endif
+{
+ if (c & 0x80) {
+ printf("\\%03o", c);
+ } else if (c < 32) {
+ printf("^%c", c + '@');
+ } else if (c == 127) {
+ printf("^?");
+ } else {
+ putchar(c);
+ }
+ return 0;
+}
+
+char line[MAX_LINE];
+
+int
+main(argc, argv)
+int argc;
+char **argv; {
+ test_term.termcap = 0;
+ test_term.baudrate = 1200;
+ test_term.pad = 0;
+ test_term.padch = 0;
+ if (argc > 1)
+ test_term.baudrate = atoi(argv[1]);
+ if (argc > 2)
+ test_term.padch = argv[2][0];
+ if (argc > 3)
+ test_term.pad = 1;
+
+ putchar('\n');
+
+ while(fgets(line, sizeof(line), stdin) != NULL) {
+ line[strlen(line)-1] = '\0';
+ tputs(line, 7, putch);
+ putchar('\n');
+ }
+ return 0;
+}
+#endif
diff --git a/lib/libmytinfo/tty.c b/lib/libmytinfo/tty.c
new file mode 100644
index 0000000..2ba2a7c
--- /dev/null
+++ b/lib/libmytinfo/tty.c
@@ -0,0 +1,446 @@
+/*
+ * tty.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:49
+ *
+ * Do some tty related things
+ *
+ */
+
+#include "defs.h"
+#include <term.h>
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo tty.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+#ifndef EXTA_IS
+#define EXTA_IS 19200
+#endif
+
+#ifndef EXTB_IS
+#define EXTB_IS 38400
+#endif
+
+#ifdef lint
+#define ioctl _ioctl
+/* shutup lint */
+/* ARGSUSED */
+/* VARARGS1 */
+static int ioctl(a, b, p) int a; long b; anyptr *p; { return 0; }
+#endif
+
+#if defined(USE_TERMIO) || defined(USE_TERMIOS)
+
+#ifdef USE_TERMIOS
+speed_t _baud_tbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800,
+ 2400, 4800, 9600, EXTA_IS, EXTB_IS
+#ifdef B57600
+ ,57600
+#endif
+#ifdef B115200
+ ,115200
+#endif
+ };
+#else
+#ifdef USE_SMALLMEM
+unsigned short _baud_tbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+ 1800, 2400, 4800, 9600, EXTA_IS, EXTB_IS};
+#else
+long _baud_tbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800,
+ 2400, 4800, 9600, EXTA_IS, EXTB_IS};
+#endif
+#endif
+
+#ifdef USE_TERMIO
+static struct termio old;
+#else
+static struct termios old;
+#endif
+
+int
+_lit_output() {
+#ifdef USE_TERMIO
+ struct termio tmp;
+ if (ioctl(cur_term->fd, TCGETA, &old) == -1)
+ return 0;
+#else
+ struct termios tmp;
+ if (tcgetattr(cur_term->fd, &old) == -1)
+ return 0;
+#endif
+ if (!(old.c_oflag & OPOST) || !(old.c_oflag & ONLCR))
+ return 0;
+ memcpy((anyptr)&tmp, (anyptr)&old, sizeof(old));
+ tmp.c_oflag &= ~OPOST;
+#ifdef USE_TERMIO
+ ioctl(cur_term->fd, TCSETA, &tmp);
+#else
+ tcsetattr(cur_term->fd, TCSADRAIN, &tmp);
+#endif
+ return 1;
+}
+
+void
+_norm_output() {
+#ifdef USE_TERMIO
+ ioctl(cur_term->fd, TCSETA, &old);
+#else
+ tcsetattr(cur_term->fd, TCSADRAIN, &old);
+#endif
+}
+
+int
+_check_tty() {
+ if ((cur_term->prog_mode.c_iflag & IXON) && cur_term->xon)
+ cur_term->pad = 0;
+ else
+ cur_term->pad = 1;
+#ifdef USE_TERMIO
+ cur_term->baudrate = _baud_tbl[cur_term->prog_mode.c_cflag & CBAUD];
+#else
+ cur_term->baudrate = cfgetospeed(&cur_term->prog_mode);
+#endif
+ return OK;
+}
+
+int
+def_prog_mode() {
+#ifdef USE_WINSZ
+#ifdef TIOCGWINSZ
+ if (ioctl(cur_term->fd, TIOCGWINSZ, &cur_term->prog_winsz) < 0)
+ return ERR;
+#endif
+#endif
+#ifdef USE_TERMIO
+ if (ioctl(cur_term->fd, TCGETA, &cur_term->prog_mode) == 0
+#else
+ if (tcgetattr(cur_term->fd, &cur_term->prog_mode) == 0
+#endif
+ && _check_tty() == OK)
+ return OK;
+ return ERR;
+}
+
+int
+def_shell_mode() {
+ cur_term->termcap = 0;
+#ifdef USE_WINSZ
+#ifdef TIOCGWINSZ
+ if (ioctl(cur_term->fd, TIOCGWINSZ, &cur_term->shell_winsz) < 0)
+ return ERR;
+#endif
+#endif
+#ifdef USE_TERMIO
+ return ioctl(cur_term->fd, TCGETA, &cur_term->shell_mode)==0 ? OK : ERR;
+#else
+ return tcgetattr(cur_term->fd, &cur_term->shell_mode)==0 ? OK : ERR;
+#endif
+}
+
+int
+reset_prog_mode() {
+#ifdef USE_TERMIO
+ return ioctl(cur_term->fd, TCSETA, &cur_term->prog_mode)==0 ? OK : ERR;
+#else
+ return tcsetattr(cur_term->fd, TCSADRAIN, &cur_term->prog_mode)==0 ? OK : ERR;
+#endif
+}
+
+int
+reset_shell_mode() {
+#ifdef USE_TERMIO
+ return ioctl(cur_term->fd, TCSETA, &cur_term->shell_mode)==0 ? OK : ERR;
+#else
+ return tcsetattr(cur_term->fd, TCSADRAIN, &cur_term->shell_mode)==0 ? OK : ERR;
+#endif
+}
+
+int
+_init_tty() {
+ cur_term->true_lines = lines;
+ cur_term->true_columns = columns;
+ if (pad_char == NULL)
+ cur_term->padch = '\000';
+ else
+ cur_term->padch = pad_char[0];
+ if (def_shell_mode() == ERR || def_prog_mode() == ERR) {
+ cur_term->pad = 0;
+ cur_term->baudrate = 1;
+ cur_term->xon = 0;
+ return OK;
+ }
+ cur_term->xon = (xoff_character == NULL || xoff_character[0] == '\021')
+ && (xon_character == NULL || xon_character[0] == '\023')
+ && xon_xoff;
+#ifdef USE_WINSZ
+#ifdef TIOCGWINSZ
+ if (cur_term->prog_winsz.ws_row != 0
+ && cur_term->prog_winsz.ws_col != 0) {
+ lines = cur_term->prog_winsz.ws_row;
+ columns = cur_term->prog_winsz.ws_col;
+ }
+#endif
+#endif
+ return OK;
+}
+
+#else
+
+#ifdef USE_SGTTY
+
+#ifdef USE_SMALLMEM
+unsigned short _baud_tbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+ 1800, 2400, 4800, 9600, EXTA_IS, EXTB_IS};
+#else
+long _baud_tbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+ 1800, 2400, 4800, 9600, EXTA_IS, EXTB_IS};
+#endif
+
+
+#ifdef TIOCLGET
+
+static int old;
+
+int
+_lit_output() {
+ struct sgttyb buf;
+ int tmp;
+
+ ioctl(cur_term->fd, TIOCGETP, &buf);
+ if (buf.sg_flags & RAW)
+ return 0;
+ ioctl(cur_term->fd, TIOCLGET, &old);
+ if (old & LLITOUT)
+ return 0;
+ tmp = old | LLITOUT;
+ ioctl(cur_term->fd, TIOCLSET, &tmp);
+ return 1;
+}
+
+void
+_norm_output() {
+ ioctl(cur_term->fd, TIOCLSET, &old);
+}
+
+#else
+
+static struct sgttyb old;
+
+int
+_lit_output() {
+ struct sgttyb tmp;
+ ioctl(cur_term->fd, TIOCGETP, &old);
+ if (old.sg_flags & RAW)
+ return 0;
+ memcpy((anyptr)&tmp, (anyptr)&old, sizeof(old));
+ tmp.sg_flags |= RAW;
+ ioctl(cur_term->fd, TIOCSETP, &tmp);
+ return 1;
+}
+
+void
+_norm_output() {
+ ioctl(cur_term->fd, TIOCSETP, &old);
+}
+
+#endif
+
+int
+_check_tty() {
+ if (!(cur_term->prog_mode.v6.sg_flags & RAW) && cur_term->xon)
+ cur_term->pad = 0;
+ else
+ cur_term->pad = 1;
+ cur_term->baudrate = _baud_tbl[cur_term->prog_mode.v6.sg_ospeed & 0xf];
+ return OK;
+}
+
+int
+def_shell_mode() {
+ if (ioctl(cur_term->fd, TIOCGETP, &cur_term->shell_mode.v6) < 0)
+ return ERR;
+#ifdef TIOCGETC
+ if (ioctl(cur_term->fd, TIOCGETC, &cur_term->shell_mode.v7) < 0)
+ return ERR;
+#endif
+#ifdef TIOCLGET
+ if (ioctl(cur_term->fd, TIOCLGET, &cur_term->shell_mode.bsd) < 0)
+ return ERR;
+#endif
+#ifdef TIOCGLTC
+ if (ioctl(cur_term->fd, TIOCGLTC, &cur_term->shell_mode.bsd_new) < 0)
+ return ERR;
+#endif
+#ifdef USE_WINSZ
+#ifdef TIOCGWINSZ
+ if (ioctl(cur_term->fd, TIOCGWINSZ, &cur_term->shell_winsz)<0)
+ return ERR;
+#endif
+#endif
+ cur_term->termcap = 0;
+ return OK;
+}
+
+int
+def_prog_mode() {
+ if (ioctl(cur_term->fd, TIOCGETP, &cur_term->prog_mode.v6) < 0)
+ return ERR;
+#ifdef TIOCGETC
+ if (ioctl(cur_term->fd, TIOCGETC, &cur_term->prog_mode.v7) < 0)
+ return ERR;
+#endif
+#ifdef TIOCLGET
+ if (ioctl(cur_term->fd, TIOCLGET, &cur_term->prog_mode.bsd) < 0)
+ return ERR;
+#endif
+#ifdef TIOCGLTC
+ if (ioctl(cur_term->fd, TIOCGLTC, &cur_term->prog_mode.bsd_new) < 0)
+ return ERR;
+#endif
+#ifdef USE_WINSZ
+#ifdef TIOCGWINSZ
+ if (ioctl(cur_term->fd, TIOCGWINSZ, &cur_term->prog_winsz)<0)
+ return ERR;
+#endif
+#endif
+ return _check_tty();
+}
+
+int
+reset_shell_mode() {
+ if (ioctl(cur_term->fd, TIOCSETP, &cur_term->shell_mode.v6) < 0)
+ return ERR;
+#ifdef TIOCGETC
+ if (ioctl(cur_term->fd, TIOCSETC, &cur_term->shell_mode.v7) < 0)
+ return ERR;
+#endif
+#ifdef TIOCLGET
+ if (ioctl(cur_term->fd, TIOCLSET, &cur_term->shell_mode.bsd) < 0)
+ return ERR;
+#endif
+#ifdef TIOCGLTC
+ if (ioctl(cur_term->fd, TIOCSLTC, &cur_term->shell_mode.bsd_new) < 0)
+ return ERR;
+#endif
+ return OK;
+}
+
+int
+reset_prog_mode() {
+ if (ioctl(cur_term->fd, TIOCSETP, &cur_term->prog_mode.v6) < 0)
+ return ERR;
+#ifdef TIOCGETC
+ if (ioctl(cur_term->fd, TIOCSETC, &cur_term->prog_mode.v7) < 0)
+ return ERR;
+#endif
+#ifdef TIOCLGET
+ if (ioctl(cur_term->fd, TIOCLSET, &cur_term->prog_mode.bsd) < 0)
+ return ERR;
+#endif
+#ifdef TIOCGLTC
+ if (ioctl(cur_term->fd, TIOCSLTC, &cur_term->prog_mode.bsd_new) < 0)
+ return ERR;
+#endif
+ return OK;
+}
+
+int
+_init_tty() {
+ cur_term->true_lines = lines;
+ cur_term->true_columns = columns;
+ if (pad_char == NULL)
+ cur_term->padch = '\000';
+ else
+ cur_term->padch = pad_char[0];
+ if (def_shell_mode() == ERR || def_prog_mode() == ERR) {
+ cur_term->pad = 0;
+ cur_term->baudrate = 1;
+ cur_term->xon = 0;
+ return OK;
+ }
+#ifndef TIOCGETC
+ cur_term->xon = (xoff_character == NULL || xoff_character[0] == '\021')
+ && (xon_character == NULL || xon_character[0] == '\023')
+ && xon_xoff;
+#else
+ if (xon_xoff) {
+ if (xon_character != NULL) {
+ cur_term->prog_mode.v7.t_startc = xon_character[0];
+ if (ioctl(cur_term->fd, TIOCSETC,
+ &cur_term->prog_mode.v7) < 0)
+ return ERR;
+ }
+ if (xoff_character != NULL) {
+ cur_term->prog_mode.v7.t_stopc = xoff_character[0];
+ if (ioctl(cur_term->fd, TIOCSETC,
+ &cur_term->prog_mode.v7) < 0)
+ return ERR;
+ }
+ }
+ cur_term->xon = xon_xoff;
+#endif
+#ifdef USE_WINSZ
+#ifdef TIOCGWINSZ
+ if (cur_term->prog_winsz.ws_row != 0
+ && cur_term->prog_winsz.ws_col != 0) {
+ lines = cur_term->prog_winsz.ws_row;
+ columns = cur_term->prog_winsz.ws_col;
+ }
+#endif
+#endif
+ return OK;
+}
+
+#else
+
+int
+_lit_output() {
+ return 0;
+}
+
+void
+_norm_output() {
+ return;
+}
+
+int
+_check_tty() {
+ return OK;
+}
+
+int
+def_prog_mode() {
+ return OK;
+}
+
+int
+reset_prog_mode() {
+ return OK;
+}
+
+int
+def_shell_mode() {
+ return OK;
+}
+
+int
+reset_shell_mode() {
+ return OK;
+}
+
+int
+_init_tty() {
+ cur_term->pad = 1;
+ cur_term->padch = 0;
+ cur_term->baudrate = 1200;
+ cur_term->xon = 0;
+ cur_term->termcap = 0;
+ cur_term->true_lines = lines;
+ cur_term->true_columns = columns;
+}
+
+#endif
+
+#endif
diff --git a/lib/libmytinfo/version.h b/lib/libmytinfo/version.h
new file mode 100644
index 0000000..917223d
--- /dev/null
+++ b/lib/libmytinfo/version.h
@@ -0,0 +1,10 @@
+/*
+ * version.h
+ *
+ * By Ross Ridge
+ * Public Domain
+ *
+ */
+
+#define RELEASE 3
+#define PATCHLEVEL 0
diff --git a/lib/libncurses/COPYRIGHT.NEW b/lib/libncurses/COPYRIGHT.NEW
new file mode 100644
index 0000000..7c5d22b
--- /dev/null
+++ b/lib/libncurses/COPYRIGHT.NEW
@@ -0,0 +1,19 @@
+/***************************************************************************
+* COPYRIGHT NOTICE *
+****************************************************************************
+* ncurses is copyright (C) 1992, 1993, 1994 *
+* by Zeyd M. Ben-Halim *
+* zmbenhal@netcom.com *
+* *
+* Permission is hereby granted to reproduce and distribute ncurses *
+* by any means and for any fee, whether alone or as part of a *
+* larger distribution, in source or in binary form, PROVIDED *
+* this notice is included with any such distribution, not removed *
+* from header files, and is reproduced in any documentation *
+* accompanying it or the applications linked with it. *
+* *
+* ncurses comes AS IS with no warranty, implied or expressed. *
+* *
+***************************************************************************/
+
+
diff --git a/lib/libncurses/COPYRIGHT.OLD b/lib/libncurses/COPYRIGHT.OLD
new file mode 100644
index 0000000..4049db0
--- /dev/null
+++ b/lib/libncurses/COPYRIGHT.OLD
@@ -0,0 +1,5 @@
+
+Pavel Curtis has given up his copyright to the public domain. This mean
+his ORIGINAL sources are in the public domain, not this current release.
+This current release IS copyrighted, see COPYRIGHT.NEW.
+
diff --git a/lib/libncurses/MKkeyname.awk b/lib/libncurses/MKkeyname.awk
new file mode 100644
index 0000000..12613ce
--- /dev/null
+++ b/lib/libncurses/MKkeyname.awk
@@ -0,0 +1,30 @@
+
+BEGIN {
+ print ""
+ print "#include <stdlib.h>"
+ print "#include \"curses.h\""
+ print ""
+ print "struct kn {"
+ print "\tchar *name;"
+ print "\tint code;"
+ print "};"
+ print ""
+ print "struct kn key_names[] = {"
+}
+
+{printf "\t{\"%s\", %s,},\n", $1, $2;}
+
+END {
+ print "};"
+ print ""
+ print "char *keyname(int c)"
+ print "{"
+ print "int i, size = sizeof(key_names)/sizeof(struct kn);"
+ print ""
+ print "\tfor (i = 0; i < size; i++) {"
+ print "\t\tif (key_names[i].code == c) return key_names[i].name;"
+ print "\t}"
+ print "\treturn NULL;"
+ print "}"
+ print ""
+}
diff --git a/lib/libncurses/MKkeys.awk b/lib/libncurses/MKkeys.awk
new file mode 100644
index 0000000..669c455
--- /dev/null
+++ b/lib/libncurses/MKkeys.awk
@@ -0,0 +1 @@
+{printf "\tadd_to_try(%s, %s);\n", $1, $2;}
diff --git a/lib/libncurses/Makefile b/lib/libncurses/Makefile
new file mode 100644
index 0000000..c0e7b35
--- /dev/null
+++ b/lib/libncurses/Makefile
@@ -0,0 +1,209 @@
+# Makefile for ncurses
+# $Id$
+
+LIB= ncurses
+SHLIB_MAJOR= 3
+SHLIB_MINOR= 0
+SRCS= lib_kernel.c lib_pad.c lib_bkgd.c \
+ lib_unctrl.c lib_raw.c lib_vidattr.c lib_trace.c lib_beep.c \
+ lib_doupdate.c lib_refresh.c lib_initscr.c lib_newwin.c lib_addch.c \
+ lib_addstr.c lib_scroll.c lib_clreol.c lib_touch.c lib_mvcur.c lib_keyname.c\
+ lib_delwin.c lib_endwin.c lib_clrbot.c lib_move.c lib_printw.c \
+ lib_scanw.c lib_erase.c lib_getch.c lib_options.c lib_acs.c lib_slk.c\
+ lib_box.c lib_clear.c lib_delch.c lib_insch.c \
+ lib_getstr.c lib_mvwin.c lib_longname.c lib_tstp.c \
+ lib_newterm.c lib_set_term.c lib_overlay.c lib_scrreg.c lib_color.c \
+ lib_insstr.c lib_insdel.c lib_twait.c lib_window.c copyright.c
+
+CFLAGS+= -I. -I${.CURDIR} -Wall -DMYTINFO
+DPADD= ${LIBMYTINFO}
+LDADD= -lmytinfo
+
+CLEANFILES+= lib_keyname.c keys.tries
+
+beforedepend: keys.tries
+
+beforeinstall:
+ ${INSTALL} -C -m 444 -o $(BINOWN) -g $(BINGRP) ${.CURDIR}/unctrl.h \
+ ${DESTDIR}/usr/include
+ ${INSTALL} -C -m 444 -o $(BINOWN) -g $(BINGRP) ${.CURDIR}/curses.h \
+ ${DESTDIR}/usr/include/ncurses.h
+
+keys.tries: ${.CURDIR}/keys.list ${.CURDIR}/MKkeys.awk
+ awk -f ${.CURDIR}/MKkeys.awk ${.CURDIR}/keys.list > keys.tries
+
+# in case you don't run make depend
+lib_options.o lib_options.so lib_options.po: keys.tries
+
+lib_keyname.c: ${.CURDIR}/keys.list ${.CURDIR}/MKkeyname.awk
+ awk -f ${.CURDIR}/MKkeyname.awk ${.CURDIR}/keys.list > lib_keyname.c
+
+MAN3 = curs_addch.3 \
+ curs_addchst.3 \
+ curs_addstr.3 \
+ curs_attr.3 \
+ curs_beep.3 \
+ curs_bkgd.3 \
+ curs_border.3 \
+ curs_clear.3 \
+ curs_color.3 \
+ curs_delch.3 \
+ curs_delln.3 \
+ curs_getch.3 \
+ curs_getstr.3 \
+ curs_getyx.3 \
+ curs_inch.3 \
+ curs_inchstr.3 \
+ curs_initscr.3 \
+ curs_inopts.3 \
+ curs_insch.3 \
+ curs_insstr.3 \
+ curs_instr.3 \
+ curs_kernel.3 \
+ curs_move.3 \
+ curs_outopts.3 \
+ curs_overlay.3 \
+ curs_pad.3 \
+ curs_printw.3 \
+ curs_refresh.3 \
+ curs_scanw.3 \
+ curs_scr_dmp.3 \
+ curs_scroll.3 \
+ curs_slk.3 \
+ curs_termatt.3 \
+ curs_termin.3 \
+ curs_touch.3 \
+ curs_util.3 \
+ curs_window.3 \
+ ncurses.3
+
+MAN5 = term.5 terminfo.5
+
+MLINKS+=curs_addch.3 addch.3 curs_addch.3 waddch.3 curs_addch.3 echochar.3 \
+ curs_addch.3 wechochar.3 curs_addch.3 mvaddch.3 \
+ curs_addch.3 mvwaddch.3
+MLINKS+=curs_addchst.3 addchstr.3 curs_addchst.3 addchnstr.3 \
+ curs_addchst.3 waddchstr.3 curs_addchst.3 waddchnstr.3 \
+ curs_addchst.3 mvaddchstr.3 curs_addchst.3 mvaddchnstr.3 \
+ curs_addchst.3 mvwaddchstr.3 curs_addchst.3 mvwaddchnstr.3
+MLINKS+=curs_addstr.3 addstr.3 curs_addstr.3 addnstr.3 \
+ curs_addstr.3 waddstr.3 curs_addstr.3 waddnstr.3 \
+ curs_addstr.3 mvaddstr.3 curs_addstr.3 mvaddnstr.3 \
+ curs_addstr.3 mvwaddstr.3 curs_addstr.3 mvwaddnstr.3
+MLINKS+=curs_attr.3 attroff.3 curs_attr.3 wattroff.3 \
+ curs_attr.3 attron.3 curs_attr.3 wattron.3 \
+ curs_attr.3 attrset.3 curs_attr.3 wattrset.3 \
+ curs_attr.3 standend.3 curs_attr.3 wstandend.3 \
+ curs_attr.3 standout.3 curs_attr.3 wstandout.3
+MLINKS+=curs_beep.3 beep.3 curs_beep.3 flash.3
+MLINKS+=curs_bkgd.3 bkgdset.3 curs_bkgd.3 wbkgdset.3 \
+ curs_bkgd.3 bkgd.3 curs_bkgd.3 wbkgd.3
+MLINKS+=curs_border.3 border.3 curs_border.3 wborder.3 curs_border.3 box.3 \
+ curs_border.3 hline.3 curs_border.3 whline.3 \
+ curs_border.3 vline.3 curs_border.3 wvline.3
+MLINKS+=curs_clear.3 erase.3 curs_clear.3 werase.3 curs_clear.3 clear.3 \
+ curs_clear.3 wclear.3 curs_clear.3 clrtobot.3 \
+ curs_clear.3 wclrtobot.3 curs_clear.3 clrtoeol.3 \
+ curs_clear.3 wclrtoeol.3
+MLINKS+=curs_color.3 start_color.3 curs_color.3 init_pair.3 \
+ curs_color.3 init_color.3 curs_color.3 has_colors.3 \
+ curs_color.3 can_change_color.3 curs_color.3 color_content.3 \
+ curs_color.3 pair_content.3
+MLINKS+=curs_delch.3 delch.3 curs_delch.3 wdelch.3 curs_delch.3 mvdelch.3 \
+ curs_delch.3 mvwdelch.3
+MLINKS+=curs_delln.3 deleteln.3 curs_delln.3 wdeleteln.3 \
+ curs_delln.3 insdelln.3 curs_delln.3 winsdelln.3 \
+ curs_delln.3 insertln.3 curs_delln.3 winsertln.3
+MLINKS+=curs_getch.3 getch.3 curs_getch.3 wgetch.3 curs_getch.3 mvgetch.3 \
+ curs_getch.3 mvwgetch.3 curs_getch.3 ungetch.3
+MLINKS+=curs_getstr.3 getstr.3 curs_getstr.3 wgetstr.3 \
+ curs_getstr.3 mvgetstr.3 curs_getstr.3 mvwgetstr.3 \
+ curs_getstr.3 wgetnstr.3
+MLINKS+=curs_getyx.3 getyx.3 curs_getyx.3 pgetparyx.3 curs_getyx.3 getbegyx.3 \
+ curs_getyx.3 getmaxyx.3
+MLINKS+=curs_inch.3 inch.3 curs_inch.3 winch.3 curs_inch.3 mvinch.3 \
+ curs_inch.3 mvwinch.3
+MLINKS+=curs_inchstr.3 inchstr.3 curs_inchstr.3 inchnstr.3 \
+ curs_inchstr.3 winchstr.3 curs_inchstr.3 winchnstr.3 \
+ curs_inchstr.3 mvinchstr.3 curs_inchstr.3 mvinchnstr.3 \
+ curs_inchstr.3 mvwinchstr.3 curs_inchstr.3 mvwinchnstr.3
+MLINKS+=curs_initscr.3 initscr.3 curs_initscr.3 newterm.3 \
+ curs_initscr.3 endwin.3 curs_initscr.3 isendwin.3 \
+ curs_initscr.3 set_term.3 curs_initscr.3 delscreen.3
+MLINKS+=curs_inopts.3 cbreak.3 curs_inopts.3 nocbreak.3 curs_inopts.3 echo.3 \
+ curs_inopts.3 noecho.3 curs_inopts.3 halfdelay.3 \
+ curs_inopts.3 intrflush.3 curs_inopts.3 keypad.3 curs_inopts.3 meta.3 \
+ curs_inopts.3 nodelay.3 curs_inopts.3 notimeout.3 curs_inopts.3 raw.3 \
+ curs_inopts.3 noraw.3 curs_inopts.3 noqiflush.3 \
+ curs_inopts.3 qiflush.3 curs_inopts.3 timeout.3 \
+ curs_inopts.3 wtimeout.3 curs_inopts.3 typeahead.3
+MLINKS+=curs_insch.3 insch.3 curs_insch.3 winsch.3 curs_insch.3 mvinsch.3 \
+ curs_insch.3 mvwinsch.3
+MLINKS+=curs_insstr.3 insstr.3 curs_insstr.3 insnstr.3 \
+ curs_insstr.3 winsstr.3 curs_insstr.3 winsnstr.3 \
+ curs_insstr.3 mvinsstr.3 curs_insstr.3 mvinsnstr.3 \
+ curs_insstr.3 mvwinsstr.3 curs_insstr.3 mvwinsnstr.3
+MLINKS+=curs_instr.3 instr.3 curs_instr.3 innstr.3 curs_instr.3 winstr.3 \
+ curs_instr.3 winnstr.3 curs_instr.3 mvinstr.3 curs_instr.3 mvinnstr.3 \
+ curs_instr.3 mvwinstr.3 curs_instr.3 mvwinnstr.3
+MLINKS+=curs_kernel.3 def_prog_mode.3 curs_kernel.3 def_shell_mode.3 \
+ curs_kernel.3 reset_prog_mode.3 curs_kernel.3 reset_shell_mode.3 \
+ curs_kernel.3 resetty.3 curs_kernel.3 savetty.3 \
+ curs_kernel.3 getsyx.3 curs_kernel.3 setsyx.3 \
+ curs_kernel.3 ripoffline.3 curs_kernel.3 curs_set.3 \
+ curs_kernel.3 napms.3
+MLINKS+=curs_move.3 move.3 curs_move.3 wmove.3
+MLINKS+=curs_outopts.3 clearok.3 curs_outopts.3 idlok.3 \
+ curs_outopts.3 idcok.3 curs_outopts.3 immedok.3 \
+ curs_outopts.3 leaveok.3 curs_outopts.3 setscrreg.3 \
+ curs_outopts.3 wsetscrreg.3 curs_outopts.3 scrollok.3 \
+ curs_outopts.3 nl.3 curs_outopts.3 nonl.3
+MLINKS+=curs_overlay.3 overlay.3 curs_overlay.3 overwrite.3 \
+ curs_overlay.3 copywin.3
+MLINKS+=curs_pad.3 newpad.3 curs_pad.3 subpad.3 curs_pad.3 prefresh.3 \
+ curs_pad.3 pnoutrefresh.3 curs_pad.3 pechochar.3
+MLINKS+=curs_printw.3 printw.3 curs_printw.3 wprintw.3 \
+ curs_printw.3 mvprintw.3 curs_printw.3 mvwprintw.3 \
+ curs_printw.3 vwprintw.3
+MLINKS+=curs_refresh.3 refresh.3 curs_refresh.3 wrefresh.3 \
+ curs_refresh.3 wnoutrefresh.3 curs_refresh.3 doupdate.3 \
+ curs_refresh.3 redrawwin.3 curs_refresh.3 wredrawln.3
+MLINKS+=curs_scanw.3 scanw.3 curs_scanw.3 wscanw.3 curs_scanw.3 mvscanw.3 \
+ curs_scanw.3 mvwscanw.3 curs_scanw.3 vwscanw.3
+MLINKS+=curs_scr_dmp.3 scr_dump.3 curs_scr_dmp.3 scr_restore.3 \
+ curs_scr_dmp.3 scr_init.3 curs_scr_dmp.3 scr_set.3
+MLINKS+=curs_scroll.3 scroll.3 curs_scroll.3 scrl.3 curs_scroll.3 wscrl.3
+MLINKS+=curs_slk.3 slk_init.3 curs_slk.3 slk_set.3 curs_slk.3 slk_refresh.3 \
+ curs_slk.3 slk_noutrefresh.3 curs_slk.3 slk_label.3 \
+ curs_slk.3 slk_clear.3 curs_slk.3 slk_restore.3 \
+ curs_slk.3 slk_touch.3 curs_slk.3 slk_attron.3 \
+ curs_slk.3 slk_attrset.3 curs_slk.3 slk_attroff.3
+MLINKS+=curs_termatt.3 baudrate.3 curs_termatt.3 erasechar.3 \
+ curs_termatt.3 has_ic.3 curs_termatt.3 has_il.3 \
+ curs_termatt.3 killchar.3 curs_termatt.3 longname.3 \
+ curs_termatt.3 termattrs.3 curs_termatt.3 termname.3
+
+# XXX name clash with termcap(3)
+# MLINKS+= curs_termin.3 tparm.3
+MLINKS+=curs_termin.3 setupterm.3 curs_termin.3 setterm.3 \
+ curs_termin.3 set_curterm.3 curs_termin.3 del_curterm.3 \
+ curs_termin.3 restartterm.3 \
+ curs_termin.3 putp.3 curs_termin.3 vidputs.3 \
+ curs_termin.3 vidattr.3 curs_termin.3 mvcur.3 \
+ curs_termin.3 tigetflag.3 curs_termin.3 tigetnum.3 \
+ curs_termin.3 tigetstr.3
+MLINKS+=curs_touch.3 touchwin.3 curs_touch.3 touchline.3 \
+ curs_touch.3 untouchwin.3 curs_touch.3 wtouchln.3 \
+ curs_touch.3 is_linetouched.3 curs_touch.3 is_wintouched.3
+MLINKS+=curs_util.3 unctrl.3 curs_util.3 keyname.3 \
+ curs_util.3 filter.3 curs_util.3 use_env.3 \
+ curs_util.3 putwin.3 curs_util.3 getwin.3 \
+ curs_util.3 delay_output.3 curs_util.3 flushinp.3
+MLINKS+=curs_window.3 newwin.3 curs_window.3 delwin.3 \
+ curs_window.3 mvwin.3 curs_window.3 subwin.3 \
+ curs_window.3 derwin.3 curs_window.3 mvderwin.3 \
+ curs_window.3 dupwin.3 curs_window.3 wsyncup.3 \
+ curs_window.3 syncok.3 curs_window.3 wcursyncup.3 \
+ curs_window.3 wsyncdown.3
+
+.include <bsd.lib.mk>
diff --git a/lib/libncurses/README b/lib/libncurses/README
new file mode 100644
index 0000000..d1f93bb
--- /dev/null
+++ b/lib/libncurses/README
@@ -0,0 +1,42 @@
+NCURSES 1.8.6 - July 24, 1994
+-----------------------------
+This file is intended to help people interested in working
+on fixing ncurses, enhancing it, or porting it to other
+platforms.
+
+PORTABILITY:
+The file matrix is an attempt at centralizing all portability
+information. The top line lists the different options, down
+the leftside are the operating systems supported. If an option
+is not needed then it should have an entry of NONE. Note the
+use of ':' to terminate each field. If somebody knows awk better
+than me, get in touch.
+
+OS: name of operating system
+ISPOSIX: -DNONPOSIX if <unistd.h> is missing
+POSIX: -DSTRICTPOSIX if _POSIX_SOURCE turns off non-POSIX features.
+ -DSVR4_ACTION if like svr4 you need _POSIX_SOURCE to have sigaction
+TERMINAL: -DNOTERMIOS if you don't have <termios.h> but have <sgtty.h>
+HEADERS: -DBRAINDEAD if system headers don't declare external variables
+TABS: -DBSDTABS if you don't have TABS3 but have OXTABS
+OPT: -DOPT_MVCUR if you want mvcur() to cost its actions or you have a
+ terminal that doesn't have direct cursor addressing.
+SRCDIR: the directory where the terminfo database lives
+CC: ANSI C compiler
+FLAGS: standard compiler flags
+EXTRA: extra flags needed by individual systems
+ Sun: -DSUNIOCTL <sys/ioctl.h> conflicts with <termios.h>
+ HP-UX: -D_HPUX_SOURCE so that we get POSIX and XOPEN features.
+ SVR4: -DBROKEN_TIOCGETWINSZ guess what?
+ AIX: -DSYS_SELECT if you need <sys/select.h>
+BASE: The directory under which headers and libraries will
+ be installed.
+INSTALL: The name of an install program similar to BSD's (ie. understands
+ -m, -g, -o, etc.) GNU install works.
+
+The awk script in script.src reads matrix and generates all the Config.*
+files.
+
+There are several problems with strict POSIX systems so extra flags
+or #define's maybe needed.
+
diff --git a/lib/libncurses/TESTS/Makefile b/lib/libncurses/TESTS/Makefile
new file mode 100644
index 0000000..64dc0e3
--- /dev/null
+++ b/lib/libncurses/TESTS/Makefile
@@ -0,0 +1,35 @@
+TESTS = test corner ensor getch ncurses hanoi knight rain worm \
+ over scroll2 battle newdemo scroll3 xmas copy firework testcurs \
+ scroll
+
+CLEANFILES += $(TESTS)
+
+LIBS += -lncurses -lmytinfo
+
+all: $(TESTS)
+
+$(TESTS):
+ $(CC) $(CFLAGS) $(LDFLAGS) ${.CURDIR}/$@.c -o $@ $(LIBS)
+
+test: test.c
+corner: corner.c
+ensor: ensor.c
+getch: getch.c
+ncurses: ncurses.c
+hanoi: hanoi.c
+knight: knight.c
+rain: rain.c
+worm: worm.c
+over: over.c
+scroll2: scroll2.c
+battle: battle.c
+newdemo: newdemo.c
+scroll3: scroll3.c
+xmas: xmas.c
+copy: copy.c
+firework: firework.c
+testcurs: testcurs.c
+scroll: scroll.c
+
+.include <bsd.prog.mk>
+
diff --git a/lib/libncurses/TESTS/README b/lib/libncurses/TESTS/README
new file mode 100644
index 0000000..279c6d8
--- /dev/null
+++ b/lib/libncurses/TESTS/README
@@ -0,0 +1,21 @@
+The programs in this directory are designed to test your newest toy :-)
+Check the sources for any further details.
+
+asc.c - tests the line drawing functions
+attr.c - display attributes available on the terminal
+bs.c - the game of battleship
+battle.c - older version of battleship with different interface
+caps.c - output a list of all capabilites to stderr (redirect to a file
+ or it will screw up the terminal)
+copy.c - test overlay
+gdc.c - Great Digital Clock, gives an example of usng color
+getch.c - tests ketpad() and getch()
+hanoi.c - the game of hanoi, also an example of using color
+knight.c - the game of Knight's Tour
+rain.c - rain drops are falling on my head..
+scroll.c - test scrolling region
+slk.c - test soft labels
+worm.c - worms run all over your screen
+firework.c - multi-colored fireworks
+newdemo.c - a demo from the PDCurses people
+testcurs.c - a test from the PDCurses people
diff --git a/lib/libncurses/TESTS/battle.c b/lib/libncurses/TESTS/battle.c
new file mode 100644
index 0000000..5b5a961
--- /dev/null
+++ b/lib/libncurses/TESTS/battle.c
@@ -0,0 +1,705 @@
+/*
+ * battle.c - original author: Bruce Holloway
+ * mods by: Chuck A DeGaul
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <signal.h>
+#include <ncurses.h>
+
+#define OTHER 1-turn
+
+char numbers[] = " 0 1 2 3 4 5 6 7 8 9";
+
+char carrier[] = "Aircraft Carrier";
+char battle[] = "Battleship";
+char sub[] = "Submarine";
+char destroy[] = "Destroyer";
+char ptboat[] = "PT Boat";
+
+char name[40];
+char dftname[] = "Stranger";
+
+struct _ships {
+ char *name;
+ char symbol;
+ char length;
+ char start; /* Coordinates - 0,0=0; 10,10=100. */
+ char dir; /* Direction - 0 = right; 1 = down. */
+ char hits; /* How many times has this ship been hit? (-1==sunk) */
+};
+
+struct _ships plyship[] = {
+ { carrier,'A',5,0,0,0 },
+ { battle,'B',4,0,0,0 },
+ { destroy,'D',3,0,0,0 },
+ { sub,'S',3,0,0,0 },
+ { ptboat,'P',2,0,0,0 },
+};
+
+struct _ships cpuship[] = {
+ { carrier,'A',5,0,0,0 },
+ { battle,'B',4,0,0,0 },
+ { destroy,'D',3,0,0,0 },
+ { sub,'S',3,0,0,0 },
+ { ptboat,'P',2,0,0,0 },
+};
+
+char hits[2][100], board[2][100]; /* "Hits" board, and main board. */
+
+int srchstep;
+int cpuhits;
+int cstart, cdir;
+int plywon=0, cpuwon=0; /* How many games has each won? */
+int turn; /* 0=player, 1=computer */
+int huntoffs; /* Offset on search strategy */
+
+int salvo, blitz, ask, seemiss; /* options */
+
+void intro(void);
+void initgame(void);
+int rnd(int);
+void plyplace(struct _ships *);
+int getdir(void);
+void placeship(struct _ships *, int, int);
+int checkplace(struct _ships *, int, int);
+void error(char *);
+void prompt(void);
+char getcoord(void);
+void cpuplace(struct _ships *);
+int awinna(void);
+int plyturn(void);
+int hitship(int);
+int cputurn(void);
+int playagain(void);
+void uninitgame();
+int sgetc(char *);
+int do_options(int, char *[]);
+int scount(int);
+
+int
+main(int argc, char **argv)
+{
+ do_options(argc, argv);
+
+ intro();
+ do {
+ initgame();
+ while(awinna() == -1) {
+ if (!blitz) {
+ if (!salvo) {
+ if (turn)
+ cputurn();
+ else plyturn();
+ } else {
+ register int i;
+
+ i = scount(turn);
+ while (i--) {
+ if (turn)
+ if (cputurn())
+ if (awinna() != -1)
+ i = 0;
+ else
+ if(plyturn())
+ if (awinna() != -1)
+ i = 0;
+ }
+ }
+ } else {
+ while((turn) ? cputurn() : plyturn());
+ }
+ turn = OTHER;
+ }
+ } while(playagain());
+ uninitgame();
+ exit(0);
+}
+
+#define PR addstr
+
+void
+intro()
+{
+char *tmpname;
+
+ srand(time(0L)); /* Kick the random number generator */
+
+ signal(SIGINT,uninitgame);
+ if(signal(SIGQUIT,SIG_IGN) != SIG_IGN) signal(SIGQUIT,uninitgame);
+#if 1
+ /* for some bizzare reason, getlogin or cuserid cause havoc with the terminal */
+ if ((tmpname = getlogin()) != NULL) {
+ strcpy(name, tmpname);
+ } else
+#endif
+ strcpy(name,dftname);
+ name[0] = toupper(name[0]);
+
+ initscr();
+ savetty();
+ nonl();
+ cbreak();
+ noecho();
+ clear();
+ mvaddstr(4,29,"Welcome to Battleship!");
+ move(8,0);
+PR(" \\\n");
+PR(" \\ \\ \\\n");
+PR(" \\ \\ \\ \\ \\_____________\n");
+PR(" \\ \\ \\_____________ \\ \\/ |\n");
+PR(" \\ \\/ \\ \\/ |\n");
+PR(" \\/ \\_____/ |__\n");
+PR(" ________________/ |\n");
+PR(" \\ S.S. Penguin |\n");
+PR(" \\ /\n");
+PR(" \\___________________________________________________/\n");
+ mvaddstr(20,27,"Hit any key to continue..."); refresh();
+ getch();
+}
+
+void
+initgame()
+{
+int i;
+
+ clear();
+ mvaddstr(0,35,"BATTLESHIP");
+ mvaddstr(4,12,"Main Board");
+ mvaddstr(6,0,numbers);
+ move(7,0);
+ for(i=0; i<10; ++i){
+ printw("%c . . . . . . . . . . %c\n",i+'A',i+'A');
+ }
+ mvaddstr(17,0,numbers);
+ mvaddstr(4,55,"Hit/Miss Board");
+ mvaddstr(6,45,numbers);
+ for(i=0; i<10; ++i){
+ mvprintw(7+i,45,"%c . . . . . . . . . . %c",i+'A',i+'A');
+ }
+ mvaddstr(17,45,numbers);
+ for(turn=0; turn<2; ++turn)
+ for(i=0; i<100; ++i){
+ hits[turn][i] = board[turn][i] = 0;
+ }
+ for(turn=0; turn<2; ++turn){
+ for(i=0; i<5; ++i)
+ if (!turn)
+ plyplace(&plyship[i]);
+ else
+ cpuplace(&cpuship[i]);
+ }
+ turn = rnd(2);
+ cstart = cdir = -1;
+ cpuhits = 0;
+ srchstep = 3;
+ huntoffs = rnd(srchstep);
+}
+
+int
+rnd(int n)
+{
+ return(((rand() & 0x7FFF) % n));
+}
+
+void
+plyplace(ss)
+struct _ships *ss;
+{
+int c, d;
+
+ do {
+ prompt();
+ printw("Place your %s (ex.%c%d) ? ",ss->name,rnd(10)+'A',rnd(10));
+ c = getcoord();
+ d = getdir();
+ } while(!checkplace(ss,c,d));
+ placeship(ss,c,d);
+}
+
+int
+getdir()
+{
+
+ prompt();
+ addstr("What direction (0=right, 1=down) ? ");
+ return(sgetc("01")-'0');
+}
+
+void
+placeship(ss,c,d)
+struct _ships *ss;
+int c, d;
+{
+int x, y, l, i;
+
+ for(l=0; l<ss->length; ++l){
+ i = c + l * ((d) ? 10 : 1);
+ board[turn][i] = ss->symbol;
+ x = (i % 10) * 3 + 3;
+ y = (i / 10) + 7;
+ if(!turn) mvaddch(y,x,ss->symbol);
+ }
+ ss->start = c;
+ ss->dir = d;
+ ss->hits = 0;
+}
+
+int
+checkplace(ss,c,d)
+struct _ships *ss;
+int c, d;
+{
+int x, y, l;
+
+ x = c%10; y = c/10;
+ if(((x+ss->length) > 10 && !d) || ((y+ss->length) > 10 && d==1)){
+ if(!turn)
+ switch(rnd(3)){
+ case 0:
+ error("Ship is hanging from the edge of the world");
+ break;
+ case 1:
+ error("Try fitting it on the board");
+ break;
+ case 2:
+ error("Figure I won't find it if you put it there?");
+ break;
+ }
+ return(0);
+ }
+ for(l=0; l<ss->length; ++l){
+ x = c + l * ((d) ? 10 : 1);
+ if(board[turn][x]){
+ if(!turn)
+ switch(rnd(3)){
+ case 0:
+ error("There's already a ship there");
+ break;
+ case 1:
+ error("Collision alert! Aaaaaagh!");
+ break;
+ case 2:
+ error("Er, Admiral, what about the other ship?");
+ break;
+ }
+ return(0);
+ }
+ }
+ return(1);
+}
+
+void
+error(s)
+char *s;
+{
+ prompt();
+ beep();
+ printw("%s -- hit any key to continue --",s);
+ refresh();
+ getch();
+}
+
+void
+prompt(){
+ move(22,0);
+ clrtoeol();
+}
+
+char
+getcoord()
+{
+int ch, x, y;
+
+redo:
+ y = sgetc("ABCDEFGHIJ");
+ do {
+ ch = getch();
+ if (ch == 0x7F || ch == 8) {
+ addstr("\b \b");
+ refresh();
+ goto redo;
+ }
+ } while(ch < '0' || ch > '9');
+ addch(x = ch);
+ refresh();
+ return((y-'A')*10+x-'0');
+}
+
+void
+cpuplace(ss)
+struct _ships *ss;
+{
+int c, d;
+
+ do{
+ c = rnd(100);
+ d = rnd(2);
+ } while(!checkplace(ss,c,d));
+ placeship(ss,c,d);
+}
+
+int
+awinna()
+{
+int i, j;
+struct _ships *ss;
+
+ for (i = 0; i < 2; ++i) {
+ ss = (i) ? cpuship : plyship;
+ for(j=0; j<5; ++j, ++ss)
+ if(ss->length != ss->hits)
+ break;
+ if(j == 5) return(OTHER);
+ }
+ return(-1);
+}
+
+int
+plyturn()
+{
+int c, res;
+char *m;
+
+ prompt();
+ addstr("Where do you want to shoot? ");
+ c = getcoord();
+ if(!(res = hits[turn][c])){
+ hits[turn][c] = res = (board[OTHER][c]) ? 'H' : 'M';
+ mvaddch(7+c/10,48+3*(c%10),(res=='H') ? 'H' : 'o');
+ if(c = hitship(c)){
+ prompt();
+ switch(rnd(3)){
+ case 0:
+ m = "You sank my %s!";
+ break;
+ case 1:
+ m = "I have this sinking feeling about my %s....";
+ break;
+ case 2:
+ m = "Have some mercy for my %s!";
+ break;
+ }
+ move(23,0);
+ clrtoeol();
+ beep();
+ printw(m,cpuship[c-1].name); refresh();
+ return(awinna() == -1);
+ }
+ }
+ prompt();
+ move(23,0); clrtoeol();
+ printw("You %s.",(res=='M')?"missed":"scored a hit"); refresh();
+ return(res == 'H');
+}
+
+int
+hitship(c)
+int c;
+{
+struct _ships *ss;
+int sym, i, j;
+
+ ss = (turn) ? plyship : cpuship;
+ if (!(sym = board[OTHER][c])) return(0);
+ for (i = 0; i < 5; ++i, ++ss)
+ if (ss->symbol == sym) {
+ j = ss->hits;
+ ++j;
+ ss->hits = j;
+ if (j == ss->length)
+ return(i+1);
+ return(0);
+ }
+}
+
+int
+cputurn()
+{
+int c, res, x, y, i, d;
+
+redo:
+ if (cstart == -1){
+ if (cpuhits){
+ for(i=0, c=rnd(100); i<100; ++i, c = (c+1) % 100)
+ if(hits[turn][c] == 'H')
+ break;
+ if(i != 100){
+ cstart = c;
+ cdir = -1;
+ goto fndir;
+ }
+ }
+ do {
+ i = 0;
+ do{
+ while(hits[turn][c=rnd(100)]);
+ x = c % 10; y = c / 10;
+ if(++i == 1000) break;
+ } while(((x+huntoffs) % srchstep) != (y % srchstep));
+ if(i == 1000) --srchstep;
+ } while(i == 1000);
+ }
+ else if(cdir == -1){
+fndir: for(i=0, d=rnd(4); i++ < 4; d = (d+1) % 4){
+ x = cstart%10; y = cstart/10;
+ switch(d){
+ case 0: ++x; break;
+ case 1: ++y; break;
+ case 2: --x; break;
+ case 3: --y; break;
+ }
+ if(x<0 || x>9 || y<0 || y>9) continue;
+ if(hits[turn][c=y*10+x]) continue;
+ cdir = -2;
+ break;
+ }
+ if(i == 4){
+ cstart = -1;
+ goto redo;
+ }
+ }
+ else{
+ x = cstart%10; y = cstart/10;
+ switch(cdir){
+ case 0: ++x; break;
+ case 1: ++y; break;
+ case 2: --x; break;
+ case 3: --y; break;
+ }
+ if(x<0 || x>9 || y<0 || y>9 || hits[turn][y*10+x]){
+ cdir = (cdir+2) % 4;
+ for(;;){
+ switch(cdir){
+ case 0: ++x; break;
+ case 1: ++y; break;
+ case 2: --x; break;
+ case 3: --y; break;
+ }
+ if(x<0 || x>9 || y<0 || y>9){ cstart = -1;
+ goto redo;
+ }
+ if(!hits[turn][y*10+x]) break;
+ }
+ }
+ c = y*10 + x;
+ }
+
+ if (!ask) {
+ res = (board[OTHER][c]) ? 'H' : 'M';
+ move(21,0); clrtoeol();
+ printw("I shoot at %c%d. I %s!",c/10+'A',c%10,(res=='H')?"hit":"miss");
+ } else {
+ for(;;){
+ prompt();
+ printw("I shoot at %c%d. Do I (H)it or (M)iss? ",c/10+'A',c%10);
+ res = sgetc("HM");
+ if((res=='H' && !board[OTHER][c]) || (res=='M' && board[OTHER][c])){
+ error("You lie!");
+ continue;
+ }
+ break;
+ }
+ addch(res);
+ }
+ hits[turn][c] = res;
+ if(res == 'H') {
+ ++cpuhits;
+ if(cstart == -1) cdir = -1;
+ cstart = c;
+ if(cdir == -2) cdir = d;
+ mvaddch(7+(c/10),3+3*(c%10),'*');
+ if (blitz && !ask) {
+ refresh();
+ sleep(1);
+ }
+ }
+ else {
+ if (seemiss) {
+ mvaddch(7+(c/10),3+3*(c%10),' ');
+ } else {
+ if(cdir == -2) cdir = -1;
+ }
+ }
+ if(c=hitship(c)){
+ cstart = -1;
+ cpuhits -= plyship[c-1].length;
+ x = plyship[c-1].start;
+ d = plyship[c-1].dir;
+ y = plyship[c-1].length;
+ for(i=0; i<y; ++i){
+ hits[turn][x] = '*';
+ x += (d) ? 10 : 1;
+ }
+ }
+ if (salvo && !ask) {
+ refresh();
+ sleep(1);
+ }
+ if(awinna() != -1) return(0);
+ return(res == 'H');
+}
+
+int
+playagain()
+{
+int i, x, y, dx, dy, j;
+
+ for(i=0; i<5; ++i){
+ x = cpuship[i].start; y = x/10+7; x = (x % 10) * 3 + 48;
+ dx = (cpuship[i].dir) ? 0 : 3;
+ dy = (cpuship[i].dir) ? 1 : 0;
+ for(j=0; j < cpuship[i].length; ++j){
+ mvaddch(y,x,cpuship[i].symbol);
+ x += dx; y += dy;
+ }
+ }
+
+ if(awinna()) ++cpuwon; else ++plywon;
+ i = 18 + strlen(name);
+ if(plywon >= 10) ++i;
+ if(cpuwon >= 10) ++i;
+ mvprintw(2,(80-i)/2,"%s: %d Computer: %d",name,plywon,cpuwon);
+
+ prompt();
+ printw((awinna()) ? "Want to be humiliated again, %s? "
+ : "Going to give me a chance for revenge, %s? ",name);
+ return(sgetc("YN") == 'Y');
+}
+
+void
+uninitgame(int sig)
+{
+ refresh();
+ endwin();
+ exit(0);
+}
+
+int
+sgetc(s)
+char *s;
+{
+char *s1;
+int ch;
+
+ refresh();
+ for (;;) {
+ ch = toupper(getch());
+ for (s1 = s; *s1 && ch != *s1; ++s1);
+ if (*s1) {
+ addch(ch);
+ refresh();
+ return(ch);
+ }
+ }
+}
+
+/*
+ * I should use getopts() from libc.a, but I'm leary that other UNIX
+ * systems might not have it, although I'd love to use it.
+ */
+
+int
+do_options(c,op)
+int c;
+char *op[];
+{
+register int i;
+
+ if (c > 1) {
+ for (i=1; i<c; i++) {
+ switch(op[i][0]) {
+ default:
+ case '?':
+ fprintf(stderr, "Usage: battle [ -s | -b ] [ -a ] [ -m ]\n");
+ fprintf(stderr, "\tWhere the options are:\n");
+ fprintf(stderr, "\t-s : play a salvo game (mutex with -b)\n");
+ fprintf(stderr, "\t-b : play a blitz game (mutex with -s)\n");
+ fprintf(stderr, "\t-a : computer asks you for hit/miss\n");
+ fprintf(stderr, "\t-m : computer misses are displayed\n");
+ exit(1);
+ break;
+ case '-':
+ switch(op[i][1]) {
+ case 'b':
+ blitz = 1;
+ if (salvo == 1) {
+ fprintf(stderr,
+ "Bad Arg: -b and -s are mutually exclusive\n");
+ exit(1);
+ }
+ break;
+ case 's':
+ salvo = 1;
+ if (blitz == 1) {
+ fprintf(stderr,
+ "Bad Arg: -s and -b are mutually exclusive\n");
+ exit(1);
+ }
+ break;
+ case 'a':
+ ask = 1;
+ break;
+ case 'm':
+ seemiss = 1;
+ break;
+ default:
+ fprintf(stderr,
+ "Bad Arg: type \"%s ?\" for usage message\n", op[0]);
+ exit(1);
+ }
+ }
+ }
+ fprintf(stdout, "Playing optional game (");
+ if (salvo)
+ fprintf(stdout, "salvo, noblitz, ");
+ else if (blitz)
+ fprintf(stdout, "blitz, nosalvo, ");
+ else
+ fprintf(stdout, "noblitz, nosalvo, ");
+
+ if (ask)
+ fprintf(stdout, "ask, ");
+ else
+ fprintf(stdout, "noask, ");
+
+ if (seemiss)
+ fprintf(stdout, "seemiss)\n");
+ else
+ fprintf(stdout, "noseemiss)\n");
+ }
+ else
+ fprintf(stdout,
+ "Playing standard game (no blitz, no slavo, no ask, no seemiss)\n");
+ sleep(2);
+ return(0);
+}
+
+int
+scount(who)
+int who;
+{
+int i, shots;
+struct _ships *sp;
+
+ if (who) {
+ /* count cpu shots */
+ sp = cpuship;
+ } else {
+ /* count player shots */
+ sp = plyship;
+ }
+ for (i=0, shots = 0; i<5; i++, sp++) {
+ /* extra test for machines with unsigned chars! */
+ if (sp->hits == (char) -1 || sp->hits >= sp->length) {
+ continue; /* dead ship */
+ } else {
+ shots++;
+ }
+ }
+ return(shots);
+}
+
diff --git a/lib/libncurses/TESTS/copy.c b/lib/libncurses/TESTS/copy.c
new file mode 100644
index 0000000..013f9db
--- /dev/null
+++ b/lib/libncurses/TESTS/copy.c
@@ -0,0 +1,39 @@
+#include <ncurses.h>
+
+main()
+{
+WINDOW *win1, *win2;
+int h, i;
+
+ initscr();
+ cbreak();
+ noecho();
+ win1 = newwin(20, 50, 0, 20);
+ for (h = 0; h < 20; h++)
+ for (i = 0; i < 50; i++)
+ mvwaddch(win1, h, i, 'X');
+ wrefresh(win1);
+ getch();
+
+ win2 = newwin(20, 50, 3, 30);
+ for (h = 0; h < 20; h++)
+ for (i = 0; i < 50; i++)
+ mvwaddch(win2, h, i, 'Y');
+ wnoutrefresh(win1);
+ wnoutrefresh(win2);
+ doupdate();
+ getch();
+
+ /* now, remove window 2 and restore the contents of window 1 */
+ i = copywin(win1, win2, 5, 10, 0, 0, 14, 39, 0);
+ wnoutrefresh(win1);
+ wnoutrefresh(win2);
+ printw("copywin returns %d\n", i);
+ wnoutrefresh(stdscr);
+ doupdate();
+
+ getch();
+
+ endwin();
+}
+
diff --git a/lib/libncurses/TESTS/corner.c b/lib/libncurses/TESTS/corner.c
new file mode 100644
index 0000000..2ab38a9
--- /dev/null
+++ b/lib/libncurses/TESTS/corner.c
@@ -0,0 +1,16 @@
+#include <ncurses.h>
+
+int main()
+{
+int i, j;
+
+ initscr();
+
+ for (i = 0; i < LINES; i++) {
+ j = mvaddch(i, COLS - 1, 'A' + i);
+ }
+ refresh();
+ endwin();
+ exit(0);
+}
+
diff --git a/lib/libncurses/TESTS/ensor.c b/lib/libncurses/TESTS/ensor.c
new file mode 100644
index 0000000..4eca9cb
--- /dev/null
+++ b/lib/libncurses/TESTS/ensor.c
@@ -0,0 +1,52 @@
+#include <ncurses.h>
+
+main()
+{
+ int i;
+ WINDOW *win;
+
+ initscr();
+ noecho();
+ nonl();
+ cbreak();
+
+ scrollok(stdscr, TRUE);
+
+ for (i=0; i<25; i++)
+ printw("This is in the background, this should be left alone!\n");
+
+ refresh();
+ win=newwin(10,50,6,20);
+ scrollok(win,TRUE);
+ wmove(win,0,0);
+ whline(win,0,49);
+ wmove(win,9,0);
+ whline(win,0,49);
+ wrefresh(win);
+ wattrset(win,A_STANDOUT);
+ mvwprintw(win, 0, 14, " Scrolling Demo! ");
+ mvwprintw(win, 9, 14, " Scrolling Demo! ");
+ wattroff(win,A_STANDOUT);
+ wsetscrreg(win, 1,8);
+
+ mvwprintw(win, 0, 5, " DOWN ");
+ wmove(win,1,0);
+ wrefresh(win);
+
+ getch();
+ for (i=0; i<25; i++){ wprintw(win, "This is window line test (%d).\n", i);
+ if (i%2) wattrset(win,A_BOLD); else wattroff(win,A_BOLD);
+ wrefresh(win); }
+
+ mvwprintw(win, 0, 5, " UP ");
+ wrefresh(win);
+ getch();
+ for (i=0; i<25; i++) { wmove(win,1,0); winsertln(win);
+ if (i%2) wattrset(win,A_BOLD); else wattroff(win,A_BOLD);
+ wprintw(win, "Scrolling backwards! (%d)\n", i); wrefresh(win); }
+
+ mvwprintw(win, 0, 5, " DONE "); wrefresh(win);
+
+ endwin();
+}
+
diff --git a/lib/libncurses/TESTS/firework.c b/lib/libncurses/TESTS/firework.c
new file mode 100644
index 0000000..b497584
--- /dev/null
+++ b/lib/libncurses/TESTS/firework.c
@@ -0,0 +1,113 @@
+#include <stdio.h>
+#include <signal.h>
+#include <ncurses.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <time.h>
+
+void explode();
+
+int main()
+{
+int start,end,row,diff,flag,direction,seed;
+
+ initscr();
+ if (has_colors())
+ start_color();
+ seed = time((time_t *)0);
+ srand(seed);
+ cbreak();
+ for (;;) {
+ do {
+ start = rand() % (COLS -3);
+ end = rand() % (COLS - 3);
+ start = (start < 2) ? 2 : start;
+ end = (end < 2) ? 2 : end;
+ direction = (start > end) ? -1 : 1;
+ diff = abs(start-end);
+ } while (diff<2 || diff>=LINES-2);
+ attrset(A_NORMAL);
+ for (row=0;row<diff;row++) {
+ mvprintw(LINES - row,start + (row * direction),
+ (direction < 0) ? "\\" : "/");
+ if (flag++) {
+ refresh();
+ erase();
+ flag = 0;
+ }
+ }
+ if (flag++) {
+ refresh();
+ flag = 0;
+ }
+ seed = time((time_t *)0);
+ srand(seed);
+ explode(LINES-row,start+(diff*direction));
+ erase();
+ refresh();
+ }
+ endwin();
+ exit(0);
+}
+
+void explode(int row, int col)
+{
+ erase();
+ mvprintw(row,col,"-");
+ refresh();
+
+ init_pair(1,get_colour(),COLOR_BLACK);
+ attrset(COLOR_PAIR(1));
+ mvprintw(row-1,col-1," - ");
+ mvprintw(row,col-1,"-+-");
+ mvprintw(row+1,col-1," - ");
+ refresh();
+
+ init_pair(1,get_colour(),COLOR_BLACK);
+ attrset(COLOR_PAIR(1));
+ mvprintw(row-2,col-2," --- ");
+ mvprintw(row-1,col-2,"-+++-");
+ mvprintw(row, col-2,"-+#+-");
+ mvprintw(row+1,col-2,"-+++-");
+ mvprintw(row+2,col-2," --- ");
+ refresh();
+
+ init_pair(1,get_colour(),COLOR_BLACK);
+ attrset(COLOR_PAIR(1));
+ mvprintw(row-2,col-2," +++ ");
+ mvprintw(row-1,col-2,"++#++");
+ mvprintw(row, col-2,"+# #+");
+ mvprintw(row+1,col-2,"++#++");
+ mvprintw(row+2,col-2," +++ ");
+ refresh();
+
+ init_pair(1,get_colour(),COLOR_BLACK);
+ attrset(COLOR_PAIR(1));
+ mvprintw(row-2,col-2," # ");
+ mvprintw(row-1,col-2,"## ##");
+ mvprintw(row, col-2,"# #");
+ mvprintw(row+1,col-2,"## ##");
+ mvprintw(row+2,col-2," # ");
+ refresh();
+
+ init_pair(1,get_colour(),COLOR_BLACK);
+ attrset(COLOR_PAIR(1));
+ mvprintw(row-2,col-2," # # ");
+ mvprintw(row-1,col-2,"# #");
+ mvprintw(row, col-2," ");
+ mvprintw(row+1,col-2,"# #");
+ mvprintw(row+2,col-2," # # ");
+ refresh();
+ return;
+}
+
+int get_colour()
+{
+ int attr;
+ attr = (rand() % 16)+1;
+ if (attr == 1 || attr == 9)
+ attr = COLOR_RED;
+ if (attr > 8)
+ attr |= A_BOLD;
+ return(attr);
+}
diff --git a/lib/libncurses/TESTS/getch.c b/lib/libncurses/TESTS/getch.c
new file mode 100644
index 0000000..90a0ee4
--- /dev/null
+++ b/lib/libncurses/TESTS/getch.c
@@ -0,0 +1,29 @@
+#include <ncurses.h>
+
+main()
+ {
+ int c,i;
+ initscr();
+ cbreak();
+ noecho();
+#if 1
+ wtimeout(stdscr,1000);
+#endif
+ scrollok(stdscr,TRUE);
+ for (c='A';c<='Z';c++)
+ for (i=0;i<25;i++)
+ {
+ move(i,i);
+ addch(c);
+ refresh();
+ }
+ move (0,0);
+ while ((c=wgetch(stdscr))!='A')
+ {
+ if (c == EOF) printw(">>wait for keypress<<");
+ else printw(">>%c<<\n",c);
+ refresh();
+ }
+ endwin();
+ }
+
diff --git a/lib/libncurses/TESTS/hanoi.c b/lib/libncurses/TESTS/hanoi.c
new file mode 100644
index 0000000..8a482d5
--- /dev/null
+++ b/lib/libncurses/TESTS/hanoi.c
@@ -0,0 +1,275 @@
+/*
+ * Name: Towers of Hanoi.
+ *
+ * Desc:
+ * This is a playable copy of towers of hanoi.
+ * Its sole purpose is to demonstrate my Amiga Curses package.
+ * This program should compile on any system that has Curses.
+ * 'hanoi' will give a manual game with 7 playing pieces.
+ * 'hanoi n' will give a manual game with n playing pieces.
+ * 'hanoi n a' will give an auto solved game with n playing pieces.
+ *
+ * Author: Simon J Raybould (sie@fulcrum.bt.co.uk).
+ *
+ * Date: 05.Nov.90
+ *
+ */
+
+#include <ncurses.h>
+
+#define NPEGS 3 /* This is not configurable !! */
+#define MINTILES 3
+#define MAXTILES 9
+#define DEFAULTTILES 7
+#define TOPLINE 6
+#define BASELINE 16
+#define STATUSLINE (LINES-3)
+#define LEFTPEG 19
+#define MIDPEG 39
+#define RIGHTPEG 59
+
+#define LENTOIND(x) (((x)-1)/2)
+#define OTHER(a,b) (3-((a)+(b)))
+
+struct Peg {
+ int Length[MAXTILES];
+ int Count;
+};
+
+struct Peg Pegs[NPEGS];
+int PegPos[] = { LEFTPEG, MIDPEG, RIGHTPEG };
+int TileColour[] = {
+ COLOR_GREEN, /* Length 3 */
+ COLOR_MAGENTA, /* Length 5 */
+ COLOR_RED, /* Length 7 */
+ COLOR_BLUE, /* Length 9 */
+ COLOR_CYAN, /* Length 11 */
+ COLOR_YELLOW, /* Length 13 */
+ COLOR_GREEN, /* Length 15 */
+ COLOR_MAGENTA, /* Length 17 */
+ COLOR_RED, /* Length 19 */
+};
+int NMoves = 0;
+
+static unsigned char AutoFlag;
+
+void InitTiles(), DisplayTiles(), MakeMove(), AutoMove(), Usage();
+
+int
+main(int argc, char **argv)
+{
+int NTiles, FromCol, ToCol;
+
+ switch(argc) {
+ case 1:
+ NTiles = DEFAULTTILES;
+ break;
+ case 2:
+ NTiles = atoi(argv[1]);
+ if (NTiles > MAXTILES || NTiles < MINTILES) {
+ fprintf(stderr, "Range %d to %d\n", MINTILES, MAXTILES);
+ exit(1);
+ }
+ break;
+ case 3:
+ if (strcmp(argv[2], "a")) {
+ Usage();
+ exit(1);
+ }
+ NTiles = atoi(argv[1]);
+ if (NTiles > MAXTILES || NTiles < MINTILES) {
+ fprintf(stderr, "Range %d to %d\n", MINTILES, MAXTILES);
+ exit(1);
+ }
+ AutoFlag = TRUE;
+ break;
+ default:
+ Usage();
+ exit(1);
+ }
+ initscr();
+ if (!has_colors()) {
+ puts("terminal doesn't support color.");
+ exit(1);
+ }
+ start_color();
+ {
+ int i;
+ for (i = 0; i < 9; i++)
+ init_pair(i+1, COLOR_BLACK, TileColour[i]);
+ }
+ cbreak();
+ if (LINES < 24) {
+ fprintf(stderr, "Min screen length 24 lines\n");
+ endwin();
+ exit(1);
+ }
+ if(AutoFlag)
+ leaveok(stdscr, TRUE); /* Attempt to remove cursor */
+ InitTiles(NTiles);
+ DisplayTiles();
+ if(AutoFlag) {
+ do {
+ noecho();
+ AutoMove(0, 2, NTiles);
+ } while(!Solved(NTiles));
+ sleep(2);
+ } else {
+ for(;;) {
+ if(GetMove(&FromCol, &ToCol))
+ break;
+ if (AutoFlag) {
+ AutoMove(0, 2, NTiles);
+ break;
+ }
+ if(InvalidMove(FromCol, ToCol)) {
+ mvaddstr(STATUSLINE, 0, "Invalid Move !!");
+ refresh();
+ beep();
+ continue;
+ }
+ MakeMove(FromCol, ToCol);
+ if(Solved(NTiles)) {
+ mvprintw(STATUSLINE, 0, "Well Done !! You did it in %d moves", NMoves);
+ refresh();
+ sleep(5);
+ break;
+ }
+ }
+ }
+ endwin();
+}
+
+int
+InvalidMove(int From, int To)
+{
+ if(From == To)
+ return TRUE;
+ if(!Pegs[From].Count)
+ return TRUE;
+ if(Pegs[To].Count &&
+ Pegs[From].Length[Pegs[From].Count-1] >
+ Pegs[To].Length[Pegs[To].Count-1])
+ return TRUE;
+ return FALSE;
+}
+
+void
+InitTiles(int NTiles)
+{
+int Size, SlotNo;
+
+ for(Size=NTiles*2+1, SlotNo=0; Size>=3; Size-=2)
+ Pegs[0].Length[SlotNo++] = Size;
+
+ Pegs[0].Count = NTiles;
+ Pegs[1].Count = 0;
+ Pegs[2].Count = 0;
+}
+
+#define gc() {noecho();getch();echo();}
+
+void
+DisplayTiles()
+{
+ int Line, Peg, SlotNo;
+ char TileBuf[BUFSIZ];
+
+ erase();
+ mvaddstr(1, 24, "T O W E R S O F H A N O I");
+ mvaddstr(3, 34, "SJR 1990");
+ mvprintw(19, 5, "Moves : %d", NMoves);
+ standout();
+ mvaddstr(BASELINE, 8, " ");
+
+ for(Line=TOPLINE; Line<BASELINE; Line++) {
+ mvaddch(Line, LEFTPEG, ' ');
+ mvaddch(Line, MIDPEG, ' ');
+ mvaddch(Line, RIGHTPEG, ' ');
+ }
+ mvaddch(BASELINE, LEFTPEG, '1');
+ mvaddch(BASELINE, MIDPEG, '2');
+ mvaddch(BASELINE, RIGHTPEG, '3');
+ standend();
+
+ /* Draw tiles */
+ for(Peg=0; Peg<NPEGS; Peg++) {
+ for(SlotNo=0; SlotNo<Pegs[Peg].Count; SlotNo++) {
+ memset(TileBuf, ' ', Pegs[Peg].Length[SlotNo]);
+ TileBuf[Pegs[Peg].Length[SlotNo]] = '\0';
+ attrset(COLOR_PAIR(LENTOIND(Pegs[Peg].Length[SlotNo])));
+ mvaddstr(BASELINE-(SlotNo+1),
+ PegPos[Peg]-Pegs[Peg].Length[SlotNo]/2, TileBuf);
+ }
+ }
+ attrset(A_NORMAL);
+ refresh();
+}
+
+int
+GetMove(int *From, int *To)
+{
+ mvaddstr(STATUSLINE, 0, "Next move ('q' to quit) from ");
+ clrtoeol();
+ refresh();
+ if((*From = getch()) == 'q')
+ return TRUE;
+ else if (*From == 'a') {
+ AutoFlag = TRUE;
+ return FALSE;
+ }
+ *From -= ('0'+1);
+ addstr(" to ");
+ clrtoeol();
+ refresh();
+ if((*To = getch()) == 'q')
+ return TRUE;
+ *To -= ('0'+1);
+ move(STATUSLINE, 0);
+ clrtoeol();
+ refresh();
+ return FALSE;
+}
+
+void
+MakeMove(int From, int To)
+{
+
+ Pegs[From].Count--;
+ Pegs[To].Length[Pegs[To].Count] = Pegs[From].Length[Pegs[From].Count];
+ Pegs[To].Count++;
+ NMoves++;
+ DisplayTiles();
+}
+
+void
+AutoMove(int From, int To, int Num)
+{
+
+ if(Num == 1) {
+ MakeMove(From, To);
+ return;
+ }
+ AutoMove(From, OTHER(From, To), Num-1);
+ MakeMove(From, To);
+ AutoMove(OTHER(From, To), To, Num-1);
+}
+
+int
+Solved(int NumTiles)
+{
+int i;
+
+ for(i = 1; i < NPEGS; i++)
+ if (Pegs[i].Count == NumTiles)
+ return TRUE;
+ return FALSE;
+}
+
+void
+Usage()
+{
+ fprintf(stderr, "Usage: hanoi [<No Of Tiles>] [a]\n");
+ fprintf(stderr, "The 'a' option causes the tower to be solved automatically\n");
+}
+
diff --git a/lib/libncurses/TESTS/knight.c b/lib/libncurses/TESTS/knight.c
new file mode 100644
index 0000000..73f7b42
--- /dev/null
+++ b/lib/libncurses/TESTS/knight.c
@@ -0,0 +1,320 @@
+/* Knights Tour - a brain game */
+
+#include <ncurses.h>
+#include <signal.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#ifdef __FreeBSD__
+#define srand48 srandom
+#define lrand48 random
+#endif
+
+short board [64]; /* the squares */
+char row, column; /* input characters */
+int rw,col; /* numeric equivalent of row and column */
+int curow,curcol; /* current row and column integers */
+int rdif, cdif; /* difference between input and current */
+int j; /* index into board */
+
+char script[]={"'_)//,/(-)/__/__(_<_(__),|/|/_///_/_<//_/_)__o__o'______///_(--_(_)___,(_/,_/__(_\0"};
+
+int ypos[] ={1,0,1,2,3,0,1,2,2,3,3,2,2,3,2,2,3,3,3,3,3,2,3,3,2,4,5,5,
+ 4,3,3,2,1,2,3,3,3,2,1,3,3,2,3,3,3,2,1,1,0,1,4,4,4,4,4,4,5,6,7,7,
+ 7,6,6,6,7,7,7,6,6,6,6,7,7,7,6,7,7,6,6,7,7};
+
+int xpos[]={0,1,2,1,0,5,4,3,2,4,6,7,8,8,9,10,10,11,12,13,14,15,15,16,
+ 16,16,15,14,15,17,18,19,20,20,20,21,22,23,24,23,25,26,27,26,28,
+ 13,23,25,27,27,2,3,4,5,6,7,4,3,2,1,0,1,2,5,4,5,6,6,7,8,9,8,9,10,
+ 11,11,12,13,14,14,15};
+
+static char *instructions[] =
+{
+" Knight's Tour is a board game for one player. It is played on",
+"an eight by eight board and is based on the allowable moves that a knight",
+"can make in the game of chess. For those who are unfamiliar with the",
+"game, a knight may move either on a row or a column but not diagonally.",
+"He may move one square in any direction and two squares in a perpendicular",
+"direction >or< two squares in any direction and one square in a",
+"perpendicular direction. He may not, of course, move off the board.",
+"",
+" At the beginning of a game you will be asked to either choose a",
+"starting square or allow the computer to select a random location.",
+"Squares are designated by a letter-number combination where the row is",
+"specified by a letter A-H and the numbers 1-8 define a column. Invalid",
+"entries are ignored and illegal moves produce a beep at the terminal.",
+"",
+" The objective is to visit every square on the board. When you claim",
+"a square a marker is placed on it to show where you've been. You may",
+"not revisit a square that you've landed on before.",
+"",
+" After each move the program checks to see if you have any legal",
+"moves left. If not, the game ends and your squares are counted. If",
+"you've made all the squares you win the game. Otherwise, you are told",
+"the number of squares you did make.",
+"END"
+};
+
+void init(void);
+int play(void);
+void drawboard(void);
+void dosquares(void);
+void getfirst(void);
+void getrc(void);
+void putstars(void);
+int evalmove(void);
+int chkmoves(void);
+int endgame(void);
+int chksqr(int, int);
+void instruct(void);
+void title(int, int);
+
+int
+main ()
+{
+ init ();
+ for (;;)
+ if (!play ()) {
+ endwin ();
+ exit (0);
+ }
+}
+
+void
+init ()
+{
+
+ srand48 (getpid());
+ initscr ();
+ cbreak (); /* immediate char return */
+ noecho (); /* no immediate echo */
+ title (1,23);
+ mvaddstr (23, 25, "Would you like instructions? ");
+ refresh();
+ if ((toupper(getch())) == 'Y')
+ instruct();
+ clear ();
+}
+
+int
+play ()
+{
+ drawboard (); /* clear screen and drawboard */
+ for (j = 0; j < 64; j++) board[j]=0;
+ getfirst (); /* get the starting square */
+ for (;;) {
+ getrc();
+ if (evalmove()) {
+ putstars ();
+ if (!chkmoves())
+ return (endgame ());
+ }
+ else beep();
+ }
+}
+
+void
+drawboard ()
+{
+ erase ();
+ dosquares ();
+ refresh ();
+ mvaddstr (0, 7, "1 2 3 4 5 6 7 8");
+ for (j = 0; j < 8; j++) mvaddch (2*j+2, 3, j + 'A');
+ refresh ();
+ mvaddstr (20, 5, "ROW:");
+ mvaddstr (20, 27, "COLUMN:");
+ mvaddstr (14, 49, "CURRENT ROW");
+ mvaddstr (16, 49, "CURRENT COL");
+ mvaddstr (22, 5, "A - H or Q to quit");
+ mvaddstr (22, 27, "1 - 8 or ESC to cancel row");
+ refresh ();
+ title (1,40);
+}
+
+void
+dosquares ()
+{
+ mvaddstr (1, 6, "-------------------------------");
+ for (j = 1; j < 9; j++){
+ mvaddstr (2*j, 5, "| | | | | | | | |");
+ mvaddstr (2*j+1, 6, "-------------------------------");
+ }
+}
+
+void
+getfirst () /* get first square */
+{
+ mvaddstr (23, 25, "(S)elect or (R)andom "); refresh ();
+ do {
+ row = toupper(getch());
+ } while ((row != 'S') && (row != 'R'));
+ if (row == 'R') {
+ rw = lrand48() % 8;
+ col = lrand48() % 8;
+ j = 8* rw + col;
+ row = rw + 'A';
+ column = col + '1';
+ }
+ else {
+ mvaddstr (23, 25, "Enter starting row and column");
+ refresh ();
+ getrc(); /* get row and column */
+ }
+ putstars ();
+ move (23, 0);
+ clrtobot();
+}
+
+void
+getrc () /* get row and column */
+{
+ noecho ();
+ do {
+ mvaddstr (20, 35, " ");
+ refresh ();
+ do {
+ mvaddch (20, 11, ' ');
+ move (20, 11);
+ refresh ();
+ row=toupper(getch());
+ if (row == 'Q') {
+ endwin ();
+ exit (1);
+ }
+ } while ((row < 'A') || (row > 'H'));
+ addch (row);
+ move (20, 35);
+ refresh ();
+ do {
+ column=getch();
+ if (column == '\033') break;
+ } while ((column < '1') || (column > '8'));
+ if (column != '\033') addch (column);
+ } while (column == '\033');
+ refresh();
+ rw = row - 'A';
+ col= column - '1';
+ j = 8 * rw + col;
+}
+
+void
+putstars () /* place the stars, update board & currents */
+{
+ mvaddch (2*curow+2, 38, ' ');
+ mvaddch (2*rw+2, 38, '<');
+ mvaddch (18, curcol*4+7, ' ');
+ mvaddch (18, col*4+7, '^');
+ curow = rw;
+ curcol= col;
+ mvaddstr (2 * rw + 2, 4*col+6, "***");
+ mvaddch (14, 61, row);
+ mvaddch (16, 61, column);
+ refresh ();
+ board[j] = 1;
+}
+
+int
+evalmove() /* convert row and column to integers */
+ /* and evaluate move */
+{
+ rdif = rw - curow;
+ cdif = col - curcol;
+ rdif = abs(rw - curow);
+ cdif = abs(col - curcol);
+ refresh ();
+ if ((rdif == 1) && (cdif == 2)) if (board [j] == 0) return (1);
+ if ((rdif == 2) && (cdif == 1)) if (board [j] == 0) return (1);
+ return (0);
+}
+
+int
+chkmoves () /* check to see if valid moves are available */
+{
+ if (chksqr(2,1)) return (1);
+ if (chksqr(2,-1)) return (1);
+ if (chksqr(-2,1)) return (1);
+ if (chksqr(-2,-1)) return (1);
+ if (chksqr(1,2)) return (1);
+ if (chksqr(1,-2)) return (1);
+ if (chksqr(-1,2)) return (1);
+ if (chksqr(-1,-2)) return (1);
+ return (0);
+}
+
+int
+endgame () /* check for filled board or not */
+{
+ rw = 0;
+ for (j = 0; j < 64; j++) if (board[j] != 0) rw+=1;
+ if (rw == 64) mvaddstr (20, 20, "Congratulations !! You got 'em all");
+ else mvprintw (20, 20, "You have ended up with %2d squares",rw);
+ mvaddstr (21, 25, "Play again ? (y/n) ");
+ refresh ();
+ if ((row=tolower(getch())) == 'y') return (1);
+ else return (0);
+}
+
+#ifndef abs
+abs(num)
+int num;
+{
+ if (num < 0) return (-num);
+ else return (num);
+}
+#endif
+
+int
+chksqr (int n1, int n2)
+{
+int r1, c1;
+
+ r1 = rw + n1;
+ c1 = col + n2;
+ if ((r1<0) || (r1>7)) return (0);
+ if ((c1<0) || (c1>7)) return (0);
+ if (board[r1*8+c1] == 0) return (1);
+ else return (0);
+}
+
+void
+instruct()
+{
+int i;
+
+ clear ();
+ for (i=0;;i++) {
+ if ((strcmp(instructions[i],"END"))) mvaddstr (i, 0, instructions[i]);
+ else {
+ mvaddstr (23, 25, "Ready to play ? (y/n) ");
+ refresh();
+ if (toupper(getch()) == 'Y') {
+ clear ();
+ return;
+ } else {
+ clear ();
+ refresh ();
+ endwin ();
+ exit (0);
+ }
+ }
+ }
+}
+
+void
+title (y,x)
+int y,x;
+{
+char c;
+
+ j = 0;
+ do {
+ c = script[j];
+ if (c == 0) break ;
+ mvaddch (ypos[j]+y, xpos[j]+x, c);
+ j++;
+ } while (c != 0);
+ refresh ();
+}
+
+
diff --git a/lib/libncurses/TESTS/ncurses.c b/lib/libncurses/TESTS/ncurses.c
new file mode 100644
index 0000000..9151236
--- /dev/null
+++ b/lib/libncurses/TESTS/ncurses.c
@@ -0,0 +1,1121 @@
+/****************************************************************************
+
+NAME
+ ncurses.c --- ncurses library exerciser
+
+SYNOPSIS
+ ncurses
+
+DESCRIPTION
+ An interactive test module for the ncurses library.
+
+AUTHOR
+ This software is Copyright (C) 1993 by Eric S. Raymond, all rights reserved.
+It is issued with ncurses under the same terms and conditions as the ncurses
+library source.
+
+***************************************************************************/
+/*LINTLIBRARY */
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <ncurses.h>
+
+#define P(s) printw("%s\n", s)
+#ifndef CTRL
+#define CTRL(x) ((x) & 0x1f)
+#endif
+
+/****************************************************************************
+ *
+ * Character input test
+ *
+ ****************************************************************************/
+
+static void getch_test(void)
+/* test the keypad feature */
+{
+char buf[BUFSIZ];
+unsigned int c;
+int incount = 0, firsttime = 0;
+bool blocking = TRUE;
+
+ refresh();
+
+ (void) printw("Delay in 10ths of a second (<CR> for blocking input)? ");
+ echo();
+ getstr(buf);
+ noecho();
+
+ if (isdigit(buf[0]))
+ {
+ timeout(atoi(buf) * 100);
+ blocking = FALSE;
+ }
+
+ c = '?';
+ for (;;)
+ {
+ if (firsttime++)
+ {
+ printw("Key pressed: %04o ", c);
+ if (c >= KEY_MIN)
+ {
+ (void) addstr(keyname(c));
+ addch('\n');
+ }
+ else if (c > 0x80)
+ {
+ if (isprint(c & ~0x80))
+ (void) printw("M-%c", c);
+ else
+ (void) printw("M-%s", unctrl(c));
+ addstr(" (high-half character)\n");
+ }
+ else
+ {
+ if (isprint(c))
+ (void) printw("%c (ASCII printable character)\n", c);
+ else
+ (void) printw("%s (ASCII control character)\n", unctrl(c));
+ }
+ }
+ if (c == 'x' || c == 'q')
+ break;
+ if (c == '?')
+ addstr("Type any key to see its keypad value, `q' to quit, `?' for help.\n");
+
+ while ((c = getch()) == ERR)
+ if (!blocking)
+ (void) printw("%05d: input timed out\n", incount++);
+ }
+
+ timeout(-1);
+ erase();
+ endwin();
+}
+
+static void attr_test(void)
+/* test text attributes */
+{
+ refresh();
+
+ mvaddstr(0, 20, "Character attribute test display");
+
+ mvaddstr(2,8,"This is STANDOUT mode: ");
+ attron(A_STANDOUT);
+ addstr("abcde fghij klmno pqrst uvwxy x");
+ attroff(A_STANDOUT);
+
+ mvaddstr(4,8,"This is REVERSE mode: ");
+ attron(A_REVERSE);
+ addstr("abcde fghij klmno pqrst uvwxy x");
+ attroff(A_REVERSE);
+
+ mvaddstr(6,8,"This is BOLD mode: ");
+ attron(A_BOLD);
+ addstr("abcde fghij klmno pqrst uvwxy x");
+ attroff(A_BOLD);
+
+ mvaddstr(8,8,"This is UNDERLINE mode: ");
+ attron(A_UNDERLINE);
+ addstr("abcde fghij klmno pqrst uvwxy x");
+ attroff(A_UNDERLINE);
+
+ mvaddstr(10,8,"This is DIM mode: ");
+ attron(A_DIM);
+ addstr("abcde fghij klmno pqrst uvwxy x");
+ attroff(A_DIM);
+
+ mvaddstr(12,8,"This is BLINK mode: ");
+ attron(A_BLINK);
+ addstr("abcde fghij klmno pqrst uvwxy x");
+ attroff(A_BLINK);
+
+ mvaddstr(14,8,"This is BOLD UNDERLINE BLINK mode: ");
+ attron(A_BOLD|A_BLINK|A_UNDERLINE);
+ addstr("abcde fghij klmno pqrst uvwxy x");
+ attroff(A_BOLD|A_BLINK|A_UNDERLINE);
+
+ attrset(A_NORMAL);
+ mvaddstr(16,8,"This is NORMAL mode: ");
+ addstr("abcde fghij klmno pqrst uvwxy x");
+
+ refresh();
+
+ move(LINES - 1, 0);
+ addstr("Press any key to continue... ");
+ (void) getch();
+
+ erase();
+ endwin();
+}
+
+/****************************************************************************
+ *
+ * Color support tests
+ *
+ ****************************************************************************/
+
+static char *colors[] =
+{
+ "black",
+ "red",
+ "green",
+ "yellow",
+ "blue",
+ "magenta",
+ "cyan",
+ "white"
+};
+
+static void color_test(void)
+/* generate a color test pattern */
+{
+ int i;
+
+ refresh();
+ (void) printw("There are %d color pairs\n", COLOR_PAIRS);
+
+ (void) mvprintw(1, 0,
+ "%dx%d matrix of foreground/background colors, bright *off*\n",
+ COLORS, COLORS);
+ for (i = 0; i < COLORS; i++)
+ mvaddstr(2, (i+1) * 8, colors[i]);
+ for (i = 0; i < COLORS; i++)
+ mvaddstr(3 + i, 0, colors[i]);
+ for (i = 1; i < COLOR_PAIRS; i++)
+ {
+ init_pair(i, i % COLORS, i / COLORS);
+ attron(COLOR_PAIR(i));
+ mvaddstr(3 + (i / COLORS), (i % COLORS + 1) * 8, "Hello");
+ attrset(A_NORMAL);
+ }
+
+ (void) mvprintw(COLORS + 4, 0,
+ "%dx%d matrix of foreground/background colors, bright *on*\n",
+ COLORS, COLORS);
+ for (i = 0; i < COLORS; i++)
+ mvaddstr(5 + COLORS, (i+1) * 8, colors[i]);
+ for (i = 0; i < COLORS; i++)
+ mvaddstr(6 + COLORS + i, 0, colors[i]);
+ for (i = 1; i < COLOR_PAIRS; i++)
+ {
+ init_pair(i, i % COLORS, i / COLORS);
+ attron(COLOR_PAIR(i) | A_BOLD);
+ mvaddstr(6 + COLORS + (i / COLORS), (i % COLORS + 1) * 8, "Hello");
+ attrset(A_NORMAL);
+ }
+
+ move(LINES - 1, 0);
+ addstr("Press any key to continue... ");
+ (void) getch();
+
+ erase();
+ endwin();
+}
+
+static void color_edit(void)
+/* display the color test pattern, without trying to edit colors */
+{
+ int i, c, value = 0, current = 0, field = 0, usebase = 0;
+
+ refresh();
+
+ for (i = 0; i < COLORS; i++)
+ init_pair(i, COLOR_WHITE, i);
+
+ do {
+ short red, green, blue;
+
+ attron(A_BOLD);
+ mvaddstr(0, 20, "Color RGB Value Editing");
+ attroff(A_BOLD);
+
+ for (i = 0; i < COLORS; i++)
+ {
+ mvprintw(2 + i, 0, "%c %-8s:",
+ (i == current ? '>' : ' '),
+ (i < sizeof(colors)/sizeof(colors[0]) ? colors[i] : ""));
+ attrset(COLOR_PAIR(i));
+ addstr(" ");
+ attrset(A_NORMAL);
+
+ /*
+ * Note: this refresh should *not* be necessary! It works around
+ * a bug in attribute handling that apparently causes the A_NORMAL
+ * attribute sets to interfere with the actual emission of the
+ * color setting somehow. This needs to be fixed.
+ */
+ refresh();
+
+ color_content(i, &red, &green, &blue);
+ addstr(" R = ");
+ if (current == i && field == 0) attron(A_STANDOUT);
+ printw("%04d", red);
+ if (current == i && field == 0) attrset(A_NORMAL);
+ addstr(", G = ");
+ if (current == i && field == 1) attron(A_STANDOUT);
+ printw("%04d", green);
+ if (current == i && field == 1) attrset(A_NORMAL);
+ addstr(", B = ");
+ if (current == i && field == 2) attron(A_STANDOUT);
+ printw("%04d", blue);
+ if (current == i && field == 2) attrset(A_NORMAL);
+ attrset(A_NORMAL);
+ addstr(")");
+ }
+
+ mvaddstr(COLORS + 3, 0,
+ "Use up/down to select a color, left/right to change fields.");
+ mvaddstr(COLORS + 4, 0,
+ "Modify field by typing nnn=, nnn-, or nnn+. ? for help.");
+
+ move(2 + current, 0);
+
+ switch (c = getch())
+ {
+ case KEY_UP:
+ current = (current == 0 ? (COLORS - 1) : current - 1);
+ value = 0;
+ break;
+
+ case KEY_DOWN:
+ current = (current == (COLORS - 1) ? 0 : current + 1);
+ value = 0;
+ break;
+
+ case KEY_RIGHT:
+ field = (field == 2 ? 0 : field + 1);
+ value = 0;
+ break;
+
+ case KEY_LEFT:
+ field = (field == 0 ? 2 : field - 1);
+ value = 0;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ do {
+ value = value * 10 + (c - '0');
+ c = getch();
+ } while
+ (isdigit(c));
+ if (c != '+' && c != '-' && c != '=')
+ beep();
+ else
+ ungetch(c);
+ break;
+
+ case '+':
+ usebase = 1;
+ goto changeit;
+
+ case '-':
+ value = -value;
+ usebase = 1;
+ goto changeit;
+
+ case '=':
+ usebase = 0;
+ changeit:
+ color_content(current, &red, &green, &blue);
+ if (field == 0)
+ red = red * usebase + value;
+ else if (field == 1)
+ green = green * usebase + value;
+ else if (field == 2)
+ blue = blue * usebase + value;
+ init_color(current, red, green, blue);
+ break;
+
+ case '?':
+ erase();
+ P(" RGB Value Editing Help");
+ P("");
+ P("You are in the RGB value editor. Use the arrow keys to select one of");
+ P("the fields in one of the RGB triples of the current colors; the one");
+ P("currently selected will be reverse-video highlighted.");
+ P("");
+ P("To change a field, enter the digits of the new value; they won't be");
+ P("echoed. Finish by typing `='; the change will take effect instantly.");
+ P("To increment or decrement a value, use the same procedure, but finish");
+ P("with a `+' or `-'.");
+ P("");
+ P("To quit, do `x' or 'q'");
+
+ move(LINES - 1, 0);
+ addstr("Press any key to continue... ");
+ (void) getch();
+ erase();
+ break;
+
+ case 'x':
+ case 'q':
+ break;
+
+ default:
+ beep();
+ break;
+ }
+ } while
+ (c != 'x' && c != 'q');
+
+ erase();
+ endwin();
+}
+
+/****************************************************************************
+ *
+ * Soft-key label test
+ *
+ ****************************************************************************/
+
+static void slk_test(void)
+/* exercise the soft keys */
+{
+ int c, fmt = 1;
+ char buf[9];
+
+ c = CTRL('l');
+ do {
+ switch(c)
+ {
+ case CTRL('l'):
+ erase();
+ attron(A_BOLD);
+ mvaddstr(0, 20, "Soft Key Exerciser");
+ attroff(A_BOLD);
+
+ move(2, 0);
+ P("Available commands are:");
+ P("");
+ P("^L -- refresh screen");
+ P("a -- activate or restore soft keys");
+ P("d -- disable soft keys");
+ P("c -- set centered format for labels");
+ P("l -- set left-justified format for labels");
+ P("r -- set right-justified format for labels");
+ P("[12345678] -- set label; labels are numbered 1 through 8");
+ P("e -- erase stdscr (should not erase labels)");
+ P("s -- test scrolling of shortened screen");
+ P("x, q -- return to main menu");
+ P("");
+ P("Note: if activating the soft keys causes your terminal to");
+ P("scroll up one line, your terminal auto-scrolls when anything");
+ P("is written to the last screen position. The ncurses code");
+ P("does not yet handle this gracefully.");
+ refresh();
+ /* fall through */
+
+ case 'a':
+ slk_restore();
+ break;
+
+ case 'e':
+ wclear(stdscr);
+ break;
+
+ case 's':
+ move(20, 0);
+ while ((c = getch()) != 'Q')
+ addch(c);
+ break;
+
+ case 'd':
+ slk_clear();
+ break;
+
+ case 'l':
+ fmt = 0;
+ break;
+
+ case 'c':
+ fmt = 1;
+ break;
+
+ case 'r':
+ fmt = 2;
+ break;
+
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8':
+ (void) mvaddstr(20, 0, "Please enter the label value: ");
+ wgetnstr(stdscr, buf, 8);
+ slk_set((c - '0'), buf, fmt);
+ slk_refresh();
+ break;
+
+ case 'x':
+ case 'q':
+ goto done;
+
+ default:
+ beep();
+ }
+ } while
+ ((c = getch()) != EOF);
+
+ done:
+ erase();
+ endwin();
+}
+
+/****************************************************************************
+ *
+ * Alternate character-set stuff
+ *
+ ****************************************************************************/
+
+static void acs_display()
+/* display the ACS character set */
+{
+ int i, j;
+
+ erase();
+ attron(A_BOLD);
+ mvaddstr(0, 20, "Display of the ACS Character Set");
+ attroff(A_BOLD);
+ refresh();
+
+#define ACSY 2
+ mvaddstr(ACSY + 0, 0, "ACS_ULCORNER: "); addch(ACS_ULCORNER);
+ mvaddstr(ACSY + 1, 0, "ACS_LLCORNER: "); addch(ACS_LLCORNER);
+ mvaddstr(ACSY + 2, 0, "ACS_URCORNER: "); addch(ACS_URCORNER);
+ mvaddstr(ACSY + 3, 0, "ACS_LRCORNER: "); addch(ACS_LRCORNER);
+ mvaddstr(ACSY + 4, 0, "ACS_RTEE: "); addch(ACS_RTEE);
+ mvaddstr(ACSY + 5, 0, "ACS_LTEE: "); addch(ACS_LTEE);
+ mvaddstr(ACSY + 6, 0, "ACS_BTEE: "); addch(ACS_BTEE);
+ mvaddstr(ACSY + 7, 0, "ACS_TTEE: "); addch(ACS_TTEE);
+ mvaddstr(ACSY + 8, 0, "ACS_HLINE: "); addch(ACS_HLINE);
+ mvaddstr(ACSY + 9, 0, "ACS_VLINE: "); addch(ACS_VLINE);
+ mvaddstr(ACSY + 10,0, "ACS_PLUS: "); addch(ACS_PLUS);
+ mvaddstr(ACSY + 11,0, "ACS_S1: "); addch(ACS_S1);
+ mvaddstr(ACSY + 12,0, "ACS_S9: "); addch(ACS_S9);
+
+ mvaddstr(ACSY + 0, 40, "ACS_DIAMOND: "); addch(ACS_DIAMOND);
+ mvaddstr(ACSY + 1, 40, "ACS_CKBOARD: "); addch(ACS_CKBOARD);
+ mvaddstr(ACSY + 2, 40, "ACS_DEGREE: "); addch(ACS_DEGREE);
+ mvaddstr(ACSY + 3, 40, "ACS_PLMINUS: "); addch(ACS_PLMINUS);
+ mvaddstr(ACSY + 4, 40, "ACS_BULLET: "); addch(ACS_BULLET);
+ mvaddstr(ACSY + 5, 40, "ACS_LARROW: "); addch(ACS_LARROW);
+ mvaddstr(ACSY + 6, 40, "ACS_RARROW: "); addch(ACS_RARROW);
+ mvaddstr(ACSY + 7, 40, "ACS_DARROW: "); addch(ACS_DARROW);
+ mvaddstr(ACSY + 8, 40, "ACS_UARROW: "); addch(ACS_UARROW);
+ mvaddstr(ACSY + 9, 40, "ACS_BOARD: "); addch(ACS_BOARD);
+ mvaddstr(ACSY + 10,40, "ACS_LANTERN: "); addch(ACS_LANTERN);
+ mvaddstr(ACSY + 11,40, "ACS_BLOCK: "); addch(ACS_BLOCK);
+
+#define HYBASE (ACSY + 13)
+ mvprintw(HYBASE + 1, 0, "High-half characters via echochar:\n");
+ for (i = 0; i < 4; i++)
+ {
+ move(HYBASE + i + 3, 24);
+ for (j = 0; j < 32; j++)
+ echochar(128 + 32 * i + j);
+ }
+
+ move(LINES - 1, 0);
+ addstr("Press any key to continue... ");
+ (void) getch();
+
+ erase();
+ endwin();
+}
+
+/****************************************************************************
+ *
+ * Windows and scrolling tester.
+ *
+ ****************************************************************************/
+
+typedef struct
+{
+ int y, x;
+}
+pair;
+
+static void report(void)
+/* report on the cursor's current position, then restore it */
+{
+ int y, x;
+
+ getyx(stdscr, y, x);
+ move(LINES - 1, COLS - 17);
+ printw("Y = %2d X = %2d", y, x);
+ move(y, x);
+}
+
+static pair *selectcell(uli, ulj, lri, lrj)
+/* arrows keys move cursor, return location at current on non-arrow key */
+int uli, ulj, lri, lrj; /* co-ordinates of corners */
+{
+ static pair res; /* result cell */
+ int si = lri - uli + 1; /* depth of the select area */
+ int sj = lrj - ulj + 1; /* width of the select area */
+ int i = 0, j = 0; /* offsets into the select area */
+
+ for (;;)
+ {
+ move(LINES - 1, COLS - 17);
+ printw("Y = %2d X = %2d", uli + i, ulj + j);
+ move(uli + i, ulj + j);
+
+ switch(getch())
+ {
+ case KEY_UP: i += si - 1; break;
+ case KEY_DOWN: i++; break;
+ case KEY_LEFT: j += sj - 1; break;
+ case KEY_RIGHT: j++; break;
+ case '\004': return((pair *)NULL);
+ default: res.y = uli + i; res.x = ulj + j; return(&res);
+ }
+ i %= si;
+ j %= sj;
+ }
+}
+
+static WINDOW *getwindow(void)
+/* Ask user for a window definition */
+{
+ WINDOW *rwindow, *bwindow;
+ pair ul, lr, *tmp;
+
+ move(0, 0); clrtoeol();
+ addstr("Use arrows to move cursor, anything else to mark corner 1");
+ refresh();
+ if ((tmp = selectcell(1, 0, LINES-1, COLS-1)) == (pair *)NULL)
+ return((WINDOW *)NULL);
+ memcpy(&ul, tmp, sizeof(pair));
+ addch(ACS_ULCORNER);
+ move(0, 0); clrtoeol();
+ addstr("Use arrows to move cursor, anything else to mark corner 2");
+ refresh();
+ if ((tmp = selectcell(ul.y, ul.x, LINES-1, COLS-1)) == (pair *)NULL)
+ return((WINDOW *)NULL);
+ memcpy(&lr, tmp, sizeof(pair));
+
+ rwindow = newwin(lr.y - ul.y + 1, lr.x - ul.x + 1, ul.y, ul.x);
+
+ bwindow = newwin(lr.y - ul.y + 3, lr.x - ul.x + 3, ul.y - 1, ul.x - 1);
+ wborder(bwindow, ACS_VLINE, ACS_VLINE, ACS_HLINE, ACS_HLINE,
+ 0, 0, 0, 0);
+ wrefresh(bwindow);
+ delwin(bwindow);
+
+ scrollok(rwindow, TRUE);
+/* immedok(rwindow); */
+ wrefresh(rwindow);
+
+ return(rwindow);
+}
+
+static void acs_and_scroll()
+/* Demonstrate windows */
+{
+ int c;
+ struct frame
+ {
+ struct frame *next, *last;
+ WINDOW *wind;
+ }
+ *oldw = (struct frame *)NULL, *current = (struct frame *)NULL, *neww;
+
+ refresh();
+ mvaddstr(LINES - 2, 0,
+ "F1 = make new window, F2 = next window, F3 = previous window, Ctrl-D = exit");
+ mvaddstr(LINES - 1, 0,
+ "All other characters are echoed, windows should scroll.");
+
+ c = KEY_F(1);
+ do {
+ report();
+ if (current)
+ wrefresh(current->wind);
+
+ switch(c)
+ {
+ case KEY_F(1):
+ neww = (struct frame *) malloc(sizeof(struct frame));
+ if ((neww->wind = getwindow()) == (WINDOW *)NULL)
+ goto breakout;
+ if (oldw == NULL) /* First element, */
+ {
+ neww->next = neww; /* so point it at itself */
+ neww->last = neww;
+ current = neww;
+ }
+ else
+ {
+ neww->last = oldw; oldw->next = neww;
+ neww->next = current; current->last = neww;
+ }
+ oldw = neww;
+ keypad(neww->wind, TRUE);
+ break;
+
+ case KEY_F(2):
+ current = current->next;
+ break;
+
+ case KEY_F(3):
+ current = current->last;
+ break;
+
+ case KEY_F(4): /* undocumented --- use this to test area clears */
+ selectcell(0, 0, LINES - 1, COLS - 1);
+ clrtobot();
+ refresh();
+ break;
+
+ case '\r':
+ c = '\n';
+ /* FALLTHROUGH */
+
+ default:
+ waddch(current->wind, c);
+ break;
+ }
+ report();
+ wrefresh(current->wind);
+ } while
+ ((c = wgetch(current->wind)) != '\004');
+
+ breakout:
+ erase();
+ endwin();
+}
+
+#define GRIDSIZE 5
+
+static void panner(WINDOW *pad, int iy, int ix, int (*pgetc)(void))
+{
+ static int porty, portx, basex = 0, basey = 0;
+ int pxmax, pymax, c;
+ WINDOW *vscroll = (WINDOW *)NULL, *hscroll = (WINDOW *)NULL;
+
+ porty = iy; portx = ix;
+
+ getmaxyx(pad, pymax, pxmax);
+
+ if (pymax > porty)
+ vscroll = newwin(porty - (pxmax > ix), 1, 0, portx - (pymax > iy));
+ if (pxmax > portx)
+ hscroll = newwin(1, portx - (pymax > iy), porty - (pxmax > ix), 0);
+
+ c = KEY_REFRESH;
+ do {
+ switch(c)
+ {
+ case KEY_REFRESH:
+ /* do nothing */
+ break;
+
+ case KEY_IC:
+ if (portx >= pxmax || portx >= ix)
+ beep();
+ else
+ {
+ mvwin(vscroll, 0, ++portx - 1);
+ delwin(hscroll);
+ hscroll = newwin(1, portx - (pymax > porty),
+ porty - (pxmax > portx), 0);
+ }
+ break;
+
+ case KEY_IL:
+ if (porty >= pymax || porty >= iy)
+ beep();
+ else
+ {
+ mvwin(hscroll, ++porty - 1, 0);
+ delwin(vscroll);
+ vscroll = newwin(porty - (pxmax > portx), 1,
+ 0, portx - (pymax > porty));
+ }
+ break;
+
+ case KEY_DC:
+ if (portx <= 0)
+ beep();
+ else
+ {
+ mvwin(vscroll, 0, --portx - 1);
+ delwin(hscroll);
+ hscroll = newwin(1, portx - (pymax > porty),
+ porty - (pxmax > portx), 0);
+ }
+ break;
+
+ case KEY_DL:
+ if (porty <= 0)
+ beep();
+ else
+ {
+ mvwin(hscroll, --porty - 1, 0);
+ delwin(vscroll);
+ vscroll = newwin(porty - (pxmax > portx), 1,
+ 0, portx - (pymax > porty));
+ }
+ break;
+
+ case KEY_LEFT:
+ if (basex > 0)
+ basex--;
+ else
+ beep();
+ break;
+
+ case KEY_RIGHT:
+ if (basex + portx < pxmax)
+ basex++;
+ else
+ beep();
+ break;
+
+ case KEY_UP:
+ if (basey > 0)
+ basey--;
+ else
+ beep();
+ break;
+
+ case KEY_DOWN:
+ if (basey + porty < pymax)
+ basey++;
+ else
+ beep();
+ break;
+ }
+
+ prefresh(pad,
+ basey, basex,
+ 0, 0,
+ porty - (hscroll != (WINDOW *)NULL) - 1,
+ portx - (vscroll != (WINDOW *)NULL) - 1);
+ if (vscroll)
+ {
+ int lowend, i, highend;
+
+ lowend = basey * ((float)porty / (float)pymax);
+ highend = (basey + porty) * ((float)porty / (float)pymax);
+
+ touchwin(vscroll);
+ for (i = 0; i < lowend; i++)
+ mvwaddch(vscroll, i, 0, ACS_VLINE);
+ wattron(vscroll, A_REVERSE);
+ for (i = lowend; i <= highend; i++)
+ mvwaddch(vscroll, i, 0, ' ');
+ wattroff(vscroll, A_REVERSE);
+ for (i = highend + 1; i < porty; i++)
+ mvwaddch(vscroll, i, 0, ACS_VLINE);
+ wrefresh(vscroll);
+ }
+ if (hscroll)
+ {
+ int lowend, j, highend;
+
+ lowend = basex * ((float)portx / (float)pxmax);
+ highend = (basex + portx) * ((float)portx / (float)pxmax);
+
+ touchwin(hscroll);
+ for (j = 0; j < lowend; j++)
+ mvwaddch(hscroll, 0, j, ACS_HLINE);
+ wattron(hscroll, A_REVERSE);
+ for (j = lowend; j <= highend; j++)
+ mvwaddch(hscroll, 0, j, ' ');
+ wattroff(hscroll, A_REVERSE);
+ for (j = highend + 1; j < portx; j++)
+ mvwaddch(hscroll, 0, j, ACS_HLINE);
+ wrefresh(hscroll);
+ }
+ mvaddch(porty - 1, portx - 1, ACS_LRCORNER);
+
+ } while
+ ((c = pgetc()) != KEY_EXIT);
+}
+
+int padgetch(void)
+{
+ int c;
+
+ switch(c = getch())
+ {
+ case 'u': return(KEY_UP);
+ case 'd': return(KEY_DOWN);
+ case 'r': return(KEY_RIGHT);
+ case 'l': return(KEY_LEFT);
+ case '+': return(KEY_IL);
+ case '-': return(KEY_DL);
+ case '>': return(KEY_IC);
+ case '<': return(KEY_DC);
+ default: return(c);
+ }
+}
+
+static void demo_pad(void)
+/* Demonstrate pads. */
+{
+ int i, j, gridcount = 0;
+ WINDOW *panpad = newpad(200, 200);
+
+ for (i = 0; i < 200; i++)
+ {
+ for (j = 0; j < 200; j++)
+ if (i % GRIDSIZE == 0 && j % GRIDSIZE == 0)
+ {
+ if (i == 0 || j == 0)
+ waddch(panpad, '+');
+ else
+ waddch(panpad, 'A' + (gridcount++ % 26));
+ }
+ else if (i % GRIDSIZE == 0)
+ waddch(panpad, '-');
+ else if (j % GRIDSIZE == 0)
+ waddch(panpad, '|');
+ else
+ waddch(panpad, ' ');
+ }
+ mvprintw(LINES - 3, 0, "Use arrow keys to pan over the test pattern");
+ mvprintw(LINES - 2, 0, "Use +,- to grow/shrink the panner vertically.");
+ mvprintw(LINES - 1, 0, "Use <,> to grow/shrink the panner horizontally.");
+ panner(panpad, LINES - 4, COLS, padgetch);
+
+ endwin();
+ erase();
+}
+
+/****************************************************************************
+ *
+ * Tests from John Burnell's PDCurses tester
+ *
+ ****************************************************************************/
+
+static void Continue (WINDOW *win)
+{
+ wmove(win, 10, 1);
+ mvwaddstr(win, 10, 1, " Press any key to continue");
+ wrefresh(win);
+ wgetch(win);
+}
+
+static void input_test(WINDOW *win)
+/* Input test, adapted from John Burnell's PDCurses tester */
+{
+ int w, h, bx, by, sw, sh, i;
+ WINDOW *subWin;
+ wclear (win);
+#ifdef FOO
+ char buffer [80];
+ int num;
+#endif /* FOO */
+
+ w = win->_maxx;
+ h = win->_maxy;
+ bx = win->_begx;
+ by = win->_begy;
+ sw = w / 3;
+ sh = h / 3;
+ if((subWin = subwin(win, sh, sw, by + h - sh - 2, bx + w - sw - 2)) == NULL)
+ return;
+
+#ifdef A_COLOR
+ if (has_colors())
+ {
+ init_pair(2,COLOR_CYAN,COLOR_BLUE);
+ wattrset(subWin, COLOR_PAIR(2) | A_BOLD);
+ }
+ else
+ wattrset(subWin, A_BOLD);
+#else
+ wattrset(subWin, A_BOLD);
+#endif
+ box(subWin, ACS_VLINE, ACS_HLINE);
+#ifdef FOO
+ mvwaddstr(subWin, 2, 1, "This is a subwindow");
+#endif /* FOO */
+ wrefresh(win);
+
+ nocbreak();
+ mvwaddstr(win, 1, 1, "Type random keys for 5 seconds.");
+ mvwaddstr(win, 2, 1,
+ "These should be discarded (not echoed) after the subwindow goes away.");
+ wrefresh(win);
+
+ for (i = 0; i < 5; i++)
+ {
+ mvwprintw (subWin, 1, 1, "Time = %d", i);
+ wrefresh(subWin);
+ sleep(1);
+ flushinp();
+ }
+
+ delwin (subWin);
+ werase(win);
+ flash();
+ wrefresh(win);
+ sleep(1);
+
+ mvwaddstr(win, 2, 1, "Press a key");
+ wmove(win, 9, 10);
+ wrefresh(win);
+ echo();
+ wgetch(win);
+ flushinp();
+ mvwaddstr(win, 12, 0,
+ "If you see any key other than what you typed, flushinp() is broken.");
+ Continue(win);
+
+ wmove(win, 9, 10);
+ wdelch(win);
+ wrefresh(win);
+ wmove(win, 12, 0);
+ clrtoeol();
+ waddstr(win,
+ "What you typed should now have been deleted; if not, wdelch() failed.");
+ Continue(win);
+
+#ifdef FOO
+ /*
+ * This test won't be portable until vsscanf() is
+ */
+ mvwaddstr(win, 6, 2, "Enter a number then a string separated by space");
+ echo();
+ mvwscanw(win, 7, 6, "%d %s", &num,buffer);
+ mvwprintw(win, 8, 6, "String: %s Number: %d", buffer,num);
+#endif /* FOO */
+
+ Continue(win);
+}
+
+/****************************************************************************
+ *
+ * Main sequence
+ *
+ ****************************************************************************/
+
+bool do_single_test(const char c)
+/* perform a single specified test */
+{
+ switch (c)
+ {
+ case 'a':
+ getch_test();
+ return(TRUE);
+
+ case 'b':
+ attr_test();
+ return(TRUE);
+
+ case 'c':
+ if (!has_colors())
+ (void) printf("This %s terminal does not support color.\n",
+ getenv("TERM"));
+ else
+ color_test();
+ return(TRUE);
+
+ case 'd':
+ if (!has_colors())
+ (void) printf("This %s terminal does not support color.\n",
+ getenv("TERM"));
+ else if (!can_change_color())
+ (void) printf("This %s terminal has hardwired color values.\n",
+ getenv("TERM"));
+ else
+ color_edit();
+ return(TRUE);
+
+ case 'e':
+ slk_test();
+ return(TRUE);
+
+ case 'f':
+ acs_display();
+ return(TRUE);
+
+ case 'g':
+ acs_and_scroll();
+ return(TRUE);
+
+ case 'p':
+ demo_pad();
+ return(TRUE);
+
+ case 'i':
+ input_test(stdscr);
+ return(TRUE);
+
+ case '?':
+ (void) puts("This is the ncurses capability tester.");
+ (void) puts("You may select a test from the main menu by typing the");
+ (void) puts("key letter of the choice (the letter to left of the =)");
+ (void) puts("at the > prompt. The commands `x' or `q' will exit.");
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+int main(const int argc, const char *argv[])
+{
+ char buf[BUFSIZ];
+
+ /* enable debugging */
+ trace(TRACE_ORDINARY);
+
+ /* tell it we're going to play with soft keys */
+ slk_init(1);
+
+ /* we must initialize the curses data structure only once */
+ initscr();
+
+ /* tests, in general, will want these modes */
+ start_color();
+ cbreak();
+ noecho();
+ scrollok(stdscr, TRUE);
+ keypad(stdscr, TRUE);
+
+ /*
+ * Return to terminal mode, so we're guaranteed of being able to
+ * select terminal commands even if the capabilities are wrong.
+ */
+ endwin();
+
+ (void) puts("Welcome to ncurses. Press ? for help.");
+
+ do {
+ (void) puts("This is the ncurses main menu");
+ (void) puts("a = character input test");
+ (void) puts("b = character attribute test");
+ (void) puts("c = color test pattern");
+ (void) puts("d = edit RGB color values");
+ (void) puts("e = exercise soft keys");
+ (void) puts("f = display ACS characters");
+ (void) puts("g = display windows and scrolling");
+ (void) puts("p = exercise pad features");
+ (void) puts("i = subwindow input test");
+ (void) puts("? = get help");
+
+ (void) fputs("> ", stdout);
+ (void) fflush(stdout); /* necessary under SVr4 curses */
+ (void) fgets(buf, BUFSIZ, stdin);
+
+ if (do_single_test(buf[0])) {
+ clear();
+ refresh();
+ endwin();
+ continue;
+ }
+ } while
+ (buf[0] != 'q' && buf[0] != 'x');
+
+ exit(0);
+}
+
+/* ncurses.c ends here */
diff --git a/lib/libncurses/TESTS/newdemo.c b/lib/libncurses/TESTS/newdemo.c
new file mode 100644
index 0000000..5573557
--- /dev/null
+++ b/lib/libncurses/TESTS/newdemo.c
@@ -0,0 +1,350 @@
+/* $Header: /home/ncvs/src/lib/libncurses/TESTS/newdemo.c,v 1.1.1.1 1994/10/07 08:58:56 ache Exp $
+ *
+ * newdemo.c - A demo program using PDCurses. The program illustrate
+ * the use of colours for text output.
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <time.h>
+#include <ncurses.h>
+
+#define delay_output(x)
+
+/*
+ * The Australian map
+ */
+char *AusMap[16] =
+{
+ " A A ",
+ " N.T. AAAAA AAAA ",
+ " AAAAAAAAAAA AAAAAAAA ",
+ " AAAAAAAAAAAAAAAAAAAAAAAAA Qld.",
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
+ " AAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
+ " AAAAAAAAAAAAAAAAAAAAAAAAA N.S.W.",
+ "W.A. AAAAAAAAA AAAAAA Vic.",
+ " AAA S.A. AA",
+ " A Tas.",
+ ""
+};
+
+/*
+ * Funny messages
+ */
+#define NMESSAGES 6
+
+char *messages[] =
+{
+ "Hello from the Land Down Under",
+ "The Land of crocs. and a big Red Rock",
+ "Where the sunflower runs along the highways",
+ "the dusty red roads lead one to loneliness",
+ "Blue sky in the morning and",
+ "freezing nights and twinkling stars",
+ ""
+};
+
+/*
+ * Main driver
+ */
+main()
+{
+WINDOW *win;
+int w, x, y, i, j, c, len;
+time_t t;
+char buffer[80], *message;
+int width, height;
+chtype save[80];
+void trap();
+
+ initscr();
+ start_color();
+ cbreak();
+ signal(SIGINT, trap);
+ width = 48;
+ height = 14; /* Create a drawing window */
+ win = newwin(height, width, (LINES-height)/2, (COLS-width)/2);
+ if(win == NULL)
+ { endwin();
+ return 1;
+ }
+
+ while(1)
+ { init_pair(1,COLOR_WHITE,COLOR_BLUE);
+ wattrset(win, COLOR_PAIR(1));
+ werase(win);
+
+ init_pair(2,COLOR_RED,COLOR_RED);
+ wattrset(win, COLOR_PAIR(2));
+ box(win, ACS_VLINE, ACS_HLINE);
+ wrefresh(win);
+ /* Do ramdom output of a character */
+ wattrset(win, COLOR_PAIR(1));
+ c = 'a';
+ for(i=0; i < 5000; ++i)
+ { x = rand() % (width-2) + 1;
+ y = rand() % (height-2) + 1;
+ mvwaddch(win, y, x, c);
+ wrefresh(win);
+ nodelay(win,TRUE);
+ if (wgetch(win) != ERR)
+ break;
+ if(i == 2000)
+ { c = 'b';
+ init_pair(3,COLOR_CYAN,COLOR_YELLOW);
+ wattron(win, COLOR_PAIR(3));
+ }
+ }
+
+ SubWinTest(win);
+ /* Erase and draw green window */
+ init_pair(4,COLOR_YELLOW,COLOR_GREEN);
+ wattrset(win, COLOR_PAIR(4) | A_BOLD);
+ werase(win);
+ wrefresh(win);
+ /* Draw RED bounding box */
+ wattrset(win, COLOR_PAIR(2));
+ box(win, ' ', ' ');
+ wrefresh(win);
+ /* Display Australia map */
+ wattrset(win, COLOR_PAIR(4) | A_BOLD);
+ i = 0;
+ while(*AusMap[i])
+ { mvwaddstr(win, i+1, 8, AusMap[i]);
+ wrefresh(win);
+ delay_output(100);
+ ++i;
+ }
+
+ init_pair(5,COLOR_BLUE,COLOR_WHITE);
+ wattrset(win, COLOR_PAIR(5) | A_BLINK);
+ mvwaddstr(win, height-2, 6, " PDCurses 2.1 for DOS, OS/2 and Unix");
+ wrefresh(win);
+
+ /* Draw running messages */
+ init_pair(6,COLOR_YELLOW,COLOR_WHITE);
+ wattrset(win, COLOR_PAIR(6));
+ message = messages[0];
+ len = strlen(message);
+ j = 0;
+ i = 2;
+ w = width-2;
+ while(j < NMESSAGES)
+ { strncpy(buffer, message, w - i);
+ buffer[w-i] = 0;
+ mvwaddstr(win, height/2, i, buffer);
+ if(w - i < len)
+ { memset(buffer, ' ', i);
+ strcpy(buffer, message + (w - i));
+ buffer[strlen(buffer)] = ' ';
+ buffer[i-2] = '\0';
+ mvwaddstr(win, height/2, 2, buffer);
+ }
+ wrefresh(win);
+ nodelay(win,TRUE);
+ if (wgetch(win) != ERR)
+ { flushinp();
+ break;
+ }
+ mvwaddch(win, height/2, i, ' ');
+ i = ++i % w;
+ if(i < 2)
+ { message = messages[++j%NMESSAGES];
+ memset(buffer, ' ', w-2);
+ buffer[w-2] = 0;
+ mvwaddstr(win, height/2, 2, buffer);
+ i = 2;
+ }
+ delay_output(300);
+ }
+
+ j = 0;
+ /* Draw running As across in RED */
+ init_pair(7,COLOR_RED,COLOR_GREEN);
+ wattron(win, COLOR_PAIR(7));
+ for(i=2; i < width - 4; ++i)
+ { c = mvwinch(win, 4, i);
+ save[j++] = c;
+ c = c & 0x7f;
+ mvwaddch(win, 4, i, c);
+ }
+ wrefresh(win);
+
+ /* Put a message up wait for a key */
+ i = height-2;
+ wattrset(win, COLOR_PAIR(5));
+ mvwaddstr(win, i, 5, " Type a key to continue or 'Q' to quit ");
+ wrefresh(win);
+
+ if(WaitForUser() == 1)
+ break;
+
+ j = 0; /* Restore the old line */
+ for(i=2; i < width - 4; ++i)
+ mvwaddch(win, 4, i, save[j++]);
+ wrefresh(win);
+
+ BouncingBalls(win);
+ /* Put a message up wait for a key */
+ i = height-2;
+ wattrset(win, COLOR_PAIR(5));
+ mvwaddstr(win, i, 5, " Type a key to continue or 'Q' to quit ");
+ wrefresh(win);
+ if(WaitForUser() == 1)
+ break;
+ }
+exit:
+ endwin();
+ return 0;
+}
+
+/*
+ * Test sub windows
+ */
+SubWinTest(WINDOW *win)
+{
+int w, h, sw, sh, bx, by;
+WINDOW *swin1, *swin2, *swin3;
+
+ w = win->_maxx;
+ h = win->_maxy;
+ bx = win->_begx;
+ by = win->_begy;
+ sw = w / 3;
+ sh = h / 3;
+ if((swin1 = subwin(win, sh, sw, by+3, bx+5)) == NULL)
+ return 1;
+ if((swin2 = subwin(win, sh, sw, by+4, bx+8)) == NULL)
+ return 1;
+ if((swin3 = subwin(win, sh, sw, by+5, bx+11)) == NULL)
+ return 1;
+
+ init_pair(8,COLOR_RED,COLOR_BLUE);
+ wattrset(swin1, COLOR_PAIR(8));
+ werase(swin1);
+ mvwaddstr(swin1, 0, 3, "Sub-window 1");
+ wrefresh(swin1);
+
+ init_pair(8,COLOR_CYAN,COLOR_MAGENTA);
+ wattrset(swin2, COLOR_PAIR(8));
+ werase(swin2);
+ mvwaddstr(swin2, 0, 3, "Sub-window 2");
+ wrefresh(swin2);
+
+ init_pair(8,COLOR_YELLOW,COLOR_GREEN);
+ wattrset(swin3, COLOR_PAIR(8));
+ werase(swin3);
+ mvwaddstr(swin3, 0, 3, "Sub-window 3");
+ wrefresh(swin3);
+
+ delwin(swin1);
+ delwin(swin2);
+ delwin(swin3);
+ WaitForUser();
+ return 0;
+}
+
+/*
+ * Bouncing balls
+ */
+BouncingBalls(WINDOW *win)
+{
+chtype c1, c2, c3;
+int w, h;
+int x1, y1, xd1, yd1;
+int x2, y2, xd2, yd2;
+int x3, y3, xd3, yd3;
+
+ w = win->_maxx;
+ h = win->_maxy;
+ x1 = 2 + rand() % (w - 4);
+ y1 = 2 + rand() % (h - 4);
+ x2 = 2 + rand() % (w - 4);
+ y2 = 2 + rand() % (h - 4);
+ x3 = 2 + rand() % (w - 4);
+ y3 = 2 + rand() % (h - 4);
+ xd1 = 1; yd1 = 1;
+ xd2 = 1; yd2 = 0;
+ xd3 = 0; yd3 = 1;
+ nodelay(win,TRUE);
+ while(wgetch(win) == ERR)
+ { x1 = xd1 > 0 ? ++x1 : --x1;
+ if(x1 <= 1 || x1 >= w - 2)
+ xd1 = xd1 ? 0 : 1;
+ y1 = yd1 > 0 ? ++y1 : --y1;
+ if(y1 <= 1 || y1 >= h - 2)
+ yd1 = yd1 ? 0 : 1;
+
+ x2 = xd2 > 0 ? ++x2 : --x2;
+ if(x2 <= 1 || x2 >= w - 2)
+ xd2 = xd2 ? 0 : 1;
+ y2 = yd2 > 0 ? ++y2 : --y2;
+ if(y2 <= 1 || y2 >= h - 2)
+ yd2 = yd2 ? 0 : 1;
+
+ x3 = xd3 > 0 ? ++x3 : --x3;
+ if(x3 <= 1 || x3 >= w - 2)
+ xd3 = xd3 ? 0 : 1;
+ y3 = yd3 > 0 ? ++y3 : --y3;
+ if(y3 <= 1 || y3 >= h - 2)
+ yd3 = yd3 ? 0 : 1;
+
+ c1 = mvwinch(win, y1, x1);
+ c2 = mvwinch(win, y2, x2);
+ c3 = mvwinch(win, y3, x3);
+
+ init_pair(8,COLOR_RED,COLOR_BLUE);
+ wattrset(win, COLOR_PAIR(8));
+ mvwaddch(win, y1, x1, 'O');
+ init_pair(8,COLOR_BLUE,COLOR_RED);
+ wattrset(win, COLOR_PAIR(8));
+ mvwaddch(win, y2, x2, '*');
+ init_pair(8,COLOR_YELLOW,COLOR_WHITE);
+ wattrset(win, COLOR_PAIR(8));
+ mvwaddch(win, y3, x3, '@');
+ wmove(win, 0, 0);
+ wrefresh(win);
+ mvwaddch(win, y1, x1, c1);
+ mvwaddch(win, y2, x2, c2);
+ mvwaddch(win, y3, x3, c3);
+ delay_output(150);
+ }
+ return 0;
+}
+
+/*
+ * Wait for user
+ */
+int WaitForUser()
+{
+ time_t t;
+ chtype key;
+
+ nodelay(stdscr,TRUE);
+ t = time((time_t *)0);
+ while(1)
+ {
+ if ((key = getch()) != ERR)
+ {
+ if (key == 'q' || key == 'Q')
+ return 1;
+ else
+ return 0;
+ }
+ if (time((time_t *)0) - t > 5)
+ return 0;
+ }
+}
+
+/*
+ * Trap interrupt
+ */
+void trap()
+{
+ endwin();
+ exit(0);
+}
+
+/* End of DEMO.C */
diff --git a/lib/libncurses/TESTS/over.c b/lib/libncurses/TESTS/over.c
new file mode 100644
index 0000000..5681916
--- /dev/null
+++ b/lib/libncurses/TESTS/over.c
@@ -0,0 +1,120 @@
+/*********************************************************************
+ * [program] overwrite() - Play with overwrite() function to *
+ * attempt pop-up windows. *
+ * ----------------------------------------------------------------- *
+ * [written] 1-Feb-1993 by Neal Ensor (ensor@cs.utk.edu) *
+ * ----------------------------------------------------------------- *
+ * [notes] Originally written on SVR4 UNIX, then recompiled on *
+ * Linux (Slackware 1.1.1, ncurses 1.8.1) *
+ * ----------------------------------------------------------------- *
+ * [problem] On ncurses, the overwrite() function doesn't seem to *
+ * overwrite. Maybe I'm missing something, but this *
+ * program in SVR4 displays three windows, waits for a *
+ * keypress, then removes the top window. With ncurses, *
+ * nothing changes on the display. *
+ *********************************************************************/
+
+# include <ncurses.h> /* ncurses include lives here */
+
+main()
+{
+ /****************************************************************
+ * Declare three little window pointers... *
+ ****************************************************************/
+ WINDOW *win, *win1, *win2;
+
+ /****************************************************************
+ * Set up the screen... *
+ ****************************************************************/
+ initscr();
+ /* traceon(); */
+ noecho();
+ nonl();
+ cbreak();
+ refresh();
+
+ /****************************************************************
+ * Draw three overlapping windows. *
+ ****************************************************************/
+ win=newwin(6,45, 6,6);
+ win1=newwin(10,20,5,5);
+ win2=newwin(10,30,7,7);
+
+ /****************************************************************
+ * Box them, and print a hidden message... *
+ ****************************************************************/
+ box(win, 0, 0);
+ box(win1, 0, 0);
+ box(win2, 0, 0);
+ mvwprintw(win1, 6,6, "Hey!");
+ mvwaddch(win, 1, 1, '0');
+ mvwaddch(win1, 1, 1, '1');
+ mvwaddch(win2, 1, 1, '2');
+ wnoutrefresh(win);
+ wnoutrefresh(win1);
+ wnoutrefresh(win2);
+ doupdate();
+
+ /****************************************************************
+ * Await a keypress to show what we've done so far. *
+ ****************************************************************/
+ getch();
+
+ /****************************************************************
+ * Now, overwrite win2 with contents of all lower windows IN *
+ * ORDER from the stdscr up... *
+ ****************************************************************/
+ if (overwrite(stdscr, win2) == ERR)
+ fprintf(stderr, "overwrite(stdscr, win2) failed!\n");
+
+ touchwin(stdscr); wnoutrefresh(stdscr);
+ touchwin(win); wnoutrefresh(win);
+ touchwin(win1); wnoutrefresh(win1);
+ touchwin(win2); wnoutrefresh(win2);
+ doupdate();
+
+ getch();
+ if (overwrite(win, win2) == ERR)
+ fprintf(stderr, "overwrite(win, win2) failed!\n");
+
+ touchwin(stdscr); wnoutrefresh(stdscr);
+ touchwin(win); wnoutrefresh(win);
+ touchwin(win1); wnoutrefresh(win1);
+ touchwin(win2); wnoutrefresh(win2);
+ doupdate();
+
+ getch();
+ if (overwrite(win1, win2) == ERR)
+ fprintf(stderr, "overwrite(win1, win2) failed!\n");
+
+ /****************************************************************
+ * Perform touches, and hidden refreshes on each window. *
+ * ------------------------------------------------------------ *
+ * NOTE: If you replace the wnoutrefresh() call with wrefresh()*
+ * you can see all windows being redrawn untouched. *
+ ****************************************************************/
+ touchwin(stdscr); wnoutrefresh(stdscr);
+ touchwin(win); wnoutrefresh(win);
+ touchwin(win1); wnoutrefresh(win1);
+ touchwin(win2); wnoutrefresh(win2);
+ doupdate();
+
+ /****************************************************************
+ * At this point, win2 should be "destroyed"; having all other *
+ * window contents overwritten onto it. The doupdate() should *
+ * effectively remove it from the screen, leaving the others *
+ * untouched. On SVR4, this happens, but not with ncurses. *
+ * I'd suspect something in overwrite() causes this, as nothing *
+ * appears to be overwritten after the calls, with no errors *
+ * being reported. This was compiled on my Linux from Slackware*
+ * 1.1.1, with ncurses1.8.1 recompiled on it, using the console *
+ * entry from the "new" terminfo from ncurses1.8.1. *
+ ****************************************************************/
+ getch();
+
+ /****************************************************************
+ * Clean up our act and exit. *
+ ****************************************************************/
+ endwin();
+}
+
diff --git a/lib/libncurses/TESTS/rain.c b/lib/libncurses/TESTS/rain.c
new file mode 100644
index 0000000..9779d02
--- /dev/null
+++ b/lib/libncurses/TESTS/rain.c
@@ -0,0 +1,96 @@
+#include <ncurses.h>
+#include <signal.h>
+/* rain 11/3/1980 EPS/CITHEP */
+
+#define cursor(col,row) move(row,col)
+
+float ranf();
+void onsig();
+
+main(argc,argv)
+int argc;
+char *argv[];
+{
+int x, y, j;
+static int xpos[5], ypos[5];
+float r;
+float c;
+
+ for (j=SIGHUP;j<=SIGTERM;j++)
+ if (signal(j,SIG_IGN)!=SIG_IGN) signal(j,onsig);
+
+ initscr();
+ nl();
+ noecho();
+ r = (float)(LINES - 4);
+ c = (float)(COLS - 4);
+ for (j=5;--j>=0;) {
+ xpos[j]=(int)(c* ranf())+2;
+ ypos[j]=(int)(r* ranf())+2;
+ }
+ for (j=0;;) {
+ x=(int)(c*ranf())+2;
+ y=(int)(r*ranf())+2;
+
+ cursor(x,y); addch('.');
+
+ cursor(xpos[j],ypos[j]); addch('o');
+
+ if (j==0) j=4; else --j;
+ cursor(xpos[j],ypos[j]); addch('O');
+
+ if (j==0) j=4; else --j;
+ cursor(xpos[j],ypos[j]-1);
+ addch('-');
+ cursor(xpos[j]-1,ypos[j]);
+ addstr("|.|");
+ cursor(xpos[j],ypos[j]+1);
+ addch('-');
+
+ if (j==0) j=4; else --j;
+ cursor(xpos[j],ypos[j]-2);
+ addch('-');
+ cursor(xpos[j]-1,ypos[j]-1);
+ addstr("/ \\");
+ cursor(xpos[j]-2,ypos[j]);
+ addstr("| O |");
+ cursor(xpos[j]-1,ypos[j]+1);
+ addstr("\\ /");
+ cursor(xpos[j],ypos[j]+2);
+ addch('-');
+
+ if (j==0) j=4; else --j;
+ cursor(xpos[j],ypos[j]-2);
+ addch(' ');
+ cursor(xpos[j]-1,ypos[j]-1);
+ addstr(" ");
+ cursor(xpos[j]-2,ypos[j]);
+ addstr(" ");
+ cursor(xpos[j]-1,ypos[j]+1);
+ addstr(" ");
+ cursor(xpos[j],ypos[j]+2);
+ addch(' ');
+ xpos[j]=x; ypos[j]=y;
+ refresh();
+ }
+}
+
+void
+onsig(n)
+int n;
+{
+ endwin();
+ exit(0);
+}
+
+float
+ranf()
+{
+ float rv;
+ long r = rand();
+
+ r &= 077777;
+ rv =((float)r/32767.);
+ return rv;
+}
+
diff --git a/lib/libncurses/TESTS/scroll.c b/lib/libncurses/TESTS/scroll.c
new file mode 100644
index 0000000..428a064
--- /dev/null
+++ b/lib/libncurses/TESTS/scroll.c
@@ -0,0 +1,30 @@
+#include <ncurses.h>
+
+main()
+{
+int i;
+
+ initscr();
+ noecho();
+ scrollok(stdscr, TRUE);
+ setscrreg(0, 9);
+ mvaddstr(0,0,"aaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+ mvaddstr(1,0,"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
+ mvaddstr(2,0,"ccccccccccccccccccccccccccccc");
+ mvaddstr(3,0,"ddddddddddddddddddddddddddddd");
+ mvaddstr(4,0,"eeeeeeeeeeeeeeeeeeeeeeeeeeeee");
+ mvaddstr(5,0,"fffffffffffffffffffffffffffff");
+ mvaddstr(6,0,"ggggggggggggggggggggggggggggg");
+ mvaddstr(7,0,"hhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
+ mvaddstr(8,0,"iiiiiiiiiiiiiiiiiiiiiiiiiiiii");
+ mvaddstr(9,0,"jjjjjjjjjjjjjjjjjjjjjjjjjjjjj");
+ refresh();
+ for (i = 0; i < 4; i++) {
+ getch();
+ scrl(-1);
+ refresh();
+ }
+ getch();
+ endwin();
+
+}
diff --git a/lib/libncurses/TESTS/scroll2.c b/lib/libncurses/TESTS/scroll2.c
new file mode 100644
index 0000000..e7b2e30
--- /dev/null
+++ b/lib/libncurses/TESTS/scroll2.c
@@ -0,0 +1,91 @@
+#include <ncurses.h>
+#define ROWS 20
+#define scroll_window wscrl
+
+main()
+{
+ int i;
+ WINDOW * w;
+
+
+ initscr();
+ cbreak();
+ noecho();
+ w = newwin (ROWS, 35, 2, 25);
+ scrollok(w, TRUE);
+ wsetscrreg(w, 0, ROWS-1);
+
+#ifdef LELE
+ mvaddstr (0, 0, "With my function");
+#else
+ mvaddstr (0, 0, "With the original wscrl");
+#endif
+ refresh();
+
+
+ for (i=0; i<ROWS-1; i++)
+ {
+ mvwprintw (w, i, 0, "Line number %d", i);
+ }
+ mvwaddstr (w, ROWS-1, 0, "Moving one line at a time");
+ wrefresh(w);
+ for (i = 0; i < 4; i++) {
+ getch();
+ scroll_window (w, 1);
+ wrefresh(w);
+ }
+ for (i = 0; i < 4; i++) {
+ getch();
+ scroll_window (w, -1);
+ wrefresh(w);
+ }
+ getch();
+ wclear (w);
+
+
+ for (i=0; i<ROWS-1; i++)
+ {
+ mvwprintw (w, i, 0, "Line number %d", i);
+ }
+ mvwaddstr (w, ROWS-1, 0, "Moving two line at a time");
+#ifndef LELE
+ mvaddstr (0, 30, "** THIS FAILS ON MY MACHINE WITH A BUS ERROR
+**");
+#endif
+
+
+ wrefresh(w);
+ for (i = 0; i < 4; i++) {
+ getch();
+ scroll_window (w, 2);
+ wrefresh(w);
+ }
+ for (i = 0; i < 4; i++) {
+ getch();
+ scroll_window (w, -2);
+ wrefresh(w);
+ }
+ getch();
+ wclear (w);
+ for (i=0; i<ROWS-1; i++)
+ {
+ mvwprintw (w, i, 0, "Line number %d", i);
+ }
+ mvwaddstr (w, ROWS-1, 0, "Moving three line at a time");
+ wrefresh(w);
+ for (i = 0; i < 4; i++) {
+ getch();
+ scroll_window (w, 3);
+ wrefresh(w);
+ }
+ for (i = 0; i < 4; i++) {
+ getch();
+ scroll_window (w, -3);
+ wrefresh(w);
+ }
+ getch();
+
+
+ endwin();
+}
+
diff --git a/lib/libncurses/TESTS/scroll3.c b/lib/libncurses/TESTS/scroll3.c
new file mode 100644
index 0000000..b2a10c3
--- /dev/null
+++ b/lib/libncurses/TESTS/scroll3.c
@@ -0,0 +1,51 @@
+#include <ncurses.h>
+
+main(int argc, char **argv)
+{
+ WINDOW *w, *x;
+
+ initscr();
+ w = newwin(0, 0, 0, 0);
+ if (argc > 2)
+ x = newwin(0, 0, 0, 0);
+ scrollok(w, TRUE);
+ if (argc > 2)
+ scrollok(x, TRUE);
+ idlok(w, TRUE);
+ if (argc > 2)
+ idlok(x, TRUE);
+ wmove(w, LINES - 1, 0);
+ waddstr(w, "test 1 in w");
+ wrefresh(w);
+ sleep(1);
+ if (argc == 2 || argc == 4)
+ {
+ waddch(w, '\n');
+ sleep(1);
+ waddch(w, '\n');
+ sleep(1);
+ waddch(w, '\n');
+ sleep(1);
+ beep();
+ wrefresh(w);
+ }
+ sleep(1);
+ if (argc > 2)
+ {
+ wmove(x, LINES - 1, 0);
+ waddstr(x, "test 2 in x");
+ sleep(1);
+ waddch(x, '\n');
+ sleep(1);
+ waddch(x, '\n');
+ sleep(1);
+ waddch(x, '\n');
+ sleep(1);
+ beep();
+ wrefresh(w);
+ sleep(1);
+ }
+ endwin();
+ return 0;
+}
+
diff --git a/lib/libncurses/TESTS/test.c b/lib/libncurses/TESTS/test.c
new file mode 100644
index 0000000..f77f3a1
--- /dev/null
+++ b/lib/libncurses/TESTS/test.c
@@ -0,0 +1,27 @@
+
+#include <ncurses.h>
+
+main()
+{
+int x, y;
+
+ initscr();
+ cbreak();
+ nodelay(stdscr, TRUE);
+
+ for (y = 0; y < 43; y++)
+ for (x =0; x < 132; x++) {
+ move(y,x);
+ printw("X");
+ refresh();
+ if (!getch()) {
+ beep();
+ sleep(1);
+ }
+ }
+
+ nocbreak();
+ endwin();
+}
+
+
diff --git a/lib/libncurses/TESTS/testcurs.c b/lib/libncurses/TESTS/testcurs.c
new file mode 100644
index 0000000..df2468a
--- /dev/null
+++ b/lib/libncurses/TESTS/testcurs.c
@@ -0,0 +1,532 @@
+/*
+ *
+ * This is a test program for the PDCurses screen package for IBM PC type
+ * machines.
+ * This program was written by John Burnell (johnb@kea.am.dsir.govt.nz)
+ *
+ */
+
+#include <stdio.h>
+#include <ncurses.h>
+
+#ifdef __STDC__
+void inputTest (WINDOW *);
+void scrollTest (WINDOW *);
+void introTest (WINDOW *);
+int initTest (WINDOW **);
+void outputTest (WINDOW *);
+void padTest (WINDOW *);
+void resizeTest (WINDOW *);
+void display_menu(int,int);
+#else
+void inputTest ();
+void scrollTest ();
+void introTest ();
+int initTest ();
+void outputTest ();
+void padTest ();
+void resizeTest ();
+void display_menu();
+#endif
+
+struct commands
+{
+ char *text;
+#ifdef __STDC__
+ void (*function)(WINDOW *);
+#else
+ void (*function)();
+#endif
+};
+typedef struct commands COMMAND;
+#define MAX_OPTIONS 6
+COMMAND command[MAX_OPTIONS] =
+{
+ {"Intro Test",introTest},
+ {"Pad Test",padTest},
+ {"Resize Test",resizeTest},
+ {"Scroll Test",scrollTest},
+ {"Input Test",inputTest},
+ {"Output Test",outputTest}
+};
+
+int width, height;
+
+main()
+{
+WINDOW *win;
+int key,old_option=(-1),new_option=0;
+bool quit=FALSE;
+
+#ifdef PDCDEBUG
+ PDC_debug("testcurs started\n");
+#endif
+ if (!initTest (&win)) {return 1;}
+
+#ifdef A_COLOR
+ if (has_colors())
+ {
+ init_pair(1,COLOR_WHITE,COLOR_BLUE);
+ wattrset(win, COLOR_PAIR(1));
+ }
+ else
+ wattrset(win, A_REVERSE);
+#else
+ wattrset(win, A_REVERSE);
+#endif
+
+ erase();
+ display_menu(old_option,new_option);
+ while(1)
+ {
+ noecho();
+ keypad(stdscr,TRUE);
+ raw();
+ key = getch();
+ switch(key)
+ {
+ case 10:
+ case 13:
+ case KEY_ENTER:
+ erase();
+ refresh();
+ (*command[new_option].function)(win);
+ erase();
+ display_menu(old_option,new_option);
+ break;
+ case KEY_UP:
+ new_option = (new_option == 0) ? new_option : new_option-1;
+ display_menu(old_option,new_option);
+ break;
+ case KEY_DOWN:
+ new_option = (new_option == MAX_OPTIONS-1) ? new_option : new_option+1;
+ display_menu(old_option,new_option);
+ break;
+ case 'Q':
+ case 'q':
+ quit = TRUE;
+ break;
+ default: break;
+ }
+ if (quit == TRUE)
+ break;
+ }
+
+ delwin (win);
+
+ endwin();
+ return 0;
+}
+#ifdef __STDC__
+void Continue (WINDOW *win)
+#else
+void Continue (win)
+WINDOW *win;
+#endif
+{
+ wmove(win, 10, 1);
+/* wclrtoeol(win);
+*/ mvwaddstr(win, 10, 1, " Press any key to continue");
+ wrefresh(win);
+ raw();
+ wgetch(win);
+}
+#ifdef __STDC_
+int initTest (WINDOW **win)
+#else
+int initTest (win)
+WINDOW **win;
+#endif
+{
+#ifdef PDCDEBUG
+ PDC_debug("initTest called\n");
+#endif
+ initscr();
+#ifdef PDCDEBUG
+ PDC_debug("after initscr()\n");
+#endif
+#ifdef A_COLOR
+ if (has_colors())
+ start_color();
+#endif
+ width = 60;
+ height = 13; /* Create a drawing window */
+ *win = newwin(height, width, (LINES-height)/2, (COLS-width)/2);
+ if(*win == NULL)
+ { endwin();
+ return 1;
+ }
+}
+#ifdef __STDC__
+void introTest (WINDOW *win)
+#else
+void introTest (win)
+WINDOW *win;
+#endif
+{
+ beep ();
+ werase(win);
+
+ box(win, ACS_VLINE, ACS_HLINE);
+ wrefresh(win);
+ cbreak ();
+ mvwaddstr(win, 1, 1, "You should have rectangle in the middle of the screen");
+ mvwaddstr(win, 2, 1, "You should have heard a beep");
+ Continue(win);
+ return;
+}
+#ifdef __STDC__
+void scrollTest (WINDOW *win)
+#else
+void scrollTest (win)
+WINDOW *win;
+#endif
+{
+ int i;
+ int OldX, OldY;
+ char *Message = "The window will now scroll slowly";
+
+ mvwprintw (win, height - 2, 1, Message);
+ wrefresh (win);
+ scrollok(win, TRUE);
+ for (i = 1; i <= height; i++) {
+ usleep (250);
+ scroll(win);
+ wrefresh (win);
+ };
+
+ getmaxyx (win, OldY, OldX);
+ mvwprintw (win, 6, 1, "The top of the window will scroll");
+ wmove (win, 1, 1);
+ wsetscrreg (win, 0, 4);
+ box(win, ACS_VLINE, ACS_HLINE);
+ wrefresh (win);
+ for (i = 1; i <= 5; i++) {
+ usleep (500);
+ scroll(win);
+ wrefresh (win);
+ };
+ wsetscrreg (win, 0, --OldY);
+
+}
+#ifdef __STDC__
+void inputTest (WINDOW *win)
+#else
+void inputTest (win)
+WINDOW *win;
+#endif
+{
+ int w, h, bx, by, sw, sh, i, c,num;
+ char buffer [80];
+ WINDOW *subWin;
+ wclear (win);
+
+ w = win->_maxx;
+ h = win->_maxy;
+ bx = win->_begx;
+ by = win->_begy;
+ sw = w / 3;
+ sh = h / 3;
+ if((subWin = subwin(win, sh, sw, by + h - sh - 2, bx + w - sw - 2)) == NULL)
+ return;
+
+#ifdef A_COLOR
+ if (has_colors())
+ {
+ init_pair(2,COLOR_CYAN,COLOR_BLUE);
+ wattrset(subWin, COLOR_PAIR(2) | A_BOLD);
+ }
+ else
+ wattrset(subWin, A_BOLD);
+#else
+ wattrset(subWin, A_BOLD);
+#endif
+ box(subWin, ACS_VLINE, ACS_HLINE);
+ wrefresh(win);
+
+ nocbreak();
+ mvwaddstr(win, 2, 1, "Press some keys for 5 seconds");
+ mvwaddstr(win, 1, 1, "Pressing ^C should do nothing");
+ wrefresh(win);
+
+ for (i = 0; i < 5; i++) {
+ werase (subWin);
+ box(subWin, ACS_VLINE, ACS_HLINE);
+ mvwprintw (subWin, 1, 1, "Time = %d", i);
+ wrefresh(subWin);
+ usleep(1000);
+ flushinp();
+ }
+
+ delwin (subWin);
+ werase(win);
+ flash();
+ wrefresh(win);
+ usleep(500);
+
+ mvwaddstr(win, 2, 1, "Press a key, followed by ENTER");
+ wmove(win, 9, 10);
+ wrefresh(win);
+ echo();
+ noraw();
+ wgetch(win);
+ flushinp();
+
+ wmove(win, 9, 10);
+ wdelch(win);
+ mvwaddstr(win, 4, 1, "The character should now have been deleted");
+ Continue(win);
+
+ wclear (win);
+ mvwaddstr(win, 2, 1, "Press a function key or an arrow key");
+ wrefresh(win);
+ keypad(win, TRUE);
+ raw();
+ c = wgetch(win);
+
+ nodelay(win, TRUE);
+ wgetch(win);
+ nodelay(win, FALSE);
+
+ refresh();
+ wclear (win);
+ mvwaddstr(win, 3, 2, "The window should have moved");
+ mvwaddstr(win, 4, 2, "This text should have appeared without you pressing a key");
+ mvwprintw(win, 2, 2, "Keycode = %d", c);
+ mvwaddstr(win, 6, 2, "Enter a number then a string seperated by space");
+ echo();
+ noraw();
+ mvwscanw(win, 7, 6, "%d %s", &num,buffer);
+ mvwprintw(win, 8, 6, "String: %s Number: %d", buffer,num);
+ Continue(win);
+}
+#ifdef __STDC__
+void outputTest (WINDOW *win)
+#else
+void outputTest (win)
+WINDOW *win;
+#endif
+{
+ WINDOW *win1;
+ char Buffer [80];
+ chtype ch;
+
+ /* traceon(); */
+ nl ();
+ wclear (win);
+ mvwaddstr(win, 1, 1, "You should now have a screen in the upper left corner, and this text should have wrapped");
+ mvwin(win, 2, 1);
+ Continue(win);
+
+ wclear(win);
+ mvwaddstr(win, 1, 1, "A new window will appear with this text in it");
+ mvwaddstr(win, 8, 1, "Press any key to continue");
+ wrefresh(win);
+ wgetch(win);
+
+ win1 = newwin(10, 50, 15, 25);
+ if(win1 == NULL)
+ { endwin();
+ return;
+ }
+#ifdef A_COLOR
+ if (has_colors())
+ {
+ init_pair(3,COLOR_BLUE,COLOR_WHITE);
+ wattrset(win1, COLOR_PAIR(3));
+ }
+ else
+ wattrset(win1, A_NORMAL);
+#else
+ wattrset(win1, A_NORMAL);
+#endif
+ wclear (win1);
+ mvwaddstr(win1, 5, 1, "This text should appear; using overlay option");
+ copywin(win, win1,0,0,0,0,10,50,TRUE);
+
+#ifdef UNIX
+ box(win1,ACS_VLINE,ACS_HLINE);
+#else
+ box(win1,0xb3,0xc4);
+#endif
+ wmove(win1, 8, 26);
+ wrefresh(win1);
+ wgetch(win1);
+
+ wclear(win1);
+ wattron(win1, A_BLINK);
+ mvwaddstr(win1, 4, 1, "This blinking text should appear in only the second window");
+ wattroff(win1, A_BLINK);
+ wrefresh(win1);
+ wgetch(win1);
+ delwin(win1);
+
+ wclear(win);
+ wrefresh(win);
+ mvwaddstr(win, 6, 2, "This line shouldn't appear");
+ mvwaddstr(win, 4, 2, "Only half of the next line is visible");
+ mvwaddstr(win, 5, 2, "Only half of the next line is visible");
+ wmove(win, 6, 1);
+ wclrtobot (win);
+ wmove(win, 5, 20);
+ wclrtoeol (win);
+ mvwaddstr(win, 8, 2, "This line also shouldn't appear");
+ wmove(win, 8, 1);
+ wdeleteln(win);
+ Continue(win);
+ /* traceoff(); */
+
+ wmove (win, 5, 9);
+ ch = winch (win);
+
+ wclear(win);
+ wmove (win, 6, 2);
+ waddstr (win, "The next char should be l: ");
+ winsch (win, ch);
+ Continue(win);
+
+ wmove(win, 5, 1);
+ winsertln (win);
+ mvwaddstr(win, 5, 2, "The lines below should have moved down");
+ Continue(win);
+
+ wclear(win);
+ wmove(win, 2, 2);
+ wprintw(win, "This is a formatted string in a window: %d %s\n", 42, "is it");
+ mvwaddstr(win, 10, 1, "Enter a string: ");
+ wrefresh(win);
+ noraw();
+ echo();
+ wscanw (win, "%s", Buffer);
+
+ wclear(win);
+ mvwaddstr(win, 10, 1, "Enter a string");
+ wrefresh(win);
+ clear();
+ move(0,0);
+ printw("This is a formatted string in stdscr: %d %s\n", 42, "is it");
+ mvaddstr(10, 1, "Enter a string: ");
+ refresh();
+ noraw();
+ echo();
+ scanw ("%s", Buffer);
+
+ wclear(win);
+ curs_set(2);
+ mvwaddstr(win, 1, 1, "The cursor should appear as a block");
+ Continue(win);
+
+ wclear(win);
+ curs_set(0);
+ mvwaddstr(win, 1, 1, "The cursor should have disappeared");
+ Continue(win);
+
+ wclear(win);
+ curs_set(1);
+ mvwaddstr(win, 1, 1, "The cursor should be an underline");
+ Continue(win);
+}
+
+#ifdef __STDC__
+void resizeTest(WINDOW *dummy)
+#else
+void resizeTest(dummy)
+WINDOW *dummy;
+#endif
+{
+ WINDOW *win1;
+ char Buffer [80];
+ chtype ch;
+
+ savetty ();
+
+ clear();
+ refresh();
+#ifdef __PDCURSES__
+ resize(50);
+#endif
+
+
+ win1 = newwin(11, 50, 14, 25);
+ if(win1 == NULL)
+ { endwin();
+ return;
+ }
+#ifdef A_COLOR
+ if (has_colors())
+ {
+ init_pair(3,COLOR_BLUE,COLOR_WHITE);
+ wattrset(win1, COLOR_PAIR(3));
+ }
+#endif
+ wclear (win1);
+
+ mvwaddstr(win1, 1, 1, "The screen may now have 50 lines");
+ Continue(win1);
+
+ resetty ();
+
+ wclear (win1);
+ mvwaddstr(win1, 1, 1, "The screen should now be reset");
+ Continue(win1);
+
+ delwin(win1);
+
+ clear();
+ refresh();
+
+}
+#ifdef __STDC__
+void padTest(WINDOW *dummy)
+#else
+void padTest(dummy)
+WINDOW *dummy;
+#endif
+{
+WINDOW *pad;
+
+ pad = newpad(50,100);
+ mvwaddstr(pad, 5, 2, "This is a new pad");
+ mvwaddstr(pad, 8, 0, "The end of this line should be truncated here:abcd");
+ mvwaddstr(pad,11, 1, "This line should not appear.");
+ wmove(pad, 10, 1);
+ wclrtoeol(pad);
+ mvwaddstr(pad, 10, 1, " Press any key to continue");
+ prefresh(pad,0,0,0,0,10,45);
+ keypad(pad, TRUE);
+ raw();
+ wgetch(pad);
+
+ mvwaddstr(pad, 35, 2, "This is displayed at line 35 in the pad");
+ mvwaddstr(pad, 40, 1, " Press any key to continue");
+ prefresh(pad,30,0,0,0,10,45);
+ keypad(pad, TRUE);
+ raw();
+ wgetch(pad);
+
+ delwin(pad);
+}
+
+#ifdef __STDC__
+void display_menu(int old_option,int new_option)
+#else
+void display_menu(old_option,new_option)
+int old_option,new_option;
+#endif
+{
+ register int i;
+
+ attrset(A_NORMAL);
+ mvaddstr(3,20,"PDCurses Test Program");
+
+ for (i=0;i<MAX_OPTIONS;i++)
+ mvaddstr(5+i,25,command[i].text);
+ if (old_option != (-1))
+ mvaddstr(5+old_option,25,command[old_option].text);
+ attrset(A_REVERSE);
+ mvaddstr(5+new_option,25,command[new_option].text);
+ attrset(A_NORMAL);
+ mvaddstr(13,3,"Use Up and Down Arrows to select - Enter to run - Q to quit");
+ refresh();
+}
+
diff --git a/lib/libncurses/TESTS/worm.c b/lib/libncurses/TESTS/worm.c
new file mode 100644
index 0000000..abbe241
--- /dev/null
+++ b/lib/libncurses/TESTS/worm.c
@@ -0,0 +1,268 @@
+/*
+
+ @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@
+ @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@
+ @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@
+ @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
+ @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
+ @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@
+ @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@
+ @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@
+ @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@
+
+ Eric P. Scott
+ Caltech High Energy Physics
+ October, 1980
+
+*/
+
+#include <ncurses.h>
+#include <signal.h>
+
+#define cursor(col,row) move(row,col)
+
+int Wrap;
+short *ref[128];
+static char flavor[]={
+ 'O', '*', '#', '$', '%', '0'
+};
+static short xinc[]={
+ 1, 1, 1, 0, -1, -1, -1, 0
+}, yinc[]={
+ -1, 0, 1, 1, 1, 0, -1, -1
+};
+static struct worm {
+ int orientation, head;
+ short *xpos, *ypos;
+} worm[40];
+static char *field;
+static int length=16, number=3, trail=' ';
+static struct options {
+ int nopts;
+ int opts[3];
+} normal[8]={
+ { 3, { 7, 0, 1 } },
+ { 3, { 0, 1, 2 } },
+ { 3, { 1, 2, 3 } },
+ { 3, { 2, 3, 4 } },
+ { 3, { 3, 4, 5 } },
+ { 3, { 4, 5, 6 } },
+ { 3, { 5, 6, 7 } },
+ { 3, { 6, 7, 0 } }
+}, upper[8]={
+ { 1, { 1, 0, 0 } },
+ { 2, { 1, 2, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 2, { 4, 5, 0 } },
+ { 1, { 5, 0, 0 } },
+ { 2, { 1, 5, 0 } }
+}, left[8]={
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 2, { 2, 3, 0 } },
+ { 1, { 3, 0, 0 } },
+ { 2, { 3, 7, 0 } },
+ { 1, { 7, 0, 0 } },
+ { 2, { 7, 0, 0 } }
+}, right[8]={
+ { 1, { 7, 0, 0 } },
+ { 2, { 3, 7, 0 } },
+ { 1, { 3, 0, 0 } },
+ { 2, { 3, 4, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 2, { 6, 7, 0 } }
+}, lower[8]={
+ { 0, { 0, 0, 0 } },
+ { 2, { 0, 1, 0 } },
+ { 1, { 1, 0, 0 } },
+ { 2, { 1, 5, 0 } },
+ { 1, { 5, 0, 0 } },
+ { 2, { 5, 6, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } }
+}, upleft[8]={
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 1, { 3, 0, 0 } },
+ { 2, { 1, 3, 0 } },
+ { 1, { 1, 0, 0 } }
+}, upright[8]={
+ { 2, { 3, 5, 0 } },
+ { 1, { 3, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 1, { 5, 0, 0 } }
+}, lowleft[8]={
+ { 3, { 7, 0, 1 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 1, { 1, 0, 0 } },
+ { 2, { 1, 7, 0 } },
+ { 1, { 7, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } }
+}, lowright[8]={
+ { 0, { 0, 0, 0 } },
+ { 1, { 7, 0, 0 } },
+ { 2, { 5, 7, 0 } },
+ { 1, { 5, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } }
+};
+
+void onsig();
+float ranf();
+
+main(argc,argv)
+int argc;
+char *argv[];
+{
+int x, y;
+int n;
+struct worm *w;
+struct options *op;
+int h;
+short *ip;
+int last, bottom;
+
+ for (x=1;x<argc;x++) {
+ register char *p;
+ p=argv[x];
+ if (*p=='-') p++;
+ switch (*p) {
+ case 'f':
+ field="WORM";
+ break;
+ case 'l':
+ if (++x==argc) goto usage;
+ if ((length=atoi(argv[x]))<2||length>1024) {
+ fprintf(stderr,"%s: Invalid length\n",*argv);
+ exit(1);
+ }
+ break;
+ case 'n':
+ if (++x==argc) goto usage;
+ if ((number=atoi(argv[x]))<1||number>40) {
+ fprintf(stderr,"%s: Invalid number of worms\n",*argv);
+ exit(1);
+ }
+ break;
+ case 't':
+ trail='.';
+ break;
+ default:
+ usage:
+ fprintf(stderr, "usage: %s [-field] [-length #] [-number #] [-trail]\n",*argv);
+ exit(1);
+ break;
+ }
+ }
+
+ signal(SIGINT, onsig);
+ initscr();
+ bottom = LINES-1;
+ last = COLS-1;
+
+ ip=(short *)malloc(LINES*COLS*sizeof (short));
+
+ for (n=0;n<LINES;) {
+ ref[n++]=ip; ip+=COLS;
+ }
+ for (ip=ref[0],n=LINES*COLS;--n>=0;) *ip++=0;
+ ref[bottom][last]=1;
+ for (n=number, w= &worm[0];--n>=0;w++) {
+ w->orientation=w->head=0;
+ if (!(ip=(short *)malloc(length*sizeof (short)))) {
+ fprintf(stderr,"%s: out of memory\n",*argv);
+ exit(1);
+ }
+ w->xpos=ip;
+ for (x=length;--x>=0;) *ip++ = -1;
+ if (!(ip=(short *)malloc(length*sizeof (short)))) {
+ fprintf(stderr,"%s: out of memory\n",*argv);
+ exit(1);
+ }
+ w->ypos=ip;
+ for (y=length;--y>=0;) *ip++ = -1;
+ }
+ if (field) {
+ register char *p;
+ p=field;
+ for (y=bottom;--y>=0;) {
+ for (x=COLS;--x>=0;) {
+ addch(*p++);
+ if (!*p) p=field;
+ }
+ addch('\n');
+ }
+ }
+ refresh();
+
+ for (;;) {
+ for (n=0,w= &worm[0];n<number;n++,w++) {
+ if ((x=w->xpos[h=w->head])<0) {
+ cursor(x=w->xpos[h]=0,y=w->ypos[h]=bottom);
+ addch(flavor[n%6]);
+ ref[y][x]++;
+ }
+ else y=w->ypos[h];
+ if (++h==length) h=0;
+ if (w->xpos[w->head=h]>=0) {
+ register int x1, y1;
+ x1=w->xpos[h]; y1=w->ypos[h];
+ if (--ref[y1][x1]==0) {
+ cursor(x1,y1); addch(trail);
+ }
+ }
+ op= &(x==0 ? (y==0 ? upleft : (y==bottom ? lowleft : left)) :
+ (x==last ? (y==0 ? upright : (y==bottom ? lowright : right)) :
+ (y==0 ? upper : (y==bottom ? lower : normal))))[w->orientation];
+ switch (op->nopts) {
+ case 0:
+ refresh();
+ endwin();
+ exit(0);
+ case 1:
+ w->orientation=op->opts[0];
+ break;
+ default:
+ w->orientation=op->opts[(int)(ranf()*(float)op->nopts)];
+ }
+ cursor(x+=xinc[w->orientation], y+=yinc[w->orientation]);
+ if (!Wrap||x!=last||y!=bottom) addch(flavor[n%6]);
+ ref[w->ypos[h]=y][w->xpos[h]=x]++;
+ }
+ refresh();
+ }
+}
+
+void
+onsig()
+{
+ endwin();
+ exit(0);
+}
+
+float
+ranf()
+{
+float rv;
+long r = rand();
+
+ r &= 077777;
+ rv =((float)r/32767.);
+ return rv;
+}
diff --git a/lib/libncurses/TESTS/xmas.c b/lib/libncurses/TESTS/xmas.c
new file mode 100644
index 0000000..57cc0ea
--- /dev/null
+++ b/lib/libncurses/TESTS/xmas.c
@@ -0,0 +1,1192 @@
+/******************************************************************************/
+/* asciixmas */
+/* December 1989 Larry Bartz Indianapolis, IN */
+/* */
+/* */
+/* I'm dreaming of an ascii character-based monochrome Christmas, */
+/* Just like the one's I used to know! */
+/* Via a full duplex communications channel, */
+/* At 9600 bits per second, */
+/* Even though it's kinda slow. */
+/* */
+/* I'm dreaming of an ascii character-based monochrome Christmas, */
+/* With ev'ry C program I write! */
+/* May your screen be merry and bright! */
+/* And may all your Christmases be amber or green, */
+/* (for reduced eyestrain and improved visibility)! */
+/* */
+/* */
+/* */
+/* */
+/* */
+/* IMPLEMENTATION */
+/* */
+/* Feel free to modify the defined string FROMWHO to reflect you, your */
+/* organization, your site, whatever. */
+/* */
+/* This really looks a lot better if you can turn off your cursor before */
+/* execution. I wanted to do that here but very few termcap entries or */
+/* terminfo definitions have the appropriate string defined. If you know */
+/* the string(s) for the terminal(s) you use or which your site supports, */
+/* you could call asciixmas from within a shell in which you issue the */
+/* string to the terminal. The cursor is distracting but it doesn't really */
+/* ruin the show. */
+/* */
+/* At our site, we invoke this for our users just after login and the */
+/* determination of terminal type. */
+/* */
+/* */
+/* PORTABILITY */
+/* */
+/* I wrote this using only the very simplest curses functions so that it */
+/* might be the most portable. I was personally able to test on five */
+/* different cpu/UNIX combinations. */
+/* */
+/* */
+/* COMPILE */
+/* */
+/* usually this: */
+/* */
+/* cc -O asciixmas.c -lcurses -o asciixmas -s */
+/* */
+/* */
+/* Zilog S8000 models 11, 21, 31, etc with ZEUS variant of SYSTEM III */
+/* maybe other SYSTEM III also: */
+/* */
+/* cc asciixmas.c -lcurses -ltermlib -o asciixmas -s */
+/* */
+/* as above with optional "peephole optimizer" installed: */
+/* */
+/* cc -O asciixmas.c -lcurses -ltermlib -o asciixmas -s */
+/* */
+/* */
+/* Zilog S8000 models 32, 130 with WE32100 chip and SYS V, REL2 */
+/* maybe 3B2 also? */
+/* */
+/* cc -f -O -K sd asciixmas.c -lcurses -o asciixmas -s */
+/* */
+/* */
+/* Pyramid, Sequent, any other "dual universe" types compile and execute */
+/* under either universe. The compile line for the ucb universe (as you */
+/* might expect) is the same as for SYS III UNIX: */
+/* */
+/* cc -O asciixmas.c -lcurses -ltermlib -o asciixmas -s */
+/* */
+/* The above compile will also hold true for other BSD systems. (I hope) */
+/* */
+/* */
+/* */
+/* */
+/* For the Scrooges out there among you who don't want this thing to loop */
+/* forever (or until the user hits a key), insert this into your compile */
+/* line just after "cc" : */
+/* */
+/* -DNOLOOP */
+/* */
+/* like so: */
+/* */
+/* cc -DNOLOOP -O asciixmas.c -lcurses -o asciixmas -s */
+/* */
+/* */
+/* */
+/******************************************************************************/
+
+#include <ncurses.h>
+#include <signal.h>
+
+#define FROMWHO "Mark Hessling - (M.Hessling@gu.edu.au)"
+
+int y_pos, x_pos;
+
+WINDOW
+ *treescrn, *treescrn2,*treescrn3, *treescrn4,*treescrn5, *treescrn6,
+ *treescrn7, *treescrn8,
+ *dotdeer0,
+ *stardeer0,
+ *lildeer0, *lildeer1, *lildeer2, *lildeer3,
+ *middeer0, *middeer1, *middeer2, *middeer3,
+ *bigdeer0, *bigdeer1, *bigdeer2, *bigdeer3, *bigdeer4,
+ *lookdeer0, *lookdeer1, *lookdeer2, *lookdeer3, *lookdeer4,
+ *w_holiday,
+ *w_del_msg;
+
+void main()
+{
+ void done();
+ int loopy;
+
+ initscr();
+ noecho();
+ nonl();
+ refresh();
+ signal(SIGINT,done);
+ signal(SIGTERM,done);
+#if !defined DOS && !defined OS2
+ signal(SIGHUP,done);
+ signal(SIGQUIT,done);
+#endif
+
+
+
+ treescrn = newwin(16,27,3,53);
+ treescrn2 = newwin(16,27,3,53);
+ treescrn3 = newwin(16,27,3,53);
+ treescrn4 = newwin(16,27,3,53);
+ treescrn5 = newwin(16,27,3,53);
+ treescrn6 = newwin(16,27,3,53);
+ treescrn7 = newwin(16,27,3,53);
+ treescrn8 = newwin(16,27,3,53);
+
+ dotdeer0 = newwin(3,71,0,8);
+
+ stardeer0 = newwin(4,56,0,8);
+
+ lildeer0 = newwin(7,53,0,8);
+ lildeer1 = newwin(2,4,0,0);
+ lildeer2 = newwin(2,4,0,0);
+ lildeer3 = newwin(2,4,0,0);
+
+ middeer0 = newwin(15,42,0,8);
+ middeer1 = newwin(3,7,0,0);
+ middeer2 = newwin(3,7,0,0);
+ middeer3 = newwin(3,7,0,0);
+
+ bigdeer0 = newwin(10,23,0,0);
+ bigdeer1 = newwin(10,23,0,0);
+ bigdeer2 = newwin(10,23,0,0);
+ bigdeer3 = newwin(10,23,0,0);
+ bigdeer4 = newwin(10,23,0,0);
+
+ lookdeer0 = newwin(10,25,0,0);
+ lookdeer1 = newwin(10,25,0,0);
+ lookdeer2 = newwin(10,25,0,0);
+ lookdeer3 = newwin(10,25,0,0);
+ lookdeer4 = newwin(10,25,0,0);
+
+ w_holiday = newwin(1,26,3,27);
+
+ w_del_msg = newwin(1,12,23,60);
+
+ mvwaddstr(w_del_msg,0,0,"Hit any key to quit");
+
+ mvwaddstr(w_holiday,0,0,"H A P P Y H O L I D A Y S");
+
+ /* set up the windows for our various reindeer */
+
+ /* lildeer1 */
+ mvwaddch(lildeer1,0,0,(chtype)'V');
+ mvwaddch(lildeer1,1,0,(chtype)'@');
+ mvwaddch(lildeer1,1,1,(chtype)'<');
+ mvwaddch(lildeer1,1,2,(chtype)'>');
+ mvwaddch(lildeer1,1,3,(chtype)'~');
+
+ /* lildeer2 */
+ mvwaddch(lildeer2,0,0,(chtype)'V');
+ mvwaddch(lildeer2,1,0,(chtype)'@');
+ mvwaddch(lildeer2,1,1,(chtype)'|');
+ mvwaddch(lildeer2,1,2,(chtype)'|');
+ mvwaddch(lildeer2,1,3,(chtype)'~');
+
+ /* lildeer3 */
+ mvwaddch(lildeer3,0,0,(chtype)'V');
+ mvwaddch(lildeer3,1,0,(chtype)'@');
+ mvwaddch(lildeer3,1,1,(chtype)'>');
+ mvwaddch(lildeer3,1,2,(chtype)'<');
+ mvwaddch(lildeer2,1,3,(chtype)'~');
+
+
+ /* middeer1 */
+ mvwaddch(middeer1,0,2,(chtype)'y');
+ mvwaddch(middeer1,0,3,(chtype)'y');
+ mvwaddch(middeer1,1,2,(chtype)'0');
+ mvwaddch(middeer1,1,3,(chtype)'(');
+ mvwaddch(middeer1,1,4,(chtype)'=');
+ mvwaddch(middeer1,1,5,(chtype)')');
+ mvwaddch(middeer1,1,6,(chtype)'~');
+ mvwaddch(middeer1,2,3,(chtype)'\\');
+ mvwaddch(middeer1,2,4,(chtype)'/');
+
+ /* middeer2 */
+ mvwaddch(middeer2,0,2,(chtype)'y');
+ mvwaddch(middeer2,0,3,(chtype)'y');
+ mvwaddch(middeer2,1,2,(chtype)'0');
+ mvwaddch(middeer2,1,3,(chtype)'(');
+ mvwaddch(middeer2,1,4,(chtype)'=');
+ mvwaddch(middeer2,1,5,(chtype)')');
+ mvwaddch(middeer2,1,6,(chtype)'~');
+ mvwaddch(middeer2,2,3,(chtype)'|');
+ mvwaddch(middeer2,2,5,(chtype)'|');
+
+ /* middeer3 */
+ mvwaddch(middeer3,0,2,(chtype)'y');
+ mvwaddch(middeer3,0,3,(chtype)'y');
+ mvwaddch(middeer3,1,2,(chtype)'0');
+ mvwaddch(middeer3,1,3,(chtype)'(');
+ mvwaddch(middeer3,1,4,(chtype)'=');
+ mvwaddch(middeer3,1,5,(chtype)')');
+ mvwaddch(middeer3,1,6,(chtype)'~');
+ mvwaddch(middeer3,2,2,(chtype)'/');
+ mvwaddch(middeer3,2,6,(chtype)'\\');
+
+
+ /* bigdeer1 */
+ mvwaddch(bigdeer1,0,17,(chtype)'\\');
+ mvwaddch(bigdeer1,0,18,(chtype)'/');
+ mvwaddch(bigdeer1,0,20,(chtype)'\\');
+ mvwaddch(bigdeer1,0,21,(chtype)'/');
+ mvwaddch(bigdeer1,1,18,(chtype)'\\');
+ mvwaddch(bigdeer1,1,20,(chtype)'/');
+ mvwaddch(bigdeer1,2,19,(chtype)'|');
+ mvwaddch(bigdeer1,2,20,(chtype)'_');
+ mvwaddch(bigdeer1,3,18,(chtype)'/');
+ mvwaddch(bigdeer1,3,19,(chtype)'^');
+ mvwaddch(bigdeer1,3,20,(chtype)'0');
+ mvwaddch(bigdeer1,3,21,(chtype)'\\');
+ mvwaddch(bigdeer1,4,17,(chtype)'/');
+ mvwaddch(bigdeer1,4,18,(chtype)'/');
+ mvwaddch(bigdeer1,4,19,(chtype)'\\');
+ mvwaddch(bigdeer1,4,22,(chtype)'\\');
+ mvwaddstr(bigdeer1,5,7,"^~~~~~~~~// ~~U");
+ mvwaddstr(bigdeer1,6,7,"( \\_____( /");
+ mvwaddstr(bigdeer1,7,8,"( ) /");
+ mvwaddstr(bigdeer1,8,9,"\\\\ /");
+ mvwaddstr(bigdeer1,9,11,"\\>/>");
+
+ /* bigdeer2 */
+ mvwaddch(bigdeer2,0,17,(chtype)'\\');
+ mvwaddch(bigdeer2,0,18,(chtype)'/');
+ mvwaddch(bigdeer2,0,20,(chtype)'\\');
+ mvwaddch(bigdeer2,0,21,(chtype)'/');
+ mvwaddch(bigdeer2,1,18,(chtype)'\\');
+ mvwaddch(bigdeer2,1,20,(chtype)'/');
+ mvwaddch(bigdeer2,2,19,(chtype)'|');
+ mvwaddch(bigdeer2,2,20,(chtype)'_');
+ mvwaddch(bigdeer2,3,18,(chtype)'/');
+ mvwaddch(bigdeer2,3,19,(chtype)'^');
+ mvwaddch(bigdeer2,3,20,(chtype)'0');
+ mvwaddch(bigdeer2,3,21,(chtype)'\\');
+ mvwaddch(bigdeer2,4,17,(chtype)'/');
+ mvwaddch(bigdeer2,4,18,(chtype)'/');
+ mvwaddch(bigdeer2,4,19,(chtype)'\\');
+ mvwaddch(bigdeer2,4,22,(chtype)'\\');
+ mvwaddstr(bigdeer2,5,7,"^~~~~~~~~// ~~U");
+ mvwaddstr(bigdeer2,6,7,"(( )____( /");
+ mvwaddstr(bigdeer2,7,7,"( / |");
+ mvwaddstr(bigdeer2,8,8,"\\/ |");
+ mvwaddstr(bigdeer2,9,9,"|> |>");
+
+ /* bigdeer3 */
+ mvwaddch(bigdeer3,0,17,(chtype)'\\');
+ mvwaddch(bigdeer3,0,18,(chtype)'/');
+ mvwaddch(bigdeer3,0,20,(chtype)'\\');
+ mvwaddch(bigdeer3,0,21,(chtype)'/');
+ mvwaddch(bigdeer3,1,18,(chtype)'\\');
+ mvwaddch(bigdeer3,1,20,(chtype)'/');
+ mvwaddch(bigdeer3,2,19,(chtype)'|');
+ mvwaddch(bigdeer3,2,20,(chtype)'_');
+ mvwaddch(bigdeer3,3,18,(chtype)'/');
+ mvwaddch(bigdeer3,3,19,(chtype)'^');
+ mvwaddch(bigdeer3,3,20,(chtype)'0');
+ mvwaddch(bigdeer3,3,21,(chtype)'\\');
+ mvwaddch(bigdeer3,4,17,(chtype)'/');
+ mvwaddch(bigdeer3,4,18,(chtype)'/');
+ mvwaddch(bigdeer3,4,19,(chtype)'\\');
+ mvwaddch(bigdeer3,4,22,(chtype)'\\');
+ mvwaddstr(bigdeer3,5,7,"^~~~~~~~~// ~~U");
+ mvwaddstr(bigdeer3,6,6,"( ()_____( /");
+ mvwaddstr(bigdeer3,7,6,"/ / /");
+ mvwaddstr(bigdeer3,8,5,"|/ \\");
+ mvwaddstr(bigdeer3,9,5,"/> \\>");
+
+ /* bigdeer4 */
+ mvwaddch(bigdeer4,0,17,(chtype)'\\');
+ mvwaddch(bigdeer4,0,18,(chtype)'/');
+ mvwaddch(bigdeer4,0,20,(chtype)'\\');
+ mvwaddch(bigdeer4,0,21,(chtype)'/');
+ mvwaddch(bigdeer4,1,18,(chtype)'\\');
+ mvwaddch(bigdeer4,1,20,(chtype)'/');
+ mvwaddch(bigdeer4,2,19,(chtype)'|');
+ mvwaddch(bigdeer4,2,20,(chtype)'_');
+ mvwaddch(bigdeer4,3,18,(chtype)'/');
+ mvwaddch(bigdeer4,3,19,(chtype)'^');
+ mvwaddch(bigdeer4,3,20,(chtype)'0');
+ mvwaddch(bigdeer4,3,21,(chtype)'\\');
+ mvwaddch(bigdeer4,4,17,(chtype)'/');
+ mvwaddch(bigdeer4,4,18,(chtype)'/');
+ mvwaddch(bigdeer4,4,19,(chtype)'\\');
+ mvwaddch(bigdeer4,4,22,(chtype)'\\');
+ mvwaddstr(bigdeer4,5,7,"^~~~~~~~~// ~~U");
+ mvwaddstr(bigdeer4,6,6,"( )______( /");
+ mvwaddstr(bigdeer4,7,5,"(/ \\");
+ mvwaddstr(bigdeer4,8,0,"v___= ----^");
+
+
+ /* lookdeer1 */
+ mvwaddstr(lookdeer1,0,16,"\\/ \\/");
+ mvwaddstr(lookdeer1,1,17,"\\Y/ \\Y/");
+ mvwaddstr(lookdeer1,2,19,"\\=/");
+ mvwaddstr(lookdeer1,3,17,"^\\o o/^");
+ mvwaddstr(lookdeer1,4,17,"//( )");
+ mvwaddstr(lookdeer1,5,7,"^~~~~~~~~// \\O/");
+ mvwaddstr(lookdeer1,6,7,"( \\_____( /");
+ mvwaddstr(lookdeer1,7,8,"( ) /");
+ mvwaddstr(lookdeer1,8,9,"\\\\ /");
+ mvwaddstr(lookdeer1,9,11,"\\>/>");
+
+ /* lookdeer2 */
+ mvwaddstr(lookdeer2,0,16,"\\/ \\/");
+ mvwaddstr(lookdeer2,1,17,"\\Y/ \\Y/");
+ mvwaddstr(lookdeer2,2,19,"\\=/");
+ mvwaddstr(lookdeer2,3,17,"^\\o o/^");
+ mvwaddstr(lookdeer2,4,17,"//( )");
+ mvwaddstr(lookdeer2,5,7,"^~~~~~~~~// \\O/");
+ mvwaddstr(lookdeer2,6,7,"(( )____( /");
+ mvwaddstr(lookdeer2,7,7,"( / |");
+ mvwaddstr(lookdeer2,8,8,"\\/ |");
+ mvwaddstr(lookdeer2,9,9,"|> |>");
+
+ /* lookdeer3 */
+ mvwaddstr(lookdeer3,0,16,"\\/ \\/");
+ mvwaddstr(lookdeer3,1,17,"\\Y/ \\Y/");
+ mvwaddstr(lookdeer3,2,19,"\\=/");
+ mvwaddstr(lookdeer3,3,17,"^\\o o/^");
+ mvwaddstr(lookdeer3,4,17,"//( )");
+ mvwaddstr(lookdeer3,5,7,"^~~~~~~~~// \\O/");
+ mvwaddstr(lookdeer3,6,6,"( ()_____( /");
+ mvwaddstr(lookdeer3,7,6,"/ / /");
+ mvwaddstr(lookdeer3,8,5,"|/ \\");
+ mvwaddstr(lookdeer3,9,5,"/> \\>");
+
+ /* lookdeer4 */
+ mvwaddstr(lookdeer4,0,16,"\\/ \\/");
+ mvwaddstr(lookdeer4,1,17,"\\Y/ \\Y/");
+ mvwaddstr(lookdeer4,2,19,"\\=/");
+ mvwaddstr(lookdeer4,3,17,"^\\o o/^");
+ mvwaddstr(lookdeer4,4,17,"//( )");
+ mvwaddstr(lookdeer4,5,7,"^~~~~~~~~// \\O/");
+ mvwaddstr(lookdeer4,6,6,"( )______( /");
+ mvwaddstr(lookdeer4,7,5,"(/ \\");
+ mvwaddstr(lookdeer4,8,0,"v___= ----^");
+
+
+
+ /***********************************************/
+ cbreak();
+ nodelay(stdscr,TRUE);
+ do
+ {
+ clear();
+ werase(treescrn);
+ touchwin(treescrn);
+ werase(treescrn2);
+ touchwin(treescrn2);
+ werase(treescrn8);
+ touchwin(treescrn8);
+ refresh();
+ usleep(1000);
+ boxit();
+ refresh();
+ usleep(1000);
+ seas();
+ refresh();
+ usleep(1000);
+ greet();
+ refresh();
+ usleep(1000);
+ fromwho();
+ refresh();
+ usleep(1000);
+ tree();
+ usleep(1000);
+ balls();
+ usleep(1000);
+ star();
+ usleep(1000);
+ strng1();
+ strng2();
+ strng3();
+ strng4();
+ strng5();
+
+
+ /* set up the windows for our blinking trees */
+ /* **************************************** */
+ /* treescrn3 */
+
+ overlay(treescrn, treescrn3);
+
+ /*balls*/
+ mvwaddch(treescrn3, 4, 18, ' ');
+ mvwaddch(treescrn3, 7, 6, ' ');
+ mvwaddch(treescrn3, 8, 19, ' ');
+ mvwaddch(treescrn3, 11, 22, ' ');
+
+ /*star*/
+ mvwaddch(treescrn3, 0, 12, '*');
+
+ /*strng1*/
+ mvwaddch(treescrn3, 3, 11, ' ');
+
+ /*strng2*/
+ mvwaddch(treescrn3, 5, 13, ' ');
+ mvwaddch(treescrn3, 6, 10, ' ');
+
+ /*strng3*/
+ mvwaddch(treescrn3, 7, 16, ' ');
+ mvwaddch(treescrn3, 7, 14, ' ');
+
+ /*strng4*/
+ mvwaddch(treescrn3, 10, 13, ' ');
+ mvwaddch(treescrn3, 10, 10, ' ');
+ mvwaddch(treescrn3, 11, 8, ' ');
+
+ /*strng5*/
+ mvwaddch(treescrn3, 11, 18, ' ');
+ mvwaddch(treescrn3, 12, 13, ' ');
+
+
+ /* treescrn4 */
+
+ overlay(treescrn, treescrn4);
+
+ /*balls*/
+ mvwaddch(treescrn4, 3, 9, ' ');
+ mvwaddch(treescrn4, 4, 16, ' ');
+ mvwaddch(treescrn4, 7, 6, ' ');
+ mvwaddch(treescrn4, 8, 19, ' ');
+ mvwaddch(treescrn4, 11, 2, ' ');
+ mvwaddch(treescrn4, 12, 23, ' ');
+
+ /*star*/
+ wstandout(treescrn4);
+ mvwaddch(treescrn4, 0, 12, '*');
+ wstandend(treescrn4);
+
+ /*strng1*/
+ mvwaddch(treescrn4, 3, 13, ' ');
+
+ /*strng2*/
+
+ /*strng3*/
+ mvwaddch(treescrn4, 7, 15, ' ');
+ mvwaddch(treescrn4, 8, 11, ' ');
+
+ /*strng4*/
+ mvwaddch(treescrn4, 9, 16, ' ');
+ mvwaddch(treescrn4, 10, 12, ' ');
+ mvwaddch(treescrn4, 11, 8, ' ');
+
+ /*strng5*/
+ mvwaddch(treescrn4, 11, 18, ' ');
+ mvwaddch(treescrn4, 12, 14, ' ');
+
+
+ /* treescrn5 */
+
+ overlay(treescrn, treescrn5);
+
+ /*balls*/
+ mvwaddch(treescrn5, 3, 15, ' ');
+ mvwaddch(treescrn5, 10, 20, ' ');
+ mvwaddch(treescrn5, 12, 1, ' ');
+
+ /*star*/
+ mvwaddch(treescrn5, 0, 12, '*');
+
+ /*strng1*/
+ mvwaddch(treescrn5, 3, 11, ' ');
+
+ /*strng2*/
+ mvwaddch(treescrn5, 5, 12, ' ');
+
+ /*strng3*/
+ mvwaddch(treescrn5, 7, 14, ' ');
+ mvwaddch(treescrn5, 8, 10, ' ');
+
+ /*strng4*/
+ mvwaddch(treescrn5, 9, 15, ' ');
+ mvwaddch(treescrn5, 10, 11, ' ');
+ mvwaddch(treescrn5, 11, 7, ' ');
+
+ /*strng5*/
+ mvwaddch(treescrn5, 11, 17, ' ');
+ mvwaddch(treescrn5, 12, 13, ' ');
+
+ /* treescrn6 */
+
+ overlay(treescrn, treescrn6);
+
+ /*balls*/
+ mvwaddch(treescrn6, 6, 7, ' ');
+ mvwaddch(treescrn6, 7, 18, ' ');
+ mvwaddch(treescrn6, 10, 4, ' ');
+ mvwaddch(treescrn6, 11, 23, ' ');
+
+ /*star*/
+ wstandout(treescrn6);
+ mvwaddch(treescrn6, 0, 12, '*');
+ wstandend(treescrn6);
+
+ /*strng1*/
+
+ /*strng2*/
+ mvwaddch(treescrn6, 5, 11, ' ');
+
+ /*strng3*/
+ mvwaddch(treescrn6, 7, 13, ' ');
+ mvwaddch(treescrn6, 8, 9, ' ');
+
+ /*strng4*/
+ mvwaddch(treescrn6, 9, 14, ' ');
+ mvwaddch(treescrn6, 10, 10, ' ');
+ mvwaddch(treescrn6, 11, 6, ' ');
+
+ /*strng5*/
+ mvwaddch(treescrn6, 11, 16, ' ');
+ mvwaddch(treescrn6, 12, 12, ' ');
+
+ /* treescrn7 */
+
+ overlay(treescrn, treescrn7);
+
+ /*balls*/
+ mvwaddch(treescrn7, 3, 15, ' ');
+ mvwaddch(treescrn7, 6, 7, ' ');
+ mvwaddch(treescrn7, 7, 18, ' ');
+ mvwaddch(treescrn7, 10, 4, ' ');
+ mvwaddch(treescrn7, 11, 22, ' ');
+
+ /*star*/
+ mvwaddch(treescrn7, 0, 12, '*');
+
+ /*strng1*/
+ mvwaddch(treescrn7, 3, 12, ' ');
+
+ /*strng2*/
+ mvwaddch(treescrn7, 5, 13, ' ');
+ mvwaddch(treescrn7, 6, 9, ' ');
+
+ /*strng3*/
+ mvwaddch(treescrn7, 7, 15, ' ');
+ mvwaddch(treescrn7, 8, 11, ' ');
+
+ /*strng4*/
+ mvwaddch(treescrn7, 9, 16, ' ');
+ mvwaddch(treescrn7, 10, 12, ' ');
+ mvwaddch(treescrn7, 11, 8, ' ');
+
+ /*strng5*/
+ mvwaddch(treescrn7, 11, 18, ' ');
+ mvwaddch(treescrn7, 12, 14, ' ');
+
+
+ usleep(1000);
+ reindeer();
+
+ touchwin(w_holiday);
+ wrefresh(w_holiday);
+ wrefresh(w_del_msg);
+
+ usleep(1000);
+ for(loopy = 0;loopy < 100;loopy++)
+ {
+ blinkit();
+ }
+
+#ifdef NOLOOP
+ done();
+#endif
+
+ }
+ while(getch() == (ERR));
+/* while(!typeahead(stdin));*/
+ done();
+}
+
+boxit()
+{
+ int x = 0;
+
+ while(x < 20)
+ {
+ mvaddch(x, 7, '|');
+ ++x;
+ }
+
+ x = 8;
+
+ while(x < 80)
+ {
+ mvaddch(19, x, '_');
+ ++x;
+ }
+
+ x = 0;
+
+ while(x < 80)
+ {
+ mvaddch(22, x, '_');
+ ++x;
+ }
+
+ return( 0 );
+}
+
+seas()
+{
+ mvaddch(4, 1, 'S');
+ mvaddch(6, 1, 'E');
+ mvaddch(8, 1, 'A');
+ mvaddch(10, 1, 'S');
+ mvaddch(12, 1, 'O');
+ mvaddch(14, 1, 'N');
+ mvaddch(16, 1, '`');
+ mvaddch(18, 1, 'S');
+
+ return( 0 );
+}
+
+
+greet()
+{
+ mvaddch(3, 5, 'G');
+ mvaddch(5, 5, 'R');
+ mvaddch(7, 5, 'E');
+ mvaddch(9, 5, 'E');
+ mvaddch(11, 5, 'T');
+ mvaddch(13, 5, 'I');
+ mvaddch(15, 5, 'N');
+ mvaddch(17, 5, 'G');
+ mvaddch(19, 5, 'S');
+
+ return( 0 );
+}
+
+
+fromwho()
+{
+ mvaddstr(21, 13, FROMWHO);
+ return( 0 );
+}
+
+
+del_msg()
+{
+ mvwaddstr(w_del_msg, 0, 0, "Hit any key to quit");
+ wrefresh(w_del_msg);
+
+ refresh();
+
+ return( 0 );
+}
+
+
+tree()
+{
+ mvwaddch(treescrn, 1, 11, (chtype)'/');
+ mvwaddch(treescrn, 2, 11, (chtype)'/');
+ mvwaddch(treescrn, 3, 10, (chtype)'/');
+ mvwaddch(treescrn, 4, 9, (chtype)'/');
+ mvwaddch(treescrn, 5, 9, (chtype)'/');
+ mvwaddch(treescrn, 6, 8, (chtype)'/');
+ mvwaddch(treescrn, 7, 7, (chtype)'/');
+ mvwaddch(treescrn, 8, 6, (chtype)'/');
+ mvwaddch(treescrn, 9, 6, (chtype)'/');
+ mvwaddch(treescrn, 10, 5, (chtype)'/');
+ mvwaddch(treescrn, 11, 3, (chtype)'/');
+ mvwaddch(treescrn, 12, 2, (chtype)'/');
+
+ mvwaddch(treescrn, 1, 13, (chtype)'\\');
+ mvwaddch(treescrn, 2, 13, (chtype)'\\');
+ mvwaddch(treescrn, 3, 14, (chtype)'\\');
+ mvwaddch(treescrn, 4, 15, (chtype)'\\');
+ mvwaddch(treescrn, 5, 15, (chtype)'\\');
+ mvwaddch(treescrn, 6, 16, (chtype)'\\');
+ mvwaddch(treescrn, 7, 17, (chtype)'\\');
+ mvwaddch(treescrn, 8, 18, (chtype)'\\');
+ mvwaddch(treescrn, 9, 18, (chtype)'\\');
+ mvwaddch(treescrn, 10, 19, (chtype)'\\');
+ mvwaddch(treescrn, 11, 21, (chtype)'\\');
+ mvwaddch(treescrn, 12, 22, (chtype)'\\');
+
+ mvwaddch(treescrn, 4, 10, (chtype)'_');
+ mvwaddch(treescrn, 4, 14, (chtype)'_');
+ mvwaddch(treescrn, 8, 7, (chtype)'_');
+ mvwaddch(treescrn, 8, 17, (chtype)'_');
+
+ mvwaddstr(treescrn, 13, 0, "//////////// \\\\\\\\\\\\\\\\\\\\\\\\");
+
+ mvwaddstr(treescrn, 14, 11, "| |");
+ mvwaddstr(treescrn, 15, 11, "|_|");
+
+ wrefresh(treescrn);
+ wrefresh(w_del_msg);
+
+ return( 0 );
+}
+
+
+balls()
+{
+
+ overlay(treescrn, treescrn2);
+
+ mvwaddch(treescrn2, 3, 9, (chtype)'@');
+ mvwaddch(treescrn2, 3, 15, (chtype)'@');
+ mvwaddch(treescrn2, 4, 8, (chtype)'@');
+ mvwaddch(treescrn2, 4, 16, (chtype)'@');
+ mvwaddch(treescrn2, 5, 7, (chtype)'@');
+ mvwaddch(treescrn2, 5, 17, (chtype)'@');
+ mvwaddch(treescrn2, 7, 6, (chtype)'@');
+ mvwaddch(treescrn2, 7, 18, (chtype)'@');
+ mvwaddch(treescrn2, 8, 5, (chtype)'@');
+ mvwaddch(treescrn2, 8, 19, (chtype)'@');
+ mvwaddch(treescrn2, 10, 4, (chtype)'@');
+ mvwaddch(treescrn2, 10, 20, (chtype)'@');
+ mvwaddch(treescrn2, 11, 2, (chtype)'@');
+ mvwaddch(treescrn2, 11, 22, (chtype)'@');
+ mvwaddch(treescrn2, 12, 1, (chtype)'@');
+ mvwaddch(treescrn2, 12, 23, (chtype)'@');
+
+ wrefresh(treescrn2);
+ wrefresh(w_del_msg);
+ return( 0 );
+}
+
+
+star()
+{
+ wstandout(treescrn2);
+ mvwaddch(treescrn2, 0, 12, (chtype)'*');
+ wstandend(treescrn2);
+
+ wrefresh(treescrn2);
+ wrefresh(w_del_msg);
+ return( 0 );
+}
+
+
+strng1()
+{
+ mvwaddch(treescrn2, 3, 13, (chtype)'\'');
+ mvwaddch(treescrn2, 3, 12, (chtype)':');
+ mvwaddch(treescrn2, 3, 11, (chtype)'.');
+
+ wrefresh(treescrn2);
+ wrefresh(w_del_msg);
+ return( 0 );
+}
+
+
+strng2()
+{
+ mvwaddch(treescrn2, 5, 14, (chtype)'\'');
+ mvwaddch(treescrn2, 5, 13, (chtype)':');
+ mvwaddch(treescrn2, 5, 12, (chtype)'.');
+ mvwaddch(treescrn2, 5, 11, (chtype)',');
+ mvwaddch(treescrn2, 6, 10, (chtype)'\'');
+ mvwaddch(treescrn2, 6, 9, (chtype)':');
+
+ wrefresh(treescrn2);
+ wrefresh(w_del_msg);
+ return( 0 );
+}
+
+
+strng3()
+{
+ mvwaddch(treescrn2, 7, 16, (chtype)'\'');
+ mvwaddch(treescrn2, 7, 15, (chtype)':');
+ mvwaddch(treescrn2, 7, 14, (chtype)'.');
+ mvwaddch(treescrn2, 7, 13, (chtype)',');
+ mvwaddch(treescrn2, 8, 12, (chtype)'\'');
+ mvwaddch(treescrn2, 8, 11, (chtype)':');
+ mvwaddch(treescrn2, 8, 10, (chtype)'.');
+ mvwaddch(treescrn2, 8, 9, (chtype)',');
+
+ wrefresh(treescrn2);
+ wrefresh(w_del_msg);
+ return( 0 );
+}
+
+
+strng4()
+{
+ mvwaddch(treescrn2, 9, 17, (chtype)'\'');
+ mvwaddch(treescrn2, 9, 16, (chtype)':');
+ mvwaddch(treescrn2, 9, 15, (chtype)'.');
+ mvwaddch(treescrn2, 9, 14, (chtype)',');
+ mvwaddch(treescrn2, 10, 13, (chtype)'\'');
+ mvwaddch(treescrn2, 10, 12, (chtype)':');
+ mvwaddch(treescrn2, 10, 11, (chtype)'.');
+ mvwaddch(treescrn2, 10, 10, (chtype)',');
+ mvwaddch(treescrn2, 11, 9, (chtype)'\'');
+ mvwaddch(treescrn2, 11, 8, (chtype)':');
+ mvwaddch(treescrn2, 11, 7, (chtype)'.');
+ mvwaddch(treescrn2, 11, 6, (chtype)',');
+ mvwaddch(treescrn2, 12, 5, (chtype)'\'');
+
+ wrefresh(treescrn2);
+ wrefresh(w_del_msg);
+ return( 0 );
+}
+
+
+strng5()
+{
+ mvwaddch(treescrn2, 11, 19, (chtype)'\'');
+ mvwaddch(treescrn2, 11, 18, (chtype)':');
+ mvwaddch(treescrn2, 11, 17, (chtype)'.');
+ mvwaddch(treescrn2, 11, 16, (chtype)',');
+ mvwaddch(treescrn2, 12, 15, (chtype)'\'');
+ mvwaddch(treescrn2, 12, 14, (chtype)':');
+ mvwaddch(treescrn2, 12, 13, (chtype)'.');
+ mvwaddch(treescrn2, 12, 12, (chtype)',');
+
+ /* save a fully lit tree */
+ overlay(treescrn2, treescrn);
+
+ wrefresh(treescrn2);
+ wrefresh(w_del_msg);
+ return( 0 );
+}
+
+
+
+blinkit()
+{
+ static int cycle;
+
+ if(cycle > 4)
+ {
+ cycle = 0;
+ }
+
+
+ touchwin(treescrn8);
+
+ switch(cycle)
+ {
+
+ case 0:
+ overlay(treescrn3, treescrn8);
+ wrefresh(treescrn8);
+ wrefresh(w_del_msg);
+
+ break;
+ case 1:
+ overlay(treescrn4, treescrn8);
+ wrefresh(treescrn8);
+ wrefresh(w_del_msg);
+
+ break;
+ case 2:
+ overlay(treescrn5, treescrn8);
+ wrefresh(treescrn8);
+ wrefresh(w_del_msg);
+
+ break;
+ case 3:
+ overlay(treescrn6, treescrn8);
+ wrefresh(treescrn8);
+ wrefresh(w_del_msg);
+
+ break;
+ case 4:
+ overlay(treescrn7, treescrn8);
+ wrefresh(treescrn8);
+ wrefresh(w_del_msg);
+
+ break;
+ }
+
+ touchwin(treescrn8);
+
+
+
+ /*ALL ON***************************************************/
+
+
+ overlay(treescrn, treescrn8);
+ wrefresh(treescrn8);
+ wrefresh(w_del_msg);
+
+
+ ++cycle;
+ return( 0 );
+}
+
+
+reindeer()
+{
+ int looper;
+
+ y_pos = 0;
+
+
+ for(x_pos = 70; x_pos > 62; x_pos--)
+ {
+ if(x_pos < 62)
+ {
+ y_pos = 1;
+ }
+ for(looper = 0; looper < 4; looper++)
+ {
+ mvwaddch(dotdeer0, y_pos, x_pos, (chtype)'.');
+ wrefresh(dotdeer0);
+ wrefresh(w_del_msg);
+ werase(dotdeer0);
+ wrefresh(dotdeer0);
+ wrefresh(w_del_msg);
+ }
+ }
+
+ y_pos = 2;
+
+ for(; x_pos > 50; x_pos--)
+ {
+
+ for(looper = 0; looper < 4; looper++)
+ {
+
+ if(x_pos < 56)
+ {
+ y_pos = 3;
+
+ mvwaddch(stardeer0, y_pos, x_pos, (chtype)'*');
+ wrefresh(stardeer0);
+ wrefresh(w_del_msg);
+ werase(stardeer0);
+ wrefresh(stardeer0);
+ wrefresh(w_del_msg);
+ }
+ else
+ {
+ mvwaddch(dotdeer0, y_pos, x_pos, (chtype)'*');
+ wrefresh(dotdeer0);
+ wrefresh(w_del_msg);
+ werase(dotdeer0);
+ wrefresh(dotdeer0);
+ wrefresh(w_del_msg);
+ }
+ }
+ }
+
+ x_pos = 58;
+
+ for(y_pos = 2; y_pos < 5; y_pos++)
+ {
+
+ touchwin(lildeer0);
+ wrefresh(lildeer0);
+ wrefresh(w_del_msg);
+
+ for(looper = 0; looper < 4; looper++)
+ {
+ mvwin(lildeer3, y_pos, x_pos);
+ wrefresh(lildeer3);
+ wrefresh(w_del_msg);
+
+ mvwin(lildeer2, y_pos, x_pos);
+ wrefresh(lildeer2);
+ wrefresh(w_del_msg);
+
+ mvwin(lildeer1, y_pos, x_pos);
+ wrefresh(lildeer1);
+ wrefresh(w_del_msg);
+
+ mvwin(lildeer2, y_pos, x_pos);
+ wrefresh(lildeer2);
+ wrefresh(w_del_msg);
+
+ mvwin(lildeer3, y_pos, x_pos);
+ wrefresh(lildeer3);
+ wrefresh(w_del_msg);
+
+ touchwin(lildeer0);
+ wrefresh(lildeer0);
+ wrefresh(w_del_msg);
+
+ x_pos -= 2;
+ }
+ }
+
+
+ x_pos = 35;
+
+ for(y_pos = 5; y_pos < 10; y_pos++)
+ {
+
+ touchwin(middeer0);
+ wrefresh(middeer0);
+ wrefresh(w_del_msg);
+
+ for(looper = 0; looper < 2; looper++)
+ {
+ mvwin(middeer3, y_pos, x_pos);
+ wrefresh(middeer3);
+ wrefresh(w_del_msg);
+
+ mvwin(middeer2, y_pos, x_pos);
+ wrefresh(middeer2);
+ wrefresh(w_del_msg);
+
+ mvwin(middeer1, y_pos, x_pos);
+ wrefresh(middeer1);
+ wrefresh(w_del_msg);
+
+ mvwin(middeer2, y_pos, x_pos);
+ wrefresh(middeer2);
+ wrefresh(w_del_msg);
+
+ mvwin(middeer3, y_pos, x_pos);
+ wrefresh(middeer3);
+ wrefresh(w_del_msg);
+
+ touchwin(middeer0);
+ wrefresh(middeer0);
+ wrefresh(w_del_msg);
+
+ x_pos -= 3;
+ }
+ }
+
+ usleep(2000);
+
+ y_pos = 1;
+
+ for(x_pos = 8; x_pos < 16; x_pos++)
+ {
+
+ mvwin(bigdeer4, y_pos, x_pos);
+ wrefresh(bigdeer4);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer3, y_pos, x_pos);
+ wrefresh(bigdeer3);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer2, y_pos, x_pos);
+ wrefresh(bigdeer2);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer1, y_pos, x_pos);
+ wrefresh(bigdeer1);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer2, y_pos, x_pos);
+ wrefresh(bigdeer2);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer3, y_pos, x_pos);
+ wrefresh(bigdeer3);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer4, y_pos, x_pos);
+ wrefresh(bigdeer4);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer0, y_pos, x_pos);
+ wrefresh(bigdeer0);
+ wrefresh(w_del_msg);
+ }
+
+ --x_pos;
+
+ for(looper = 0; looper < 6; looper++)
+ {
+ mvwin(lookdeer4, y_pos, x_pos);
+ wrefresh(lookdeer4);
+ wrefresh(w_del_msg);
+
+ mvwin(lookdeer3, y_pos, x_pos);
+ wrefresh(lookdeer3);
+ wrefresh(w_del_msg);
+
+ mvwin(lookdeer2, y_pos, x_pos);
+ wrefresh(lookdeer2);
+ wrefresh(w_del_msg);
+
+ mvwin(lookdeer1, y_pos, x_pos);
+ wrefresh(lookdeer1);
+ wrefresh(w_del_msg);
+
+ mvwin(lookdeer2, y_pos, x_pos);
+ wrefresh(lookdeer2);
+ wrefresh(w_del_msg);
+
+ mvwin(lookdeer3, y_pos, x_pos);
+ wrefresh(lookdeer3);
+ wrefresh(w_del_msg);
+
+ mvwin(lookdeer4, y_pos, x_pos);
+ wrefresh(lookdeer4);
+ wrefresh(w_del_msg);
+
+ }
+
+ mvwin(lookdeer0, y_pos, x_pos);
+ wrefresh(lookdeer0);
+ wrefresh(w_del_msg);
+
+ for(; y_pos < 10; y_pos++)
+ {
+
+ for(looper = 0; looper < 2; looper++)
+ {
+ mvwin(bigdeer4, y_pos, x_pos);
+ wrefresh(bigdeer4);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer3, y_pos, x_pos);
+ wrefresh(bigdeer3);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer2, y_pos, x_pos);
+ wrefresh(bigdeer2);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer1, y_pos, x_pos);
+ wrefresh(bigdeer1);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer2, y_pos, x_pos);
+ wrefresh(bigdeer2);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer3, y_pos, x_pos);
+ wrefresh(bigdeer3);
+ wrefresh(w_del_msg);
+
+ mvwin(bigdeer4, y_pos, x_pos);
+ wrefresh(bigdeer4);
+ wrefresh(w_del_msg);
+ }
+ mvwin(bigdeer0, y_pos, x_pos);
+ wrefresh(bigdeer0);
+ wrefresh(w_del_msg);
+ }
+
+ --y_pos;
+
+ mvwin(lookdeer3, y_pos, x_pos);
+ wrefresh(lookdeer3);
+ wrefresh(w_del_msg);
+ return( 0 );
+}
+
+
+
+void done()
+{
+ signal(SIGINT,done);
+ signal(SIGTERM,done);
+#if !defined DOS && !defined OS2
+ signal(SIGHUP,done);
+ signal(SIGQUIT,done);
+#endif
+ clear();
+ refresh();
+ endwin();
+ exit(0);
+}
diff --git a/lib/libncurses/copyright.c b/lib/libncurses/copyright.c
new file mode 100644
index 0000000..5964afc
--- /dev/null
+++ b/lib/libncurses/copyright.c
@@ -0,0 +1,19 @@
+char _ncurses_copyright[] = "\n\
+/***************************************************************************
+* COPYRIGHT NOTICE *
+****************************************************************************
+* ncurses is copyright (C) 1992, 1993, 1994 *
+* by Zeyd M. Ben-Halim *
+* zmbenhal@netcom.com *
+* *
+* Permission is hereby granted to reproduce and distribute ncurses *
+* by any means and for any fee, whether alone or as part of a *
+* larger distribution, in source or in binary form, PROVIDED *
+* this notice is included with any such distribution, not removed *
+* from header files, and is reproduced in any documentation *
+* accompanying it or the applications linked with it. *
+* *
+* ncurses comes AS IS with no warranty, implied or expressed. *
+* *
+***************************************************************************/
+\n";
diff --git a/lib/libncurses/curs_addch.3 b/lib/libncurses/curs_addch.3
new file mode 100644
index 0000000..5b26e32
--- /dev/null
+++ b/lib/libncurses/curs_addch.3
@@ -0,0 +1,115 @@
+.\" $Id$
+.\"
+.TH curs_addch 3 ""
+.SH NAME
+\fBaddch\fR, \fBwaddch\fR, \fBmvaddch\fR, \fBmvwaddch\fR,
+\fBechochar\fR,
+\fBwechochar\fR - add a character (with attributes) to a \fBncurses\fR window, then advance the cursor
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBaddch(chtype ch);\fR
+.br
+\fBwaddch(WINDOW *win, chtype ch);\fR
+.br
+\fBmvaddch(int y, int x, chtype ch);\fR
+.br
+\fBmvwaddch(WINDOW *win, int y, int x, chtype ch);\fR
+.br
+\fBechochar(chtype ch);\fR
+.br
+\fBwechochar(WINDOW *win, chtype ch);\fR
+.br
+.SH DESCRIPTION
+The \fBaddch\fR, \fBwaddch\fR, \fBmvaddch\fR and \fBmvwaddch\fR routines put
+the character \fIch\fR into the given window at its current window position,
+which is then advanced. They are analogous to \fBputchar\fR in \fBstdio\fR(3).
+If the advance is at the right margin, the cursor automatically wraps to the
+beginning of the next line. At the bottom of the scrolling region, if
+\fBscrollok\fR is enabled, the scrolling region is scrolled up one line.
+
+If \fIch\fR is a tab, newline, or backspace, the cursor is moved appropriately
+within the window. A newline also does a \fBclrtoeol\fR before moving. Tabs
+are considered to be at every eighth column.
+
+If \fIch\fR is any control character other than tab, newline, or backspace, it
+is drawn in \fB^\fR\fIX\fR notation. Calling \fBwinch\fR after adding a
+control character does not return the control character, but instead returns
+the representation of the control character. (To emit control characters
+literally, use \fBechochar\fR.)
+
+Video attributes can be combined with a character by OR-ing them into the
+parameter. This results in these attributes also being set. (The intent here
+is that text, including attributes, can be copied from one place to another
+using \fBinch\fR and \fBaddch\fR.) [see \fBstandout\fR, predefined video
+attribute constants, on the curs_attr(3) page].
+
+The \fBechochar\fR and \fBwechochar\fR routines are functionally equivalent to
+a call to \fBaddch\fR followed by a call to \fBrefresh\fR, or a call to
+\fBwaddch\fR followed by a call to \fBwrefresh\fR. The knowledge that only a
+single character is being output is taken into consideration and, for
+non-control characters, a considerable performance gain might be seen by using
+these routines instead of their equivalents.
+.SS Line Graphics
+The following variables may be used to add line drawing characters to the
+screen with routines of the \fBaddch\fR family. The default character listed
+below is used if the \fBacsc\fR capability doesn't define a terminal-specific
+replacement for it. The names are taken from the VT100 nomenclature.
+
+.TS
+l l l
+_ _ _
+l l l.
+\fIName\fR \fIDefault\fR \fIDescription\fR
+ACS_ULCORNER + upper left-hand corner
+ACS_LLCORNER + lower left-hand corner
+ACS_URCORNER + upper right-hand corner
+ACS_LRCORNER + lower right-hand corner
+ACS_RTEE + right tee
+ACS_LTEE + left tee
+ACS_BTEE + bottom tee
+ACS_TTEE + top tee
+ACS_HLINE - horizontal line
+ACS_VLINE | vertical line
+ACS_PLUS + plus
+ACS_S1 - scan line 1
+ACS_S9 \&_ scan line 9
+ACS_DIAMOND + diamond
+ACS_CKBOARD : checker board (stipple)
+ACS_DEGREE ' degree symbol
+ACS_PLMINUS # plus/minus
+ACS_BULLET o bullet
+ACS_LARROW < arrow pointing left
+ACS_RARROW > arrow pointing right
+ACS_DARROW v arrow pointing down
+ACS_UARROW ^ arrow pointing up
+ACS_BOARD # board of squares
+ACS_LANTERN # lantern symbol
+ACS_BLOCK # solid square block
+.TE
+
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion, unless otherwise noted in the
+preceding routine descriptions.
+.SH BUGS
+.SH NOTES
+Note that \fBaddch\fR, \fBmvaddch\fR, \fBmvwaddch\fR, and
+\fBechochar\fR may be macros.
+
+On 386 and 486 consoles, giving \fBwechochar\fR an argument with its high
+bit set will produce the corresponding high-half ASCIIZ graphic (SVr4 curses
+also has this feature but does not document it). A control-character argument,
+however, will not typically produce the corresponding graphic;
+characters such as CR, NL, FF and TAB are typically interpreted by the console
+driver itself, and ESC will be interpreted as the leader of a control sequence.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_attr\fR(3), \fBcurs_clear\fR(3),
+\fBcurs_inch\fR(3), \fBcurs_outopts\fR(3), \fBcurs_refresh\fR(3),
+\fBputc\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_addchst.3 b/lib/libncurses/curs_addchst.3
new file mode 100644
index 0000000..2991dcd
--- /dev/null
+++ b/lib/libncurses/curs_addchst.3
@@ -0,0 +1,49 @@
+.TH curs_addchstr 3 ""
+.SH NAME
+\fBaddchstr\fR, \fBaddchnstr\fR, \fBwaddchstr\fR,
+\fBwaddchnstr\fR, \fBmvaddchstr\fR, \fBmvaddchnstr\fR, \fBmvwaddchstr\fR,
+\fBmvwaddchnstr\fR - add string of characters (and attributes) to a \fBncurses\fR window
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint addchstr(chtype *chstr);\fR
+.br
+\fBint addchnstr(chtype *chstr, int n);\fR
+.br
+\fBint waddchstr(WINDOW *win, chtype *chstr);\fR
+.br
+\fBint waddchnstr(WINDOW *win, chtype *chstr, int n);\fR
+.br
+\fBint mvaddchstr(int y, int x, chtype *chstr);\fR
+.br
+\fBint mvaddchnstr(int y, int x, chtype *chstr, int n);\fR
+.br
+\fBint mvwaddchstr(WINDOW *win, int y, int x, chtype *chstr);\fR
+.br
+\fBint mvwaddchnstr(WINDOW *win, int y, int x, chtype *chstr, int n);\fR
+.SH DESCRIPTION
+These routines copy \fIchstr\fR into the window image structure at and after
+the current cursor position. The four routines with \fIn\fR as the last
+argument copy at most \fIn\fR elements, but no more than will fit on the line.
+If \fBn\fR=\fB-1\fR then the whole string is copied, to the maximum number of
+characters that will fit on the line.
+
+The window cursor is \fINOT\fR advanced, and these routines work faster than
+\fBwaddnstr\fR. On the other hand, care must be taken when using them because
+they don't perform any kind of checking (such as for the newline character),
+they don't advance the current cursor position, and they truncate the string if
+it crosses the right margin, rather then wrapping it around to the new line.
+.SH RETURN VALUES
+All these routines return the integer \fBERR\fR upon failure and an integer
+value other than \fBERR\fR upon successful completion, unless
+otherwise noted in the preceding routine descriptions.
+.SH NOTES
+Note that all routines except \fBwaddchnstr\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_addstr.3 b/lib/libncurses/curs_addstr.3
new file mode 100644
index 0000000..c55c2f5
--- /dev/null
+++ b/lib/libncurses/curs_addstr.3
@@ -0,0 +1,44 @@
+.TH curs_addstr 3 ""
+.SH NAME
+\fBaddstr\fR, \fBaddnstr\fR, \fBwaddstr\fR, \fBwaddnstr\fR,
+\fBmvaddstr\fR, \fBmvaddnstr\fR, \fBmvwaddstr\fR,
+\fBmvwaddnstr\fR - add a string of characters to a \fBncurses\fR window and advance cursor
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint addstr(char *str);\fR
+.br
+\fBint addnstr(char *str, int n);\fR
+.br
+\fBint waddstr(WINDOW *win, char *str);\fR
+.br
+\fBint waddnstr(WINDOW *win, char *str, int n);\fR
+.br
+\fBint mvaddstr(y, int x, char *str);\fR
+.br
+\fBint mvaddnstr(y, int x, char *str, int n);\fR
+.br
+\fBint mvwaddstr(WINDOW *win, int y, int x, char *str);\fR
+.br
+\fBint mvwaddnstr(WINDOW *win, int y, int x, char *str,
+ int n);\fR
+.SH DESCRIPTION
+These routines write the characters of the null terminated character string
+\fIstr\fR on the given window. It is similar to calling \fBwaddch\fR once for
+each character in the string. The four routines with \fIn\fR as the last
+argument write at most \fIn\fR characters. If \fIn\fR is negative, then the
+entire string will be added.
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion.
+.SH NOTES
+Note that all of these routines except \fBwaddstr\fR and \fBwaddnstr\fR may be
+macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_addch\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_attr.3 b/lib/libncurses/curs_attr.3
new file mode 100644
index 0000000..a7a2b45
--- /dev/null
+++ b/lib/libncurses/curs_attr.3
@@ -0,0 +1,84 @@
+.TH curs_attr 3 ""
+.SH NAME
+\fBattroff\fR, \fBwattroff\fR, \fBattron\fR, \fBwattron\fR,
+\fBattrset\fR, \fBwattrset\fR, \fBstandend\fR, \fBwstandend\fR, \fBstandout\fR,
+\fBwstandout\fR - \fBncurses\fR character and window attribute control routines
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+.br
+\fBint attroff(int attrs);\fR
+.br
+\fBint wattroff(WINDOW *win, int attrs);\fR
+.br
+\fBint attron(int attrs);\fR
+.br
+\fBint wattron(WINDOW *win, int attrs);\fR
+.br
+\fBint attrset(int attrs);\fR
+.br
+\fBint wattrset(WINDOW *win, int attrs);\fR
+.br
+\fBint standend(void);\fR
+.br
+\fBint wstandend(WINDOW *win);\fR
+.br
+\fBint standout(void);\fR
+.br
+\fBint wstandout(WINDOW *win);\fR
+.br
+.SH DESCRIPTION
+These routines manipulate the current attributes of the named window. The
+current attributes of a window apply to all characters that are written into
+the window with \fBwaddch\fR, \fBwaddstr\fR and \fBwprintw\fR. Attributes are
+a property of the character, and move with the character through any scrolling
+and insert/delete line/character operations. To the extent possible, they are
+displayed as appropriate modifications to the graphic rendition of characters
+put on the screen.
+
+The routine \fBattrset\fR sets the current attributes of the given window to
+\fIattrs\fR. The routine \fBattroff\fR turns off the named attributes without
+turning any other attributes on or off. The routine \fBattron\fR turns on the
+named attributes without affecting any others. The routine \fBstandout\fR is
+the same as \fBattron(A_STANDOUT)\fR. The routine \fBstandend\fR is the same
+as \fBattrset(A_NORMAL)\fR or \fBattrset(0)\fR, that is, it turns off all
+attributes.
+.SS Attributes
+The following video attributes, defined in \fB<ncurses.h>\fR, can be passed to
+the routines \fBattron\fR, \fBattroff\fR, and \fBattrset\fR, or OR-ed with the
+characters passed to \fBaddch\fR.
+
+.nf
+\fBA_NORMAL\fR Normal display (no highlight)
+\fBA_STANDOUT\fR Best highlighting mode of the terminal.
+\fBA_UNDERLINE\fR Underlining
+\fBA_REVERSE\fR Reverse video
+\fBA_BLINK\fR Blinking
+\fBA_DIM\fR Half bright
+\fBA_BOLD\fR Extra bright or bold
+\fBA_ALTCHARSET\fR Alternate character set
+\fBA_CHARTEXT\fR Bit-mask to extract a character
+\fBCOLOR_PAIR(\fR\fIn\fR\fB)\fR Color-pair number \fIn\fR
+.fi
+
+The following macro is the reverse of \fBCOLOR_PAIR(\fR\fIn\fR\fB)\fR:
+
+.DS C
+\fBPAIR_NUMBER(\fIattrs\fR) Returns the pair number associated
+ with the \fBCOLOR_PAIR(\fR\fIn\fR\fB)\fR attribute.
+.DE
+
+The return values of these routines are not meaningful (many are implemented
+as macro-expanded assignments and simply return their argument). The SVr4
+manual page claims (falsely) that these routines always return \fB1\fR.
+.SH NOTES
+Note that \fBattroff\fR, \fBwattroff\fR, \fBattron\fR, \fBwattron\fR,
+\fBattrset\fR, \fBwattrset\fR, \fBstandend\fR and \fBstandout\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_addch\fR(3), \fBcurs_addstr\fR(3),
+\fBcurs_printw\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_beep.3 b/lib/libncurses/curs_beep.3
new file mode 100644
index 0000000..b80fd52
--- /dev/null
+++ b/lib/libncurses/curs_beep.3
@@ -0,0 +1,29 @@
+.TH curs_beep 3 ""
+.SH NAME
+\fBbeep\fR, \fBflash\fR - \fBncurses\fR bell and screen flash routines
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint beep(void);\fR
+.br
+\fBint flash(void);\fR
+.br
+.SH DESCRIPTION
+The \fBbeep\fR and \fBflash\fR routines are used to alert the terminal user.
+The routine \fBbeep\fR sounds an audible alarm on the terminal, if possible;
+otherwise it flashes the screen (visible bell). The routine \fBflash\fR
+flashes the screen, and if that is not possible, sounds the alert. If neither
+alert is possible, nothing happens. Nearly all terminals have an audible alert
+(bell or beep), but only some can flash the screen.
+.SH RETURN VALUE
+These routines always return \fBOK\fR.
+.SH CAPABILITIES
+\fBbell\fR, \fBflash_screen\fR.
+.SH SEE ALSO
+\fBncurses\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_bkgd.3 b/lib/libncurses/curs_bkgd.3
new file mode 100644
index 0000000..7e360705
--- /dev/null
+++ b/lib/libncurses/curs_bkgd.3
@@ -0,0 +1,50 @@
+.TH curs_bkgd 3 ""
+.SH NAME
+\fBbkgdset\fR, \fBwbkgdset\fR, \fBbkgd\fR,
+\fBwbkgd\fR - \fBncurses\fR window background manipulation routines
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBvoid bkgdset(chtype ch);\fR
+.br
+\fBvoid wbkgdset(WINDOW *win, chtype ch);\fR
+.br
+\fBint bkgd(chtype ch);\fR
+.br
+\fBint wbkgd(WINDOW *win, chtype ch);\fR
+.br
+.SH DESCRIPTION
+The \fBbkgdset\fR and \fBwbkgdset\fR routines manipulate the
+background of the named window. Background is a \fBchtype\fR
+consisting of any combination of attributes and a character. The
+attribute part of the background is combined (ORed) with all non-blank
+characters that are written into the window with \fBwaddch\fR. Both
+the character and attribute parts of the background are combined with
+the blank characters. The background becomes a property of the
+character and moves with the character through any scrolling and
+insert/delete line/character operations. To the extent possible on a
+particular terminal, the attribute part of the background is displayed
+as the graphic rendition of the character put on the screen.
+
+The \fBbkgd\fR and \fBwbkgd\fR routines combine the new background
+with every position in the window. Background is any combination of
+attributes and a character. Only the attribute part is used to set
+the background of non-blank characters, while both character and
+attributes are used for blank positions. To the extent possible on a
+particular terminal, the attribute part of the background is displayed
+as the graphic rendition of the character put on the screen.
+.SH RETURN VALUE
+\fBbkgd\fR and \fBwbkgd\fR return the integer \fBOK\fR, or a
+non-negative integer, if \fBimmedok\fR is set.
+.SH NOTES
+Note that \fBbkgdset\fR and \fBbkgd\fR may be macros.
+.SH BUGS
+\fBimmedok\fR is not yet implemented in ncurses 1.8.6.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_addch\fR(3), \fBcurs_outopts\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_border.3 b/lib/libncurses/curs_border.3
new file mode 100644
index 0000000..874e9ea
--- /dev/null
+++ b/lib/libncurses/curs_border.3
@@ -0,0 +1,67 @@
+.TH curs_border 3 ""
+.SH NAME
+\fBborder\fR, \fBwborder\fR, \fBbox\fR,
+\fBhline\fR, \fBwhline\fR, \fBvline\fR,
+\fBwvline\fR - create \fBncurses\fR borders, horizontal and vertical lines
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+.br
+\fBint border(chtype ls, chtype rs, chtype ts, chtype bs,
+ chtype tl, chtype tr, chtype bl, chtype br);\fR
+.br
+\fBint wborder(WINDOW *win, chtype ls, chtype rs,
+ chtype ts, chtype bs, chtype tl, chtype tr,
+ chtype bl, chtype br);\fR
+.br
+\fBint box(WINDOW *win, chtype verch, chtype horch);\fR
+.br
+\fBint hline(chtype ch, int n);\fR
+.br
+\fBint whline(WINDOW *win, chtype ch, int n);\fR
+.br
+\fBint vline(chtype ch, int n);\fR
+.br
+\fBint wvline(WINDOW *win, chtype ch, int n);\fR
+.br
+.SH DESCRIPTION
+The \fBborder\fR, \fBwborder\fR and \fBbox\fR routines draw a box around the
+edges of a window. The argument \fIls\fR is a character and attributes used
+for the left side of the border, \fIrs\fR - right side, \fIts\fR - top side,
+\fIbs\fR - bottom side, \fItl\fR - top left-hand corner, \fItr\fR - top
+right-hand corner, \fIbl\fR - bottom left-hand corner, and \fIbr\fR - bottom
+right-hand corner. If any of these arguments is zero, then the following
+default values (defined in \fBncurses.h\fR) are used instead: \fBACS_VLINE,
+ACS_VLINE, ACS_HLINE, ACS_HLINE, \fBACS_ULCORNER, ACS_URCORNER, ACS_BLCORNER,
+ACS_BRCORNER.\fR
+
+\fBbox(\fR\fIwin\fR\gB, \fR\fIverch\fR\fB, \fR\fIhorch\fR\fB)\fR is a shorthand
+for the following call: \fBwborder(\fR\fIwin\fR\fB,\fR \fIverch\fR\fB,\fR
+\fIverch\fR\fB,\fR \fIhorch\fR\fB,\fR \fIhorch\fR\fB, 0, 0, 0, 0)\fR.
+
+The \fBhline\fR and \fBwhline\fR functions draw a horizontal (left to right)
+line using \fIch\fR starting at the current cursor position in the window. The
+current cursor position is not changed. The line is at most \fIn\fR characters
+long, or as many as fit into the window.
+
+The \fBvline\fR and \fBwvline\fR functions draw a vertical (top to bottom) line
+using \fIch\fR starting at the current cursor position in the window. The
+current cursor position is not changed. The line is at most \fIn\fR characters
+long, or as many as fit into the window.
+.SH RETURN VALUE
+All routines return the integer \fBOK\fR. The SVr4.0 manual says "or a
+non-negative integer if \fBimmedok\fR is set", but this appears to be an error.
+.SH NOTES
+The borders generated by these functions are \fIinside\fR borders (this
+is also true of SVr4 curses, though the fact is not documented).
+
+Note that \fBborder\fR and \fBbox\fR may be macros.
+.SH BUGS
+The \fBimmedok\fR function is not yet implemented in ncurses 1.8.6.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_outopts\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_clear.3 b/lib/libncurses/curs_clear.3
new file mode 100644
index 0000000..60c637b
--- /dev/null
+++ b/lib/libncurses/curs_clear.3
@@ -0,0 +1,53 @@
+.TH curs_clear 3 ""
+.SH NAME
+\fBerase\fR, \fBwerase\fR, \fBclear\fR,
+\fBwclear\fR, \fBclrtobot\fR, \fBwclrtobot\fR, \fBclrtoeol\fR,
+\fBwclrtoeol\fR - clear all or part of a \fBncurses\fR window
+.SH SYNOPSIS
+\fB# include <ncurses.h>\fR
+
+\fBint erase(void);\fR
+.br
+\fBint werase(WINDOW *win);\fR
+.br
+\fBint clear(void);\fR
+.br
+\fBint wclear(WINDOW *win);\fR
+.br
+\fBint clrtobot(void);\fR
+.br
+\fBint wclrtobot(WINDOW *win);\fR
+.br
+\fBint clrtoeol(void);\fR
+.br
+\fBint wclrtoeol(WINDOW *win);\fR
+.br
+.SH DESCRIPTION
+The \fBerase\fR and \fBwerase\fR routines copy blanks to every
+position in the window, clearing the screen.
+
+The \fBclear\fR and \fBwclear\fR routines are like \fBerase\fR and
+\fBwerase\fR, but they also call \fBclearok\fR, so that the screen is
+cleared completely on the next call to \fBwrefresh\fR for that window
+and repainted from scratch.
+
+The \fBclrtobot\fR and \fBwclrtobot\fR routines erase from the cursor to the
+end of screen. That is, they erase all lines below the cursor in the window.
+Also, the current line to the right of the cursor, inclusive, is erased.
+
+The \fBclrtoeol\fR and \fBwclrtoeol\fR routines erase the current line
+to the right of the cursor, inclusive.
+.SH RETURN VALUE
+All routines return the integer \fBOK\fR, or a non-negative integer if
+\fBimmedok\fR is set.
+.SH NOTES
+Note that \fBerase\fR, \fBwerase\fR, \fBclear\fR, \fBwclear\fR,
+\fBclrtobot\fR, and \fBclrtoeol\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_outopts\fR(3), \fBcurs_refresh\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_color.3 b/lib/libncurses/curs_color.3
new file mode 100644
index 0000000..cd32cf3
--- /dev/null
+++ b/lib/libncurses/curs_color.3
@@ -0,0 +1,138 @@
+.TH curs_color 3 ""
+.SH NAME
+\fBstart_color\fR, \fBinit_pair\fR,
+\fBinit_color\fR, \fBhas_colors\fR, \fBcan_change_color\fR,
+\fBcolor_content\fR,
+\fBpair_content\fR - \fBncurses\fR color manipulation routines
+.SH SYNOPSIS
+\fB# include <ncurses.h>\fR
+.br
+\fBint start_color(void);\fR
+.br
+\fBint init_pair(short pair, short f, short b);\fR
+.br
+\fBint init_color(short color, short r, short g, short b);\fR
+.br
+\fBbool has_colors(void);\fR
+.br
+\fBbool can_change_color(void);\fR
+.br
+\fBint color_content(short color, short *r, short *g, short *b);\fR
+.br
+\fBint pair_content(short pair, short *f, short *b);\fR
+.br
+.SH DESCRIPTION
+.SS Overview
+\fBncurses\fR support color attributes on terminals with that capability. To
+use these routines \fBstart_color\fR must be called, usually right after
+\fBinitscr\fR. Colors are always used in pairs (referred to as color-pairs).
+A color-pair consists of a foreground color (for characters) and a background
+color (for the blank field on which the characters are displayed). A
+programmer initializes a color-pair with the routine \fBinit_pair\fR. After it
+has been initialized, \fBCOLOR_PAIR\fR(\fIn\fR), a macro defined in
+\fB<ncurses.h>\fR, can be used as a new video attribute.
+
+If a terminal is capable of redefining colors, the programmer can use the
+routine \fBinit_color\fR to change the definition of a color. The routines
+\fBhas_colors\fR and \fBcan_change_color\fR return \fBTRUE\fR or \fBFALSE\fR,
+depending on whether the terminal has color capabilities and whether the
+programmer can change the colors. The routine \fBcolor_content\fR allows a
+programmer to extract the amounts of red, green, and blue components in an
+initialized color. The routine \fBpair_content\fR allows a programmer to find
+out how a given color-pair is currently defined.
+.SS Routine Descriptions
+The \fBstart_color\fR routine requires no arguments. It must be
+called if the programmer wants to use colors, and before any other
+color manipulation routine is called. It is good practice to call
+this routine right after \fBinitscr\fR. \fBstart_color\fR initializes
+eight basic colors (black, red, green, yellow, blue, magenta, cyan,
+and white), and two global variables, \fBCOLORS\fR and
+\fBCOLOR_PAIRS\fR (respectively defining the maximum number of colors
+and color-pairs the terminal can support). It also restores the
+colors on the terminal to the values they had when the terminal was
+just turned on.
+
+The \fBinit_pair\fR routine changes the definition of a color-pair. It takes
+three arguments: the number of the color-pair to be changed, the foreground
+color number, and the background color number. The value of the first argument
+must be between \fB1\fR and \fBCOLOR_PAIRS-1\fR. The value of the second and
+third arguments must be between 0 and \fBCOLORS\fR (the 0 color pair is wired
+to white on black and cannot be changed). If the color-pair was previously
+initialized, the screen is refreshed and all occurrences of that color-pair is
+changed to the new definition.
+
+The \fBinit_color\fR routine changes the definition of a color. It takes four
+arguments: the number of the color to be changed followed by three RGB values
+(for the amounts of red, green, and blue components). The value of the first
+argument must be between \fB0\fR and \fBCOLORS\fR. (See the section
+\fBColors\fR for the default color index.) Each of the last three arguments
+must be a value between 0 and 1000. When \fBinit_color\fR is used, all
+occurrences of that color on the screen immediately change to the new
+definition.
+
+The \fBhas_colors\fR routine requires no arguments. It returns \fBTRUE\fR if
+the terminal can manipulate colors; otherwise, it returns \fBFALSE\fR. This
+routine facilitates writing terminal-independent programs. For example, a
+programmer can use it to decide whether to use color or some other video
+attribute.
+
+The \fBcan_change_color\fR routine requires no arguments. It returns
+\fBTRUE\fR if the terminal supports colors and can change their definitions;
+other, it returns \fBFALSE\fR. This routine facilitates writing
+terminal-independent programs.
+
+The \fBcolor_content\fR routine gives programmers a way to find the intensity
+of the red, green, and blue (RGB) components in a color. It requires four
+arguments: the color number, and three addresses of \fBshort\fRs for storing
+the information about the amounts of red, green, and blue components in the
+given color. The value of the first argument must be between 0 and
+\fBCOLORS\fR. The values that are stored at the addresses pointed to by the
+last three arguments are between 0 (no component) and 1000 (maximum amount of
+component).
+
+The \fBpair_content\fR routine allows programmers to find out what colors a
+given color-pair consists of. It requires three arguments: the color-pair
+number, and two addresses of \fBshort\fRs for storing the foreground and the
+background color numbers. The value of the first argument must be between 1
+and \fBCOLOR_PAIRS-1\fR. The values that are stored at the addresses pointed
+to by the second and third arguments are between 0 and \fBCOLORS\fR.
+.SS Colors
+In \fB<ncurses.h>\fR the following macros are defined. These are the default
+colors. \fBncurses\fR also assumes that \fBCOLOR_BLACK\fR is the default
+background color for all terminals.
+
+.nf
+ \fBCOLOR_BLACK\fR
+ \fBCOLOR_RED\fR
+ \fBCOLOR_GREEN\fR
+ \fBCOLOR_YELLOW\fR
+ \fBCOLOR_BLUE\fR
+ \fBCOLOR_MAGENTA\fR
+ \fBCOLOR_CYAN\fR
+ \fBCOLOR_WHITE\fR
+.fi
+.SH RETURN VALUE
+All routines that return an integer return \fBERR\fR upon failure and \fBOK\fR
+upon successful completion.
+.SH NOTES
+Several caveats apply onn 386 and 486 machines with VGA-compatible graphics:
+
+COLOR_YELLOW is actually brown. To get yellow, use COLOR_YELLOW combined with
+the \fBA_BOLD\fR attribute.
+
+The A_BLINK attribute should in theory cause the background to go bright. This
+often fails to work, and even some cards for which it mostly works (such as the
+Paradise and compatibles) do the wrong thing when you try to set a bright
+"yellow" background (you get a blinking yellow foreground instead).
+
+Color RGB values are not settable.
+.SH CAPABILITIES
+\fBsetf\fR, \fBsetb\fR, \fBsetaf\fR, \fBsetab\fR. The ncurses library uses
+the second pair by preference, falling back to the first.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_initscr\fR(3), \fBcurs_attr\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
diff --git a/lib/libncurses/curs_delch.3 b/lib/libncurses/curs_delch.3
new file mode 100644
index 0000000..441eaac
--- /dev/null
+++ b/lib/libncurses/curs_delch.3
@@ -0,0 +1,34 @@
+.TH curs_delch 3 ""
+.SH NAME
+\fBdelch\fR, \fBwdelch\fR, \fBmvdelch\fR,
+\fBmvwdelch\fR - delete character under the cursor in a \fBncurses\fR window
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint delch(void);\fR
+.br
+\fBint wdelch(WINDOW *win);\fR
+.br
+\fBint mvdelch(int y, int x);\fR
+.br
+\fBint mvwdelch(WINDOW *win, int y, int x);\fR
+.br
+.SH DESCRIPTION
+These routines delete the character under the cursor; all characters to the
+right of the cursor on the same line are moved to the left one position and the
+last character on the line is filled with a blank. The cursor position does
+not change (after moving to \fIy\fR, \fIx\fR, if specified). (This does not
+imply use of the hardware delete character feature.)
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion.
+.SH NOTES
+Note that \fBdelch\fR, \fBmvdelch\fR, and \fBmvwdelch\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_delln.3 b/lib/libncurses/curs_delln.3
new file mode 100644
index 0000000..6ae1025
--- /dev/null
+++ b/lib/libncurses/curs_delln.3
@@ -0,0 +1,50 @@
+.TH curs_deleteln 3 ""
+.SH NAME
+\fBdeleteln\fR, \fBwdeleteln\fR, \fBinsdelln\fR,
+\fBwinsdelln\fR, \fBinsertln\fR,
+\fBwinsertln\fR - delete and insert lines in a \fBncurses\fR window
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint deleteln(void);\fR
+.br
+\fBint wdeleteln(WINDOW *win);\fR
+.br
+\fBint insdelln(int n);\fR
+.br
+\fBint winsdelln(WINDOW *win, int n);\fR
+.br
+\fBint insertln(void);\fR
+.br
+\fBint winsertln(WINDOW *win);\fR
+.br
+.SH DESCRIPTION
+The \fBdeleteln\fR and \fBwdeleteln\fR routines delete the line under the
+cursor in the window; all lines below the current line are moved up one line.
+The bottom line of the window is cleared. The cursor position does not change.
+
+The \fBinsdelln\fR and \fBwinsdelln\fR routines, for positive \fIn\fR, insert
+\fIn\fR lines into the specified window above the current line. The \fIn\fR
+bottom lines are lost. For negative \fIn\fR, delete \fIn\fR lines (starting
+with the one under the cursor), and move the remaining lines up. The bottom
+\fIn\fR lines are cleared. The current cursor position remains the same.
+
+The \fBinsertln\fR and \fBinsertln\fR routines, insert a blank line above the
+current line and the bottom line is lost.
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer
+value other than \fBERR\fR upon successful completion.
+.SH NOTES
+Note that all but \fBwinsdelln\fR may be a macros.
+
+These routines do not require a hardware line delete or insert feature in the
+terminal. In fact, they won't use hardware line delete/insert unless
+\fBidlok(..., TRUE)\fR has been set on the current window.
+.SH SEE ALSO
+\fBncurses\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_getch.3 b/lib/libncurses/curs_getch.3
new file mode 100644
index 0000000..8a5c9ae
--- /dev/null
+++ b/lib/libncurses/curs_getch.3
@@ -0,0 +1,188 @@
+.TH curs_getch 3 ""
+.SH NAME
+\fBgetch\fR, \fBwgetch\fR, \fBmvgetch\fR,
+\fBmvwgetch\fR,
+\fBungetch\fR - get (or push back) characters from \fBncurses\fR terminal keyboard
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint getch(void);\fR
+.br
+\fBint wgetch(WINDOW *win);\fR
+.br
+\fBint mvgetch(int y, int x);\fR
+.br
+\fBint mvwgetch(WINDOW *win, int y, int x);\fR
+.br
+\fBint ungetch(int ch);\fR
+.br
+.SH DESCRIPTION
+The \fBgetch\fR, \fBwgetch\fR, \fBmvgetch\fR and \fBmvwgetch\fR, routines read
+a character from the window. In no-delay mode, if no input is waiting, the
+value \fBERR\fR is returned. In delay mode, the program waits until the system
+passes text through to the program. Depending on the setting of \fBcbreak\fR,
+this is after one character (cbreak mode), or after the first newline (nocbreak
+mode). In half-delay mode, the program waits until a character is typed or the
+specified timeout has been reached. Unless \fBnoecho\fR has been set, the
+character will also be echoed into the designated window.
+
+If the window is not a pad, and it has been moved or modified since the last
+call to \fBwrefresh\fR, \fBwrefresh\fR will be called before another character
+is read.
+
+If \fBkeypad\fR is \fBTRUE\fR, and a function key is pressed, the token for
+that function key is returned instead of the raw characters. Possible function
+keys are defined in \fB<ncurses.h>\fR as macros with values outside the range
+of 8-bit characters whose names begin with \fBKEY_.\fR Thus, a variable
+intended to hold the return value of a function key must be of short size or
+larger.
+
+When a character that could be the beginning of a function key is received
+(which, on modern terminals, means an escape character), \fBncurses\fR sets a
+timer. If the remainder of the sequence does not come in within the designated
+time, the character is passed through; otherwise, the function key value is
+returned. For this reason, many terminals experience a delay between the time
+a user presses the escape key and the escape is returned to the program.
+
+The \fBungetch\fR routine places \fIch\fR back onto the input queue to be
+returned by the next call to \fBwgetch\fR. Note that there is, in effect,
+just one input queue for all windows.
+
+.SS Function Keys
+The following function keys, defined in \fB<ncurses.h>\fR, might be returned by
+\fBgetch\fR if \fBkeypad\fR has been enabled. Note that not all of these are
+necessarily supported on any particular terminal.
+.nf
+__________________________________________________________________
+\fIName\fR \fIKey\fR \fIname\fR
+__________________________________________________________________
+KEY_BREAK Break key
+KEY_DOWN The four arrow keys ...
+KEY_UP
+KEY_LEFT
+KEY_RIGHT
+KEY_HOME Home key (upward+left arrow)
+KEY_BACKSPACE Backspace
+KEY_F0 Function keys; space for 64 keys is reserved.
+KEY_F(\fIn\fR) For 0 \fI<\fR \fIn\fR \fI<\fR 63
+KEY_DL Delete line
+KEY_IL Insert line
+KEY_DC Delete character
+KEY_IC Insert char or enter insert mode
+KEY_EIC Exit insert char mode
+KEY_CLEAR Clear screen
+KEY_EOS Clear to end of screen
+KEY_EOL Clear to end of line
+KEY_SF Scroll 1 line forward
+KEY_SR Scroll 1 line backward (reverse)
+KEY_NPAGE Next page
+KEY_PPAGE Previous page
+KEY_STAB Set tab
+KEY_CTAB Clear tab
+KEY_CATAB Clear all tabs
+KEY_ENTER Enter or send
+KEY_SRESET Soft (partial) reset
+KEY_RESET Reset or hard reset
+KEY_PRINT Print or copy
+KEY_LL Home down or bottom (lower left). Keypad is
+ arranged like this:
+ \fBA1\fR \fBup\fR \fBA3\fR
+ \fBleft\fR \fBB2\fR \fBright\fR
+ \fBC1\fR \fBdown\fR \fBC3\fR
+KEY_A1 Upper left of keypad
+KEY_A3 Upper right of keypad
+KEY_B2 Center of keypad
+KEY_C1 Lower left of keypad
+KEY_C3 Lower right of keypad
+KEY_BTAB Back tab key
+KEY_BEG Beg(inning) key
+KEY_CANCEL Cancel key
+KEY_CLOSE Close key
+KEY_COMMAND Cmd (command) key
+KEY_COPY Copy key
+KEY_CREATE Create key
+KEY_END End key
+KEY_EXIT Exit key
+KEY_FIND Find key
+KEY_HELP Help key
+KEY_MARK Mark key
+KEY_MESSAGE Message key
+KEY_MOVE Move key
+KEY_NEXT Next object key
+KEY_OPEN Open key
+KEY_OPTIONS Options key
+KEY_PREVIOUS Previous object key
+KEY_REDO Redo key
+KEY_REFERENCE Ref(erence) key
+KEY_REFRESH Refresh key
+KEY_REPLACE Replace key
+KEY_RESTART Restart key
+KEY_RESUME Resume key
+KEY_SAVE Save key
+KEY_SBEG Shifted beginning key
+KEY_SCANCEL Shifted cancel key
+KEY_SCOMMAND Shifted command key
+KEY_SCOPY Shifted copy key
+KEY_SCREATE Shifted create key
+KEY_SDC Shifted delete char key
+KEY_SDL Shifted delete line key
+KEY_SELECT Select key
+KEY_SEND Shifted end key
+KEY_SEOL Shifted clear line key
+KEY_SEXIT Shifted exit key
+KEY_SFIND Shifted find key
+KEY_SHELP Shifted help key
+KEY_SHOME Shifted home key
+KEY_SIC Shifted input key
+KEY_SLEFT Shifted left arrow key
+KEY_SMESSAGE Shifted message key
+KEY_SMOVE Shifted move key
+KEY_SNEXT Shifted next key
+KEY_SOPTIONS Shifted options key
+KEY_SPREVIOUS Shifted prev key
+KEY_SPRINT Shifted print key
+KEY_SREDO Shifted redo key
+KEY_SREPLACE Shifted replace key
+KEY_SRIGHT Shifted right arrow
+KEY_SRSUME Shifted resume key
+KEY_SSAVE Shifted save key
+KEY_SSUSPEND Shifted suspend key
+KEY_SUNDO Shifted undo key
+KEY_SUSPEND Suspend key
+KEY_UNDO Undo key
+.fi
+
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer
+value other than \fBERR\fR upon successful completion.
+.SH NOTES
+Use of the escape key by a programmer for a single character function is
+discouraged, as it will cause a delay of up to one second while the
+keypad code looks for a following function-key sequence.
+
+When using \fBgetch\fR, \fBwgetch\fR, \fBmvgetch\fR, or
+\fBmvwgetch\fR, nocbreak mode (\fBnocbreak\fR) and echo mode
+(\fBecho\fR) should not be used at the same time. Depending on the
+state of the tty driver when each character is typed, the program may
+produce undesirable results.
+
+Note that \fBgetch\fR, \fBmvgetch\fR, and \fBmvwgetch\fR may be macros.
+
+Historically, the set of keypad macros was largely defined by the extremely
+function-key-rich keyboard of the AT&T 7300, aka 3B1, aka Safari 4. Modern
+personal computers usually have only a small subset of these. IBM PC-style
+consoles typically support little more than \fBKEY_UP\fR, \fBKEY_DOWN\fR,
+\fBKEY_LEFT\fR, \fBKEY_RIGHT\fR, \fBKEY_HOME\fR, \fBKEY_END\fR,
+\fBKEY_NPAGE\fR, \fBKEY_PPAGE\fR, and function keys 1 through 12. The Ins key
+is usually mapped to \fBKEY_IC\fR.
+.SH CAPABILITIES
+All of the key_* capabilities; also \fBkeypad_local\fR and \fBkeypad_xmit\fR.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_inopts\fR(3), \fBcurs_move\fR(3),
+\fBcurs_refresh\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_getstr.3 b/lib/libncurses/curs_getstr.3
new file mode 100644
index 0000000..91d934b
--- /dev/null
+++ b/lib/libncurses/curs_getstr.3
@@ -0,0 +1,53 @@
+.TH curs_getstr 3 ""
+.SH NAME
+\fBgetstr\fR, \fBwgetstr\fR, \fBmvgetstr\fR,
+\fBmvwgetstr\fR,
+\fBwgetnstr\fR - accept character strings from \fBncurses\fR terminal keyboard
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint getstr(char *str);\fR
+.br
+\fBint wgetstr(WINDOW *win, char *str);\fR
+.br
+\fBint mvgetstr(int y, int x, char *str);\fR
+.br
+\fBint mvwgetstr(WINDOW *win, int y, int x, char *str);\fR
+.br
+\fBint wgetnstr(WINDOW *win, char *str, int n);\fR
+.br
+.SH DESCRIPTION
+The function \fBgetstr\fR is equivalent to a series of calls to \fBgetch\fR,
+until a newline or carriage return is received (the terminating character is
+not included in the returned string). The resulting value is placed in the
+area pointed to by the character pointer \fIstr\fR.
+
+\fBwgetnstr\fR reads at most \fIn\fR characters, thus preventing a possible
+overflow of the input buffer. Any attempt to enter more characters (other
+than the terminating newline or carriage return) causes a beep.
+
+The user's erase and kill characters are interpreted. If keypad
+mode is on for the window, \fBKEY_LEFT\fR and \fBKEY_BACKSPACE\fR
+are both considered equivalent to the user's kill character.
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion.
+.SH BUGS
+When the window is in keypad mode and the user types any special key
+other than those named above, the `character' value appended to the
+string by the ncurses implementation is predictable but not useful
+(being, in fact, the low-order eight bits of the key's KEY_ value).
+
+The SVr4.0 documentation claims that "special keys (such as function
+keys, "home" key, "clear" key, \fIetc\fR.) are interpreted" without
+giving details. It lies. The actual behavior is like that of ncurses.
+.SH NOTES
+Note that \fBgetstr\fR, \fBmvgetstr\fR, and \fBmvwgetstr\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_getch\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_getyx.3 b/lib/libncurses/curs_getyx.3
new file mode 100644
index 0000000..8d46126
--- /dev/null
+++ b/lib/libncurses/curs_getyx.3
@@ -0,0 +1,41 @@
+.TH curs_getyx 3 ""
+.SH NAME
+\fBgetyx\fR, \fBgetparyx\fR, \fBgetbegyx\fR,
+\fBgetmaxyx\fR - get \fBncurses\fR cursor and window coordinates
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBvoid getyx(WINDOW *win, int y, int x);\fR
+.br
+\fBvoid getparyx(WINDOW *win, int y, int x);\fR
+.br
+\fBvoid getbegyx(WINDOW *win, int y, int x);\fR
+.br
+\fBvoid getmaxyx(WINDOW *win, int y, int x);\fR
+.br
+.SH DESCRIPTION
+The \fBgetyx\fR macro places the cursor position of the window in the two
+integer variables \fIy\fR and \fIx\fR.
+
+If \fIwin\fR is a subwindow, the \fBgetparyx\fR macro places the beginning
+coordinates of the subwindow relative to the parent window into two integer
+variables \fIy\fR and \fIx\fR. Otherwise, \fB-1\fR is placed into \fIy\fR and
+\fIx\fR.
+
+Like \fBgetyx\fR, the \fBgetbegyx\fR and \fBgetmaxyx\fR macros store
+the current beginning coordinates and size of the specified window.
+.SH RETURN VALUE
+The return values of these macros are undefined (\fIi\fR.\fIe\fR.,
+they should not be used as the right-hand side of assignment
+statements).
+.SH NOTES
+All of these interfaces are macros and that "\fB&\fR" is not
+necessary before the variables \fIy\fR and \fIx\fR.
+.SH SEE ALSO
+\fBncurses\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_inch.3 b/lib/libncurses/curs_inch.3
new file mode 100644
index 0000000..7e9e218
--- /dev/null
+++ b/lib/libncurses/curs_inch.3
@@ -0,0 +1,40 @@
+.TH curs_inch 3 ""
+.SH NAME
+\fBinch\fR, \fBwinch\fR, \fBmvinch\fR,
+\fBmvwinch\fR - get a character and attributes from a \fBncurses\fR window
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBchtype inch(void);\fR
+.br
+\fBchtype winch(WINDOW *win);\fR
+.br
+\fBchtype mvinch(int y, int x);\fR
+.br
+\fBchtype mvwinch(WINDOW *win, int y, int x);\fR
+.br
+.SH DESCRIPTION
+These routines return the character, of type \fBchtype\fR, at the current
+position in the named window. If any attributes are set for that position,
+their values are OR-ed into the value returned. Constants defined in
+\fB<ncurses.h>\fR can be used with the \fB&\fR (logical AND) operator to
+extract the character or attributes alone.
+
+.SS Attributes
+The following bit-masks may be AND-ed with characters returned by \fBwinch\fR.
+
+.nf
+\fBA_CHARTEXT\fR Bit-mask to extract character
+\fBA_ATTRIBUTES\fR Bit-mask to extract attributes
+\fBA_COLOR\fR Bit-mask to extract color-pair field information
+.fi
+.SH NOTES
+Note that all of these routines may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_inchstr.3 b/lib/libncurses/curs_inchstr.3
new file mode 100644
index 0000000..83e7ee7
--- /dev/null
+++ b/lib/libncurses/curs_inchstr.3
@@ -0,0 +1,45 @@
+.TH curs_inchstr 3 ""
+.SH NAME
+\fBinchstr\fR, \fBinchnstr\fR, \fBwinchstr\fR,
+\fBwinchnstr\fR, \fBmvinchstr\fR, \fBmvinchnstr\fR, \fBmvwinchstr\fR,
+\fBmvwinchnstr\fR - get a string of characters (and attributes) from a \fBncurses\fR window
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint inchstr(chtype *chstr);\fR
+.br
+\fBint inchnstr(chtype *chstr, int n);\fR
+.br
+\fBint winchstr(WINDOW *win, chtype *chstr);\fR
+.br
+\fBint winchnstr(WINDOW *win, chtype *chstr, int n);\fR
+.br
+\fBint mvinchstr(int y, int x, chtype *chstr);\fR
+.br
+\fBint mvinchnstr(int y, int x, chtype *chstr, int n);\fR
+.br
+\fBint mvwinchstr(WINDOW *win, int y, int x, chtype *chstr);\fR
+.br
+\fBint mvwinchnstr(WINDOW *win, int y, int x, chtype *chstr, int n);\fR
+.br
+.SH DESCRIPTION
+These routines return a NULL-terminated array of \fBchtype\fR quantities,
+starting at the current cursor position in the named window and ending at the
+right margin of the window. The four functions with \fIn\fR as
+the last argument, return a leading substring at most \fIn\fR characters long.
+Constants defined in \fB<ncurses.h>\fR can be used with the \fB&\fR (logical
+AND) operator to extract the character or the attribute alone from any position
+in the \fIchstr\fR [see curs_inch(3)].
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion.
+.SH NOTES
+Note that all routines except \fBwinchnstr\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_inch\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_initscr.3 b/lib/libncurses/curs_initscr.3
new file mode 100644
index 0000000..20ee121
--- /dev/null
+++ b/lib/libncurses/curs_initscr.3
@@ -0,0 +1,84 @@
+.TH curs_initscr 3 ""
+.SH NAME
+\fBinitscr\fR, \fBnewterm\fR, \fBendwin\fR,
+\fBisendwin\fR, \fBset_term\fR,
+\fBdelscreen\fR - \fBncurses\fR screen initialization and manipulation routines
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBWINDOW *initscr(void);\fR
+.br
+\fBint endwin(void);\fR
+.br
+\fBint isendwin(void);\fR
+.br
+\fBSCREEN *newterm(char *type, FILE *outfd, FILE *infd);\fR
+.br
+\fBSCREEN *set_term(SCREEN *new);\fR
+.br
+\fBvoid delscreen(SCREEN* sp);\fR
+.br
+.SH DESCRIPTION
+\fBinitscr\fR is normally the first \fBncurses\fR routine to call when
+initializing a program. A few special routines sometimes need to be
+called before it; these are \fBslk_init\fR, \fBfilter\fR, \fBripoffline\fR,
+\fBuse_env\fR. For multiple-terminal applications, or in order to test
+for the presence of given capabilities, \fBnewterm\fR may be called before
+\fBinitscr\fR.
+
+The initscr code determines the terminal type and initializes all \fBncurses\fR
+data structures. \fBinitscr\fR also causes the first call to \fBrefresh\fR to
+clear the screen. If errors occur, \fBinitscr\fR writes an appropriate error
+message to standard error and exits; otherwise, a pointer is returned to
+\fBstdscr\fR.
+
+A program that outputs to more than one terminal should use the \fBnewterm\fR
+routine for each terminal instead of \fBinitscr\fR. A program that needs to
+inspect capabilities, so it can continue to run in a line-oriented mode if the
+terminal cannot support a screen-oriented program, would also use
+\fBnewterm\fR. The routine \fBnewterm\fR should be called once for each
+terminal. It returns a variable of type \fBSCREEN *\fR which should be saved
+as a reference to that terminal. The arguments are the \fItype\fR of the
+terminal to be used in place of \fB$TERM\fR, a file pointer for output to the
+terminal, and another file pointer for input from the terminal (if \fItype\fR
+is \fBNULL\fR, \fB$TERM\fR will be used). The program must also call
+\fBendwin\fR for each terminal being used before exiting from ncurses. If
+\fBnewterm\fR is called more than once for the same terminal, the first
+terminal referred to must be the last one for which \fBendwin\fR is called.
+
+A program should always call \fBendwin\fR before exiting or escaping from
+\fBncurses\fR mode temporarily. This routine restores tty modes, moves the
+cursor to the lower left-hand corner of the screen and resets the terminal into
+the proper non-visual mode. Calling \fBrefresh\fR or \fBdoupdate\fR after a
+temporary escape causes the program to resume visual mode.
+
+The \fBisendwin\fR routine returns \fBTRUE\fR if \fBendwin\fR has been
+called without any subsequent calls to \fBwrefresh\fR, and \fBFALSE\fR
+otherwise.
+
+The \fBset_term\fR routine is used to switch between different
+terminals. The screen reference \fBnew\fR becomes the new current
+terminal. The previous terminal is returned by the routine. This is
+the only routine which manipulates \fBSCREEN\fR pointers; all other
+routines affect only the current terminal.
+
+The \fBdelscreen\fR routine frees storage associated with the
+\fBSCREEN\fR data structure. The \fBendwin\fR routine does not do
+this, so \fBdelscreen\fR should be called after \fBendwin\fR if a
+particular \fBSCREEN\fR is no longer needed.
+.SH RETURN VALUE
+\fBendwin\fR returns the integer \fBERR\fR upon failure and \fBOK\fR
+upon successful completion.
+
+Routines that return pointers always return \fBNULL\fR on error.
+.SH NOTES
+Note that \fBinitscr\fR and \fBnewterm\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_kernel\fR(3), \fBcurs_refresh\fR(3),
+\fBcurs_slk\fR(3), \fBcurs_util\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_inopts.3 b/lib/libncurses/curs_inopts.3
new file mode 100644
index 0000000..f8cd814
--- /dev/null
+++ b/lib/libncurses/curs_inopts.3
@@ -0,0 +1,170 @@
+.TH curs_inopts 3 ""
+.SH NAME
+\fBcbreak\fR, \fBnocbreak\fR, \fBecho\fR,
+\fBnoecho\fR, \fBhalfdelay\fR, \fBintrflush\fR, \fBkeypad\fR,
+\fBmeta\fR, \fBnodelay\fR, \fBnotimeout\fR, \fBraw\fR, \fBnoraw\fR,
+\fBnoqiflush\fR, \fBqiflush\fR, \fBtimeout\fR, \fBwtimeout\fR,
+\fBtypeahead\fR - \fBncurses\fR input options
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint cbreak(void);\fR
+.br
+\fBint nocbreak(void);\fR
+.br
+\fBint echo(void);\fR
+.br
+\fBint noecho(void);\fR
+.br
+\fBint halfdelay(int tenths);\fR
+.br
+\fBint intrflush(WINDOW *win, bool bf);\fR
+.br
+\fBint keypad(WINDOW *win, bool bf);\fR
+.br
+\fBint meta(WINDOW *win, bool bf);\fR
+.br
+\fBint nodelay(WINDOW *win, bool bf);\fR
+.br
+\fBint notimeout(WINDOW *win, bool bf);\fR
+.br
+\fBint raw(void);\fR
+.br
+\fBint noraw(void);\fR
+.br
+\fBvoid noqiflush(void);\fR
+.br
+\fBvoid qiflush(void);\fR
+.br
+\fBvoid timeout(int delay);\fR
+.br
+\fBvoid wtimeout(WINDOW *win, int delay);\fR
+.br
+\fBint typeahead(int fd);\fR
+.br
+.SH DESCRIPTION
+Normally, the tty driver buffers typed characters until a newline or carriage
+return is typed. The \fBcbreak\fR routine disables line buffering and
+erase/kill character-processing (interrupt and flow control characters are
+unaffected), making characters typed by the user immediately available to the
+program. The \fBnocbreak\fR routine returns the terminal to normal (cooked)
+mode.
+
+Initially the terminal may or may not be in \fBcbreak\fR mode, as the mode is
+inherited; therefore, a program should call \fBcbreak\fR or \fBnocbreak\fR
+explicitly. Most interactive programs using \fBncurses\fR set the \fBcbreak\fR
+mode. Note that \fBcbreak\fR overrides \fBraw\fR. [See curs_getch(3) for a
+discussion of how these routines interact with \fBecho\fR and \fBnoecho\fR.]
+
+The \fBecho\fR and \fBnoecho\fR routines control whether characters typed by
+the user are echoed by \fBgetch\fR as they are typed. Echoing by the tty
+driver is always disabled, but initially \fBgetch\fR is in echo mode, so
+characters typed are echoed. Authors of most interactive programs prefer to do
+their own echoing in a controlled area of the screen, or not to echo at all, so
+they disable echoing by calling \fBnoecho\fR. [See curs_getch(3) for a
+discussion of how these routines interact with \fBcbreak\fR and
+\fBnocbreak\fR.]
+
+The \fBhalfdelay\fR routine is used for half-delay mode, which is similar to
+\fBcbreak\fR mode in that characters typed by the user are immediately
+available to the program. However, after blocking for \fItenths\fR tenths of
+seconds, ERR is returned if nothing has been typed. The value of \fBtenths\fR
+must be a number between 1 and 255. Use \fBnocbreak\fR to leave half-delay
+mode.
+
+If the \fBintrflush\fR option is enabled, (\fIbf\fR is \fBTRUE\fR), when an
+interrupt key is pressed on the keyboard (interrupt, break, quit) all output in
+the tty driver queue will be flushed, giving the effect of faster response to
+the interrupt, but causing \fBncurses\fR to have the wrong idea of what is on
+the screen. Disabling (\fIbf\fR is \fBFALSE\fR), the option prevents the
+flush. The default for the option is inherited from the tty driver settings.
+The window argument is ignored.
+
+The \fBkeypad\fR option enables the keypad of the user's terminal. If
+enabled (\fIbf\fR is \fBTRUE\fR), the user can press a function key
+(such as an arrow key) and \fBwgetch\fR returns a single value
+representing the function key, as in \fBKEY_LEFT\fR. If disabled
+(\fIbf\fR is \fBFALSE\fR), \fBncurses\fR does not treat function keys
+specially and the program has to interpret the escape sequences
+itself. If the keypad in the terminal can be turned on (made to
+transmit) and off (made to work locally), turning on this option
+causes the terminal keypad to be turned on when \fBwgetch\fR is
+called. The default value for keypad is false.
+
+Initially, whether the terminal returns 7 or 8 significant bits on
+input depends on the control mode of the tty driver [see termios(4)].
+To force 8 bits to be returned, invoke \fBmeta\fR(\fIwin\fR,
+\fBTRUE\fR). To force 7 bits to be returned, invoke
+\fBmeta\fR(\fIwin\fR, \fBFALSE\fR). The window argument, \fIwin\fR,
+is always ignored. If the terminfo capabilities \fBsmm\fR (meta_on)
+and \fBrmm\fR (meta_off) are defined for the terminal, \fBsmm\fR is
+sent to the terminal when \fBmeta\fR(\fIwin\fR, \fBTRUE\fR) is called
+and \fBrmm\fR is sent when \fBmeta\fR(\fIwin\fR, \fBFALSE\fR) is
+called.
+
+The \fBnodelay\fR option causes \fBgetch\fR to be a non-blocking call.
+If no input is ready, \fBgetch\fR returns \fBERR\fR. If disabled
+(\fIbf\fR is \fBFALSE\fR), \fBgetch\fR waits until a key is pressed.
+
+While interpreting an input escape sequence, \fBwgetch\fR sets a timer
+while waiting for the next character. If \fBnotimeout(\fR\fIwin\fR,
+\fBTRUE\fR) is called, then \fBwgetch\fR does not set a timer. The
+purpose of the timeout is to differentiate between sequences received
+from a function key and those typed by a user.
+
+With the \fBraw\fR and \fBnoraw\fR routines, the terminal is placed
+into or out of raw mode. Raw mode is similar to \fBcbreak\fR mode, in
+that characters typed are immediately passed through to the user
+program. The differences are that in raw mode, the interrupt, quit,
+suspend, and flow control characters are all passed through
+uninterpreted, instead of generating a signal. The behavior of the
+BREAK key depends on other bits in the tty driver that are not set by
+\fBncurses\fR.
+
+When the \fBnoqiflush\fR routine is used, normal flush of input and
+output queues associated with the \fBINTR\fR, \fBQUIT\fR and
+\fBSUSP\fR characters will not be done [see termios(4)]. When
+\fBqiflush\fR is called, the queues will be flushed when these control
+characters are read.
+
+The \fBtimeout\fR and \fBwtimeout\fR routines set blocking or
+non-blocking read for a given window. If \fIdelay\fR is negative,
+blocking read is used (\fIi\fR.\fIe\fR., waits indefinitely for
+input). If \fIdelay\fR is zero, then non-blocking read is used
+(\fIi\fR.\fIe\fR., read returns \fBERR\fR if no input is waiting). If
+\fIdelay\fR is positive, then read blocks for \fIdelay\fR
+milliseconds, and returns \fBERR\fR if there is still no input.
+Hence, these routines provide the same functionality as \fBnodelay\fR,
+plus the additional capability of being able to block for only
+\fIdelay\fR milliseconds (where \fIdelay\fR is positive).
+
+\fBncurses\fR does ``line-breakout optimization'' by looking for
+typeahead periodically while updating the screen. If input is found,
+and it is coming from a tty, the current update is postponed until
+\fBrefresh\fR or \fBdoupdate\fR is called again. This allows faster
+response to commands typed in advance. Normally, the input FILE
+pointer passed to \fBnewterm\fR, or \fBstdin\fR in the case that
+\fBinitscr\fR was used, will be used to do this typeahead checking.
+The \fBtypeahead\fR routine specifies that the file descriptor
+\fIfd\fR is to be used to check for typeahead instead. If \fIfd\fR is
+-1, then no typeahead checking is done.
+.SH RETURN VALUE
+All routines that return an integer return \fBERR\fR upon failure and an
+integer value other than \fBERR\fR upon successful completion, unless otherwise
+noted in the preceding routine descriptions.
+.SH NOTES
+Note that \fBecho\fR, \fBnoecho\fR, \fBhalfdelay\fR, \fBintrflush\fR,
+\fBmeta\fR, \fBnodelay\fR, \fBnotimeout\fR, \fBnoqiflush\fR,
+\fBqiflush\fR, \fBtimeout\fR, and \fBwtimeout\fR may be macros.
+.SH BUGS
+The entry points \fBintrflush\fR, \fBqiflush\fR, \fBnoqiflush\fR, and
+\fBtypeahead\fR are not yet implemented in ncurses 1.8.6. The ncurses
+code does not do typeahead checking during input as SVr4 curses does.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_getch\fR(3), \fBcurs_initscr\fR(3), \fBtermios\fR(4)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_insch.3 b/lib/libncurses/curs_insch.3
new file mode 100644
index 0000000..a4ab456
--- /dev/null
+++ b/lib/libncurses/curs_insch.3
@@ -0,0 +1,36 @@
+.TH curs_insch 3 ""
+.SH NAME
+\fBinsch\fR, \fBwinsch\fR, \fBmvinsch\fR,
+\fBmvwinsch\fR - insert a character before cursor in a \fBncurses\fR window
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint insch(chtype ch);\fR
+.br
+\fBint winsch(WINDOW *win, chtype ch);\fR
+.br
+\fBint mvinsch(int y, int x, chtype ch);\fR
+.br
+\fBint mvwinsch(WINDOW *win, int y, int x, chtype ch);\fR
+.br
+.SH DESCRIPTION
+These routines, insert the character \fIch\fR before the character under the
+cursor. All characters to the right of the cursor are moved one space to the
+right, with the possibility of the rightmost character on the line being lost.
+The insertion operation does not change the cursor position.
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion.
+.SH NOTES
+These routines do not necessarily imply use of a hardware insert character
+feature.
+
+Note that \fBinsch\fR, \fBmvinsch\fR, and \fBmvwinsch\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_insstr.3 b/lib/libncurses/curs_insstr.3
new file mode 100644
index 0000000..735dd1b
--- /dev/null
+++ b/lib/libncurses/curs_insstr.3
@@ -0,0 +1,59 @@
+.\" $Id$
+.\"
+.TH curs_insstr 3 ""
+.SH NAME
+\fBinsstr\fR, \fBinsnstr\fR, \fBwinsstr\fR, \fBwinsnstr\fR,
+\fBmvinsstr\fR, \fBmvinsnstr\fR, \fBmvwinsstr\fR,
+\fBmvwinsnstr\fR - insert string before cursor a \fBncurses\fR window
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+.br
+\fBint insstr(char *str);\fR
+.br
+\fBint insnstr(char *str, int n);\fR
+.br
+\fBint winsstr(WINDOW *win, char *str);\fR
+.br
+\fBint winsnstr(WINDOW *win, char *str, int n);\fR
+.br
+\fBint mvinsstr(int y, int x, char *str);\fR
+.br
+\fBint mvinsnstr(int y, int x, char *str, int n);\fR
+.br
+\fBint mvwinsstr(WINDOW *win, int y, int x, char *str);\fR
+.br
+\fBint mvwinsnstr(WINDOW *win, int y, int x, char *str, int n);\fR
+.br
+.SH DESCRIPTION
+These routines insert a character string (as many characters as will fit on the
+line) before the character under the cursor. All characters to the right of
+the cursor are shifted right, with the possibility of the rightmost characters
+on the line being lost. The cursor position does not change (after moving to
+\fIy\fR, \fIx\fR, if specified). The four routines with \fIn\fR as the last
+argument insert a leading substring of at most \fIn\fR characters. If
+\fIn\fR<=0, then the entire string is inserted.
+
+If a character in \fIstr\fR is a tab, newline, carriage return or
+backspace, the cursor is moved appropriately within the window. A
+newline also does a \fBclrtoeol\fR before moving. Tabs are considered
+to be at every eighth column. If a character in \fIstr\fR is another
+control character, it is drawn in the \fB^\fR\fIX\fR notation.
+Calling \fBwinch\fR after adding a control character (and moving to
+it, if necessary) does not return the control character, but instead
+returns a character in the ^-representation of the control character.
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion.
+.SH BUGS
+Entry points for these functions are in ncurses.h but they are not
+implemented as of ncurses 1.8.6.
+.SH NOTES
+Note that all but \fBwinsnstr\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_clear\fR(3), \fBcurs_inch\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_instr.3 b/lib/libncurses/curs_instr.3
new file mode 100644
index 0000000..0aa539b
--- /dev/null
+++ b/lib/libncurses/curs_instr.3
@@ -0,0 +1,44 @@
+.TH curs_instr 3 ""
+.SH NAME
+\fBinstr\fR, \fBinnstr\fR, \fBwinstr\fR, \fBwinnstr\fR,
+\fBmvinstr\fR, \fBmvinnstr\fR, \fBmvwinstr\fR,
+\fBmvwinnstr\fR - get a string of characters from a \fBncurses\fR window
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint instr(char *str);\fR
+.br
+\fBint innstr(char *str, int n);\fR
+.br
+\fBint winstr(WINDOW *win, char *str);\fR
+.br
+\fBint winnstr(WINDOW *win, char *str, int n);\fR
+.br
+\fBint mvinstr(int y, int x, char *str);\fR
+.br
+\fBint mvinnstr(int y, int x, char *str, int n);\fR
+.br
+\fBint mvwinstr(WINDOW *win, int y, int x, char *str);\fR
+.br
+\fBint mvwinnstr(WINDOW *win, int y, int x, char *str, int n);\fR
+.br
+.SH DESCRIPTION
+These routines return a string of characters in \fIstr\fR, extracted starting
+at the current cursor position in the named window and ending at the right
+margin of the window. Attributes are stripped from the characters. The four
+functions with \fIn\fR as the last argument return a leading substring at most
+\fIn\fR characters long.
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion.
+.SH NOTES
+Note that all routines except \fBwinnstr\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
+
diff --git a/lib/libncurses/curs_kernel.3 b/lib/libncurses/curs_kernel.3
new file mode 100644
index 0000000..1eff4e1
--- /dev/null
+++ b/lib/libncurses/curs_kernel.3
@@ -0,0 +1,115 @@
+.TH curs_kernel 3 ""
+.SH NAME
+\fBdef_prog_mode\fR, \fBdef_shell_mode\fR,
+\fBreset_prog_mode\fR, \fBreset_shell_mode\fR, \fBresetty\fR,
+\fBsavetty\fR, \fBgetsyx\fR, \fBsetsyx\fR, \fBripoffline\fR,
+\fBcurs_set\fR, \fBnapms\fR - low-level \fBncurses\fR routines
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint def_prog_mode(void);\fR
+.br
+\fBint def_shell_mode(void);\fR
+.br
+\fBint reset_prog_mode(void);\fR
+.br
+\fBint reset_shell_mode(void);\fR
+.br
+\fBint resetty(void);\fR
+.br
+\fBint savetty(void);\fR
+.br
+\fBint getsyx(int y, int x);\fR
+.br
+\fBint setsyx(int y, int x);\fR
+.br
+\fBint ripoffline(int line, int (*init)(WINDOW *, int));\fR
+.br
+\fBint curs_set(int visibility);\fR
+.br
+\fBint napms(int ms);\fR
+.br
+.SH DESCRIPTION
+The following routines give low-level access to various \fBncurses\fR
+capabilities. Theses routines typically are used inside library
+routines.
+
+The \fBdef_prog_mode\fR and \fBdef_shell_mode\fR routines save the
+current terminal modes as the "program" (in \fBncurses\fR) or "shell"
+(not in \fBncurses\fR) state for use by the \fBreset_prog_mode\fR and
+\fBreset_shell_mode\fR routines. This is done automatically by
+\fBinitscr\fR.
+
+The \fBreset_prog_mode\fR and \fBreset_shell_mode\fR routines restore
+the terminal to "program" (in \fBncurses\fR) or "shell" (out of
+\fBncurses\fR) state. These are done automatically by \fBendwin\fR
+and, after an \fBendwin\fR, by \fBdoupdate\fR, so they normally are
+not called.
+
+The \fBresetty\fR and \fBsavetty\fR routines save and restore the
+state of the terminal modes. \fBsavetty\fR saves the current state in
+a buffer and \fBresetty\fR restores the state to what it was at the
+last call to \fBsavetty\fR.
+
+With the \fBgetsyx\fR routine, the current coordinates of the virtual
+screen cursor are returned in \fIy\fR and \fIx\fR. If \fBleaveok\fR
+is currently \fBTRUE\fR, then \fB-1\fR,\fB-1\fR is returned. If lines
+have been removed from the top of the screen, using \fBripoffline\fR,
+\fIy\fR and \fIx\fR include these lines; therefore, \fIy\fR and
+\fIx\fR should be used only as arguments for \fBsetsyx\fR.
+
+With the \fBsetsyx\fR routine, the virtual screen cursor is set to
+\fIy\fR, \fIx\fR. If \fIy\fR and \fIx\fR are both \fB-1\fR, then
+\fBleaveok\fR is set. The two routines \fBgetsyx\fR and \fBsetsyx\fR
+are designed to be used by a library routine, which manipulates
+\fBncurses\fR windows but does not want to change the current position
+of the program's cursor. The library routine would call \fBgetsyx\fR
+at the beginning, do its manipulation of its own windows, do a
+\fBwnoutrefresh\fR on its windows, call \fBsetsyx\fR, and then call
+\fBdoupdate\fR.
+
+The \fBripoffline\fR routine provides access to the same facility that
+\fBslk_init\fR [see curs_slk(3)] uses to reduce the size of the
+screen. \fBripoffline\fR must be called before \fBinitscr\fR or
+\fBnewterm\fR is called. If \fIline\fR is positive, a line is removed
+from the top of \fBstdscr\fR; if \fIline\fR is negative, a line is
+removed from the bottom. When this is done inside \fBinitscr\fR, the
+routine \fBinit\fR (supplied by the user) is called with two
+arguments: a window pointer to the one-line window that has been
+allocated and an integer with the number of columns in the window.
+Inside this initialization routine, the integer variables \fBLINES\fR
+and \fBCOLS\fR (defined in \fB<ncurses.h>\fR) are not guaranteed to be
+accurate and \fBwrefresh\fR or \fBdoupdate\fR must not be called. It
+is allowable to call \fBwnoutrefresh\fR during the initialization
+routine.
+
+\fBripoffline\fR can be called up to five times before calling \fBinitscr\fR or
+\fBnewterm\fR.
+
+The \fBcurs_set\fR routine sets the cursor state is set to invisible,
+normal, or very visible for \fBvisibility\fR equal to \fB0\fR,
+\fB1\fR, or \fB2\fR respectively. If the terminal supports the
+\fIvisibility\fR requested, the previous \fIcursor\fR state is
+returned; otherwise, \fBERR\fR is returned.
+
+The \fBnapms\fR routine is used to sleep for \fIms\fR milliseconds.
+.SH RETURN VALUE
+Except for \fBcurs_set\fR, these routines always return \fBOK\fR.
+\fBcurs_set\fR returns the previous cursor state, or \fBERR\fR if the
+requested \fIvisibility\fR is not supported.
+.SH NOTES
+Note that \fBgetsyx\fR is a macro, so \fB&\fR is not necessary before
+the variables \fIy\fR and \fIx\fR.
+
+The SVr4 man pages warn that the return value of \fBcurs_set\fR "is currently
+incorrect". This implementation gets it right, but it may be unwise to count
+on the correctness of the return value anywhere else.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_initscr\fR(3), \fBcurs_outopts\fR(3), \fBcurs_refresh\fR(3),
+\fBcurs_scr_dmp\fR(3), \fBcurs_slk\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_move.3 b/lib/libncurses/curs_move.3
new file mode 100644
index 0000000..fcb36f3
--- /dev/null
+++ b/lib/libncurses/curs_move.3
@@ -0,0 +1,28 @@
+.TH curs_move 3 ""
+.SH NAME
+\fBmove\fR, \fBwmove\fR - move \fBncurses\fR window cursor
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint move(int y, int x);\fR
+.br
+\fBint wmove(WINDOW *win, int y, int x);\fR
+.br
+.SH DESCRIPTION
+These routines move the cursor associated with the window to line \fIy\fR and
+column \fIx\fR. This routine does not move the physical cursor of the terminal
+until \fBrefresh\fR is called. The position specified is relative to the upper
+left-hand corner of the window, which is (0,0).
+.SH RETURN VALUE
+These routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion.
+.SH NOTES
+Note that \fBmove\fR may be a macro.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_refresh\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_outopts.3 b/lib/libncurses/curs_outopts.3
new file mode 100644
index 0000000..6c1f382
--- /dev/null
+++ b/lib/libncurses/curs_outopts.3
@@ -0,0 +1,115 @@
+.TH curs_outopts 3 ""
+.SH NAME
+\fBclearok\fR, \fBidlok\fR, \fBidcok immedok\fR,
+\fBleaveok\fR, \fBsetscrreg\fR, \fBwsetscrreg\fR, \fBscrollok\fR,
+\fBnl\fR, \fBnonl\fR - \fBncurses\fR output options
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint clearok(WINDOW *win, bool bf);\fR
+.br
+\fBint idlok(WINDOW *win, bool bf);\fR
+.br
+\fBvoid idcok(WINDOW *win, bool bf);\fR
+.br
+\fBvoid immedok(WINDOW *win, bool bf);\fR
+.br
+\fBint leaveok(WINDOW *win, bool bf);\fR
+.br
+\fBint setscrreg(int top, int bot);\fR
+.br
+\fBint wsetscrreg(WINDOW *win, int top, int bot);\fR
+.br
+\fBint scrollok(WINDOW *win, bool bf);\fR
+.br
+\fBint nl(void);\fR
+.br
+\fBint nonl(void);\fR
+.br
+.SH DESCRIPTION
+These routines set options that change the style of output within
+\fBncurses\fR. All options are initially \fBFALSE\fR, unless otherwise stated.
+It is not necessary to turn these options off before calling \fBendwin\fR.
+
+With the \fBclearok\fR routine, if enabled (\fIbf\fR is \fBTRUE\fR), the next
+call to \fBwrefresh\fR with this window will clear the screen completely and
+redraw the entire screen from scratch. This is useful when the contents of the
+screen are uncertain, or in some cases for a more pleasing visual effect. If
+the \fIwin\fR argument to \fBclearok\fR is the global variable \fBcurscr\fR,
+the next call to \fBwrefresh\fR with any window causes the screen to be cleared
+and repainted from scratch.
+
+With the \fBidlok\fR routine, if enabled (\fIbf\fR is \fBTRUE\fR),
+\fBncurses\fR considers using the hardware insert/delete line feature of
+terminals so equipped. If disabled (\fIbf\fR is \fBFALSE\fR), \fBncurses\fR
+very seldom uses this feature. (The insert/delete character feature is always
+considered.) This option should be enabled only if the application needs
+insert/delete line, for example, for a screen editor. It is disabled by
+default because insert/delete line tends to be visually annoying when used in
+applications where it isn't really needed. If insert/delete line cannot be
+used, \fBncurses\fR redraws the changed portions of all lines.
+
+With the \fBidcok\fR routine, if enabled (\fIbf\fR is \fBTRUE\fR),
+\fBncurses\fR considers using the hardware insert/delete character feature of
+terminals so equipped. This is enabled by default.
+
+With the \fBimmedok\fR routine, if enabled (\fIbf\fR is \fBTRUE)\fR, any change
+in the window image, such as the ones caused by \fBwaddch, wclrtobot, wscrl\fR,
+\fIetc\fR., automatically cause a call to \fBwrefresh\fR. However, it may
+degrade the performance considerably, due to repeated calls to \fBwrefresh\fR.
+It is disabled by default.
+
+Normally, the hardware cursor is left at the location of the window cursor
+being refreshed. The \fBleaveok\fR option allows the cursor to be left
+wherever the update happens to leave it. It is useful for applications where
+the cursor is not used, since it reduces the need for cursor motions. If
+possible, the cursor is made invisible when this option is enabled.
+
+The \fBsetscrreg\fR and \fBwsetscrreg\fR routines allow the application
+programmer to set a software scrolling region in a window. \fItop\fR and
+\fIbot\fR are the line numbers of the top and bottom margin of the scrolling
+region. (Line 0 is the top line of the window.) If this option and
+\fBscrollok\fR are enabled, an attempt to move off the bottom margin line
+causes all lines in the scrolling region to scroll up one line. Only the text
+of the window is scrolled. (Note that this has nothing to do with the use of a
+physical scrolling region capability in the terminal, like that in the VT100.
+If \fBidlok\fR is enabled and the terminal has either a scrolling region or
+insert/delete line capability, they will probably be used by the output
+routines.)
+
+The \fBscrollok\fR option controls what happens when the cursor of a window is
+moved off the edge of the window or scrolling region, either as a result of a
+newline action on the bottom line, or typing the last character of the last
+line. If disabled, (\fIbf\fR is \fBFALSE\fR), the cursor is left on the bottom
+line. If enabled, (\fIbf\fR is \fBTRUE\fR), \fBwrefresh\fR is called on the
+window, and the physical terminal and window are scrolled up one line. [Note
+that in order to get the physical scrolling effect on the terminal, it is also
+necessary to call \fBidlok\fR.]
+
+The \fBnl\fR and \fBnonl\fR routines control whether newline is translated into
+carriage return and linefeed on output, and whether return is translated into
+newline on input. Initially, the translations do occur. By disabling these
+translations using \fBnonl\fR, \fBncurses\fR is able to make better use of the
+linefeed capability, resulting in faster cursor motion.
+.SH RETURN VALUE
+\fBsetscrreg\fR and \fBwsetscrreg\fR return \fBOK\fR upon success and \fBERR\fR upon failure.
+All other routines that return an integer always return \fBOK\fR.
+.SH BUGS
+The entry points \fBidcok\fR, \fBimmedok\fR are not yet implemented in
+ncurses 1.8.6. Setting \fIidlok\fR has unfortunate effects on scrolling
+windows.
+.SH NOTES
+Note that \fBclearok\fR, \fBleaveok\fR, \fBscrollok\fR, \fBidcok\fR, \fBnl\fR,
+\fBnonl\fR and \fBsetscrreg\fR may be macros.
+
+The \fBimmedok\fR routine is useful for windows that are used as terminal
+emulators.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_addch\fR(3), \fBcurs_clear\fR(3),
+\fBcurs_initscr\fR(3), \fBcurs_scroll\fR(3), \fBcurs_refresh\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_overlay.3 b/lib/libncurses/curs_overlay.3
new file mode 100644
index 0000000..302fa17
--- /dev/null
+++ b/lib/libncurses/curs_overlay.3
@@ -0,0 +1,41 @@
+.TH curs_overlay 3 ""
+.SH NAME
+\fBoverlay\fR, \fBoverwrite\fR,
+\fBcopywin\fR - overlay and manipulate overlapped \fBncurses\fR windows
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint overlay(WINDOW *srcwin, WINDOW *dstwin);\fR
+.br
+\fBint overwrite(WINDOW *srcwin, WINDOW *dstwin);\fR
+.br
+\fBint copywin(WINDOW *srcwin, WINDOW *dstwin, int sminrow,
+ int smincol, int dminrow, int dmincol, int dmaxrow,
+ int dmaxcol, int overlay);\fR
+.SH DESCRIPTION
+The \fBoverlay\fR and \fBoverwrite\fR routines overlay \fIsrcwin\fR on
+top of \fIdstwin\fR. \fIscrwin\fR and \fIdstwin\fR are not required
+to be the same size; only text where the two windows overlap is
+copied. The difference is that \fBoverlay\fR is non-destructive
+(blanks are not copied) whereas \fBoverwrite\fR is destructive.
+
+The \fBcopywin\fR routine provides a finer granularity of control over the
+\fBoverlay\fR and \fBoverwrite\fR routines. Like in the \fBprefresh\fR
+routine, a rectangle is specified in the destination window, (\fIdminrow\fR,
+\fIdmincol\fR) and (\fIdmaxrow\fR, \fIdmaxcol\fR), and the upper-left-corner
+coordinates of the source window, (\fIsminrow\fR, \fIsmincol\fR). If the
+argument \fIoverlay\fR is \fBtrue\fR, then copying is non-destructive, as in
+\fBoverlay\fR.
+.SH RETURN VALUE
+Routines that return an integer return \fBERR\fR upon failure and an integer
+value other than \fBERR\fR upon successful completion.
+.SH NOTES
+Note that \fBoverlay\fR and \fBoverwrite\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_pad\fR(3), \fBcurs_refresh\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_pad.3 b/lib/libncurses/curs_pad.3
new file mode 100644
index 0000000..cba5e92
--- /dev/null
+++ b/lib/libncurses/curs_pad.3
@@ -0,0 +1,74 @@
+.TH curs_pad 3 ""
+.SH NAME
+\fBnewpad\fR, \fBsubpad\fR, \fBprefresh\fR,
+\fBpnoutrefresh\fR, \fBpechochar\fR - create and display \fBncurses\fR pads
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBWINDOW *newpad(int nlines, int ncols);\fR
+.br
+\fBWINDOW *subpad(WINDOW *orig, int nlines, int ncols,
+ int begin_y, int begin_x);\fR
+\fBint prefresh(WINDOW *pad, int pminrow, int pmincol,
+ int sminrow, int smincol, int smaxrow, int smaxcol);\fR
+\fBint pnoutrefresh(WINDOW *pad, int pminrow, int pmincol,
+ int sminrow, int smincol, int smaxrow, int smaxcol);\fR
+\fBint pechochar(WINDOW *pad, chtype ch);\fR
+.SH DESCRIPTION
+The \fBnewpad\fR routine creates and returns a pointer to a new pad data
+structure with the given number of lines, \fInlines\fR, and columns,
+\fIncols\fR. A pad is like a window, except that it is not restricted by the
+screen size, and is not necessarily associated with a particular part of the
+screen. Pads can be used when a large window is needed, and only a part of the
+window will be on the screen at one time. Automatic refreshes of pads
+(\fIe\fR.\fIg\fR., from scrolling or echoing of input) do not occur. It is not
+legal to call \fBwrefresh\fR with a \fIpad\fR as an argument; the routines
+\fBprefresh\fR or \fBpnoutrefresh\fR should be called instead. Note that these
+routines require additional parameters to specify the part of the pad to be
+displayed and the location on the screen to be used for the display.
+
+The \fBsubpad\fR routine creates and returns a pointer to a subwindow within a
+pad with the given number of lines, \fInlines\fR, and columns, \fIncols\fR.
+Unlike \fBsubwin\fR, which uses screen coordinates, the window is at position
+(\fIbegin\fR_\fIx\fR\fB,\fR \fIbegin\fR_\fIy\fR) on the pad. The window is
+made in the middle of the window \fIorig\fR, so that changes made to one window
+affect both windows. During the use of this routine, it will often be
+necessary to call \fBtouchwin\fR or \fBtouchline\fR on \fIorig\fR before
+calling \fBprefresh\fR.
+
+The \fBprefresh\fR and \fBpnoutrefresh\fR routines are analogous to
+\fBwrefresh\fR and \fBwnoutrefresh\fR except that they relate to pads instead
+of windows. The additional parameters are needed to indicate what part of the
+pad and screen are involved. \fIpminrow\fR and \fIpmincol\fR specify the upper
+left-hand corner of the rectangle to be displayed in the pad. \fIsminrow\fR,
+\fIsmincol\fR, \fIsmaxrow\fR, and \fIsmaxcol\fR specify the edges of the
+rectangle to be displayed on the screen. The lower right-hand corner of the
+rectangle to be displayed in the pad is calculated from the screen coordinates,
+since the rectangles must be the same size. Both rectangles must be entirely
+contained within their respective structures. Negative values of
+\fIpminrow\fR, \fIpmincol\fR, \fIsminrow\fR, or \fIsmincol\fR are treated as if
+they were zero.
+
+The \fBpechochar\fR routine is functionally equivalent to a call to \fBaddch\fR
+followed by a call to \fBrefresh\fR, a call to \fBwaddch\fR followed by a call
+to \fBwrefresh\fR, or a call to \fBwaddch\fR followed by a call to
+\fBprefresh.\fR The knowledge that only a single character is being output is
+taken into consideration and, for non-control characters, a considerable
+performance gain might be seen by using these routines instead of their
+equivalents. In the case of \fBpechochar\fR, the last location of the pad on
+the screen is reused for the arguments to \fBprefresh\fR.
+.SH RETURN VALUE
+Routines that return an integer return \fBERR\fR upon failure and an integer
+value other than \fBERR\fR upon successful completion.
+
+Routines that return pointers return \fBNULL\fR on error.
+.SH NOTES
+Note that \fBpechochar\fR may be a macro.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_refresh\fR(3), \fBcurs_touch\fR(3), \fBcurs_addch\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_printw.3 b/lib/libncurses/curs_printw.3
new file mode 100644
index 0000000..d2f6688
--- /dev/null
+++ b/lib/libncurses/curs_printw.3
@@ -0,0 +1,41 @@
+.TH curs_printw 3 ""
+.SH NAME
+\fBprintw\fR, \fBwprintw\fR, \fBmvprintw\fR,
+\fBmvwprintw\fR, \fBvwprintw\fR - print formatted output in \fBncurses\fR windows
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint printw(char *fmt\fR [\fB, arg\fR] \fB...);\fR
+.br
+\fBint wprintw(WINDOW *win, char *fmt\fR [\fB, arg\fR] \fB...);\fR
+.br
+\fBint mvprintw(int y, int x, char *fmt\fR [\fB, arg\fR] \fB...);\fR
+.br
+\fBint mvwprintw(WINDOW *win, int y, int x,
+ \fBchar *fmt\fR [\fB, arg]\fR ...);
+
+\fB#include <varargs.h>\fR
+.br
+\fBint vwprintw(WINDOW *win, char *fmt, varglist);\fR
+.br
+.SH DESCRIPTION
+The \fBprintw\fR, \fBwprintw\fR, \fBmvprintw\fR and \fBmvwprintw\fR
+routines are analogous to \fBprintf\fR [see \fBprintf\fR(3)]. In
+effect, the string that would be output by \fBprintf\fR is output
+instead as though \fBwaddstr\fR were used on the given window.
+
+The \fBvwprintw\fR routine is analogous to \fBvprintf\fR [see
+\fBprintf\fR(3)] and performs a \fBwprintw\fR using a variable
+argument list. The third argument is a \fBva_list\fR, a pointer to a
+list of arguments, as defined in \fB<varargs.h>\fR.
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBprintf\fR(3), \fBvprintf(3)\fR
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_refresh.3 b/lib/libncurses/curs_refresh.3
new file mode 100644
index 0000000..3c204e2
--- /dev/null
+++ b/lib/libncurses/curs_refresh.3
@@ -0,0 +1,69 @@
+.TH curs_refresh 3 ""
+.SH NAME
+\fBrefresh\fR, \fBwrefresh\fR, \fBwnoutrefresh\fR,
+\fBdoupdate\fR, \fBredrawwin\fR,
+\fBwredrawln\fR - refresh \fBncurses\fR windows and lines
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint refresh(void);\fR
+.br
+\fBint wrefresh(WINDOW *win);\fR
+.br
+\fBint wnoutrefresh(WINDOW *win);\fR
+.br
+\fBint doupdate(void);\fR
+.br
+\fBint redrawwin(WINDOW *win);\fR
+.br
+\fBint wredrawln(WINDOW *win, int beg_line, int num_lines);\fR
+.br
+.SH DESCRIPTION
+The \fBrefresh\fR and \fBwrefresh\fR routines (or \fBwnoutrefresh\fR and
+\fBdoupdate\fR) must be called to get actual output to the terminal, as other
+routines merely manipulate data structures. The routine \fBwrefresh\fR copies
+the named window to the physical terminal screen, taking into account what is
+already there in order to do optimizations. The \fBrefresh\fR routine is the
+same, using \fBstdscr\fR as the default window. Unless \fBleaveok\fR has been
+enabled, the physical cursor of the terminal is left at the location of the
+cursor for that window.
+
+The \fBwnoutrefresh\fR and \fBdoupdate\fR routines allow multiple updates with
+more efficiency than \fBwrefresh\fR alone. In addition to all the window
+structures, \fBncurses\fR keeps two data structures representing the terminal
+screen: a physical screen, describing what is actually on the screen, and a
+virtual screen, describing what the programmer wants to have on the screen.
+
+The routine \fBwrefresh\fR works by first calling \fBwnoutrefresh\fR, which
+copies the named window to the virtual screen, and then calling \fBdoupdate\fR,
+which compares the virtual screen to the physical screen and does the actual
+update. If the programmer wishes to output several windows at once, a series
+of calls to \fBwrefresh\fR results in alternating calls to \fBwnoutrefresh\fR
+and \fBdoupdate\fR, causing several bursts of output to the screen. By first
+calling \fBwnoutrefresh\fR for each window, it is then possible to call
+\fBdoupdate\fR once, resulting in only one burst of output, with fewer total
+characters transmitted and less CPU time used. If the \fIwin\fR argument to
+\fBwrefresh\fR is the global variable \fBcurscr\fR, the screen is immediately
+cleared and repainted from scratch.
+
+The \fBredrawwin\fR routine indicates to \fBncurses\fR that some screen lines
+are corrupted and should be thrown away before anything is written over them.
+These routines could be used for programs such as editors, which want a command
+to redraw some part of the screen or the entire screen. The routine
+\fBredrawln\fR is preferred over \fBredrawwin\fR where a noisy communication
+line exists and redrawing the entire window could be subject to even more
+communication noise. Just redrawing several lines offers the possibility that
+they would show up unblemished.
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion.
+.SH NOTES
+Note that \fBrefresh\fR and \fBredrawwin\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_outopts\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_scanw.3 b/lib/libncurses/curs_scanw.3
new file mode 100644
index 0000000..22a8b60
--- /dev/null
+++ b/lib/libncurses/curs_scanw.3
@@ -0,0 +1,43 @@
+.TH curs_scanw 3 ""
+.SH NAME
+\fBscanw\fR, \fBwscanw\fR, \fBmvscanw\fR,
+\fBmvwscanw\fR, \fBvwscanw\fR - convert formatted input from a \fBncurses\fR widow
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint scanw(char *fmt\fR [\fB, arg\fR] \fB...);\fR
+.br
+\fBint wscanw(WINDOW *win, char *fmt\fR [\fB, arg\fR] \fB...);\fR
+.br
+\fBint mvscanw(int y, int x, char *fmt\fR [\fB, arg\fR] \fB...);\fR
+.br
+\fBint mvwscanw(WINDOW *win, int y, int x,
+ char *fmt\fR [\fB, arg]\fR \fB...);\fR
+.br
+\fBint vwscanw(WINDOW *win, char *fmt, va_list varglist);\fR
+.SH DESCRIPTION
+The \fBscanw\fR, \fBwscanw\fR and \fBmvscanw\fR routines are analogous to
+\fBscanf\fR [see \fBscanf\fR(3)]. The effect of these routines is as though
+\fBwgetstr\fR were called on the window, and the resulting line used as input
+for \fBsscanf\fR(3). Fields which do not map to a variable in the \fIfmt\fR
+field are lost.
+
+The \fBvwscanw\fR routine is similar to \fBvwprintw\fR in that it performs a
+\fBwscanw\fR using a variable argument list. The third argument is a
+\fIva\fR_\fIlist\fR, a pointer to a list of arguments, as defined in
+\fB<varargs.h>\fR.
+.SH RETURN VALUE
+\fBvwscanw\fR returns \fBERR\fR on failure and an integer equal to the
+number of fields scanned on success.
+
+Applications may use the return value from the \fBscanw\fR, \fBwscanw\fR,
+\fBmvscanw\fR and \fBmvwscanw\fR routines to determine the number of fields
+which were mapped in the call.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_getstr\fR(3), \fBcurs_printw\fR(3), \fBscanf\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_scr_dmp.3 b/lib/libncurses/curs_scr_dmp.3
new file mode 100644
index 0000000..622b0f9
--- /dev/null
+++ b/lib/libncurses/curs_scr_dmp.3
@@ -0,0 +1,58 @@
+.TH curs_scr_dump 3 ""
+.SH NAME
+\fBscr_dump\fR, \fBscr_restore\fR,
+\fBscr_init\fR,
+\fBscr_set\fR - read (write) a \fBncurses\fR screen from (to) a file
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint scr_dump(char *filename);\fR
+.br
+\fBint scr_restore(char *filename);\fR
+.br
+\fBint scr_init(char *filename);\fR
+.br
+\fBint scr_set(char *filename);\fR
+.br
+.SH DESCRIPTION
+The \fBscr_dump\fR routine dumps the current contents of the virtual screen
+to the file \fIfilename\fR.
+
+The \fBscr_restore\fR routine sets the virtual screen to the contents
+of \fIfilename\fR, which must have been written using \fBscr_dump\fR. The next
+call to \fBdoupdate\fR restores the screen to the way it looked in the dump
+file.
+
+The \fBscr_init\fR routine reads in the contents of \fIfilename\fR and uses
+them to initialize the \fBncurses\fR data structures about what the terminal
+currently has on its screen. If the data is determined to be valid,
+\fBncurses\fR bases its next update of the screen on this information rather
+than clearing the screen and starting from scratch. \fBscr_init\fR is used
+after \fBinitscr\fR or a \fBsystem\fR [see \fBsystem\fR(BA_LIB)] call to share
+the screen with another process which has done a \fBscr_dump\fR after its
+\fBendwin\fR call. The data is declared invalid if the time-stamp of the tty
+is old or the terminfo capabilities \fBrmcup\fR and \fBnrrmc\fR exist.
+
+The \fBscr_set\fR routine is a combination of \fBscr_restore\fR and
+\fBscr_init\fR. It tells the program that the information in \fIfilename\fR is
+what is currently on the screen, and also what the program wants on the screen.
+This can be thought of as a screen inheritance function.
+
+To read (write) a window from (to) a file, use the \fBgetwin\fR and
+\fBputwin\fR routines [see \fBcurs_util\fR(3)].
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and \fBOK\fR
+upon success.
+.SH NOTES
+Note that \fBscr_init\fR, \fBscr_set\fR, and \fBscr_restore\fR may be macros.
+.BUGS
+The time-stamp and rmcup/nrrmc checks are not implemented in \fBncurses\fR(3).
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_initscr\fR(3), \fBcurs_refresh\fR(3),
+\fBcurs_util\fR(3), \fBsystem\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_scroll.3 b/lib/libncurses/curs_scroll.3
new file mode 100644
index 0000000..a779a90
--- /dev/null
+++ b/lib/libncurses/curs_scroll.3
@@ -0,0 +1,37 @@
+.TH curs_scroll 3 ""
+.SH NAME
+\fBscroll\fR, \fBscrl\fR, \fBwscrl\fR - scroll a \fBncurses\fR window
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint scroll(WINDOW *win);\fR
+.br
+\fBint scrl(int n);\fR
+.br
+\fBint wscrl(WINDOW *win, int n);\fR
+.br
+.SH DESCRIPTION
+The \fBscroll\fR routine scrolls the window up one line. This involves moving
+the lines in the window data structure. As an optimization, if the scrolling
+region of the window is the entire screen, the physical screen is scrolled at
+the same time.
+
+With the \fBscrl\fR and \fBwscrl\fR routines, for positive \fIn\fR scroll the
+window up \fIn\fR lines (line \fIi\fR+\fIn\fR becomes \fIi\fR); otherwise
+scroll the window down \fIn\fR lines. This involves moving the lines in the
+window character image structure. The current cursor position is not changed.
+
+For these functions to work, scrolling must be enabled via \fBscrollok\fR.
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion.
+.SH NOTES
+Note that \fBscrl\fR and \fBscroll\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_outopts\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_slk.3 b/lib/libncurses/curs_slk.3
new file mode 100644
index 0000000..c391701
--- /dev/null
+++ b/lib/libncurses/curs_slk.3
@@ -0,0 +1,85 @@
+.TH curs_slk 3 ""
+.SH NAME
+\fBslk_init\fR, \fBslk_set\fR, \fBslk_refresh\fR,
+\fBslk_noutrefresh\fR, \fBslk_label\fR, \fBslk_clear\fR, \fBslk_restore\fR,
+\fBslk_touch\fR, \fBslk_attron\fR, \fBslk_attrset\fR,
+\fBslk_attroff\fR - \fBncurses\fR soft label routines
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint slk_init(int fmt);\fR
+.br
+\fBint slk_set(int labnum, char *label, int fmt);\fR
+.br
+\fBint slk_refresh(void);\fR
+.br
+\fBint slk_noutrefresh(void);\fR
+.br
+\fBchar *slk_label(int labnum);\fR
+.br
+\fBint slk_clear(void);\fR
+.br
+\fBint slk_restore(void);\fR
+.br
+\fBint slk_touch(void);\fR
+.br
+\fBint slk_attron(chtype attrs);\fR
+.br
+\fBint slk_attrset(chtype attrs);\fR
+.br
+\fBint slk_attroff(chtype attrs);\fR
+.br
+.SH DESCRIPTION
+The slk* functions manipulate the set of soft function-key labels that exist on
+many terminals. For those terminals that do not have soft labels,
+\fBncurses\fR takes over the bottom line of \fBstdscr\fR, reducing the size of
+\fBstdscr\fR and the variable \fBLINES\fR. \fBncurses\fR standardizes on eight
+labels of up to eight characters each.
+
+The \fBslk_init\fR routine must be called before \fBinitscr\fR or \fBnewterm\fR
+is called. If \fBinitscr\fR eventually uses a line from \fBstdscr\fR to
+emulate the soft labels, then \fIfmt\fR determines how the labels are arranged
+on the screen. Setting \fIfmt\fR to \fB0\fR indicates a 3-2-3 arrangement of
+the labels; \fB1\fR indicates a 4-4 arrangement.
+
+With the \fBslk_set\fR routine, \fIlabnum\fR is the label number, from \fB1\fR
+to \fB8\fR. \fIlabel\fR is the string to be put on the label, up to eight
+characters in length. A null string or a null pointer sets up a blank label.
+\fIfmt\fR is either \fB0\fR, \fB1\fR, or \fB2\fR, indicating whether the label
+is to be left-justified, centered, or right-justified, respectively, within the
+label.
+
+The \fBslk_refresh\fR and \fBslk_noutrefresh\fR routines correspond to
+the \fBwrefresh\fR and \fBwnoutrefresh\fR routines.
+
+The \fBslk_label\fR routine returns the current label for label number
+\fIlabnum\fR, with leading and trailing blanks stripped.
+
+The \fBslk_clear\fR routine clears the soft labels from the screen.
+
+The \fBslk_restore\fR routine, restores the soft labels to the screen
+after a \fBslk_clear\fR has been performed.
+
+The \fBslk_touch\fR routine forces all the soft labels to be output
+the next time a \fBslk_noutrefresh\fR is performed.
+
+The \fBslk_attron\fR, \fBslk_attrset\fR and \fBslk_attroff\fR routines
+correspond to \fBattron\fR, \fBattrset\fR, and \fBattroff\fR. They
+have an effect only if soft labels are simulated on the bottom line of
+the screen.
+.SH RETURN VALUE
+Routines that return an integer return \fBERR\fR upon failure and an integer
+value other than \fBERR\fR upon successful completion.
+
+\fBslk_label\fR returns \fBNULL\fR on error.
+.SH NOTES
+Most applications would use \fBslk_noutrefresh\fR because a
+\fBwrefresh\fR is likely to follow soon.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_attr\fR(3), \fBcurs_initscr\fR(3), \fBcurs_refresh\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_termatt.3 b/lib/libncurses/curs_termatt.3
new file mode 100644
index 0000000..e7a5078
--- /dev/null
+++ b/lib/libncurses/curs_termatt.3
@@ -0,0 +1,74 @@
+.TH curs_termattrs 3 ""
+.SH NAME
+\fBbaudrate\fR, \fBerasechar\fR, \fBhas_ic\fR,
+\fBhas_il\fR, \fBkillchar\fR, \fBlongname\fR, \fBtermattrs\fR,
+\fBtermname\fR - \fBncurses\fR environment query routines
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBint baudrate(void);\fR
+.br
+\fBchar erasechar(void);\fR
+.br
+\fBint has_ic(void);\fR
+.br
+\fBint has_il(void);\fR
+.br
+\fBchar killchar(void);\fR
+.br
+\fBchar *longname(void);\fR
+.br
+\fBchtype termattrs(void);\fR
+.br
+\fBchar *termname(void);\fR
+.br
+.SH DESCRIPTION
+The \fBbaudrate\fR routine returns the output speed of the terminal. The
+number returned is in bits per second, for example \fB9600\fR, and is an
+integer.
+
+The \fBerasechar\fR routine returns the user's current erase character.
+
+The \fBhas_ic\fR routine is true if the terminal has insert- and delete-
+character capabilities.
+
+The \fBhas_il\fR routine is true if the terminal has insert- and delete-line
+capabilities, or can simulate them using scrolling regions. This might
+be used to determine if it would be appropriate to turn on physical
+scrolling using \fBscrollok\fR.
+
+The \fBkillchar\fR routine returns the user's current line kill character.
+
+The \fBlongname\fR routine returns a pointer to a static area
+containing a verbose description of the current terminal. The maximum
+length of a verbose description is 128 characters. It is defined only
+after the call to \fBinitscr\fR or \fBnewterm\fR. The area is
+overwritten by each call to \fBnewterm\fR and is not restored by
+\fBset_term\fR, so the value should be saved between calls to
+\fBnewterm\fR if \fBlongname\fR is going to be used with multiple
+terminals.
+
+If a given terminal doesn't support a video attribute that an
+application program is trying to use, \fBncurses\fR may substitute a
+different video attribute for it. The \fBtermattrs\fR function
+returns a logical \fBOR\fR of all video attributes supported by the
+terminal. This information is useful when a \fBncurses\fR program
+needs complete control over the appearance of the screen.
+
+The \fBtermname\fR routine returns the value of the environmental
+variable \fBTERM\fR (truncated to 14 characters).
+.SH RETURN VALUE
+\fBlongname\fR and \fBtermname\fR return \fBNULL\fR on error.
+
+Routines that return an integer return \fBERR\fR upon failure and an integer
+value other than \fBERR\fR upon successful completion.
+.SH NOTES
+Note that \fBtermattrs\fR may be a macro.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_initscr\fR(3), \fBcurs_outopts\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_termin.3 b/lib/libncurses/curs_termin.3
new file mode 100644
index 0000000..a624b65
--- /dev/null
+++ b/lib/libncurses/curs_termin.3
@@ -0,0 +1,191 @@
+.TH curs_terminfo 3 ""
+.ds n 5
+.SH NAME
+\fBsetupterm\fR, \fBsetterm\fR,
+\fBset_curterm\fR, \fBdel_curterm\fR, \fBrestartterm\fR, \fBtparm\fR,
+\fBtputs\fR, \fBputp\fR, \fBvidputs\fR, \fBvidattr\fR, \fBmvcur\fR,
+\fBtigetflag\fR, \fBtigetnum\fR,
+\fBtigetstr\fR - \fBncurses\fR interfaces to terminfo database
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+.br
+\fB#include <term.h>\fR
+
+\fBint setupterm(char *term, int fildes, int *errret);\fR
+.br
+\fBint setterm(char *term);\fR
+.br
+\fBint set_curterm(TERMINAL *nterm);\fR
+.br
+\fBint del_curterm(TERMINAL *oterm);\fR
+.br
+\fBint restartterm(char *term, int fildes, int *errret);\fR
+.br
+\fBchar *tparm(char *str, long int p1, long int p2,
+ long int p3, long int p4, long int p5, long int p6,
+ long int p7, long int p8, long int p9);\fR
+.br
+\fBint tputs(char *str, int affcnt, int (*putc)(char));\fR
+.br
+\fBint putp(char *str);\fR
+.br
+\fBint vidputs(chtype attrs, int (*putc)(char));\fR
+.br
+\fBint vidattr(chtype attrs);\fR
+.br
+\fBint mvcur(int oldrow, int oldcol, int newrow, int newcol);\fR
+.br
+\fBint tigetflag(char *capname);\fR
+.br
+\fBint tigetnum(char *capname);\fR
+.br
+\fBint tigetstr(char *capname);\fR
+.br
+.SH DESCRIPTION
+These low-level routines must be called by programs that have to deal
+directly with the \fBterminfo\fR database to handle certain terminal
+capabilities, such as programming function keys. For all other
+functionality, \fBncurses\fR routines are more suitable and their use is
+recommended.
+
+Initially, \fBsetupterm\fR should be called. Note that
+\fBsetupterm\fR is automatically called by \fBinitscr\fR and
+\fBnewterm\fR. This defines the set of terminal-dependent variables
+[listed in \fBterminfo\fR(5)]. The \fBterminfo\fR variables
+\fBlines\fR and \fBcolumns\fR are initialized by \fBsetupterm\fR as
+follows: If \fBuse_env(FALSE)\fR has been called, values for
+\fBlines\fR and \fBcolumns\fR specified in \fBterminfo\fR are used.
+Otherwise, if the environment variables \fBLINES\fR and \fBCOLUMNS\fR
+exist, their values are used. If these environment variables do not
+exist and the program is running in a window, the current window size
+is used. Otherwise, if the environment variables do not exist, the
+values for \fBlines\fR and \fBcolumns\fR specified in the
+\fBterminfo\fR database are used.
+
+The header files \fBncurses.h\fR and \fBnterm.h\fR should be included (in this
+order) to get the definitions for these strings, numbers, and flags (these
+correspond to the SVr4 headers \fBcurses.h\fR and \fBterm.h\fR). Parameterized
+strings should be passed through \fBtparm\fR to instantiate them. All
+\fBterminfo\fR strings [including the output of \fBtparm\fR] should be printed
+with \fBtputs\fR or \fBputp\fR. Call the \fBreset_shell_mode\fR to restore the
+tty modes before exiting [see \fBcurs_kernel\fR(3)]. Programs which use
+cursor addressing should output \fBenter_ca_mode\fR upon startup and should
+output \fBexit_ca_mode\fR before exiting. Programs desiring shell escapes
+should call
+
+\fBreset_shell_mode\fR and output \fBexit_ca_mode\fR before the shell
+is called and should output \fBenter_ca_mode\fR and call
+\fBreset_prog_mode\fR after returning from the shell.
+
+The \fBsetupterm\fR routine reads in the \fBterminfo\fR database,
+initializing the \fBterminfo\fR structures, but does not set up the
+output virtualization structures used by \fBncurses\fR. The terminal
+type is the character string \fIterm\fR; if \fIterm\fR is null, the
+environment variable \fBTERM\fR is used. All output is to file
+descriptor \fBfildes\fR which is initialized for output. If
+\fIerrret\fR is not null, then \fBsetupterm\fR returns \fBOK\fR or
+\fBERR\fR and stores a status value in the integer pointed to by
+\fIerrret\fR. A status of \fB1\fR in \fIerrret\fR is normal, \fB0\fR
+means that the terminal could not be found, and \fB-1\fR means that
+the \fBterminfo\fR database could not be found. If \fIerrret\fR is
+null, \fBsetupterm\fR prints an error message upon finding an error
+and exits. Thus, the simplest call is:
+
+ \fBsetupterm((char *)0, 1, (int *)0);\fR,
+
+which uses all the defaults and sends the output to \fBstdout\fR.
+
+The \fBsetterm\fR routine is being replaced by \fBsetupterm\fR. The call:
+
+ \fBsetupterm(\fR\fIterm\fR\fB, 1, (int *)0)\fR
+
+provides the same functionality as \fBsetterm(\fR\fIterm\fR\fB)\fR.
+The \fBsetterm\fR routine is included here for BSD compatibility, and
+is not recommended for new programs.
+
+The \fBset_curterm\fR routine sets the variable \fBcur_term\fR to
+\fInterm\fR, and makes all of the \fBterminfo\fR boolean, numeric, and
+string variables use the values from \fInterm\fR.
+
+The \fBdel_curterm\fR routine frees the space pointed to by
+\fIoterm\fR and makes it available for further use. If \fIoterm\fR is
+the same as \fBcur_term\fR, references to any of the \fBterminfo\fR
+boolean, numeric, and string variables thereafter may refer to invalid
+memory locations until another \fBsetupterm\fR has been called.
+
+The \fBrestartterm\fR routine is similar to \fBsetupterm\fR and
+\fBinitscr\fR, except that it is called after restoring memory to a
+previous state. It assumes that the windows and the input and output
+options are the same as when memory was saved, but the terminal type
+and baud rate may be different.
+
+The \fBtparm\fR routine instantiates the string \fIstr\fR with
+parameters \fIpi\fR. A pointer is returned to the result of \fIstr\fR
+with the parameters applied.
+
+The \fBtputs\fR routine applies padding information to the string
+\fIstr\fR and outputs it. The \fIstr\fR must be a terminfo string
+variable or the return value from \fBtparm\fR, \fBtgetstr\fR, or
+\fBtgoto\fR. \fIaffcnt\fR is the number of lines affected, or 1 if
+not applicable. \fIputc\fR is a \fBputchar\fR-like routine to which
+the characters are passed, one at a time.
+
+The \fBputp\fR routine calls \fBtputs(\fR\fIstr\fR\fB, 1, putchar)\fR.
+Note that the output of \fBputp\fR always goes to \fBstdout\fR, not to
+the \fIfildes\fR specified in \fBsetupterm\fR.
+
+The \fBvidputs\fR routine displays the string on the terminal in the
+video attribute mode \fIattrs\fR, which is any combination of the
+attributes listed in \fBncurses\fR(3). The characters are passed to
+the \fBputchar\fR-like routine \fIputc\fR.
+
+The \fBvidattr\fR routine is like the \fBvidputs\fR routine, except
+that it outputs through \fBputchar\fR.
+
+The \fBmvcur\fR routine provides low-level cursor motion. It takes
+effect immediately (rather than at the next refresh).
+
+The \fBtigetflag\fR, \fBtigetnum\fR and \fBtigetstr\fR routines return
+the value of the capability corresponding to the \fBterminfo\fR
+\fIcapname\fR passed to them, such as \fBxenl\fR.
+
+With the \fBtigetflag\fR routine, the value \fB-1\fR is returned if
+\fIcapname\fR is not a boolean capability.
+
+With the \fBtigetnum\fR routine, the value \fB-2\fR is returned if
+\fIcapname\fR is not a numeric capability.
+
+With the \fBtigetstr\fR routine, the value \fB(char *)-1\fR is
+returned if \fIcapname\fR is not a string capability.
+
+The \fIcapname\fR for each capability is given in the table column entitled
+\fIcapname\fR code in the capabilities section of \fBterminfo\fR(5).
+
+\fBchar *boolnames\fR, \fB*boolcodes\fR, \fB*boolfnames\fR
+
+\fBchar *numnames\fR, \fB*numcodes\fR, \fB*numfnames\fR
+
+\fBchar *strnames\fR, \fB*strcodes\fR, \fB*strfnames\fR
+
+These null-terminated arrays contain the \fIcapnames\fR, the
+\fBtermcap\fR codes, and the full C names, for each of the
+\fBterminfo\fR variables.
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion, unless otherwise noted in the
+preceding routine descriptions.
+
+Routines that return pointers always return \fBNULL\fR on error.
+.SH NOTES
+The \fBsetupterm\fR routine should be used in place of \fBsetterm\fR.
+
+Note that \fBvidattr\fR and \fBvidputs\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_initscr\fR(3), \fBcurs_kernel\fR(3),
+\fBputc\fR(3), \fBterminfo\fR(5)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_touch.3 b/lib/libncurses/curs_touch.3
new file mode 100644
index 0000000..5d3a620
--- /dev/null
+++ b/lib/libncurses/curs_touch.3
@@ -0,0 +1,57 @@
+.TH curs_touch 3 ""
+.SH NAME
+\fBtouchwin\fR, \fBtouchline\fR, \fBuntouchwin\fR,
+\fBwtouchln\fR, \fBis_linetouched\fR,
+\fBis_wintouched\fR - \fBncurses\fR refresh control routines
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+.br
+\fBint touchwin(WINDOW *win);\fR
+.br
+\fBint touchline(WINDOW *win, int start, int count);\fR
+.br
+\fBint untouchwin(WINDOW *win);\fR
+.br
+\fBint wtouchln(WINDOW *win, int y, int n, int changed);\fR
+.br
+\fBint is_linetouched(WINDOW *win, int line);\fR
+.br
+\fBint is_wintouched(WINDOW *win);\fR
+.br
+.SH DESCRIPTION
+The \fBtouchwin\fR and \fBtouchline\fR routines throw away all
+optimization information about which parts of the window have been
+touched, by pretending that the entire window has been drawn on. This
+is sometimes necessary when using overlapping windows, since a change
+to one window affects the other window, but the records of which lines
+have been changed in the other window do not reflect the change. The
+routine \fBtouchline\fR only pretends that \fIcount\fR lines have been
+changed, beginning with line \fIstart\fR.
+
+The \fBuntouchwin\fR routine marks all lines in the window as unchanged since
+the last call to \fBwrefresh\fR.
+
+The \fBwtouchln\fR routine makes \fIn\fR lines in the window, starting
+at line \fIy\fR, look as if they have (\fIchanged\fR\fB=1\fR) or have
+not (\fIchanged\fR\fB=0\fR) been changed since the last call to
+\fBwrefresh\fR.
+
+The \fBis_linetouched\fR and \fBis_wintouched\fR routines return
+\fBTRUE\fR if the specified line/window was modified since the last
+call to \fBwrefresh\fR; otherwise they return \fBFALSE\fR. In
+addition, \fBis_linetouched\fR returns \fBERR\fR if \fIline\fR is not
+valid for the given window.
+.SH RETURN VALUE
+All routines return the integer \fBERR\fR upon failure and an integer value
+other than \fBERR\fR upon successful completion, unless otherwise noted in the
+preceding routine descriptions.
+.SH NOTES
+Note that all routines except \fBwtouchln\fR may be macros.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_refresh\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_util.3 b/lib/libncurses/curs_util.3
new file mode 100644
index 0000000..ee46fad
--- /dev/null
+++ b/lib/libncurses/curs_util.3
@@ -0,0 +1,81 @@
+.TH curs_util 3 ""
+.SH NAME
+\fBunctrl\fR, \fBkeyname\fR, \fBfilter\fR,
+\fBuse_env\fR, \fBputwin\fR, \fBgetwin\fR, \fBdelay_output\fR,
+\fBflushinp\fR - miscellaneous \fBncurses\fR utility routines
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBchar *unctrl(chtype c);\fR
+.br
+\fBchar *keyname(int c);\fR
+.br
+\fBint filter(void);\fR
+.br
+\fBvoid use_env(char bool);\fR
+.br
+\fBint putwin(WINDOW *win, FILE *filep);\fR
+.br
+\fBWINDOW *getwin(FILE *filep);\fR
+.br
+\fBint delay_output(int ms);\fR
+.br
+\fBint flushinp(void);\fR
+.br
+.SH DESCRIPTION
+The \fBunctrl\fR macro expands to a character string which is a printable
+representation of the character \fIc\fR. Control characters are displayed in
+the \fB^\fR\fIX\fR notation. Printing characters are displayed as is.
+
+The \fBkeyname\fR routine returns a character string corresponding to
+the key \fIc\fR.
+
+The \fBfilter\fR routine, if used, must be called before \fBinitscr\fR or
+\fBnewterm\fR are called. It makes \fBncurses\fR think that there is a
+one-line screen. \fBncurses\fR does not use any terminal capabilities
+that assume that they know on what line of the screen the cursor is
+positioned.
+
+The \fBuse_env\fR routine, if used, is called before \fBinitscr\fR or
+\fBnewterm\fR are called. When called with \fBFALSE\fR as an
+argument, the values of \fBlines\fR and \fBcolumns\fR specified in the
+\fIterminfo\fR database will be used, even if environment variables
+\fBLINES\fR and \fBCOLUMNS\fR (used by default) are set, or if
+\fBncurses\fR is running in a window (in which case default behavior
+would be to use the window size if \fBLINES\fR and \fBCOLUMNS\fR are
+not set).
+
+The \fBputwin\fR routine writes all data associated with window \fIwin\fR into
+the file to which \fIfilep\fR points. This information can be later retrieved
+using the \fBgetwin\fR function.
+
+The \fBgetwin\fR routine reads window related data stored in the file by
+\fBputwin\fR. The routine then creates and initializes a new window using that
+data. It returns a pointer to the new window.
+
+The \fBdelay_output\fR routine inserts an \fIms\fR millisecond pause
+in output. This routine should not be used extensively because
+padding characters are used rather than a CPU pause.
+
+The \fBflushinp\fR routine throws away any typeahead that has been typed by the
+user and has not yet been read by the program.
+.SH RETURN VALUE
+Except for \fBflushinp\fR, routines that return an integer return
+\fBERR\fR upon failure and an integer value other than \fBERR\fR upon
+successful completion.
+
+\fBflushinp\fR always returns \fBOK\fR.
+
+Routines that return pointers return \fBNULL\fR on error.
+.SH BUGS
+The \fBfilter\fR entry point is not yet supported.
+.SH NOTES
+Note that \fBunctrl\fR is a macro, which is defined in <\fBunctrl.h\fR>.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_initscr\fR(3), \fBcurs_scr_dmp\fR(3).
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curs_window.3 b/lib/libncurses/curs_window.3
new file mode 100644
index 0000000..5ac63f4
--- /dev/null
+++ b/lib/libncurses/curs_window.3
@@ -0,0 +1,123 @@
+.TH curs_window 3 ""
+.SH NAME
+\fBnewwin\fR, \fBdelwin\fR, \fBmvwin\fR,
+\fBsubwin\fR, \fBderwin\fR, \fBmvderwin\fR, \fBdupwin\fR,
+\fBwsyncup\fR, \fBsyncok\fR, \fBwcursyncup\fR,
+\fBwsyncdown\fR - create \fBncurses\fR windows
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+
+\fBWINDOW *newwin(int nlines, int ncols, int begin_y,\fR
+ \fBintbegin_x);\fR
+
+\fBint delwin(WINDOW *win);\fR
+.br
+\fBint mvwin(WINDOW *win, int y, int x);\fR
+.br
+\fBWINDOW *subwin(WINDOW *orig, int nlines, int ncols,
+ int begin_y, int begin_x);\fR
+\fBWINDOW *derwin(WINDOW *orig, int nlines, int ncols,
+ int begin_y, int begin_x);\fR
+\fBint mvderwin(WINDOW *win, int par_y, int par_x);\fR
+.br
+\fBWINDOW *dupwin(WINDOW *win);\fR
+.br
+\fBvoid wsyncup(WINDOW *win);\fR
+.br
+\fBint syncok(WINDOW *win, bool bf);\fR
+.br
+\fBvoid wcursyncup(WINDOW *win);\fR
+.br
+\fBvoid wsyncdown(WINDOW *win);\fR
+.br
+.SH DESCRIPTION
+The \fBnewwin\fR routine creates and returns a pointer to a new window with the
+given number of lines and columns. The upper left-hand corner of the window is
+at line \fIbegin\fR_\fIy\fR, column \fIbegin\fR_\fIx\fR. If either
+\fInlines\fR or \fIncols\fR is zero, they default to \fBLINES -\fR
+\fIbegin\fR_\fIy\fR and \fBCOLS -\fR \fIbegin\fR_\fIx\fR. A new full-screen
+window is created by calling \fBnewwin(0,0,0,0)\fR.
+
+The \fBdelwin\fR routine deletes the named window, freeing all memory
+associated with it (it does not actually erase the window's screen
+image). Subwindows must be deleted before the main window can be
+deleted.
+
+The \fBmvwin\fR routine moves the window so that the upper left-hand
+corner is at position (\fIx\fR, \fIy\fR). If the move would cause the
+window to be off the screen, it is an error and the window is not
+moved. Moving subwindows is allowed, but should be avoided.
+
+The \fBsubwin\fR routine creates and returns a pointer to a new window
+with the given number of lines, \fInlines\fR, and columns,
+\fIncols\fR. The window is at position (\fIbegin\fR_\fIy\fR,
+\fIbegin\fR_\fIx\fR) on the screen. (This position is relative to the
+screen, and not to the window \fIorig\fR.) The window is made in the
+middle of the window \fIorig\fR, so that changes made to one window
+will affect both windows. The subwindow shares memory with the window
+\fIorig\fR. When using this routine, it is necessary to call
+\fBtouchwin\fR or \fBtouchline\fR on \fIorig\fR before calling
+\fBwrefresh\fR on the subwindow.
+
+The \fBderwin\fR routine is the same as \fBsubwin,\fR except that
+\fIbegin\fR_\fIy\fR and \fIbegin\fR_\fIx\fR are relative to the origin
+of the window \fIorig\fR rather than the screen. There is no
+difference between the subwindows and the derived windows.
+
+The \fBmvderwin\fR routine moves a derived window (or subwindow)
+inside its parent window. The screen-relative parameters of the
+window are not changed. This routine is used to display different
+parts of the parent window at the same physical position on the
+screen.
+
+The \fBdupwin\fR routine creates an exact duplicate of the window \fIwin\fR.
+
+Each \fBncurses\fR window maintains two data structures: the character
+image structure and the status structure. The character image
+structure is shared among all windows in the window hierarchy
+(\fIi\fR.\fIe\fR., the window with all subwindows). The status
+structure, which contains information about individual line changes in
+the window, is private to each window. The routine \fBwrefresh\fR
+uses the status data structure when performing screen updating. Since
+status structures are not shared, changes made to one window in the
+hierarchy may not be properly reflected on the screen.
+
+The routine \fBwsyncup\fR causes the changes in the status structure
+of a window to be reflected in the status structures of its ancestors.
+If \fBsyncok\fR is called with second argument \fBTRUE\fR then
+\fBwsyncup\fR is called automatically whenever there is a change in
+the window.
+
+The routine \fBwcursyncup\fR updates the current cursor position of all the
+ancestors of the window to reflect the current cursor position of the
+window.
+
+The routine \fBwsyncdown\fR updates the status structure of the window
+to reflect the changes in the status structures of its ancestors.
+Applications seldom call this routine because it is called
+automatically by \fBwrefresh\fR.
+.SH RETURN VALUE
+Routines that return an integer return the integer \fBERR\fR upon failure and
+an integer value other than \fBERR\fR upon successful completion.
+
+\fBdelwin\fR returns the integer \fBERR\fR upon failure and \fBOK\fR
+upon successful completion.
+
+Routines that return pointers return \fBNULL\fR on error.
+.SH NOTES
+If many small changes are made to the window, the \fBwsyncup\fR option could
+degrade performance.
+
+Note that \fBsyncok\fR may be a macro.
+.SH BUGS
+The subwindow functions (\fIsubwin\fR, \fIderwin\fR, etc.) are flaky,
+incompletely implemented, and not well tested, especially in their
+interaction with scrolling.
+.SH SEE ALSO
+\fBncurses\fR(3), \fBcurs_refresh\fR(3), \fBcurs_touch\fR(3)
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/curses.h b/lib/libncurses/curses.h
new file mode 100644
index 0000000..5aa5f64
--- /dev/null
+++ b/lib/libncurses/curses.h
@@ -0,0 +1,530 @@
+
+/***************************************************************************
+* COPYRIGHT NOTICE *
+****************************************************************************
+* ncurses is copyright (C) 1992, 1993, 1994 *
+* by Zeyd M. Ben-Halim *
+* zmbenhal@netcom.com *
+* *
+* Permission is hereby granted to reproduce and distribute ncurses *
+* by any means and for any fee, whether alone or as part of a *
+* larger distribution, in source or in binary form, PROVIDED *
+* this notice is included with any such distribution, not removed *
+* from header files, and is reproduced in any documentation *
+* accompanying it or the applications linked with it. *
+* *
+* ncurses comes AS IS with no warranty, implied or expressed. *
+* *
+***************************************************************************/
+
+#ifndef __NCURSES_H
+#define __NCURSES_H
+#define CURSES 1
+#define CURSES_H 1
+
+#include <stdio.h>
+#include <stdarg.h>
+#ifndef NOTERMIOS
+#include <termios.h>
+#ifndef TERMIOS
+#define TERMIOS 1
+#endif
+#else
+#include <sgtty.h>
+#include <sys/ioctl.h>
+#endif
+#include <unctrl.h>
+
+#define bool char
+
+typedef unsigned long chtype;
+
+/* attributes */
+#define A_ATTRIBUTES 0xffffff00
+#define A_NORMAL 0x00000000
+#define A_STANDOUT 0x00010000
+#define A_UNDERLINE 0x00020000
+#define A_REVERSE 0x00040000
+#define A_BLINK 0x00080000
+#define A_DIM 0x00100000
+#define A_BOLD 0x00200000
+#define A_ALTCHARSET 0x00400000
+#define A_INVIS 0x00800000
+#define A_PROTECT 0x01000000
+#define A_CHARTEXT 0x000000ff
+#define A_COLOR 0x0000ff00
+#define COLOR_PAIR(n) (n << 8)
+#define PAIR_NUMBER(a) ((a & A_COLOR) >> 8)
+
+/* colors */
+extern int COLORS;
+extern int COLOR_PAIRS;
+extern unsigned char *color_pairs;
+
+#define COLOR_BLACK 0
+#define COLOR_RED 1
+#define COLOR_GREEN 2
+#define COLOR_YELLOW 3
+#define COLOR_BLUE 4
+#define COLOR_MAGENTA 5
+#define COLOR_CYAN 6
+#define COLOR_WHITE 7
+
+/* line graphics */
+
+extern chtype acs_map[];
+
+
+#define ACS_ULCORNER (acs_map['l'])
+#define ACS_LLCORNER (acs_map['m'])
+#define ACS_URCORNER (acs_map['k'])
+#define ACS_LRCORNER (acs_map['j'])
+#define ACS_RTEE (acs_map['u'])
+#define ACS_LTEE (acs_map['t'])
+#define ACS_BTEE (acs_map['v'])
+#define ACS_TTEE (acs_map['w'])
+#define ACS_HLINE (acs_map['q'])
+#define ACS_VLINE (acs_map['x'])
+#define ACS_PLUS (acs_map['n'])
+#define ACS_S1 (acs_map['o']) /* scan line 1 */
+#define ACS_S9 (acs_map['s']) /* scan line 9 */
+#define ACS_DIAMOND (acs_map['`']) /* diamond */
+#define ACS_CKBOARD (acs_map['a']) /* checker board (stipple) */
+#define ACS_DEGREE (acs_map['f']) /* degree symbol */
+#define ACS_PLMINUS (acs_map['g']) /* plus/minus */
+#define ACS_BULLET (acs_map['~']) /* bullet */
+#define ACS_LARROW (acs_map[',']) /* arrow pointing left */
+#define ACS_RARROW (acs_map['+']) /* arrow pointing right */
+#define ACS_DARROW (acs_map['.']) /* arrow pointing down */
+#define ACS_UARROW (acs_map['-']) /* arrow pointing up */
+#define ACS_BOARD (acs_map['h']) /* board of squares */
+#define ACS_LANTERN (acs_map['I']) /* lantern symbol */
+#define ACS_BLOCK (acs_map['0']) /* solid square block */
+
+#ifndef TRUE
+# define TRUE (1)
+# define FALSE (0)
+#endif
+
+#define ERR (-1)
+#define OK (0)
+
+#define _SUBWIN 0x01
+#define _ENDLINE 0x02
+#define _FULLWIN 0x04
+#define _SCROLLWIN 0x08
+#define _ISPAD 0x10
+#define _HASMOVED 0x20
+
+#define _NOCHANGE -1
+
+typedef struct screen SCREEN;
+typedef struct _win_st WINDOW;
+
+struct _win_st {
+ short _cury, _curx; /* current cursor position */
+ short _maxy, _maxx; /* maximum values of x and y NOT the screen dimensions */
+ short _begy, _begx;
+ short _flags;
+ chtype _attrs;
+ chtype _bkgd;
+
+ /* The following should be consolidated into one bitset */
+ bool _notimeout;
+ bool _use_idc;
+ bool _clear;
+ bool _leave;
+ bool _scroll;
+ bool _idlok;
+ bool _immed;
+ bool _sync;
+ bool _use_keypad; /* 0=no, 1=yes */
+ bool _use_meta; /* T=use the meta key */
+
+ int _delay; /* 0 = nodelay
+ <0 = blocking
+ >0 = delay */
+ chtype **_line;
+ short *_firstchar; /* First changed character in the line */
+ short *_lastchar; /* Last changed character in the line */
+ short _regtop; /* Top and bottom of scrolling region */
+ short _regbottom;
+ int _parx;
+ int _pary;
+ WINDOW *_parent; /* parent if a sub-window */
+};
+
+extern WINDOW *stdscr, *curscr, *newscr;
+
+extern int LINES, COLS;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char ttytype[]; /* needed for backward compatibility */
+
+extern int tigetflag(char *);
+extern int tigetnum(char *);
+extern char *tigetstr(char *);
+
+/* Debugging : use with libdcurses.a */
+
+extern void _init_trace(void);
+extern void _tracef(char *, ...);
+extern char *_traceattr(int mode);
+extern char *_tracechar(const unsigned char mode);
+extern void trace(const unsigned int tracelevel);
+
+/* trace masks */
+#define TRACE_DISABLE 0x00 /* turn off tracing */
+#define TRACE_ORDINARY 0x01 /* ordinary trace mode */
+#define TRACE_CHARPUT 0x02 /* also trace all character outputs */
+#define TRACE_MAXIMUM 0x0f /* maximum trace level */
+
+/* function prototypes */
+
+extern int baudrate(void);
+extern int beep(void);
+extern int cbreak(void);
+extern int clearok(WINDOW *,int);
+extern int copywin(WINDOW *,WINDOW *,int,int,int,int,int,int,int);
+extern int curs_set(int);
+extern int def_prog_mode(void);
+extern int def_shell_mode(void);
+extern int delwin(WINDOW *);
+extern WINDOW *derwin(WINDOW *,int,int,int,int);
+extern int doupdate(void);
+extern WINDOW *dupwin(WINDOW *);
+extern int echo(void);
+extern int endwin(void);
+extern char erasechar(void);
+extern int flash(void);
+extern int flushinp(void);
+extern int halfdelay(int);
+extern int idlok(WINDOW *,int);
+extern int intrflush(WINDOW *,bool);
+extern int is_linetouched(WINDOW *,int);
+extern int is_wintouched(WINDOW *);
+extern WINDOW *initscr(void);
+extern int isendwin(void);
+extern char *keyname(int);
+extern int keypad(WINDOW *,int);
+extern char killchar(void);
+extern int leaveok(WINDOW *,int);
+extern char *longname(void);
+extern int meta(WINDOW *,int);
+extern int mvcur(int,int,int,int);
+extern int mvprintw(int,int,char *,...);
+extern int mvscanw(int,int,char *,...);
+extern int mvwin(WINDOW *,int,int);
+extern int mvwprintw(WINDOW *,int,int,char *,...);
+extern int mvwscanw(WINDOW *,int,int,char *,...);
+extern WINDOW *newpad(int,int);
+extern SCREEN *newterm(char *,FILE *,FILE *);
+extern WINDOW *newwin(int,int,int,int);
+extern int nl(void);
+extern int nocbreak(void);
+extern int nodelay(WINDOW *,int);
+extern int noecho(void);
+extern int nonl(void);
+extern int noraw(void);
+extern int notimeout(WINDOW *,bool);
+extern int overlay(WINDOW *,WINDOW *);
+extern int overwrite(WINDOW *,WINDOW *);
+extern int pnoutrefresh(WINDOW *,int,int,int,int,int,int);
+extern int prefresh(WINDOW *,int,int,int,int,int,int);
+extern int printw(char *,...);
+extern int putp(char *);
+extern int raw(void);
+extern int reset_prog_mode(void);
+extern int reset_shell_mode(void);
+extern int resetty(void);
+extern int ripoffline(int line, int (*init)(WINDOW *, int));
+extern int savetty(void);
+extern int scanw(char *,...);
+extern int scrollok(WINDOW *,int);
+extern SCREEN *set_term(SCREEN *);
+extern int setupterm(char *,int,int *);
+extern WINDOW *subwin(WINDOW *,int,int,int,int);
+extern int timeout(int);
+extern char *tparm(const char *, ...);
+extern int tputs(const char *,int,int (*)(int));
+extern int typeahead(int);
+extern int ungetch(int);
+extern int vidattr(chtype);
+extern int vidputs(chtype,int (*)(int));
+extern int vwscanw(WINDOW *,char *,va_list);
+extern int vwprintw(WINDOW *,char *,va_list);
+extern int waddch(WINDOW *,chtype);
+extern int waddchnstr(WINDOW *,chtype *,int);
+extern int waddnstr(WINDOW *,char *,int);
+extern int wattron(WINDOW *,chtype);
+extern int wattroff(WINDOW *,chtype);
+extern int wbkgd(WINDOW *,chtype);
+extern int wborder(WINDOW *,chtype,chtype,chtype,chtype,chtype,chtype,chtype,chtype);
+extern int wclear(WINDOW *);
+extern int wclrtobot(WINDOW *);
+extern int wclrtoeol(WINDOW *);
+extern int wdelch(WINDOW *);
+extern int wechochar(WINDOW *, chtype);
+extern int werase(WINDOW *);
+extern int wgetch(WINDOW *);
+extern int wgetnstr(WINDOW *,char *,int maxlen);
+extern int whline(WINDOW *,chtype,int);
+extern int winsch(WINDOW *,chtype);
+extern int winsdelln(WINDOW *,int);
+extern int winsnstr(WINDOW *,char *,int);
+extern int wmove(WINDOW *,int,int);
+extern int wnoutrefresh(WINDOW *);
+extern int wprintw(WINDOW *,char *,...);
+extern int wredrawln(WINDOW *,int,int);
+extern int wrefresh(WINDOW *);
+extern int wscanw(WINDOW *,char *,...);
+extern int wscrl(WINDOW *,int);
+extern int wsetscrreg(WINDOW *,int,int);
+extern int wtimeout(WINDOW *,int);
+extern int wtouchln(WINDOW *,int,int,int);
+extern int wvline(WINDOW *,chtype,int);
+
+extern bool can_change_color(void);
+extern int color_content(short,short *,short *, short *);
+extern int has_colors(void);
+extern int init_color(short,short,short,short);
+extern int init_pair(short,short,short);
+extern int pair_content(short,short*,short*);
+extern int start_color(void);
+
+extern int slk_init(int);
+extern int slk_set(int,char *,int);
+extern int slk_refresh(void);
+extern int slk_noutrefresh(void);
+extern char *slk_label(int);
+extern int slk_clear(void);
+extern int slk_restore(void);
+extern int slk_touch(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * pseudo functions
+ */
+#define wgetstr(w, s) wgetnstr(w, s, -1)
+
+#define napms(x) usleep(1000*x)
+#define setterm(term) setupterm(term, 1, (int *)0)
+
+#define fixterm() reset_prog_mode()
+#define resetterm() reset_shell_mode()
+#define saveterm() def_prog_mode()
+#define crmode() cbreak()
+#define nocrmode() nocbreak()
+#define gettmode()
+
+#define getyx(win,y,x) (y = (win)->_cury, x = (win)->_curx)
+#define getbegyx(win,y,x) (y = (win)->_begy, x = (win)->_begx)
+#define getmaxyx(win,y,x) (y = (win)->_maxy + 1, x = (win)->_maxx + 1)
+#define getsyx(y,x) getyx(stdscr, y, x)
+#define setsyx(y,x) (stdscr->_cury = y, stdscr->_curx = x)
+
+#define wbkgdset(win,ch) ((win)->_bkgd = ch)
+
+/* It seems older SYSV curses define these */
+#define getattrs(win) (win->_attrs)
+#define getmaxx(win) ((win)->_maxx + 1)
+#define getmaxy(win) ((win)->_maxy + 1)
+
+#define winch(win) ((win)->_line[(win)->_cury][(win)->_curx])
+#define wstandout(win) (wattrset(win,A_STANDOUT))
+#define wstandend(win) (wattrset(win,A_NORMAL))
+#define wattrset(win,at) ((win)->_attrs = (at))
+
+#define subpad(p,l,c,y,x) derwin(p,l,c,y,x)
+#define scroll(win) wscrl(win,1)
+
+#define touchwin(win) wtouchln((win), 0, (win)->_maxy + 1, 1)
+#define touchline(win, s, c) wtouchln((win), s, c, 1)
+#define untouchwin(win) wtouchln((win), 0, (win)->_maxy + 1, 0)
+
+#define box(win, v, h) wborder(win, v, v, h, h, 0, 0, 0, 0)
+#define border(ls, rs, ts, bs, tl, tr, bl, br) wborder(stdscr, ls, rs, ts, bs, tl, tr, bl, br)
+#define hline(ch, n) whline(stdscr, ch, n)
+#define vline(ch, n) wvline(stdscr, ch, n)
+
+#define winsstr(w, s) winsnstr(w, s, 0)
+
+#define redrawwin(w) wredrawln(w, 0, w->_maxy+1)
+#define waddstr(win,str) waddnstr(win,str,-1)
+#define waddchstr(win,str) waddchnstr(win,str,-1)
+
+/*
+ * pseudo functions for standard screen
+ */
+
+#define bkgdset(ch) wbkgdset(stdscr,ch)
+#define bkgd(ch) wbkgd(stdscr,ch)
+#define inch() winch(stdscr)
+#define standout() wstandout(stdscr)
+#define standend() wstandend(stdscr)
+#define attron(at) wattron(stdscr,at)
+#define attroff(at) wattroff(stdscr,at)
+#define attrset(at) wattrset(stdscr,at)
+#define addch(ch) waddch(stdscr,ch)
+#define echochar(c) wechochar(stdscr, c)
+#define getch() wgetch(stdscr)
+#define addstr(str) waddnstr(stdscr,str,-1)
+#define getstr(str) wgetstr(stdscr,str)
+#define move(y, x) wmove(stdscr,y,x)
+#define clear() wclear(stdscr)
+#define erase() werase(stdscr)
+#define clrtobot() wclrtobot(stdscr)
+#define clrtoeol() wclrtoeol(stdscr)
+#define insertln() winsdelln(stdscr, 1)
+#define winsertln(w) winsdelln(w, 1)
+#define deleteln() winsdelln(stdscr, -1)
+#define wdeleteln(w) winsdelln(w, -1)
+#define refresh() wrefresh(stdscr)
+#define insch(c) winsch(stdscr,c)
+#define delch() wdelch(stdscr)
+#define setscrreg(t,b) wsetscrreg(stdscr,t,b)
+#define scrl(n) wscrl(stdscr,n)
+#define timeout(delay) wtimeout(stdscr, delay)
+#define addnstr(str,n) waddnstr(stdscr,str,n)
+#define addchstr(str) waddchstr(stdscr,str)
+#define addchnstr(str,n) waddchnstr(stdscr,str, n)
+#define insdelln(n) winsdelln(stdscr, n)
+#define insstr(s) winsstr(stdscr, s)
+#define insnstr(s,n) winsnstr(stdscr, s, n)
+
+/*
+ * mv functions
+*/
+
+#define mvwaddch(win,y,x,ch) (wmove(win,y,x) == ERR ? ERR : waddch(win,ch))
+#define mvwgetch(win,y,x) (wmove(win,y,x) == ERR ? ERR : wgetch(win))
+#define mvwaddchnstr(win,y,x,str,n) (wmove(win,y,x) == ERR ? ERR : waddchnstr(win,str,n))
+#define mvwaddchstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : waddchnstr(win,str,-1))
+#define mvwaddnstr(win,y,x,str,n) (wmove(win,y,x) == ERR ? ERR : waddnstr(win,str,n))
+#define mvwaddstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : waddnstr(win,str,-1))
+#define mvwgetstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : wgetstr(win,str))
+#define mvwinch(win,y,x) (wmove(win,y,x) == ERR ? ERR : winch(win))
+#define mvwdelch(win,y,x) (wmove(win,y,x) == ERR ? ERR : wdelch(win))
+#define mvwinsch(win,y,x,c) (wmove(win,y,x) == ERR ? ERR : winsch(win,c))
+#define mvaddch(y,x,ch) mvwaddch(stdscr,y,x,ch)
+#define mvgetch(y,x) mvwgetch(stdscr,y,x)
+#define mvaddnstr(y,x,str,n) mvwaddnstr(stdscr,y,x,str,n)
+#define mvaddstr(y,x,str) mvwaddstr(stdscr,y,x,str)
+#define mvgetstr(y,x,str) mvwgetstr(stdscr,y,x,str)
+#define mvinch(y,x) mvwinch(stdscr,y,x)
+#define mvdelch(y,x) mvwdelch(stdscr,y,x)
+#define mvinsch(y,x,c) mvwinsch(stdscr,y,x,c)
+#define mvwinsstr(w, y, x, s) (wmove(w,y,x) == ERR ? ERR : winsstr(w,s))
+#define mvwinsnstr(w, y, x, s, n) (wmove(w,y,x) == ERR ? ERR : winsnstr(w,s,n))
+#define mvinsstr(y,x,s) mvwinsstr(stdscr,y,x,s)
+#define mvinsnstr(y,x,s,n) mvwinsnstr(stdscr,y,x,s,n)
+
+/* Funny "characters" enabled for various special function keys for input */
+/* Whether such a key exists depend if its definition is in the terminfo entry */
+
+#define KEY_MIN 0401 /* Minimum curses key */
+#define KEY_BREAK 0401 /* break key (unreliable) */
+#define KEY_DOWN 0402 /* The four arrow keys ... */
+#define KEY_UP 0403
+#define KEY_LEFT 0404
+#define KEY_RIGHT 0405 /* ... */
+#define KEY_HOME 0406 /* Home key (upward+left arrow) */
+#define KEY_BACKSPACE 0407 /* backspace (unreliable) */
+#define KEY_F0 0410 /* Function keys. Space for 64 */
+#define KEY_F(n) (KEY_F0+(n)) /* keys is reserved. */
+#define KEY_DL 0510 /* Delete line */
+#define KEY_IL 0511 /* Insert line */
+#define KEY_DC 0512 /* Delete character */
+#define KEY_IC 0513 /* Insert char or enter insert mode */
+#define KEY_EIC 0514 /* Exit insert char mode */
+#define KEY_CLEAR 0515 /* Clear screen */
+#define KEY_EOS 0516 /* Clear to end of screen */
+#define KEY_EOL 0517 /* Clear to end of line */
+#define KEY_SF 0520 /* Scroll 1 line forward */
+#define KEY_SR 0521 /* Scroll 1 line backwards (reverse) */
+#define KEY_NPAGE 0522 /* Next page */
+#define KEY_PPAGE 0523 /* Previous page */
+#define KEY_STAB 0524 /* Set tab */
+#define KEY_CTAB 0525 /* Clear tab */
+#define KEY_CATAB 0526 /* Clear all tabs */
+#define KEY_ENTER 0527 /* Enter or send (unreliable) */
+#define KEY_SRESET 0530 /* soft (partial) reset (unreliable) */
+#define KEY_RESET 0531 /* reset or hard reset (unreliable) */
+#define KEY_PRINT 0532 /* print or copy */
+#define KEY_LL 0533 /* home down or bottom (lower left) */
+
+/* The keypad is arranged like this: */
+/* a1 up a3 */
+/* left b2 right */
+/* c1 down c3 */
+
+#define KEY_A1 0534 /* Upper left of keypad */
+#define KEY_A3 0535 /* Upper right of keypad */
+#define KEY_B2 0536 /* Center of keypad */
+#define KEY_C1 0537 /* Lower left of keypad */
+#define KEY_C3 0540 /* Lower right of keypad */
+#define KEY_BTAB 0541 /* Back tab key */
+#define KEY_BEG 0542 /* beg(inning) key */
+#define KEY_CANCEL 0543 /* cancel key */
+#define KEY_CLOSE 0544 /* close key */
+#define KEY_COMMAND 0545 /* cmd (command) key */
+#define KEY_COPY 0546 /* copy key */
+#define KEY_CREATE 0547 /* create key */
+#define KEY_END 0550 /* end key */
+#define KEY_EXIT 0551 /* exit key */
+#define KEY_FIND 0552 /* find key */
+#define KEY_HELP 0553 /* help key */
+#define KEY_MARK 0554 /* mark key */
+#define KEY_MESSAGE 0555 /* message key */
+#define KEY_MOVE 0556 /* move key */
+#define KEY_NEXT 0557 /* next object key */
+#define KEY_OPEN 0560 /* open key */
+#define KEY_OPTIONS 0561 /* options key */
+#define KEY_PREVIOUS 0562 /* previous object key */
+#define KEY_REDO 0563 /* redo key */
+#define KEY_REFERENCE 0564 /* ref(erence) key */
+#define KEY_REFRESH 0565 /* refresh key */
+#define KEY_REPLACE 0566 /* replace key */
+#define KEY_RESTART 0567 /* restart key */
+#define KEY_RESUME 0570 /* resume key */
+#define KEY_SAVE 0571 /* save key */
+#define KEY_SBEG 0572 /* shifted beginning key */
+#define KEY_SCANCEL 0573 /* shifted cancel key */
+#define KEY_SCOMMAND 0574 /* shifted command key */
+#define KEY_SCOPY 0575 /* shifted copy key */
+#define KEY_SCREATE 0576 /* shifted create key */
+#define KEY_SDC 0577 /* shifted delete char key */
+#define KEY_SDL 0600 /* shifted delete line key */
+#define KEY_SELECT 0601 /* select key */
+#define KEY_SEND 0602 /* shifted end key */
+#define KEY_SEOL 0603 /* shifted clear line key */
+#define KEY_SEXIT 0604 /* shifted exit key */
+#define KEY_SFIND 0605 /* shifted find key */
+#define KEY_SHELP 0606 /* shifted help key */
+#define KEY_SHOME 0607 /* shifted home key */
+#define KEY_SIC 0610 /* shifted input key */
+#define KEY_SLEFT 0611 /* shifted left arrow key */
+#define KEY_SMESSAGE 0612 /* shifted message key */
+#define KEY_SMOVE 0613 /* shifted move key */
+#define KEY_SNEXT 0614 /* shifted next key */
+#define KEY_SOPTIONS 0615 /* shifted options key */
+#define KEY_SPREVIOUS 0616 /* shifted prev key */
+#define KEY_SPRINT 0617 /* shifted print key */
+#define KEY_SREDO 0620 /* shifted redo key */
+#define KEY_SREPLACE 0621 /* shifted replace key */
+#define KEY_SRIGHT 0622 /* shifted right arrow */
+#define KEY_SRSUME 0623 /* shifted resume key */
+#define KEY_SSAVE 0624 /* shifted save key */
+#define KEY_SSUSPEND 0625 /* shifted suspend key */
+#define KEY_SUNDO 0626 /* shifted undo key */
+#define KEY_SUSPEND 0627 /* suspend key */
+#define KEY_UNDO 0630 /* undo key */
+#define KEY_MAX 0777 /* Maximum curses key */
+
+#endif
diff --git a/lib/libncurses/curses.priv.h b/lib/libncurses/curses.priv.h
new file mode 100644
index 0000000..42952ce
--- /dev/null
+++ b/lib/libncurses/curses.priv.h
@@ -0,0 +1,122 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+ * curses.priv.h
+ *
+ * Header file for curses library objects which are private to
+ * the library.
+ *
+ */
+
+#include "version.h"
+
+#ifndef __GNUC__
+#define inline
+#endif
+
+#ifndef NOACTION
+#include <unistd.h>
+typedef struct sigaction sigaction_t;
+#else
+#include "SigAction.h"
+#endif
+
+#include "curses.h"
+
+#define min(a,b) ((a) > (b) ? (b) : (a))
+#define max(a,b) ((a) < (b) ? (b) : (a))
+
+#define FG(n) ((n) & 0x0f)
+#define BG(n) (((n) & 0xf0) >> 4)
+
+#define CHANGED -1
+
+extern WINDOW *newscr;
+
+#ifdef TRACE
+#define T(a) if (_tracing & TRACE_ORDINARY) _tracef a
+#define TR(n, a) if (_tracing & (n)) _tracef a
+extern int _tracing;
+extern char *visbuf(const char *);
+#else
+#define T(a)
+#define TR(n, a)
+#endif
+
+extern int _outch(int);
+extern void init_acs(void);
+extern void tstp(int);
+extern WINDOW *makenew(int, int, int, int);
+extern int timed_wait(int fd, int wait, int *timeleft);
+
+struct try {
+ struct try *child; /* ptr to child. NULL if none */
+ struct try *sibling; /* ptr to sibling. NULL if none */
+ unsigned char ch; /* character at this node */
+ unsigned short value; /* code of string so far. 0 if none. */
+};
+
+/*
+ * Structure for soft labels.
+ */
+
+typedef struct {
+ char dirty; /* all labels have changed */
+ char hidden; /* soft lables are hidden */
+ WINDOW *win;
+ struct slk_ent {
+ char text[9]; /* text for the label */
+ char form_text[9]; /* formatted text (left/center/...) */
+ int x; /* x coordinate of this field */
+ char dirty; /* this label has changed */
+ char visible; /* field is visible */
+ } ent[8];
+} SLK;
+
+#define FIFO_SIZE 32
+
+struct screen {
+ FILE *_ifp; /* input file ptr for this terminal */
+ FILE *_ofp; /* output file ptr for this terminal */
+ int _checkfd;
+#ifdef MYTINFO
+ struct _terminal *_term;
+#else
+ struct term *_term; /* used by terminfo stuff */
+#endif
+ WINDOW *_curscr; /* windows specific to a given terminal */
+ WINDOW *_newscr;
+ WINDOW *_stdscr;
+ struct try *_keytry; /* "Try" for use with keypad mode */
+ unsigned int _fifo[FIFO_SIZE]; /* Buffer for pushed back characters */
+ signed char _fifohead,
+ _fifotail,
+ _fifopeek;
+ bool _endwin;
+ chtype _current_attr;
+ bool _coloron;
+ int _cursor; /* visibility of the cursor */
+ int _cursrow; /* Row and column of physical cursor */
+ int _curscol;
+ bool _nl; /* True if NL -> CR/NL is on */
+ bool _raw; /* True if in raw mode */
+ int _cbreak; /* 1 if in cbreak mode */
+ /* > 1 if in halfdelay mode */
+ bool _echo; /* True if echo on */
+ bool _nlmapping; /* True if terminal is really doing */
+ /* NL mapping (fn of raw and nl) */
+ SLK *_slk; /* ptr to soft key struct / NULL */
+ int _costs[9]; /* costs of cursor movements for mvcur */
+ int _costinit; /* flag wether costs[] is initialized */
+};
+
+extern struct screen *SP;
+
+extern int _slk_format; /* format specified in slk_init() */
+
+#define MAXCOLUMNS 135
+#define MAXLINES 66
+#define UNINITIALISED ((struct try * ) -1)
diff --git a/lib/libncurses/doc/color.doc b/lib/libncurses/doc/color.doc
new file mode 100644
index 0000000..55f3346
--- /dev/null
+++ b/lib/libncurses/doc/color.doc
@@ -0,0 +1,71 @@
+
+ 5.10. Color Manipulation
+
+ Ncurses provides support for the use of color on terminals
+ that are capable of display it. Note the BSD and older SYSV
+ curses don't support color. Color support in the PC version
+ is not compatible with SYSR4.
+
+ has_colors()
+ this function returns TRUE if the terminal supports color,
+ FALSE otherwise. Other color handling funtions will return
+ ERR if has_colors() is FALSE. You should always check before
+ using color and use other video attributes to replace color.
+
+ can_change_color()
+ This function returns TRUE if the terminal is capable of
+ redefining colors using the init_color function, FALSE if it
+ can't. Don't use init_color and color_content if it returns
+ FALSE.
+
+ start_color()
+ This function must be called before any other color handling
+ function is called. It initializes the 8 basic colors (see
+ appendix I) and sets the global variables COLORS and COLOR_
+ PAIRS to the maximum number of colors and color-pairs a
+ terminal can handle.
+
+ init_pair(pair, fg, bg)
+ This function changes the definition of a color-pair, pair.
+ Each pair has a foregroung color fg, and a background color
+ bg. Both values must be between 0 and COLORS-1. pair must be
+ between 1 and COLOR_PAIRS-1.
+ [If a pair is changed from a previous definition, the screen
+ is refreshed and all occurances of the color-pair are
+ changed to reflect the change.]
+
+ pair_content(pair, f, b)
+ This function stores the foreground and background colors of
+ the color-pair pair into the variables pointed to by f, b.
+ pair should be between 1 and COLOR_PAIRS-1.
+
+ init_color(color, r, g, b)
+ This function changes the value of a given color. A color is
+ defined by its red, green, and blue components, r, g, and b.
+ These values must be between 0 and 1000. color should be
+ between 0 and COLORS-1.
+
+ color_content(color, r, g, b)
+ This function puts the red, green, and blue components of
+ color into the variable pointed to by r, g, b respectively.
+ color should be between 0 and COLORS-1.
+
+ COLOR_PAIR(n) set color-pair to that stored in n
+ PAIR_NUMBER(a) get color-pair stored in attribute a
+
+
+ Appendix II: COLORS
+ -------------------
+
+ Colors are defined in <ncurses.h> are used with init_pair().
+
+ COLOR_BLACK 0
+ COLOR_RED 1
+ COLOR_GREEN 2
+ COLOR_YELLOW 3
+ COLOR_BLUE 4
+ COLOR_MAGENTA 5
+ COLOR_CYAN 6
+ COLOR_WHITE 7
+
+
diff --git a/lib/libncurses/doc/manual.doc b/lib/libncurses/doc/manual.doc
new file mode 100644
index 0000000..5ae7d39
--- /dev/null
+++ b/lib/libncurses/doc/manual.doc
@@ -0,0 +1,1361 @@
+
+
+
+
+
+
+
+
+
+ The Curses Reference Manual
+
+ Pavel Curtis 1982
+ Zeyd M. Ben-Halim 1993
+ zmbenhal@netcom.com
+
+
+
+
+
+
+ Caveat Emptor:
+ I'm slowly but surely updating the documentation of
+ ncurses to reflect the current status of the code. The text
+ below may refer to yet to be implemented functions or
+ missing functionality. Description of functions may be
+ missing or out of date. ncurses is aimed at being compatible
+ with AT&T curses as defined in SysVR4.
+
+ There is no ?roff sources for this document. I may one day
+ go nuts and create one, but don't hold your breath :-)
+
+ 1. Introduction
+
+ Terminfo is a database describing many capabilities of over
+ 150 different terminals. Curses is a subroutine package
+ which presents a high level screen model to the programmer,
+ while dealing with issues such as terminal differences and
+ optimization of output to change one screenfull of text into
+ another.
+ Terminfo is based on Berkeley's termcap database, but con-
+ tains a number of improvements and extensions. Parameterized
+ strings are introduced, making it possible to describe such
+ capabilities as video attributes, and to handle far more
+ unusual terminals than possible with termcap.
+ Curses is also based on Berkeley's curses package, with many
+ improvements. The package makes use of the insert and
+ delete line and character features of terminals so equipped,
+ and determines how to optimally use these features with no
+ help from the programmer. It allows arbitrary combinations
+ of video attributes to be displayed, even on terminals that
+ leave ``magic cookies'' on the screen to mark changes in
+ attributes.+
+
+ 2. An Overview of the Package
+
+ 2.1. Terminology
+
+ In this document, the following terminology is kept
+ to with reasonable consistency:
+
+ window An internal representation containing an image of
+ what a section of the terminal screen may look
+ like at some point in time. This subsection can
+ either encompass the entire terminal screen, or
+ any smaller portion down to a single character
+ within that screen.
+ terminal Sometimes called terminal screen. The package's
+ idea of what the terminal's screen currently looks
+ like, i.e., what the user sees now. This is a
+ special screen.
+ screen This is a subset of windows which are as large as
+ the terminal screen, i.e., they start at the upper
+ left hand corner and encompass the lower right
+ hand corner. One of these, stdscr, is automati-
+ cally provided for the programmer.
+
+ 2.2. Compiling Programs using the Package
+
+ In order to use the library, it is necessary to have
+ certain types and variables defined. Therefore, the pro-
+ grammer must have a line:
+ #include <ncurses.h>
+ at the top of the program source. The screen package
+ uses the Standard I/O library, so <ncurses.h> includes
+ <stdio.h>. Ncurses also includes <termios.h>, <termio.h>, or
+ <sgtty.h> depending on your system. It is redundant (but
+ harmless) for the programmer to do it, too. In linking with
+ ncurses you need to have `-lncurses' in your LDFLAGS or on
+ the command line. There is no need for any other libraries.
+
+ 2.3. Updating the Screen
+
+ In order to update the screen optimally, it is
+ necessary for the routines to know what the screen currently
+ looks like and what the programmer wants it to look like
+ next. For this purpose, a data type (structure) named WINDOW
+ is defined which describes a window image to the routines,
+ including its starting position on the screen (the (y, x)
+ coordinates of the upper left hand corner) and its size.
+ One of these (called curscr, for current screen) is a screen
+ image of what the terminal currently looks like. Another
+ screen (called stdscr, for standard screen) is provided by
+ default to make changes on.
+ A window is a purely internal representation. It is
+ used to build and store a potential image of a portion of
+ the terminal. It doesn't bear any necessary relation to
+ what is really on the terminal screen. It is more like an
+ array of characters on which to make changes.
+ When one has a window which describes what some part of
+ the terminal screen should look like, the routine refresh()
+ (or wrefresh() if the window is not stdscr) is called.
+ Refresh() in the area covered by the window, look like that
+ window. Note, therefore, that changing something on a win-
+ dow does not change the terminal. Actual updates to the
+ terminal screen are made only by calling refresh() or wre-
+ fresh(). This allows the programmer to maintain several
+ different ideas of what a portion of the terminal screen
+ should look like. Also, changes can be made to windows in
+ any order, without regard to motion efficiency. Then, at
+ will, the programmer can effectively say ``make it look like
+ this,'' and let the package worry about the best way to do
+ this.
+
+ 2.4. Naming Conventions
+
+ As hinted above, the routines can use several windows,
+ but two are automatically given: curscr, which knows what
+ the terminal looks like, and stdscr, which is what the pro-
+ grammer wants the terminal to look like next. The user
+ should never really access curscr directly. Changes should
+ be made to the appropriate screen, and then the routine
+ refresh() (or wrefresh()) should be called.
+ Many functions are set up to deal with stdscr as a
+ default screen. For example, to add a character to stdscr,
+ one calls addch() with the desired character. If a differ-
+ ent window is to be used, the routine waddch() (for
+ `w'indow-specific addch()) is provided. This convention of
+ prepending function names with a ``w'' when they are to be
+ applied to specific windows is consistent. The only rou-
+ tines which do not do this are those to which a window must
+ always be specified.
+ In order to move the current (y, x) coordinates from
+ one point to another, the routines move() and wmove() are
+ provided. However, it is often desirable to first move and
+ then perform some I/O operation. In order to avoid clumsy-
+ ness, most I/O routines can be preceded by the prefix 'mv'
+ and the desired (y, x) coordinates then can be added to the
+ arguments to the function. For example, the calls
+ move(y, x);
+ addch(ch);
+ can be replaced by
+ mvaddch(y, x, ch);
+ and
+ wmove(win, y, x);
+ waddch(win, ch);
+ can be replaced by
+ mvwaddch(win, y, x, ch);
+ Note that the window description pointer (win) comes before
+ the added (y, x) coordinates. If such pointers are need,
+ they are always the first parameters passed.
+
+ 3. Variables
+
+ Many variables which are used to describe the terminal
+ environment are available to the programmer. They are:
+
+ type name description
+ ------------------------------------------------------------------
+ WINDOW *curscr current version of the screen (terminal screen).
+ WINDOW *stdscr standard screen. Most updates are done here.
+ int LINES number of lines on the terminal
+ int COLS number of columns on the terminal
+
+ There are also several `#define' constants and types which
+ are of general usefulness:
+
+ bool boolean type, actually a `char' (e.g., bool doneit;)
+ TRUE boolean `true' flag (1).
+ FALSE boolean `false' flag (0).
+ ERR -1 error flag returned by routines on a fail.
+ OK 0 error flag returned by routines when things
+ go right.
+
+ 4. Usage
+
+ This is a description of how to actually use the screen
+ package. In it, we assume all updating, reading, etc. is
+ applied to stdscr. All instructions will work on any win-
+ dow, with changing the function name and parameters as men-
+ tioned above.
+
+ 4.1. Starting up
+
+ In order to use the screen package, the routines must
+ know about terminal characteristics, and the space for
+ curscr and stdscr must be allocated. These functions are
+ performed by initscr(). Since it must allocate space for the
+ windows, it can overflow memory when attempting to do so. On
+ this rather rare occasion, initscr() returns ERR.
+ initscr() must always be called before any of the routines
+ which affect windows are used. If it is not, the program
+ will core dump as soon as either curscr or stdscr are
+ referenced. However, it is usually best to wait to call it
+ until after you are sure you will need it, like after
+ checking for startup errors. Terminal status changing
+ routines like nl() and cbreak() should be called after
+ initscr().
+ Now that the screen windows have been allocated, you
+ can set them up for the run. If you want to, say, allow the
+ window to scroll, use scrollok(). If you want the cursor to
+ be left after the last change, use leaveok(). If this isn't
+ done, refresh() will move the cursor to the window's current
+ (y, x) coordinates after updating it. New windows of your
+ own can be created, too, by using the functions newwin(),
+ derwin(), and subwin(). delwin() will allow you to get rid
+ of old windows.
+
+ 4.2. Output
+
+ Now that we have set things up, we will want to actu-
+ ally update the terminal. The basic functions used to
+ change what will go on a window are addch() and move().
+ addch() adds a character at the current (y, x) coordinates,
+ returning ERR if it would cause the window to illegally
+ scroll, i.e., printing a character in the lower right-hand
+ corner of a terminal which automatically scrolls if
+ scrolling is not allowed. move() changes the current (y, x)
+ coordinates to whatever you want them to be. It returns ERR
+ if you try to move off the window. As mentioned above, you
+ can combine the two into mvaddch() to do both things at
+ once.
+ The other output functions, such as addstr() and
+ printw(), all call addch() to add characters to the window.
+ After you have put on the window what you want there,
+ when you want the portion of the terminal covered by the
+ window to be made to look like it, you must call refresh().
+ In order to optimize finding changes, refresh() assumes that
+ any part of the window not changed since the last refresh()
+ of that window has not been changed on the terminal, i.e.,
+ that you have not refreshed a portion of the terminal with
+ an overlapping window. If this is not the case, the routine
+ touchwin() is provided to make it look like the entire win-
+ dow has been changed, thus making refresh() check the whole
+ subsection of the terminal for changes.
+ If you call wrefresh() with curscr(), it will make the
+ screen look like curscr thinks it looks like. This is use-
+ ful for implementing a command which would redraw the screen
+ in case it get messed up.
+
+ 4.3. Input
+
+ Input is essentially a mirror image of output. The
+ complementary function to addch() is getch() which, if echo
+ is set, will call addch() to echo the character. Since the
+ screen package needs to know what is on the terminal at all
+ times, if characters are to be echoed, the tty must be in
+ raw or cbreak mode. Since initially the terminal has echo-
+ ing enable and is in nocreak mode, one or the other has to
+ changed before calling getch(). The result of not doing this
+ is unpredictable output.
+
+ 4.4. Miscellaneous
+
+ A plethora of other functions exist for maintaining and
+ changing information about the windows. For the most part,
+ the descriptions in section 5 should suffice.
+
+ 4.5. Finishing Up
+
+ In order to do certain optimizations, and, on some ter-
+ minals, to work at all, some things must be done before the
+ screen routines start up. In order to clean up after the
+ routines, the routine endwin() is provided. It restores tty
+ modes to what they were when initscr() was first called,
+ moves the cursor down to the lower-left corner, etc. Thus,
+ anytime after the call to initscr, endwin() should be called
+ before exiting.
+
+ 5. Descriptions of the Functions
+
+ This section describes all the functions available to the
+ programmer in the curses package. For an alphabetical list,
+ see the manual page ncurses(3).
+
+ 5.1. Initialization
+
+ These functions are called when initializing a program.
+
+ initscr()
+ The first function called should always be initscr. This
+ will determine the terminal type and initialize curses data
+ structures. initscr also arranges that the first call to
+ refresh will clear the screen. If an error occurs a message
+ is writen to standard error and the program exits. Otherwise
+ it returns a pointer to stdscr. Some function may be called
+ before initscr (slk_init, filter, ripofflines, use_env, and
+ if you are using multiple terminals newterm.)
+
+ endwin()
+ A program should always call endwin before exiting or
+ shelling out of the program. This function will restore tty
+ modes, move the cursor to the lower left corner of the
+ screen, reset the terminal into the proper nonvisual mode.
+ Calling refresh() or doupdate() after a temporary escape
+ from the program will restore the screen to its original
+ status.
+
+ newterm(type, ofp, ifp)
+ A program which outputs to more than one terminal should use
+ newterm instead of initscr. newterm should be called once
+ for each terminal. It returns a variable of type SCREEN
+ * which should be saved as a reference to that terminal. The
+ arguments are the type of the terminal (a string) and FILE
+ pointers for the output and input of the terminal. If type
+ is NULL then the environment variable $TERM is used. endwin
+ must called for each terminal opened using this function.
+
+ set_term(new)
+ This function is used to switch to a different terminal.
+ The screen reference for the new terminal is passed as the
+ parameter. The previous terminal is returned by the func-
+ tion. All other calls affect only the current terminal.
+
+ delscreen(sp)
+
+ longname()
+ This function returns a pointer to a static area containing
+ a verbose description of the current terminal. It is defined
+ only after a call to initscr or newterm.
+
+ termattrs()
+
+ termname()
+
+ 5.2. Option Setting
+
+ These functions set options within curses. In each case,
+ win is the window affected, and bf is a boolean flag with
+ value TRUE or FALSE indicating whether to enable or disable
+ the option. All options are initially FALSE. It is not
+ necessary to turn these options off before calling endwin.
+
+ clearok(win,bf)
+ If set, the next call to wrefresh with this window will
+ clear the screen and redraw the entire screen. If win is
+ curscr, the next call to wrefresh with any window will cause
+ the screen to be cleared. This is useful when the contents
+ of the screen are uncertain, or in some cases for a more
+ pleasing visual effect.
+
+ idlok(win,bf)
+ If enabled, curses will consider using the hardware
+ insert/delete line feature of terminals so equipped. If
+ disabled, curses will not use this feature. Enable this
+ option only if your application needs insert/delete line,
+ for example, for a screen editor. It is disabled by default
+ because insert/delete line is visually annoying when used in
+ applications where it isn't really needed.
+
+ idcok(win,bf)
+ This option allows curses will use inset/delete character
+ capabilities if any are defined. This option is on be
+ default.
+
+ immedok(win,bf)
+ If this option is enabled any change in the window's image
+ causes a call to wrefresh. Enabling this option can degrade
+ performance; it is disabled by default.
+
+ keypad(win,bf)
+ This option enables the keypad of the users terminal. If
+ enabled, the user can press a function key (such as an arrow
+ key) and getch will return a single value representing the
+ function key. If disabled, curses will not treat function
+ keys specially. If the keypad in the terminal can be turned
+ on (made to transmit) and off (made to work locally), turn-
+ ing on this option will turn on the terminal keypad. All the
+ possible function keys are defined in ncurses.h as KEY_*.
+
+ leaveok(win,bf)
+ Normally, the hardware cursor is left at the location of the
+ window cursor being refreshed. This option allows the cur-
+ sor to be left wherever the update happens to leave it. It
+ is useful for applications where the cursor is not used,
+ since it saves cursor motions. If possible, the cursor is
+ made invisible when this option is enabled.
+
+ meta(win,bf)
+ If enabled, characters returned by getch are transmitted
+ with all 8 bits, instead of stripping the highest bit. It
+ is useful for extending the non-text command set in applica-
+ tions where the terminal has a meta shift key, such as
+ EMACS. NOTE: This function is currently unsupported.
+
+ notimeout(win,bf)
+ This option controls whether a timer is set when wgetch is
+ trying to interpret an input sequence. See keypad.
+
+ scrollok(win,bf)
+ This option controls what happens when the cursor of a win-
+ dow is moved off the edge of the window, either from a new-
+ line on the bottom line, or typing the last character of the
+ last line. If disabled, the cursor is left on the bottom
+ line. If enabled, wrefresh is called on the window, and then
+ the physical terminal and window are scrolled up one line.
+
+ setscrreg(t,b)
+ wsetscrreg(win,t,b)
+ These functions allow the user to set a software scrolling
+ region in a window win or stdscr. t and b are the line num-
+ bers of the top and bottom margin of the scrolling region.
+ (Line 0 is the top line of the screen.) If this option and
+ scrollok are enabled, an attempt to move off the bottom mar-
+ gin line will cause all lines in the scrolling region to
+ scroll up one line. Note that this has nothing to do with
+ use of a physical scrolling region capability in the termi-
+ nal, like that in the VT100. Only the text of the window is
+ scrolled.
+ The scrolling region really acts as a sort of barrier, lim-
+ iting the area of a window over which changes take place.
+ For this reason, an attempt to create a scrolling region in
+ an area of the screen which does not contain the current (y,
+ x) coordinates for that window is an error. Similarly,
+ attempts to move the (y, x) coordinates out of the region
+ will also fail with an ERR return.
+ When a scrolling region is in place, all changes are limited
+ to the region. For example, erase() will only erase the
+ area inside the region; insertln() will only shift lines
+ down to the bottom of the region, etc. It is anticipated
+ that this method of controlling the area of change will
+ prove quite handy in a number of applications.
+ To disable the scrolling region, once defined, simply rede-
+ fine it to be the whole window. For example, to disable the
+ scrolling region on stdscr, the following call would be
+ used:
+ setscrreg(0, LINES - 1)
+ For other windows, the height of the window should be used
+ instead of (LINES - 1).
+
+ 5.3. Terminal Mode Setting
+
+ These functions are used to set modes in the tty driver. The
+ initial mode usually depends on the setting when the program
+ was called: the initial modes documented here represenet the
+ normal situation.
+
+ cbreak()
+ nocbreak()
+ crmode()
+ nocrmode()
+ These functions put the terminal into and out of CBREAK
+ mode. In this mode, characters typed by the user are immedi-
+ ately available to the program. When out of this mode, the
+ device driver will buffer characters typed until newline is
+ typed. Interrupt and flow control characters are unaffected
+ by this mode. Initially the terminal is not in CBREAK mode.
+ Most interactive programs using curses will set this mode.
+ The functions crmode() and nocrmode() are the result of an
+ accident in the first version of curses and are retained
+ solely for upward compatibility. crmode() is the same as
+ cbreak() and nocrmode() is the same as nocbreak(). See 4.3
+ for a important note on using these functions.
+
+ raw()
+ noraw()
+ These functions put the terminal into and out of RAW mode.
+ RAW mode is just like CBREAK mode except that no special
+ character processing is done (e.g. the interrupt character
+ will be passed through to the program, uninterpreted, as
+ will the kill character, etc.) and all 8 bits of the input
+ character are retained; in CBREAK mode, the eighth bit is
+ stripped off before it is given to the program. Because of
+ the lack of interpretation of special characters, it is not
+ recommended that programs use this mode.
+
+ echo()
+ noecho()
+ These functions control whether characters typed by the user
+ are echoed as typed. Initially, characters typed are echoed
+ by the teletype driver. Authors of most interactive pro-
+ grams prefer to do their own echoing in a controlled area of
+ the screen, or not to echo at all, so they disable echoing.
+
+ halfdelay(t)
+ This options is similar to cbreak mode except that if after
+ blocking for t tenth of a seconds no input is received ERR
+ is returned. t must between 1 and 255. Use nocbreak to leave
+ this mode.
+
+ nodelay(win,bf)
+ This option causes getch to be a non-blocking call. If no
+ input is ready, getch will return ERR. If disabled, getch
+ will hang until a key is pressed.
+
+ timeout(t)
+ wtimeout(win,t)
+ These functions offer control over the blocking action of a
+ read. If t is negative, reading will block until there is
+ input. If t is zero, no blocking will occur, read returns
+ ERR if no input is available. If t is posistive, the read
+ will block for t milliseconds and return ERR if there is
+ still no input.
+ These routines offer better and finer control than nodelay()
+ and halfdelay() and their use is recommended.
+
+ nl()
+ nonl()
+ These functions control whether newline is translated into
+ carriage return and linefeed on output, and whether return
+ is translated into newline on input. Initially, the trans-
+ lations do occur. By disabling these translations, curses
+ is able to make better use of the linefeed capability,
+ resulting in faster cursor motion.
+
+ savetty()
+ resetty()
+ These functions save and restore the state of the tty modes.
+ savetty saves the current state in a buffer, resetty
+ restores the state to what it was at the last call to save-
+ tty.
+
+ 5.4. Window Manipulation
+
+ newwin(num_lines, num_cols, begy, begx)
+ Create a new window with the given number of lines and
+ columns. The upper left corner of the window is at line
+ begy column begx. If either num_lines or num_cols is zero,
+ they will be defaulted to LINES-begy and COLS-begx. A new
+ full-screen window is created by calling newwin(0,0,0,0).
+
+ subwin(orig, num_lines, num_cols, begy, begx)
+ Create a new window with the given number of lines and
+ columns. The window is at position (begy, begx) on the
+ screen. (It is relative to the screen, not orig.) The win-
+ dow is made in the middle of the window orig, so that
+ changes made to one window will affect both windows. When
+ using this function, often it will be necessary to call
+ touchwin before calling wrefresh.
+
+ derwin(orig, num_lines, num_cols, begy, begx)
+ Is similar to subwin only the new window is created relative
+ to the original window, not the screen.
+
+ delwin(win)
+ Deletes the named window, freeing up all memory associated
+ with it. In the case of sub-windows, they should be deleted
+ before the main window.
+
+ dupwin(win)
+
+ mvderwin(win,y,x)
+
+ syncok(win,bf)
+ wsyncup(win)
+ wcursyncup(win)
+ wsyncdown(win)
+
+ mvwin(win, by, bx)
+ Move the window so that the upper left corner will be at
+ position (by, bx). If the move would cause the window to be
+ off the screen, it is an error and the window is not moved.
+
+ touchline(win,start,count)
+ touchwin(win)
+ Throw away all optimization information about which parts of
+ the window have been touched, by pretending the entire win-
+ dow has been drawn on. This is sometimes necessary when
+ using overlapping windows, since a change to one window will
+ affect the other window, but the optimization records of the
+ other window will not reflect the change.
+
+ wtouchln(win,y,n,changed)
+ Throw away optimization information, or mark as unchanged,
+ n lines starting at y, depending on the value of changed.
+
+ untouchwin(win)
+ Mark the whole window as unchcnged since the lat wrefresh.
+
+ is_linetouched(win,line)
+ is_wintouched(win)
+ These routines are used to check if the given line/window
+ has been modified since the last wrefresh. They will return
+ TRUE is that is the case, FALSE otherwise. is_linetouched
+ will return ERR if there is no such line.
+
+ overlay(win1, win2)
+ overwrite(win1, win2)
+ These functions overlay win1 on top of win2, that is, all
+ text in win1 is copied into win2, after lining up the two
+ windows' origins. The difference between the functions is
+ that overlay is nondestructive (blanks are not copied) while
+ overwrite is destructive.
+
+ copywin(win,win,sminrow,smincol,dminrow,dmincol,dmaxrow,
+ dmaxcol,overlay)
+ Low level function used to implement overlay/overwrite.
+
+ 5.5. Causing Output to the Terminal
+
+ refresh()
+ wrefresh(win)
+ These functions must be called to actually get any output on
+ the terminal, as other routines merely manipulate data
+ structures. wrefresh copies the named window to the physi-
+ cal terminal screen, taking into account what is already
+ there in order to do optimizations. refresh is the same,
+ using stdscr as a default screen. Unless leaveok has been
+ enabled, the physical cursor of the terminal is left at the
+ location of the window's cursor.
+
+ doupdate()
+ wnoutrefresh(win)
+ These two functions allow multiple updates with more effi-
+ ciency than wrefresh. To use them, it is important to
+ understand how curses works. In addition to all the window
+ structures, curses keeps two data structures representing
+ the terminal screen: a physical screen, describing what is
+ actually on the screen, and a virtual screen, describing
+ what the programmer wants to have on the screen. wrefresh
+ works by first copying the named window to the virtual
+ screen (wnoutrefresh), and then calling the routine to
+ update the screen (doupdate). If the programmer wishes to
+ output several windows at once, a series of calls to wre-
+ fresh will result in alternating calls to wnoutrefresh and
+ doupdate, causing several bursts of output to the screen.
+ By calling wnoutrefresh for each window, it is then possible
+ to call doupdate once, resulting in only one burst of out-
+ put, with probably fewer total characters transmitted.
+
+ redrawwin(win)
+ wredrawln(win,start,count)
+
+ 5.6. Writing on Window Structures
+
+ These routines are used to ``draw'' text on windows. In all
+ cases, a missing win is taken to be stdscr. y and x are the
+ row and column, respectively. The upper left corner is
+ always (0, 0) not (1, 1). The mv functions imply a call to
+ move before the call to the other function.
+
+ 5.6.1. Moving the Cursor
+
+ move(y, x)
+ wmove(win, y, x)
+ The cursor associated with the window is moved to the given
+ location. This does not move the physical cursor of the
+ terminal until refresh is called.
+
+ 5.6.2. Writing One Character
+
+ addch(ch)
+ waddch(win, ch)
+ mvaddch(y, x, ch)
+ mvwaddch(win, y, x, ch)
+ The character ch is put in the window at the current cursor
+ position of the window. If ch is a tab, newline, or
+ backspace, the cursor will be moved appropriately in the
+ window. If ch is a different control character, it will be
+ drawn in the ^X notation. The position of the window cursor
+ is advanced. At the right margin, an automatic newline is
+ performed. At the bottom of the scrolling region, if scrol-
+ lok is enabled, the scrolling region will be scrolled up one
+ line.
+
+ 5.6.3. Writing a String
+
+ addstr(str)
+ addnstr(str,n)
+ waddstr(win,str)
+ waddnstr(win,str,n)
+ mvaddstr(y,x,str)
+ mvaddnstr(y,x,str,n)
+ mvwaddstr(win,y,x,str)
+ mvwaddnstr(win,y,x,str,n)
+ These functions write all the characters of the null termi-
+ nated character string str on the given window. They are
+ identical to a series of calls to addch. Routines with 'n'
+ write n characters of str. If n is -1 then the entire string
+ is written.
+
+ addchstr(chstr)
+ addchnstr(chstr,n)
+ waddchstr(win,chstr)
+ waddchnstr(win,chstr,n)
+ mvaddchstr(y,x,chstr)
+ mvaddchnstr(y,x,chstr,n)
+ mvwaddchstr(win,y,x,chstr)
+ mvwaddchnstr(win,y,x,chstr,n)
+ These functions copy chstr onto the window image starting at
+ the current cursor position. Routines with 'n' write at most
+ n characters of chstr (as many as will fit on the line). If
+ n is -1 then the entire string is written. The cursor is not
+ advanced and no checking for control characters is done.
+ These routines are faster than the addstr() group. chstr is
+ a pointer to an array of chtype.
+
+ 5.6.4. Clearing Areas of the Screen
+
+ erase()
+ werase(win)
+ These functions copy blanks to every position in the window.
+
+ clear()
+ wclear(win)
+ These functions are like erase and werase but they also call
+ clearok, arranging that the screen will be cleared on the
+ next refresh. The result can visually annoying.
+
+ clrtobot()
+ wclrtobot(win)
+ All lines below the cursor in this window are erased. Also,
+ the current line to the right of the cursor is erased.
+
+ clrtoeol()
+ wclrtoeol(win)
+ The current line to the right of the cursor is erased.
+
+ 5.6.5. Inserting and Deleting Text
+
+ delch()
+ wdelch(win)
+ mvdelch(y,x)
+ mvwdelch(win,y,x)
+ The character under the cursor in the window is deleted.
+ All characters to the right on the same line are moved to
+ the left one position. This does not imply use of the hard-
+ ware delete character feature.
+
+ deleteln()
+ wdeleteln(win)
+ The line under the cursor in the window is deleted. All
+ lines below the current line are moved up one line. The
+ bottom line of the window is cleared. This does not imply
+ use of the hardware delete line feature.
+
+ insch(c)
+ winsch(win, c)
+ mvinsch(y,x,c)
+ mvwinsch(win,y,x,c)
+ The character c is inserted before the character under the
+ cursor. All characters to the right are moved one space to
+ the right, possibly losing the rightmost character on the
+ line. This does not imply use of the hardware insert char-
+ acter feature.
+
+ insertln()
+ winsertln(win)
+ A blank line is inserted above the current line. The bottom
+ line is lost. This does not imply use of the hardware
+ insert line feature.
+
+ 5.6.6. Formatted Output
+
+ printw(fmt, ...)
+ wprintw(win, fmt, ...)
+ mvprintw(y, x, fmt, ...)
+ mvwprintw(win, y, x, fmt, ...)
+ vwprintw(win, fmt, va_list)
+ These functions correspond to printf. The characters which
+ would be output by printf are instead output using waddch on
+ the given window. vwprintw() acts like vprintf().
+
+ 5.6.7. Line drawing
+
+ Borders are drawn inside a window and not around it.
+
+ border(ls, rs, ts, bs, tl, tr, bl, br)
+ wborder(win, ls, rs, ts, bs, tl, tr, bl, br)
+ box(win, vert, hor)
+ A border is drawn around the edges of the window. ls, rs,
+ ts, bs, tl, tr, bl, and br are the character and attribute
+ to draw the left side, right side, top side, bottom side,
+ top left, top right, bottom left, and bottom right respec-
+ tively.
+ If any of these are 0, the follwing defaults are used:
+ ACS_VLINE. ACS_VLINE, ACS_HLINE, ACS_HLINE, ACS_ULCORNER,
+ ACS_URCORNER, ACS_LLCORNER, ACS_LRCORNER. box is shorthand
+ for wborder(win, vert, vert, hor, hor, 0, 0, 0, 0).
+
+ vline(ch,n)
+ wvline(win,ch,n)
+ These functions draw a vertical line starting at the current
+ cursor position using ch for n characters or as many as will
+ fit on the window. The cursor position is not advanced.
+
+ hline(ch,n)
+ whline(win,ch,n)
+ These functions draw a horizontal line starting at the
+ current cursor position using ch for n characters or as many
+ as will fit on the window. The cursor position is not
+ advanced.
+
+ 5.6.8 Scrolling
+
+ Scrolling only works if enabled via scrollok(). The cursor
+ position is unchanged by these functions. As an optimization
+ the physical screen is scrolled if the window in question is
+ covering the entire screen.
+
+ scroll(win)
+ The window is scrolled up one line. This involves moving
+ the lines in the window data structure.
+
+ scrl(n)
+ wscrl(win,n)
+ These functions scroll thw window up/down n lines depending
+ on the sign on n (+ for up, - for down).
+
+ 5.7. Querying the Contents of a Window
+
+ getyx(win,y,x)
+ The cursor position of the window is placed in the two
+ integer variables y and x. Since this is a macro, no & is
+ necessary.
+
+ inch()
+ winch(win)
+ mvinch(y,x)
+ mvwinch(win,y,x)
+ The character at the current position in the named window is
+ returned.
+
+ 5.8. Input from the Terminal
+
+ getch()
+ wgetch(win)
+ mvgetch(y,x)
+ mvwgetch(win,y,x)
+ A character is read from the terminal associated with the
+ window. In nodelay mode, if there is no input waiting, the
+ value -1 is returned. In delay mode, the program will hang
+ until a character is typed.
+
+ If keypad mode is enabled, and a function key is pressed,
+ the code for that function key will be returned instead of
+ the raw characters. Possible function keys are defined with
+ integers beginning with 0401, whose names begin with KEY_,
+ defined in <ncurses.h>. If a character is received that
+ could be the beginning of a function key (such as escape),
+ curses will set a one second timer. If the remainder of the
+ sequence does not come in within one second, the character
+ will be passed through, otherwise the function key value
+ will be returned. For this reason, on many terminals, there
+ will be a one second delay after a user presses the escape
+ key. (Use by a programmer of the escape key for a single
+ character function is discouraged.) The one second delay can
+ be turned off using the notimeout() function.
+
+ getstr(str)
+ wgetstr(win,str)
+ mvgetstr(y,x,str)
+ mvwgetstr(win,y,x,str)
+ A series of calls to getch is made, until a newline is
+ received. The resulting value is placed in the area pointed
+ at by the character pointer str. The users erase and kill
+ characters are interpreted, and the string is echoed.
+
+ scanw(fmt, ...)
+ wscanw(win, fmt, ...)
+ mvscanw(y, x, fmt, ...)
+ mvwscanw(win, y, x, fmt, ...)
+ vwscanw(win,fmt,va_list)
+ These functions corresponds to scanf. wgetstr is called on
+ the window, and the resulting line is used as input for the
+ scan.
+
+ 5.9. Video Attributes
+
+ attroff(at)
+ wattroff(win, attrs)
+ attron(at)
+ wattron(win, attrs)
+ attrset(at)
+ wattrset(win, attrs)
+ standout()
+ standend()
+ wstandout(win)
+ wstandend(win)
+ These functions set the current attributes of the named win-
+ dow. These attributes can be any combination of A_STANDOUT,
+ A_REVERSE, A_BOLD, A_DIM, A_BLINK, A_BLANK, A_UNDERLINE,
+ A_PROTECT, A_INVIS, and A_ALTCHARSET. These constants are
+ defined in <ncurses.h> and can be combined with the C | (or)
+ operator. The current attributes of a window are applied to
+ all characters that are written into the window. Attributes
+ are a property of the character, and move with the char-
+ acter through any scrolling and insert/delete line/character
+ operations. To the extent possible on the particular
+ terminal, they will be displayed as the graphic rendition
+ of characters put on the screen.
+ attrset(at) sets the current attributes of the given window
+ to at. attroff(at) turns off the named attributes without
+ affecting any other attributes. attron(at) turns on the
+ named attributes without affecting any others. standout is
+ the same as attrset(A_STANDOUT), standend is the same as
+ attrset(0), that is, it turns off all attributes.
+
+ 5.10. Color Manipulation
+
+ Ncurses provides support for the use of color on terminals
+ that are capable of display it. Note the BSD and older SYSV
+ curses don't support color. Color support in the PC version
+ is not compatible with SYSR4.
+
+ has_colors()
+ this function returns TRUE if the terminal supports color,
+ FALSE otherwise. Other color handling funtions will return
+ ERR if has_colors() is FALSE. You should always check before
+ using color and use other video attributes to replace color.
+
+ can_change_color()
+ This function returns TRUE if the terminal is capable of
+ redefining colors using the init_color function, FALSE if it
+ can't. Don't use init_color and color_content if it returns
+ FALSE.
+
+ start_color()
+ This function must be called before any other color handling
+ function is called. It initializes the 8 basic colors (see
+ appendix I) and sets the global variables COLORS and COLOR_
+ PAIRS to the maximum number of colors and color-pairs a
+ terminal can handle.
+
+ init_pair(pair, fg, bg)
+ This function changes the definition of a color-pair, pair.
+ Each pair has a foregroung color fg, and a background color
+ bg. Both values must be between 0 and COLORS-1. pair must be
+ between 1 and COLOR_PAIRS-1.
+ [If a pair is changed from a previous definition, the screen
+ is refreshed and all occurances of the color-pair are
+ changed to reflect the change.]
+
+ pair_content(pair, f, b)
+ This function stores the foreground and background colors of
+ the color-pair pair into the variables pointed to by f, b.
+ pair should be between 1 and COLOR_PAIRS-1.
+
+ init_color(color, r, g, b)
+ This function changes the value of a given color. A color is
+ defined by its red, green, and blue components, r, g, and b.
+ These values must be between 0 and 1000. color should be
+ between 0 and COLORS-1.
+
+ color_content(color, r, g, b)
+ This function puts the red, green, and blue components of
+ color into the variable pointed to by r, g, b respectively.
+ color should be between 0 and COLORS-1.
+
+ 5.11. Pads
+
+ 5.12. Soft Labels
+
+ 5.13. Bells and Flashing Lights
+
+ beep()
+ flash()
+ These functions are used to signal the programmer. beep
+ will sound the audible alarm on the terminal, if possible,
+ and if not, will flash the screen (visible bell), if that is
+ possible. flash will flash the screen, and if that is not
+ possible, will sound the audible signal. If neither signal
+ is possible, nothing will happen. Nearly all terminals have
+ an audible signal (bell or beep) but only some can flash the
+ screen.
+
+ 5.14. Portability Functions
+
+ These functions do not have anything to do with terminal
+ dependent character output, but tend to be needed by pro-
+ grams that use curses. Unfortunately, their implemention
+ varies from one version of UNIX* to another. They have been
+ included here to enhance the portability of programs using
+ curses.
+
+ baudrate()
+ baudrate returns the output speed of the terminal. The num-
+ ber returned is the integer baud rate, for example, 9600,
+ rather than a table index such as B9600.
+
+ erasechar()
+ The erase character chosen by the user is returned. This is
+ the character typed by the user to erase the character just
+ typed.
+
+ killchar()
+ The line kill character chosen by the user is returned.
+ This is the character typed by the user to forget the entire
+ line being typed.
+
+ flushinp()
+ flushinp throws away any typeahead that has been typed by
+ the user and has not yet been read by the program.
+
+ 5.15. Debugging
+
+ These functions are useful when debugging a program with
+ curses.
+
+ unctrl(ch)
+ This macro expands to a character string which is a print-
+ able representation of the character ch. The program must
+ include the file <unctrl.h>. Control characters are dis-
+ played in the ^x notation. Printing characters are displayed
+ as is.
+
+ traceoff()
+ traceon()
+ It is possible to compile a debugging version of curses with
+ tracing turned on, and with the -g option for gdb. This
+ library may be available on your system as -ldcurses. When
+ using this version, the file ``trace'' will be created each
+ time the program is run, containing verbose information
+ showing each step done by curses. This output is useful for
+ finding bugs in curses, and may be useful for finding bugs
+ in user programs. Since the output is so verbose, with any
+ bug that cannot be easily and quickly reproduced, it may be
+ necessary to turn the debugging output off in some parts of
+ the program. These functions can be used to turn tracing
+ off and back on. When initscr is first called, tracing is
+ automatically turned on.
+ You should use -DTRACE when compiling programs that use
+ tracing.
+
+ _tracef()
+ This function can be used to output your own debugging info-
+ rmation. It is only available only if you compile with the
+ -DTRACE flag and linking with -ldcurses. It can be used the
+ same way as printf, only it outputs a newline after the end
+ of arguments.
+
+ 6. Lower Level Functions
+
+ These functions are provided for programs not needing the
+ screen optimization capabilities of curses. Programs are
+ discouraged from working at this level, since they must han-
+ dle various glitches in certain terminals. However, a pro-
+ gram can be smaller if it only brings in the low level rou-
+ tines.
+
+ gettmode()
+ setterm(type)
+ These two initialization routines are provided for upward
+ compatibility with the old curses. gettmode does nothing.
+ setterm results in a call to setupterm with appropriate
+ arguments.
+
+ def_prog_mode()
+ def_shell_mode()
+ These functions define "program" mode and "shell" mode. The
+ first describes the status of a terminal while in curses,
+ the second the status outside curses.
+
+ reset_prog_mode()
+ reset_shell_mode()
+ These functions restore a terminal to "program" mode after
+ shelling out, or to "shell" mode before shelling out.
+
+ fixterm()
+ resetterm()
+ These functions are obselete and have been replaced by
+ reset_prog_mode() and reset_prog_mode() respectively.
+
+ saveterm()
+ This fucntion is obselete and is replaced by
+ def_prog_mode().
+
+ mvcur(oldrow, oldcol, newrow, newcol)
+ This routine optimally moves the cursor from (oldrow, old-
+ col) to (newrow, newcol). The user program is expected to
+ keep track of the current cursor position. Note that unless
+ a full screen image is kept, curses will have to make pes-
+ simistic assumptions, sometimes resulting in less than opti-
+ mal cursor motion. For example, moving the cursor a few
+ spaces to the right can be done by transmitting the charac-
+ ters being moved over, but if curses does not have access to
+ the screen image, it doesn't know what these characters are.
+ If either of oldcol or oldrow are negative, mvcur() will
+ refrain from using any relative motions. This is handy for
+ occasions when a program is unsure as to the current cursor
+ location.
+
+ 7. Terminfo Level
+
+ These routines are called by low level programs that need
+ access to specific capabilities of terminfo. A program
+ working at this level should include both <ncurses.h> and
+ <term.h>. After a call to setupterm, the capabilities will
+ be available with macro names defined in <term.h>. See ter-
+ minfo(5) for a detailed description of the capabilies. If
+ the program only needs to handle one terminal, the defini-
+ tion -DSINGLE can be passed to the C compiler, resulting in
+ static references to capabilities instead of dynamic refer-
+ ences. This can result in smaller code, but prevents use of
+ more than one terminal at a time. Very few programs use
+ more than one terminal, so almost all programs can use this
+ flag.
+
+ setupterm(term, filenum, errret)
+ This routine is called to initialize a terminal. term is
+ the character string representing the name of the terminal
+ being used. filenum is the UNIX file descriptor of the ter-
+ minal being used for output. errret is a pointer to an
+ integer, in which a success or failure indication is
+ returned. The values returned can be 1 (all is well), 0 (no
+ such terminal), or -1 (some problem locating the terminfo
+ database).
+ The value of term can be given as 0, which will cause the
+ value of TERM in the environment to be used. The errret
+ pointer can also be given as 0, meaning no error code is
+ wanted. If errret is defaulted, and something goes wrong,
+ setupterm will print an appropriate error message and exit,
+ rather than returning. Thus, a simple program can call
+ setupterm(0, 1, 0) and not worry about initialization
+ errors.
+ setupterm will check the tty driver mode bits, and change
+ any that might prevent the correct operation of other low
+ level routines. Currently, the mode that expands tabs into
+ spaces is disabled, because the tab character is sometimes
+ used for different functions by different terminals. (Some
+ terminals use it to move right one space. Others use it to
+ address the cursor to row or column 9.) If the system is
+ expanding tabs, setupterm will remove the definition of the
+ tab and backtab functions, assuming that since the user is
+ not using hardware tabs, they may not be properly set in the
+ terminal.
+ After the call to setupterm, the global variable cur_term is
+ set to point to the current structure of terminal capabili-
+ ties. By calling setupterm for each terminal, and saving
+ and restoring cur_term, it is possible for a program to use
+ two or more terminals at once. Setupterm also stores the
+ names section of the terminal description in the global
+ character array ttytype[]. Subsequent calls to setupterm
+ will overwrite this array, so you'll have to save it your-
+ self if need be.
+ The mode that turns newlines into CRLF on output is not dis-
+ abled. Programs that use cud1 or ind should avoid these
+ capabilities if their value is linefeed unless they disable
+ this mode. setupterm calls fixterm after any changes it
+ makes.
+
+ vidattr(newmode)
+ vidputs(newmode, outc)
+ newmode is any combination of attributes, defined in
+ <ncurses.h>. The proper string to put the terminal in the
+ given video mode is output. The routine vidattr() sends the
+ output characters to putchar; vidputs sends them to the
+ given routine outc, one character at a time. That routine
+ should therefore expect one char parameter. The previous
+ mode is remembered by this routine.
+
+ tparm(instring, p1, p2, p3, p4, p5, p6, p7, p8, p9)
+ tparm is used to instantiate a parameterized string. The
+ character string returned is suitable for tputs. Up to 9
+ parameters can be passed, in addition to the parameterized
+ string.
+
+ tputs(cp, affcnt, outc)
+ A string capability, possibly containing padding informa-
+ tion, is processed. Enough padding characters to delay for
+ the specified time replace the padding specification, and
+ the resulting string is passed, one character at a time, to
+ the routine outc, which should expect one character parame-
+ ter. (This routine often just calls putchar.) cp is the
+ capability string. affcnt is the number of units affected
+ by the capability, which varies with the particular capabil-
+ ity. (For example, the affcnt for insert_line is the number
+ of lines below the inserted line on the screen, that is, the
+ number of lines that will have to be moved by the terminal.)
+ affcnt is used by the padding information of some terminals
+ as a multiplication factor. If the capability does not have
+ a factor, the value 1 should be passed.
+
+ putp(str)
+ This is a convenient function to output a capability with no
+ affcnt. The string is output to putchar with an affcnt of
+ 1. It can be used in simple applications that do not need
+ to process the output of tputs.
+
+
+ 8. Termcap Emulation
+
+ Appendix I: Attributes
+ ----------------------
+
+ Attributes are used with wattron(), wattroff(), wattrset(),
+ or or'ed with the character passed to waddch(). They are
+ defined in <ncurses.h>
+
+ A_ATTRIBUTES mask chtype for attributes
+ A_NORMAL reset all attributes
+ A_STANDOUT best highlighting mode
+ A_UNDERLINE underline
+ A_REVERSE reverse video, background and foreground reversed
+ A_BLINK blinking
+ A_DIM dim or half bright
+ A_BOLD bold or extra bright
+ A_ALTCHARSET use alternate character set
+ A_INVIS invisible, background same as foreground
+ A_PROTECT I haven't a clue
+ A_CHARTEXT mask chtype for actual character
+ A_COLOR mask for color
+ COLOR_PAIR(n) set color-pair to that stored in n
+ PAIR_NUMBER(a) get color-pair stored in attribute a
+
+
+ Appendix II: COLORS
+ -------------------
+
+ Colors are defined in <ncurses.h> are used with init_pair().
+
+ COLOR_BLACK 0
+ COLOR_RED 1
+ COLOR_GREEN 2
+ COLOR_YELLOW 3
+ COLOR_BLUE 4
+ COLOR_MAGENTA 5
+ COLOR_CYAN 6
+ COLOR_WHITE 7
+
+ Appendix III: Alternative character sets
+ ----------------------------------------
+
+ ACS variables are used to add line-drawing capability to
+ ncurses on terminals that support it. When defined for a
+ given terminal (using acs) the A_ALTCHARSET attribute is
+ set for that variable, otherwise the default value is
+ used.
+
+ ACS_ULCORNER +
+ ACS_LLCORNER +
+ ACS_URCORNER +
+ ACS_LRCORNER +
+ ACS_RTEE +
+ ACS_LTEE +
+ ACS_BTEE +
+ ACS_TTEE +
+ ACS_HLINE -
+ ACS_VLINE |
+ ACS_PLUS +
+ ACS_S1 ~ /* scan line 1 */
+ ACS_S9 _ /* scan line 9 */
+ ACS_DIAMOND + /* diamond */
+ ACS_CKBOARD : /* checker board (stipple) */
+ ACS_DEGREE ' /* degree symbol */
+ ACS_PLMINUS # /* plus/minus */
+ ACS_BULLET 0 /* bullet */
+ ACS_LARROW < /* arrow pointing left */
+ ACS_RARROW > /* arrow pointing right */
+ ACS_DARROW v /* arrow pointing down */
+ ACS_UARROW ^ /* arrow pointing up */
+ ACS_BOARD # /* board of squares */
+ ACS_LANTERN # /* lantern symbol */
+ ACS_BLOCK # /* solid square block */
+
+
+ Appendix IV: Function keys, their codes, and their definition
+ -------------------------------------------------------------
+
+ Function keys can return their respective codes if keypad()
+ is enabled and they are defined in the terminal's terminfo
+ description (assuming the terminal transmits unique sequences
+ for the key. They are defined in <ncurses.h>
+
+ KEY_BREAK 0401 /* break key (unreliable) */
+ KEY_DOWN 0402 /* The four arrow keys ... */
+ KEY_UP 0403
+ KEY_LEFT 0404
+ KEY_RIGHT 0405 /* ... */
+ KEY_HOME 0406 /* Home key (upward+left arrow) */
+ KEY_BACKSPACE 0407 /* backspace (unreliable) */
+ KEY_F0 0410 /* Function keys. Space for 64 */
+ KEY_F(n) (KEY_F0+(n)) /* keys is reserved. */
+ KEY_DL 0510 /* Delete line */
+ KEY_IL 0511 /* Insert line */
+ KEY_DC 0512 /* Delete character */
+ KEY_IC 0513 /* Insert char or enter insert mode */
+ KEY_EIC 0514 /* Exit insert char mode */
+ KEY_CLEAR 0515 /* Clear screen */
+ KEY_EOS 0516 /* Clear to end of screen */
+ KEY_EOL 0517 /* Clear to end of line */
+ KEY_SF 0520 /* Scroll 1 line forward */
+ KEY_SR 0521 /* Scroll 1 line backwards (reverse) */
+ KEY_NPAGE 0522 /* Next page */
+ KEY_PPAGE 0523 /* Previous page */
+ KEY_STAB 0524 /* Set tab */
+ KEY_CTAB 0525 /* Clear tab */
+ KEY_CATAB 0526 /* Clear all tabs */
+ KEY_ENTER 0527 /* Enter or send (unreliable) */
+ KEY_SRESET 0530 /* soft (partial) reset (unreliable) */
+ KEY_RESET 0531 /* reset or hard reset (unreliable) */
+ KEY_PRINT 0532 /* print or copy */
+ KEY_LL 0533 /* home down or bottom (lower left) */
+
+ /* The keypad is arranged like this: */
+ /* a1 up a3 */
+ /* left b2 right */
+ /* c1 down c3 */
+
+ KEY_A1 0534 /* Upper left of keypad */
+ KEY_A3 0535 /* Upper right of keypad */
+ KEY_B2 0536 /* Center of keypad */
+ KEY_C1 0537 /* Lower left of keypad */
+ KEY_C3 0540 /* Lower right of keypad */
+ KEY_BTAB 0541 /* Back tab key */
+ KEY_BEG 0542 /* beg(inning) key */
+ KEY_CANCEL 0543 /* cancel key */
+ KEY_CLOSE 0544 /* close key */
+ KEY_COMMAND 0545 /* cmd (command) key */
+ KEY_COPY 0546 /* copy key */
+ KEY_CREATE 0547 /* create key */
+ KEY_END 0550 /* end key */
+ KEY_EXIT 0551 /* exit key */
+ KEY_FIND 0552 /* find key */
+ KEY_HELP 0553 /* help key */
+ KEY_MARK 0554 /* mark key */
+ KEY_MESSAGE 0555 /* message key */
+ KEY_MOVE 0556 /* move key */
+ KEY_NEXT 0557 /* next object key */
+ KEY_OPEN 0560 /* open key */
+ KEY_OPTIONS 0561 /* options key */
+ KEY_PREVIOUS 0562 /* previous object key */
+ KEY_REDO 0563 /* redo key */
+ KEY_REFERENCE 0564 /* ref(erence) key */
+ KEY_REFRESH 0565 /* refresh key */
+ KEY_REPLACE 0566 /* replace key */
+ KEY_RESTART 0567 /* restart key */
+ KEY_RESUME 0570 /* resume key */
+ KEY_SAVE 0571 /* save key */
+ KEY_SBEG 0572 /* shifted beginning key */
+ KEY_SCANCEL 0573 /* shifted cancel key */
+ KEY_SCOMMAND 0574 /* shifted command key */
+ KEY_SCOPY 0575 /* shifted copy key */
+ KEY_SCREATE 0576 /* shifted create key */
+ KEY_SDC 0577 /* shifted delete char key */
+ KEY_SDL 0600 /* shifted delete line key */
+ KEY_SELECT 0601 /* select key */
+ KEY_SEND 0602 /* shifted end key */
+ KEY_SEOL 0603 /* shifted clear line key */
+ KEY_SEXIT 0604 /* shifted exit key */
+ KEY_SFIND 0605 /* shifted find key */
+ KEY_SHELP 0606 /* shifted help key */
+ KEY_SHOME 0607 /* shifted home key */
+ KEY_SIC 0610 /* shifted input key */
+ KEY_SLEFT 0611 /* shifted left arrow key */
+ KEY_SMESSAGE 0612 /* shifted message key */
+ KEY_SMOVE 0613 /* shifted move key */
+ KEY_SNEXT 0614 /* shifted next key */
+ KEY_SOPTIONS 0615 /* shifted options key */
+ KEY_SPREVIOUS 0616 /* shifted prev key */
+ KEY_SPRINT 0617 /* shifted print key */
+ KEY_SREDO 0620 /* shifted redo key */
+ KEY_SREPLACE 0621 /* shifted replace key */
+ KEY_SRIGHT 0622 /* shifted right arrow */
+ KEY_SRSUME 0623 /* shifted resume key */
+ KEY_SSAVE 0624 /* shifted save key */
+ KEY_SSUSPEND 0625 /* shifted suspend key */
+ KEY_SUNDO 0626 /* shifted undo key */
+ KEY_SUSPEND 0627 /* suspend key */
+ KEY_UNDO 0630 /* undo key */
+ KEY_MAX 0777 /* Maximum curses key */
+
diff --git a/lib/libncurses/keys.list b/lib/libncurses/keys.list
new file mode 100644
index 0000000..e766f32
--- /dev/null
+++ b/lib/libncurses/keys.list
@@ -0,0 +1,149 @@
+key_a1 KEY_A1
+key_a3 KEY_A3
+key_b2 KEY_B2
+key_backspace KEY_BACKSPACE
+key_beg KEY_BEG
+key_btab KEY_BTAB
+key_c1 KEY_C1
+key_c3 KEY_C3
+key_cancel KEY_CANCEL
+key_catab KEY_CATAB
+key_clear KEY_CLEAR
+key_close KEY_CLOSE
+key_command KEY_COMMAND
+key_copy KEY_COPY
+key_create KEY_CREATE
+key_ctab KEY_CTAB
+key_dc KEY_DC
+key_dl KEY_DL
+key_down KEY_DOWN
+key_eic KEY_EIC
+key_end KEY_END
+key_enter KEY_ENTER
+key_eol KEY_EOL
+key_eos KEY_EOS
+key_exit KEY_EXIT
+key_f0 KEY_F(0)
+key_f1 KEY_F(1)
+key_f2 KEY_F(2)
+key_f3 KEY_F(3)
+key_f4 KEY_F(4)
+key_f5 KEY_F(5)
+key_f6 KEY_F(6)
+key_f7 KEY_F(7)
+key_f8 KEY_F(8)
+key_f9 KEY_F(9)
+key_f10 KEY_F(10)
+key_f11 KEY_F(11)
+key_f12 KEY_F(12)
+key_f13 KEY_F(13)
+key_f14 KEY_F(14)
+key_f15 KEY_F(15)
+key_f16 KEY_F(16)
+key_f17 KEY_F(17)
+key_f18 KEY_F(18)
+key_f19 KEY_F(19)
+key_f20 KEY_F(20)
+key_f21 KEY_F(21)
+key_f22 KEY_F(22)
+key_f23 KEY_F(23)
+key_f24 KEY_F(24)
+key_f25 KEY_F(25)
+key_f26 KEY_F(26)
+key_f27 KEY_F(27)
+key_f28 KEY_F(28)
+key_f29 KEY_F(29)
+key_f30 KEY_F(30)
+key_f31 KEY_F(31)
+key_f32 KEY_F(32)
+key_f33 KEY_F(33)
+key_f34 KEY_F(34)
+key_f35 KEY_F(35)
+key_f36 KEY_F(36)
+key_f37 KEY_F(37)
+key_f38 KEY_F(38)
+key_f39 KEY_F(39)
+key_f40 KEY_F(40)
+key_f41 KEY_F(41)
+key_f42 KEY_F(42)
+key_f43 KEY_F(43)
+key_f44 KEY_F(44)
+key_f45 KEY_F(45)
+key_f46 KEY_F(46)
+key_f47 KEY_F(47)
+key_f48 KEY_F(48)
+key_f49 KEY_F(49)
+key_f50 KEY_F(50)
+key_f51 KEY_F(51)
+key_f52 KEY_F(52)
+key_f53 KEY_F(53)
+key_f54 KEY_F(54)
+key_f55 KEY_F(55)
+key_f56 KEY_F(56)
+key_f57 KEY_F(57)
+key_f58 KEY_F(58)
+key_f59 KEY_F(59)
+key_f60 KEY_F(60)
+key_f61 KEY_F(61)
+key_f62 KEY_F(62)
+key_f63 KEY_F(63)
+key_find KEY_FIND
+key_help KEY_HELP
+key_home KEY_HOME
+key_ic KEY_IC
+key_il KEY_IL
+key_left KEY_LEFT
+key_ll KEY_LL
+key_mark KEY_MARK
+key_message KEY_MESSAGE
+key_move KEY_MOVE
+key_next KEY_NEXT
+key_npage KEY_NPAGE
+key_open KEY_OPEN
+key_options KEY_OPTIONS
+key_ppage KEY_PPAGE
+key_previous KEY_PREVIOUS
+key_print KEY_PRINT
+key_redo KEY_REDO
+key_reference KEY_REFERENCE
+key_refresh KEY_REFRESH
+key_replace KEY_REPLACE
+key_restart KEY_RESTART
+key_resume KEY_RESUME
+key_right KEY_RIGHT
+key_save KEY_SAVE
+key_sbeg KEY_SBEG
+key_scancel KEY_SCANCEL
+key_scommand KEY_SCOMMAND
+key_scopy KEY_SCOPY
+key_screate KEY_SCREATE
+key_sdc KEY_SDC
+key_sdl KEY_SDL
+key_select KEY_SELECT
+key_send KEY_SEND
+key_seol KEY_SEOL
+key_sexit KEY_SEXIT
+key_sf KEY_SF
+key_sfind KEY_SFIND
+key_shelp KEY_SHELP
+key_shome KEY_SHOME
+key_sic KEY_SIC
+key_sleft KEY_SLEFT
+key_smessage KEY_SMESSAGE
+key_smove KEY_SMOVE
+key_snext KEY_SNEXT
+key_soptions KEY_SOPTIONS
+key_sprevious KEY_SPREVIOUS
+key_sprint KEY_SPRINT
+key_sr KEY_SR
+key_sredo KEY_SREDO
+key_sreplace KEY_SREPLACE
+key_sright KEY_SRIGHT
+key_srsume KEY_SRSUME
+key_ssave KEY_SSAVE
+key_ssuspend KEY_SSUSPEND
+key_stab KEY_STAB
+key_sundo KEY_SUNDO
+key_suspend KEY_SUSPEND
+key_undo KEY_UNDO
+key_up KEY_UP
diff --git a/lib/libncurses/lib_acs.c b/lib/libncurses/lib_acs.c
new file mode 100644
index 0000000..2b6d25b
--- /dev/null
+++ b/lib/libncurses/lib_acs.c
@@ -0,0 +1,98 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+
+#include "curses.priv.h"
+#include "terminfo.h"
+#include <string.h>
+
+/* line graphics */
+
+
+chtype acs_map[128];
+
+void init_acs()
+{
+
+/*
+ ACS_ULCORNER (acs_map['l'])
+ ACS_LLCORNER (acs_map['m'])
+ ACS_URCORNER (acs_map['k'])
+ ACS_LRCORNER (acs_map['j'])
+ ACS_RTEE (acs_map['u'])
+ ACS_LTEE (acs_map['t'])
+ ACS_BTEE (acs_map['v'])
+ ACS_TTEE (acs_map['w'])
+ ACS_HLINE (acs_map['q'])
+ ACS_VLINE (acs_map['x'])
+ ACS_PLUS (acs_map['n'])
+ ACS_S1 (acs_map['o']) scan line 1
+ ACS_S9 (acs_map['s']) scan line 9
+ ACS_DIAMOND (acs_map['`']) diamond
+ ACS_CKBOARD (acs_map['a']) checker board (stipple)
+ ACS_DEGREE (acs_map['f']) degree symbol
+ ACS_PLMINUS (acs_map['g']) plus/minus
+ ACS_BULLET (acs_map['~']) bullet
+ ACS_LARROW (acs_map[',']) arrow pointing left
+ ACS_RARROW (acs_map['+']) arrow pointing right
+ ACS_DARROW (acs_map['.']) arrow pointing down
+ ACS_UARROW (acs_map['-']) arrow pointing up
+ ACS_BOARD (acs_map['h']) board of squares
+ ACS_LANTERN (acs_map['I']) lantern symbol
+ ACS_BLOCK (acs_map['0']) solid square block
+*/
+
+ T(("initializing ACS map"));
+
+ acs_map['l'] = acs_map['m'] = acs_map['k'] = acs_map['j'] =
+ acs_map['u'] = acs_map['t'] = acs_map['v'] = acs_map['w'] = (chtype)'+' & A_CHARTEXT;
+ acs_map['q'] = (chtype)'-' & A_CHARTEXT;
+ acs_map['x'] = (chtype)'|' & A_CHARTEXT;
+ acs_map['n'] = (chtype)'+' & A_CHARTEXT;
+ acs_map['o'] = (chtype)'~' & A_CHARTEXT;
+ acs_map['s'] = (chtype)'_' & A_CHARTEXT;
+ acs_map['`'] = (chtype)'+' & A_CHARTEXT;
+ acs_map['a'] = (chtype)':' & A_CHARTEXT;
+ acs_map['f'] = (chtype)'\'' & A_CHARTEXT;
+ acs_map['g'] = (chtype)'#' & A_CHARTEXT;
+ acs_map['~'] = (chtype)'o' & A_CHARTEXT;
+ acs_map[','] = (chtype)'<' & A_CHARTEXT;
+ acs_map['+'] = (chtype)'>' & A_CHARTEXT;
+ acs_map['.'] = (chtype)'v' & A_CHARTEXT;
+ acs_map['-'] = (chtype)'^' & A_CHARTEXT;
+ acs_map['h'] = (chtype)'#' & A_CHARTEXT;
+ acs_map['I'] = (chtype)'#' & A_CHARTEXT;
+ acs_map['0'] = (chtype)'#' & A_CHARTEXT;
+
+ if (ena_acs != NULL)
+ putp(ena_acs);
+
+ if (acs_chars != NULL) {
+ int i = 0;
+ int length = strlen(acs_chars);
+
+ while (i < length)
+ switch (acs_chars[i]) {
+ case 'l':case 'm':case 'k':case 'j':
+ case 'u':case 't':case 'v':case 'w':
+ case 'q':case 'x':case 'n':case 'o':
+ case 's':case '`':case 'a':case 'f':
+ case 'g':case '~':case ',':case '+':
+ case '.':case '-':case 'h':case 'I':
+ case '0':
+ acs_map[(unsigned int)(unsigned char)acs_chars[i]] =
+ (acs_chars[++i] & A_CHARTEXT) | A_ALTCHARSET;
+ default:
+ i++;
+ break;
+ }
+ }
+#ifdef TRACE
+ else {
+ T(("acsc not defined, using default mapping"));
+ }
+#endif
+}
+
diff --git a/lib/libncurses/lib_addch.c b/lib/libncurses/lib_addch.c
new file mode 100644
index 0000000..00684ed
--- /dev/null
+++ b/lib/libncurses/lib_addch.c
@@ -0,0 +1,107 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_addch.c
+**
+** The routine waddch().
+**
+*/
+
+#include "curses.priv.h"
+#include "unctrl.h"
+
+static int
+wladdch(WINDOW *win, chtype c, bool literal)
+{
+int x, y;
+int newx;
+chtype ch = c;
+
+ x = win->_curx;
+ y = win->_cury;
+
+ if (y > win->_maxy || x > win->_maxx || y < 0 || x < 0)
+ return(ERR);
+
+ /* ugly, but necessary --- and, bizarrely enough, even portable! */
+ if (literal)
+ goto noctrl;
+
+ switch (ch&A_CHARTEXT) {
+ case '\t':
+ for (newx = x + (8 - (x & 07)); x < newx; x++)
+ if (waddch(win, ' ') == ERR)
+ return(ERR);
+ return(OK);
+ case '\n':
+ wclrtoeol(win);
+ x = 0;
+ goto newline;
+ case '\r':
+ x = 0;
+ break;
+ case '\b':
+ if (--x < 0)
+ x = 0;
+ break;
+ default:
+ if (ch < ' ')
+ return(waddstr(win, unctrl(ch)));
+
+ /* FALL THROUGH */
+ noctrl:
+ T(("win attr = %x", win->_attrs));
+ ch |= win->_attrs;
+
+ if (win->_line[y][x]&A_CHARTEXT == ' ')
+ ch |= win->_bkgd;
+ else
+ ch |= (win->_bkgd&A_ATTRIBUTES);
+ T(("bkg = %x -> ch = %x", win->_bkgd, ch));
+
+ if (win->_line[y][x] != ch) {
+ if (win->_firstchar[y] == _NOCHANGE)
+ win->_firstchar[y] = win->_lastchar[y] = x;
+ else if (x < win->_firstchar[y])
+ win->_firstchar[y] = x;
+ else if (x > win->_lastchar[y])
+ win->_lastchar[y] = x;
+
+ }
+
+ T(("char %d of line %d is %x", x, y, ch));
+ win->_line[y][x++] = ch;
+ if (x > win->_maxx) {
+ x = 0;
+newline:
+ y++;
+ if (y > win->_regbottom) {
+ y--;
+ if (win->_scroll)
+ scroll(win);
+ }
+ }
+ break;
+ }
+
+ win->_curx = x;
+ win->_cury = y;
+
+ return(OK);
+}
+
+int waddch(WINDOW *win, chtype ch)
+{
+ TR(TRACE_CHARPUT, ("waddch(%x,%c (%x)) called", win, ch&A_CHARTEXT, ch));
+ return wladdch(win, ch, FALSE);
+}
+
+int wechochar(WINDOW *win, chtype ch)
+{
+ T(("wechochar(%x,%c (%x)) called", win, ch&A_CHARTEXT, ch));
+
+ return wladdch(win, ch, TRUE);
+}
diff --git a/lib/libncurses/lib_addstr.c b/lib/libncurses/lib_addstr.c
new file mode 100644
index 0000000..d9cb30a
--- /dev/null
+++ b/lib/libncurses/lib_addstr.c
@@ -0,0 +1,56 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_addstr.c
+*
+** The routines waddnstr(), waddchnstr().
+**
+*/
+
+#include "curses.priv.h"
+
+int
+waddnstr(WINDOW *win, char *str, int n)
+{
+ T(("waddnstr(%x,\"%s\",%d) called", win, visbuf(str), n));
+
+ if (str == NULL)
+ return ERR;
+
+ if (n < 0) {
+ while (*str != '\0') {
+ if (waddch(win, (chtype)(unsigned char)*str++) == ERR)
+ return(ERR);
+ }
+ return OK;
+ }
+
+ while((n-- > 0) && (*str != '\0')) {
+ if (waddch(win, (chtype)(unsigned char)*str++) == ERR)
+ return ERR;
+ }
+ return OK;
+}
+
+int
+waddchnstr(WINDOW *win, chtype *str, int n)
+{
+ T(("waddchnstr(%x,%x,%d) called", win, str, n));
+
+ if (n < 0) {
+ while (*str) {
+ if (waddch(win, (chtype)(unsigned char)*str++) == ERR)
+ return(ERR);
+ }
+ return OK;
+ }
+
+ while(n-- > 0) {
+ if (waddch(win, (chtype)(unsigned char)*str++) == ERR)
+ return ERR;
+ }
+ return OK;
+}
diff --git a/lib/libncurses/lib_beep.c b/lib/libncurses/lib_beep.c
new file mode 100644
index 0000000..60ce592
--- /dev/null
+++ b/lib/libncurses/lib_beep.c
@@ -0,0 +1,56 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+ * beep.c
+ *
+ * Routines beep() and flash()
+ *
+ */
+
+#include "curses.priv.h"
+#include "terminfo.h"
+
+/*
+ * beep()
+ *
+ * Sound the current terminal's audible bell if it has one. If not,
+ * flash the screen if possible.
+ *
+ */
+
+int beep()
+{
+ T(("beep() called"));
+
+ /* should make sure that we are not in altchar mode */
+ if (bell)
+ return(putp(bell));
+ else if (flash_screen)
+ return(putp(flash_screen));
+ else
+ return(ERR);
+}
+
+/*
+ * flash()
+ *
+ * Flash the current terminal's screen if possible. If not,
+ * sound the audible bell if one exists.
+ *
+ */
+
+int flash()
+{
+ T(("flash() called"));
+
+ /* should make sure that we are not in altchar mode */
+ if (flash_screen)
+ return(putp(flash_screen));
+ else if (bell)
+ return(putp(bell));
+ else
+ return(ERR);
+}
diff --git a/lib/libncurses/lib_bkgd.c b/lib/libncurses/lib_bkgd.c
new file mode 100644
index 0000000..4b8043a
--- /dev/null
+++ b/lib/libncurses/lib_bkgd.c
@@ -0,0 +1,37 @@
+
+/***************************************************************************
+* COPYRIGHT NOTICE *
+****************************************************************************
+* ncurses is copyright (C) 1992, 1993, 1994 *
+* by Zeyd M. Ben-Halim *
+* zmbenhal@netcom.com *
+* *
+* Permission is hereby granted to reproduce and distribute ncurses *
+* by any means and for any fee, whether alone or as part of a *
+* larger distribution, in source or in binary form, PROVIDED *
+* this notice is included with any such distribution, not removed *
+* from header files, and is reproduced in any documentation *
+* accompanying it or the applications linked with it. *
+* *
+* ncurses comes AS IS with no warranty, implied or expressed. *
+* *
+***************************************************************************/
+
+#include "curses.h"
+#include "curses.priv.h"
+
+int wbkgd(WINDOW *win, chtype ch)
+{
+int x, y;
+
+ T(("wbkgd(%x, %x) called", win, ch));
+ for (y = 0; y <= win->_maxy; y++)
+ for (x = 0; x <= win->_maxx; x++)
+ if (win->_line[y][x]&A_CHARTEXT == ' ')
+ win->_line[y][x] |= ch;
+ else
+ win->_line[y][x] |= (ch&A_ATTRIBUTES);
+ touchwin(win);
+ return OK;
+}
+
diff --git a/lib/libncurses/lib_box.c b/lib/libncurses/lib_box.c
new file mode 100644
index 0000000..a0ffd12
--- /dev/null
+++ b/lib/libncurses/lib_box.c
@@ -0,0 +1,131 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_box.c
+**
+** line drawing routines:
+** wborder()
+** whline()
+** wvline()
+**
+*/
+
+#include "curses.priv.h"
+
+int wborder(WINDOW *win, chtype ls, chtype rs, chtype ts,
+ chtype bs, chtype tl, chtype tr, chtype bl, chtype br)
+{
+int i;
+int endx, endy;
+
+ T(("wborder() called"));
+
+ if (ls == 0) ls = ACS_VLINE;
+ if (rs == 0) rs = ACS_VLINE;
+ if (ts == 0) ts = ACS_HLINE;
+ if (bs == 0) bs = ACS_HLINE;
+ if (tl == 0) tl = ACS_ULCORNER;
+ if (tr == 0) tr = ACS_URCORNER;
+ if (bl == 0) bl = ACS_LLCORNER;
+ if (br == 0) br = ACS_LRCORNER;
+
+ ls |= win->_attrs;
+ rs |= win->_attrs;
+ ts |= win->_attrs;
+ bs |= win->_attrs;
+ tl |= win->_attrs;
+ tr |= win->_attrs;
+ bl |= win->_attrs;
+ br |= win->_attrs;
+
+ T(("using %x, %x, %x, %x, %x, %x, %x, %x", ls, rs, ts, bs, tl, tr, bl, br));
+
+ endx = win->_maxx;
+ endy = win->_maxy;
+
+ for (i = 0; i <= endx; i++) {
+ win->_line[0][i] = ts;
+ win->_line[endy][i] = bs;
+ }
+ win->_firstchar[endy] = win->_firstchar[0] = 0;
+ win->_lastchar[endy] = win->_lastchar[0] = endx;
+
+ for (i = 0; i <= endy; i++) {
+ win->_line[i][0] = ls;
+ win->_line[i][endx] = rs;
+ win->_firstchar[i] = 0;
+ win->_lastchar[i] = endx;
+ }
+ win->_line[0][0] = tl;
+ win->_line[0][endx] = tr;
+ win->_line[endy][0] = bl;
+ win->_line[endy][endx] = br;
+
+#if 0
+ if (! win->_scroll && (win->_flags & _SCROLLWIN))
+ fp[0] = fp[endx] = lp[0] = lp[endx] = ' ';
+#endif
+
+ return OK;
+}
+
+int whline(WINDOW *win, chtype ch, int n)
+{
+int line;
+int start;
+int end;
+
+ T(("whline(%x,%x,%d) called", win, ch, n));
+
+ line = win->_cury;
+ start = win->_curx;
+ end = start + n - 1;
+ if (end > win->_maxx)
+ end = win->_maxx;
+
+ if (win->_firstchar[line] == _NOCHANGE || win->_firstchar[line] > start)
+ win->_firstchar[line] = start;
+ if (win->_lastchar[line] == _NOCHANGE || win->_lastchar[line] < start)
+ win->_lastchar[line] = end;
+
+ if (ch == 0)
+ ch = ACS_HLINE;
+ while ( end >= start) {
+ win->_line[line][end] = ch | win->_attrs;
+ end--;
+ }
+
+ return OK;
+}
+
+int wvline(WINDOW *win, chtype ch, int n)
+{
+int row, col;
+int end;
+
+ T(("wvline(%x,%x,%d) called", win, ch, n));
+
+ row = win->_cury;
+ col = win->_curx;
+ end = row + n - 1;
+ if (end > win->_maxy)
+ end = win->_maxy;
+
+ if (ch == 0)
+ ch = ACS_VLINE;
+
+ while(end >= row) {
+ win->_line[end][col] = ch | win->_attrs;
+ if (win->_firstchar[end] == _NOCHANGE || win->_firstchar[end] > col)
+ win->_firstchar[end] = col;
+ if (win->_lastchar[end] == _NOCHANGE || win->_lastchar[end] < col)
+ win->_lastchar[end] = col;
+ end--;
+ }
+
+ return OK;
+}
+
diff --git a/lib/libncurses/lib_clear.c b/lib/libncurses/lib_clear.c
new file mode 100644
index 0000000..c82db9b
--- /dev/null
+++ b/lib/libncurses/lib_clear.c
@@ -0,0 +1,24 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_clear.c
+**
+** The routine wclear().
+**
+*/
+
+#include "curses.priv.h"
+
+int wclear(WINDOW *win)
+{
+ T(("wclear(%x) called", win));
+
+ werase(win);
+
+ win->_clear = TRUE;
+
+ return OK;
+}
diff --git a/lib/libncurses/lib_clrbot.c b/lib/libncurses/lib_clrbot.c
new file mode 100644
index 0000000..fa48db8
--- /dev/null
+++ b/lib/libncurses/lib_clrbot.c
@@ -0,0 +1,53 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_clrbot.c
+**
+** The routine wclrtobot().
+**
+*/
+
+#include "curses.priv.h"
+
+#define BLANK ' '|A_NORMAL
+
+int wclrtobot(WINDOW *win)
+{
+chtype *ptr, *end, *maxx = NULL;
+int y, startx, minx;
+
+ T(("wclrtobot(%x) called", win));
+
+ startx = win->_curx;
+
+ T(("clearing from y = %d to y = %d with maxx = %d", win->_cury, win->_maxy, win->_maxx));
+
+ for (y = win->_cury; y <= win->_maxy; y++) {
+ minx = _NOCHANGE;
+ end = &win->_line[y][win->_maxx];
+
+ for (ptr = &win->_line[y][startx]; ptr <= end; ptr++) {
+ if (*ptr != BLANK) {
+ maxx = ptr;
+ if (minx == _NOCHANGE)
+ minx = ptr - win->_line[y];
+ *ptr = BLANK;
+ }
+ }
+
+ if (minx != _NOCHANGE) {
+ if (win->_firstchar[y] > minx
+ || win->_firstchar[y] == _NOCHANGE)
+ win->_firstchar[y] = minx;
+
+ if (win->_lastchar[y] < maxx - win->_line[y])
+ win->_lastchar[y] = maxx - win->_line[y];
+ }
+
+ startx = 0;
+ }
+ return OK;
+}
diff --git a/lib/libncurses/lib_clreol.c b/lib/libncurses/lib_clreol.c
new file mode 100644
index 0000000..a22d6b2
--- /dev/null
+++ b/lib/libncurses/lib_clreol.c
@@ -0,0 +1,48 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_clreol.c
+**
+** The routine wclrtoeol().
+**
+*/
+
+#include "curses.priv.h"
+
+#define BLANK ' '|A_NORMAL
+
+int wclrtoeol(WINDOW *win)
+{
+chtype *maxx, *ptr, *end;
+int y, x, minx;
+
+ T(("wclrtoeol(%x) called", win));
+
+ y = win->_cury;
+ x = win->_curx;
+
+ end = &win->_line[y][win->_maxx];
+ minx = _NOCHANGE;
+ maxx = &win->_line[y][x];
+
+ for (ptr = maxx; ptr <= end; ptr++) {
+ if (*ptr != BLANK) {
+ maxx = ptr;
+ if (minx == _NOCHANGE)
+ minx = ptr - win->_line[y];
+ *ptr = BLANK;
+ }
+ }
+
+ if (minx != _NOCHANGE) {
+ if (win->_firstchar[y] > minx || win->_firstchar[y] == _NOCHANGE)
+ win->_firstchar[y] = minx;
+
+ if (win->_lastchar[y] < maxx - win->_line[y])
+ win->_lastchar[y] = maxx - win->_line[y];
+ }
+ return(OK);
+}
diff --git a/lib/libncurses/lib_color.c b/lib/libncurses/lib_color.c
new file mode 100644
index 0000000..3d40a69
--- /dev/null
+++ b/lib/libncurses/lib_color.c
@@ -0,0 +1,107 @@
+/* This work is copyrighted. See COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/* lib_color.c
+ *
+ * Handles color emulation of SYS V curses
+ *
+ */
+
+#include <stdlib.h>
+#include "curses.priv.h"
+#include "terminfo.h"
+
+int COLOR_PAIRS;
+int COLORS;
+unsigned char *color_pairs;
+
+int start_color()
+{
+ T(("start_color() called."));
+
+ if (orig_pair != NULL)
+ putp(orig_pair);
+ else return ERR;
+ if (max_pairs != -1)
+ COLOR_PAIRS = max_pairs;
+ else return ERR;
+ color_pairs = malloc(max_pairs);
+ if (max_colors != -1)
+ COLORS = max_colors;
+ else return ERR;
+ SP->_coloron = 1;
+
+ T(("started color: COLORS = %d, COLOR_PAIRS = %d", COLORS, COLOR_PAIRS));
+
+ return OK;
+}
+
+int init_pair(short pair, short f, short b)
+{
+ T(("init_pair( %d, %d, %d )", pair, f, b));
+
+ if ((pair < 1) || (pair >= COLOR_PAIRS))
+ return ERR;
+ if ((f < 0) || (f >= COLORS) || (b < 0) || (b >= COLORS))
+ return ERR;
+
+ /* still to do:
+ if pair was initialized before a screen update is performed
+ replacing original pair colors with the new ones
+ */
+
+ color_pairs[pair] = ( (f & 0x0f) | (b & 0x0f) << 4 );
+
+ return OK;
+}
+
+int init_color(short color, short r, short g, short b)
+{
+ if (initialize_color != NULL) {
+ if (color < 0 || color >= COLORS)
+ return ERR;
+ if (hue_lightness_saturation == TRUE)
+ if (r < 0 || r > 360 || g < 0 || g > 100 || b < 0 || b > 100)
+ return ERR;
+ if (hue_lightness_saturation == FALSE)
+ if (r < 0 || r > 1000 || g < 0 || g > 1000 || b < 0 || b > 1000)
+ return ERR;
+
+ putp(tparm(initialize_color, color, r, g, b));
+ return OK;
+ }
+
+ return ERR;
+}
+
+bool can_change_color()
+{
+ return can_change;
+}
+
+int has_colors()
+{
+ return ((orig_pair != NULL) && (max_colors != -1) && (max_pairs != -1)
+ &&
+ (((set_foreground != NULL) && (set_background != NULL)) ||
+ ((set_a_foreground != NULL) && (set_a_background != NULL)))
+ );
+}
+
+int color_content(short color, short *r, short *g, short *b)
+{
+ return ERR;
+}
+
+int pair_content(short pair, short *f, short *b)
+{
+
+ if ((pair < 1) || (pair > COLOR_PAIRS))
+ return ERR;
+ *f = color_pairs[pair] & 0x0f;
+ *b = color_pairs[pair] & 0xf0;
+ *b >>= 4;
+ return OK;
+}
+
diff --git a/lib/libncurses/lib_delch.c b/lib/libncurses/lib_delch.c
new file mode 100644
index 0000000..bc802ca
--- /dev/null
+++ b/lib/libncurses/lib_delch.c
@@ -0,0 +1,38 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_delch.c
+**
+** The routine wdelch().
+**
+*/
+
+#include "curses.priv.h"
+#include "terminfo.h"
+
+int wdelch(WINDOW *win)
+{
+chtype *temp1, *temp2;
+chtype *end;
+
+ T(("wdelch(%x) called", win));
+
+ end = &win->_line[win->_cury][win->_maxx];
+ temp2 = &win->_line[win->_cury][win->_curx + 1];
+ temp1 = temp2 - 1;
+
+ while (temp1 < end)
+ *temp1++ = *temp2++;
+
+ *temp1 = ' ' | win->_attrs;
+
+ win->_lastchar[win->_cury] = win->_maxx;
+
+ if (win->_firstchar[win->_cury] == _NOCHANGE
+ || win->_firstchar[win->_cury] > win->_curx)
+ win->_firstchar[win->_cury] = win->_curx;
+ return OK;
+}
diff --git a/lib/libncurses/lib_delwin.c b/lib/libncurses/lib_delwin.c
new file mode 100644
index 0000000..0edc73b
--- /dev/null
+++ b/lib/libncurses/lib_delwin.c
@@ -0,0 +1,36 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_delwin.c
+**
+** The routine delwin().
+**
+*/
+
+#include <stdlib.h>
+#include "curses.priv.h"
+
+int delwin(WINDOW *win)
+{
+int i;
+
+ T(("delwin(%x) called", win));
+
+ if (! (win->_flags & _SUBWIN)) {
+ for (i = 0; i < win->_maxy && win->_line[i]; i++)
+ free(win->_line[i]);
+ }
+
+ free(win->_firstchar);
+ free(win->_lastchar);
+ free(win->_line);
+
+ touchwin((win->_flags & _SUBWIN) ? win->_parent : curscr);
+
+ free(win);
+
+ return(OK);
+}
diff --git a/lib/libncurses/lib_doupdate.c b/lib/libncurses/lib_doupdate.c
new file mode 100644
index 0000000..2dba944
--- /dev/null
+++ b/lib/libncurses/lib_doupdate.c
@@ -0,0 +1,595 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*-----------------------------------------------------------------
+ *
+ * lib_doupdate.c
+ *
+ * The routine doupdate() and its dependents
+ *
+ *-----------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <sys/time.h>
+#ifdef SYS_SELECT
+#include <sys/select.h>
+#endif
+#include <string.h>
+#include "curses.priv.h"
+#include "terminfo.h"
+#ifdef SVR4_ACTION
+#define _POSIX_SOURCE
+#endif
+#include <signal.h>
+
+static void ClrUpdate( WINDOW *scr );
+static void TransformLine( int lineno );
+static void NoIDcTransformLine( int lineno );
+static void IDcTransformLine( int lineno );
+static void ClearScreen( void );
+static void InsStr( chtype *line, int count );
+static void DelChar( int count );
+
+static inline void PutAttrChar(chtype ch)
+{
+ TR(TRACE_CHARPUT, ("PutAttrChar(%s, %s)",
+ _tracechar(ch & A_CHARTEXT),
+ _traceattr((ch & (chtype)A_ATTRIBUTES))));
+ if (curscr->_attrs != (ch & (chtype)A_ATTRIBUTES)) {
+ curscr->_attrs = ch & (chtype)A_ATTRIBUTES;
+ vidputs(curscr->_attrs, _outch);
+ }
+ putc(ch & A_CHARTEXT, SP->_ofp);
+}
+
+static int LRCORNER = FALSE;
+
+static inline void PutChar(chtype ch)
+{
+ if (LRCORNER == TRUE && SP->_curscol == columns-1) {
+ int i = lines -1;
+ int j = columns -1;
+
+ LRCORNER = FALSE;
+ if ( (!enter_insert_mode || !exit_insert_mode)
+ && !insert_character
+ )
+ return;
+ if (cursor_left)
+ putp(cursor_left);
+ else
+ mvcur(-1, -1, i, j);
+ PutAttrChar(ch);
+ if (cursor_left)
+ putp(cursor_left);
+ else
+ mvcur(-1, -1, i, j);
+ if (enter_insert_mode && exit_insert_mode) {
+ putp(enter_insert_mode);
+ PutAttrChar(newscr->_line[i][j-1]);
+ putp(exit_insert_mode);
+ } else if (insert_character) {
+ putp(insert_character);
+ PutAttrChar(newscr->_line[i][j-1]);
+ }
+ return;
+ }
+ PutAttrChar(ch);
+ SP->_curscol++;
+ if (SP->_curscol >= columns) {
+ if (auto_right_margin) {
+ SP->_curscol = 0;
+ SP->_cursrow++;
+ } else {
+ SP->_curscol--;
+ }
+ }
+}
+
+static inline void GoTo(int row, int col)
+{
+ mvcur(SP->_cursrow, SP->_curscol, row, col);
+ SP->_cursrow = row;
+ SP->_curscol = col;
+}
+
+int _outch(int ch)
+{
+ if (SP != NULL)
+ putc(ch, SP->_ofp);
+ else
+ putc(ch, stdout);
+ return OK;
+}
+
+int doupdate(void)
+{
+int i;
+sigaction_t act, oact;
+
+ T(("doupdate() called"));
+
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGTSTP, &act, &oact);
+
+ if (SP->_endwin == TRUE) {
+ T(("coming back from shell mode"));
+ reset_prog_mode();
+ /* is this necessary? */
+ if (enter_alt_charset_mode)
+ init_acs();
+ newscr->_clear = TRUE;
+ SP->_endwin = FALSE;
+ }
+
+#if 0 /* Not works for output-only pgms */
+ /* check for pending input */
+ {
+ fd_set fdset;
+ struct timeval timeout = {0,0};
+
+ FD_ZERO(&fdset);
+ FD_SET(SP->_checkfd, &fdset);
+ if (select(SP->_checkfd+1, &fdset, NULL, NULL, &timeout) != 0) {
+ fflush(SP->_ofp);
+ return OK;
+ }
+ }
+#endif
+
+ if (curscr->_clear) { /* force refresh ? */
+ T(("clearing and updating curscr"));
+ ClrUpdate(curscr); /* yes, clear all & update */
+ curscr->_clear = FALSE; /* reset flag */
+ } else {
+ if (newscr->_clear) {
+ T(("clearing and updating newscr"));
+ ClrUpdate(newscr);
+ newscr->_clear = FALSE;
+ } else {
+ T(("Transforming lines"));
+ for (i = 0; i < lines ; i++) {
+ if(newscr->_firstchar[i] != _NOCHANGE)
+ TransformLine(i);
+ }
+ }
+ }
+ T(("marking screen as updated"));
+ for (i = 0; i < lines; i++) {
+ newscr->_firstchar[i] = _NOCHANGE;
+ newscr->_lastchar[i] = _NOCHANGE;
+ }
+
+ curscr->_curx = newscr->_curx;
+ curscr->_cury = newscr->_cury;
+
+ GoTo(curscr->_cury, curscr->_curx);
+
+ /* perhaps we should turn attributes off here */
+
+ if (curscr->_attrs != A_NORMAL)
+ vidattr(curscr->_attrs = A_NORMAL);
+
+ fflush(SP->_ofp);
+
+ sigaction(SIGTSTP, &oact, NULL);
+
+ return OK;
+}
+
+static int move_right_cost = -1;
+
+static int countc(int c)
+{
+ return(move_right_cost++);
+}
+
+/*
+** ClrUpdate(scr)
+**
+** Update by clearing and redrawing the entire screen.
+**
+*/
+
+#define BLANK ' '|A_NORMAL
+
+static void ClrUpdate(WINDOW *scr)
+{
+int i = 0, j = 0;
+int lastNonBlank;
+
+ T(("ClrUpdate(%x) called", scr));
+ if (back_color_erase && curscr->_attrs != A_NORMAL) {
+ T(("back_color_erase, turning attributes off"));
+ vidattr(curscr->_attrs = A_NORMAL);
+ }
+ ClearScreen();
+
+ if ((move_right_cost == -1) && parm_right_cursor) {
+ move_right_cost = 0;
+ tputs(tparm(parm_right_cursor, 10), 1, countc);
+ }
+
+ T(("updating screen from scratch"));
+ for (i = 0; i < lines; i++) {
+ lastNonBlank = columns - 1;
+
+ while (lastNonBlank >= 0 && scr->_line[i][lastNonBlank] == BLANK)
+ lastNonBlank--;
+
+ /* check if we are at the lr corner */
+ if (i == lines-1)
+ if ((auto_right_margin) && !(eat_newline_glitch) &&
+ (lastNonBlank == columns-1))
+ {
+ T(("Lower-right corner needs special handling"));
+ LRCORNER = TRUE;
+ }
+
+ for (j = 0; j <= lastNonBlank; j++) {
+ if (parm_right_cursor) {
+ static int inspace = 0;
+
+ T(("trying to use parm_right_cursor"));
+ if ((scr->_line[i][j]) == BLANK) {
+ inspace++;
+ continue;
+ } else if(inspace) {
+ if (inspace < move_right_cost) {
+ for (; inspace > 0; inspace--)
+ PutChar(scr->_line[i][j-1]);
+ } else {
+ putp(tparm(parm_right_cursor, inspace));
+ SP->_curscol += inspace;
+ }
+ inspace = 0;
+ }
+ }
+ PutChar(scr->_line[i][j]);
+ }
+ /* move cursor to the next line */
+ if ((!auto_right_margin) || (lastNonBlank < columns - 1) ||
+ (auto_right_margin && eat_newline_glitch && lastNonBlank == columns-1))
+ {
+ SP->_curscol = (lastNonBlank < 0) ? 0 : lastNonBlank;
+ SP->_cursrow++;
+ GoTo(i+1, 0);
+ }
+ }
+
+
+ if (scr != curscr) {
+ for (i = 0; i < lines ; i++)
+ for (j = 0; j < columns; j++)
+ curscr->_line[i][j] = scr->_line[i][j];
+ }
+}
+
+/*
+** TransformLine(lineno)
+**
+** Call either IDcTransformLine or NoIDcTransformLine to do the
+** update, depending upon availability of insert/delete character.
+*/
+
+static void TransformLine(int lineno)
+{
+
+ T(("TransformLine(%d) called",lineno));
+
+ if ( (insert_character || (enter_insert_mode && exit_insert_mode))
+ && delete_character)
+ IDcTransformLine(lineno);
+ else
+ NoIDcTransformLine(lineno);
+}
+
+
+
+/*
+** NoIDcTransformLine(lineno)
+**
+** Transform the given line in curscr to the one in newscr, without
+** using Insert/Delete Character.
+**
+** firstChar = position of first different character in line
+** lastChar = position of last different character in line
+**
+** overwrite all characters between firstChar and lastChar.
+**
+*/
+
+static void NoIDcTransformLine(int lineno)
+{
+int firstChar, lastChar;
+chtype *newLine = newscr->_line[lineno];
+chtype *oldLine = curscr->_line[lineno];
+int k;
+int attrchanged = 0;
+
+ T(("NoIDcTransformLine(%d) called", lineno));
+
+ firstChar = 0;
+ while (firstChar < columns - 1 && newLine[firstChar] == oldLine[firstChar]) {
+ if(ceol_standout_glitch) {
+ if((newLine[firstChar] & (chtype)A_ATTRIBUTES) != (oldLine[firstChar] & (chtype)A_ATTRIBUTES))
+ attrchanged = 1;
+ }
+ firstChar++;
+ }
+
+ T(("first char at %d is %x", firstChar, newLine[firstChar]));
+ if (firstChar > columns)
+ return;
+
+ if(ceol_standout_glitch && attrchanged) {
+ firstChar = 0;
+ lastChar = columns - 1;
+ GoTo(lineno, firstChar);
+ if(clr_eol) {
+ if (back_color_erase && curscr->_attrs != A_NORMAL) {
+ T(("back_color_erase, turning attributes off"));
+ vidattr(curscr->_attrs = A_NORMAL);
+ }
+ putp(clr_eol);
+ }
+ } else {
+ lastChar = columns - 1;
+ while (lastChar > firstChar && newLine[lastChar] == oldLine[lastChar])
+ lastChar--;
+ GoTo(lineno, firstChar);
+ }
+
+ /* check if we are at the lr corner */
+ if (lineno == lines-1)
+ if ((auto_right_margin) && !(eat_newline_glitch) &&
+ (lastChar == columns-1))
+ {
+ T(("Lower-right corner needs special handling"));
+ LRCORNER = TRUE;
+ }
+
+ T(("updating chars %d to %d", firstChar, lastChar));
+ for (k = firstChar; k <= lastChar; k++) {
+ PutChar(newLine[k]);
+ oldLine[k] = newLine[k];
+ }
+}
+
+/*
+** IDcTransformLine(lineno)
+**
+** Transform the given line in curscr to the one in newscr, using
+** Insert/Delete Character.
+**
+** firstChar = position of first different character in line
+** oLastChar = position of last different character in old line
+** nLastChar = position of last different character in new line
+**
+** move to firstChar
+** overwrite chars up to min(oLastChar, nLastChar)
+** if oLastChar < nLastChar
+** insert newLine[oLastChar+1..nLastChar]
+** else
+** delete oLastChar - nLastChar spaces
+*/
+
+static void IDcTransformLine(int lineno)
+{
+int firstChar, oLastChar, nLastChar;
+chtype *newLine = newscr->_line[lineno];
+chtype *oldLine = curscr->_line[lineno];
+int k, n;
+int attrchanged = 0;
+
+ T(("IDcTransformLine(%d) called", lineno));
+
+ if(ceol_standout_glitch && clr_eol) {
+ firstChar = 0;
+ while(firstChar < columns) {
+ if((newLine[firstChar] & (chtype)A_ATTRIBUTES) != (oldLine[firstChar] & (chtype)A_ATTRIBUTES))
+ attrchanged = 1;
+ firstChar++;
+ }
+ }
+
+ firstChar = 0;
+
+ if (attrchanged) {
+ GoTo(lineno, firstChar);
+ if (back_color_erase && curscr->_attrs != A_NORMAL) {
+ T(("back_color_erase, turning attributes off"));
+ vidattr(curscr->_attrs = A_NORMAL);
+ }
+ putp(clr_eol);
+
+ /* check if we are at the lr corner */
+ if (lineno == lines-1)
+ if ((auto_right_margin) && !(eat_newline_glitch))
+ {
+ T(("Lower-right corner needs special handling"));
+ LRCORNER = TRUE;
+ }
+
+ for( k = 0 ; k <= (columns-1) ; k++ )
+ PutChar(newLine[k]);
+ } else {
+ while (firstChar < columns &&
+ newLine[firstChar] == oldLine[firstChar])
+ firstChar++;
+
+ if (firstChar >= columns)
+ return;
+
+ oLastChar = columns - 1;
+ while (oLastChar > firstChar && oldLine[oLastChar] == BLANK)
+ oLastChar--;
+
+ nLastChar = columns - 1;
+ while (nLastChar > firstChar && newLine[nLastChar] == BLANK)
+ nLastChar--;
+
+ if((nLastChar == firstChar) && clr_eol) {
+ GoTo(lineno, firstChar);
+ if (back_color_erase && curscr->_attrs != A_NORMAL) {
+ T(("back_color_erase, turning attributes off"));
+ vidattr(curscr->_attrs = A_NORMAL);
+ }
+ putp(clr_eol);
+
+ if(newLine[firstChar] != BLANK ) {
+ /* check if we are at the lr corner */
+ if (lineno == lines-1)
+ if ((auto_right_margin) && !(eat_newline_glitch) &&
+ (firstChar == columns-1))
+ {
+ T(("Lower-right corner needs special handling"));
+ LRCORNER = TRUE;
+ }
+ PutChar(newLine[firstChar]);
+ }
+ } else if( newLine[nLastChar] != oldLine[oLastChar] ) {
+ n = max( nLastChar , oLastChar );
+
+ GoTo(lineno, firstChar);
+
+ /* check if we are at the lr corner */
+ if (lineno == lines-1)
+ if ((auto_right_margin) && !(eat_newline_glitch) &&
+ (n == columns-1))
+ {
+ T(("Lower-right corner needs special handling"));
+ LRCORNER = TRUE;
+ }
+
+ for( k=firstChar ; k <= n ; k++ )
+ PutChar(newLine[k]);
+ } else {
+ while (newLine[nLastChar] == oldLine[oLastChar]) {
+ nLastChar--;
+ oLastChar--;
+ }
+
+ n = min(oLastChar, nLastChar);
+
+ GoTo(lineno, firstChar);
+
+ /* check if we are at the lr corner */
+ if (lineno == lines-1)
+ if ((auto_right_margin) && !(eat_newline_glitch) &&
+ (n == columns-1))
+ {
+ T(("Lower-right corner needs special handling"));
+ LRCORNER = TRUE;
+ }
+
+ for (k=firstChar; k <= n; k++)
+ PutChar(newLine[k]);
+
+ if (oLastChar < nLastChar)
+ InsStr(&newLine[k], nLastChar - oLastChar);
+
+ else if (oLastChar > nLastChar )
+ DelChar(oLastChar - nLastChar);
+ }
+ }
+ for (k = firstChar; k < columns; k++)
+ oldLine[k] = newLine[k];
+}
+
+/*
+** ClearScreen()
+**
+** Clear the physical screen and put cursor at home
+**
+*/
+
+static void ClearScreen()
+{
+
+ T(("ClearScreen() called"));
+
+ if (clear_screen) {
+ putp(clear_screen);
+ SP->_cursrow = SP->_curscol = 0;
+ } else if (clr_eos) {
+ SP->_cursrow = SP->_curscol = -1;
+ GoTo(0,0);
+
+ putp(clr_eos);
+ } else if (clr_eol) {
+ SP->_cursrow = SP->_curscol = -1;
+
+ while (SP->_cursrow < lines) {
+ GoTo(SP->_cursrow, 0);
+ putp(clr_eol);
+ }
+ GoTo(0,0);
+ }
+ T(("screen cleared"));
+}
+
+
+/*
+** InsStr(line, count)
+**
+** Insert the count characters pointed to by line.
+**
+*/
+
+static void InsStr(chtype *line, int count)
+{
+ T(("InsStr(%x,%d) called", line, count));
+
+ if (enter_insert_mode && exit_insert_mode) {
+ putp(enter_insert_mode);
+ while (count) {
+ PutChar(*line);
+ line++;
+ count--;
+ }
+ putp(exit_insert_mode);
+ } else if (parm_ich) {
+ putp(tparm(parm_ich, count));
+ while (count) {
+ PutChar(*line);
+ line++;
+ count--;
+ }
+ } else {
+ while (count) {
+ putp(insert_character);
+ PutChar(*line);
+ line++;
+ count--;
+ }
+ }
+}
+
+/*
+** DelChar(count)
+**
+** Delete count characters at current position
+**
+*/
+
+static void DelChar(int count)
+{
+ T(("DelChar(%d) called", count));
+
+ if (back_color_erase && curscr->_attrs != A_NORMAL) {
+ T(("back_color_erase, turning attributes off"));
+ vidattr(curscr->_attrs = A_NORMAL);
+ }
+ if (parm_dch) {
+ putp(tparm(parm_dch, count));
+ } else {
+ while (count--)
+ putp(delete_character);
+ }
+}
+
diff --git a/lib/libncurses/lib_endwin.c b/lib/libncurses/lib_endwin.c
new file mode 100644
index 0000000..4e07e8f
--- /dev/null
+++ b/lib/libncurses/lib_endwin.c
@@ -0,0 +1,50 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_endwin.c
+**
+** The routine endwin().
+**
+*/
+
+#include "terminfo.h"
+#include "curses.priv.h"
+
+int isendwin()
+{
+ if (SP == NULL)
+ return FALSE;
+ return SP->_endwin;
+}
+
+int
+endwin()
+{
+ T(("endwin() called"));
+
+ SP->_endwin = TRUE;
+
+ if (change_scroll_region)
+ putp(tparm(change_scroll_region, 0, lines - 1));
+
+ mvcur(-1, -1, lines - 1, 0);
+
+ if (exit_ca_mode)
+ putp(exit_ca_mode);
+
+ if (SP->_coloron == TRUE)
+ putp(orig_pair);
+
+ if (curscr && (curscr->_attrs != A_NORMAL))
+ vidattr(curscr->_attrs = A_NORMAL);
+
+ if (SP->_cursor != 1)
+ putp(cursor_normal);
+
+ fflush(SP->_ofp);
+
+ return(reset_shell_mode());
+}
diff --git a/lib/libncurses/lib_erase.c b/lib/libncurses/lib_erase.c
new file mode 100644
index 0000000..f7b79c1
--- /dev/null
+++ b/lib/libncurses/lib_erase.c
@@ -0,0 +1,50 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_erase.c
+**
+** The routine werase().
+**
+*/
+
+#include "curses.priv.h"
+#include "terminfo.h"
+
+#define BLANK ' '
+
+int werase(WINDOW *win)
+{
+int y;
+chtype *sp, *end, *start, *maxx = NULL;
+int minx;
+
+ T(("werase(%x) called", win));
+
+ for (y = win->_regtop; y <= win->_regbottom; y++) {
+ minx = _NOCHANGE;
+ start = win->_line[y];
+ end = &start[win->_maxx];
+
+ maxx = start;
+ for (sp = start; sp <= end; sp++) {
+ maxx = sp;
+ if (minx == _NOCHANGE)
+ minx = sp - start;
+ *sp = BLANK;
+ }
+
+ if (minx != _NOCHANGE) {
+ if (win->_firstchar[y] > minx ||
+ win->_firstchar[y] == _NOCHANGE)
+ win->_firstchar[y] = minx;
+
+ if (win->_lastchar[y] < maxx - win->_line[y])
+ win->_lastchar[y] = maxx - win->_line[y];
+ }
+ }
+ win->_curx = win->_cury = 0;
+ return OK;
+}
diff --git a/lib/libncurses/lib_getch.c b/lib/libncurses/lib_getch.c
new file mode 100644
index 0000000..c30f7f2
--- /dev/null
+++ b/lib/libncurses/lib_getch.c
@@ -0,0 +1,224 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_getch.c
+**
+** The routine getch().
+**
+*/
+
+#include <sys/types.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#if defined(BRAINDEAD)
+extern int errno;
+#endif
+#include "curses.priv.h"
+
+#define head SP->_fifohead
+#define tail SP->_fifotail
+#define peek SP->_fifopeek
+
+#define h_inc() { head == FIFO_SIZE-1 ? head = 0 : head++; if (head == tail) head = -1, tail = 0;}
+#define h_dec() { head == 0 ? head = FIFO_SIZE-1 : head--; if (head == tail) tail = -1;}
+#define t_inc() { tail == FIFO_SIZE-1 ? tail = 0 : tail++; if (tail == head) tail = -1;}
+#define p_inc() { peek == FIFO_SIZE-1 ? peek = 0 : peek++;}
+
+static int fifo_peek()
+{
+ T(("peeking at %d", peek+1));
+ return SP->_fifo[++peek];
+}
+
+static inline void fifo_dump()
+{
+int i;
+ T(("head = %d, tail = %d, peek = %d", head, tail, peek));
+ for (i = 0; i < 10; i++)
+ T(("char %d = %d (%c)", i, SP->_fifo[i], (unsigned char)SP->_fifo[i]));
+}
+
+static inline int fifo_pull()
+{
+int ch;
+ ch = SP->_fifo[head];
+ T(("pulling %d from %d", ch, head));
+
+ h_inc();
+ fifo_dump();
+ return ch;
+}
+
+int ungetch(int ch)
+{
+ if (tail == -1)
+ return ERR;
+ if (head == -1) {
+ head = 0;
+ t_inc()
+ } else
+ h_dec();
+
+ SP->_fifo[head] = ch;
+ T(("ungetch ok"));
+ fifo_dump();
+ return OK;
+}
+
+static inline int fifo_push()
+{
+int n;
+unsigned char ch;
+
+ if (tail == -1) return ERR;
+again:
+ n = read(fileno(SP->_ifp), &ch, 1);
+ if (n == -1 && errno == EINTR)
+ goto again;
+ T(("read %d characters", n));
+ SP->_fifo[tail] = ch;
+ if (head == -1) head = tail;
+ t_inc();
+ T(("pushed %d at %d", ch, tail));
+ fifo_dump();
+ return ch;
+}
+
+static inline void fifo_clear()
+{
+int i;
+ for (i = 0; i < FIFO_SIZE; i++)
+ SP->_fifo[i] = 0;
+ head = -1; tail = peek = 0;
+}
+
+static int kgetch(WINDOW *);
+
+int
+wgetch(WINDOW *win)
+{
+bool setHere = FALSE; /* cbreak mode was set here */
+int ch;
+
+ T(("wgetch(%x) called", win));
+
+ /* this should be eliminated */
+ if (! win->_scroll && (SP->_echo) && (win->_flags & _FULLWIN)
+ && win->_curx == win->_maxx && win->_cury == win->_maxy)
+ return(ERR);
+
+ if ((is_wintouched(win) || (win->_flags & _HASMOVED)) &&
+ !(win->_flags & _ISPAD))
+ wrefresh(win);
+
+ if (SP->_echo && ! (SP->_raw || SP->_cbreak)) {
+ cbreak();
+ setHere = TRUE;
+ }
+
+ if (win->_delay >= 0 || SP->_cbreak > 1) {
+ int delay;
+
+ T(("timed delay in wgetch()"));
+ if (SP->_cbreak > 1)
+ delay = (SP->_cbreak-1) * 100;
+ else
+ delay = win->_delay;
+
+ T(("delay is %d microseconds", delay));
+
+ if (head == -1) /* fifo is empty */
+ if (timed_wait(fileno(SP->_ifp), delay, NULL) == 0)
+ return ERR;
+ /* else go on to read data available */
+ }
+
+ if (win->_use_keypad)
+ ch = kgetch(win);
+ else {
+ if (head == -1)
+ fifo_push();
+ ch = fifo_pull();
+ }
+
+ /* This should be eliminated */
+ /* handle 8-bit input */
+ if (ch & 0x80)
+ if (!win->_use_meta)
+ ch &= 0x7f;
+
+ /* there must be a simpler way of doing this */
+ if (!(win->_flags & _ISPAD) &&
+ SP->_echo && ch < 0400) { /* ch < 0400 => not a keypad key */
+ mvwaddch(curscr, win->_begy + win->_cury,
+ win->_begx + win->_curx, ch | win->_attrs);
+ waddch(win, ch | win->_attrs);
+ }
+ if (setHere)
+ nocbreak();
+
+ T(("wgetch returning : '%c', '0x%x'", ch, ch));
+
+ return(ch);
+}
+
+
+/*
+** int
+** kgetch()
+**
+** Get an input character, but take care of keypad sequences, returning
+** an appropriate code when one matches the input. After each character
+** is received, set a one-second alarm call. If no more of the sequence
+** is received by the time the alarm goes off, pass through the sequence
+** gotten so far.
+**
+*/
+
+static int
+kgetch(WINDOW *win)
+{
+struct try *ptr;
+int ch = 0;
+int timeleft = 1000;
+
+ T(("kgetch(%x) called", win));
+
+ ptr = SP->_keytry;
+
+ if (head == -1) {
+ ch = fifo_push();
+ peek = 0;
+ while (ptr != NULL) {
+ T(("ch = %d", ch));
+ while ((ptr != NULL) && (ptr->ch != (unsigned char)ch))
+ ptr = ptr->sibling;
+
+ if (ptr != NULL)
+ if (ptr->value != 0) { /* sequence terminated */
+ T(("end of sequence"));
+ fifo_clear();
+ return(ptr->value);
+ } else { /* go back for another character */
+ ptr = ptr->child;
+ T(("going back for more"));
+ } else
+ break;
+
+ T(("waiting for rest of sequence"));
+ if (timed_wait(fileno(SP->_ifp), timeleft, &timeleft) < 1) {
+ T(("ran out of time"));
+ return(fifo_pull());
+ } else {
+ T(("got more!"));
+ fifo_push();
+ ch = fifo_peek();
+ }
+ }
+ }
+ return(fifo_pull());
+}
diff --git a/lib/libncurses/lib_getstr.c b/lib/libncurses/lib_getstr.c
new file mode 100644
index 0000000..0eda9b9
--- /dev/null
+++ b/lib/libncurses/lib_getstr.c
@@ -0,0 +1,113 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_getstr.c
+**
+** The routine wgetstr().
+**
+*/
+
+#include "curses.priv.h"
+#include "unctrl.h"
+
+inline void backspace(WINDOW *win)
+{
+ mvwaddstr(curscr, win->_begy + win->_cury, win->_begx + win->_curx,
+ "\b \b");
+ waddstr(win, "\b \b");
+ fputs("\b \b", SP->_ofp);
+ fflush(SP->_ofp);
+ SP->_curscol--;
+}
+
+int wgetnstr(WINDOW *win, char *str, int maxlen)
+{
+bool oldnl, oldecho, oldraw, oldcbreak, oldkeypad;
+char erasec;
+char killc;
+char *oldstr;
+int ch;
+
+ T(("wgetnstr(%x,%x, %d) called", win, str, maxlen));
+
+ oldnl = SP->_nl;
+ oldecho = SP->_echo;
+ oldraw = SP->_raw;
+ oldcbreak = SP->_cbreak;
+ oldkeypad = win->_use_keypad;
+ nl();
+ noecho();
+ noraw();
+ cbreak();
+ keypad(win, TRUE);
+
+ erasec = erasechar();
+ killc = killchar();
+
+ oldstr = str;
+
+ vidattr(win->_attrs);
+ if (is_wintouched(win) || (win->_flags & _HASMOVED))
+ wrefresh(win);
+
+ while ((ch = wgetch(win)) != ERR) {
+ if (ch == '\n' || ch == '\r')
+ break;
+ if (ch == erasec || ch == KEY_LEFT || ch == KEY_BACKSPACE) {
+ if (str > oldstr) {
+ str--;
+ backspace(win);
+ }
+ } else if (ch == killc) {
+ while (str > oldstr) {
+ str--;
+ backspace(win);
+ }
+ } else if (maxlen >= 0 && str - oldstr >= maxlen) {
+ beep();
+ } else {
+ mvwaddstr(curscr, win->_begy + win->_cury,
+ win->_begx + win->_curx, unctrl(ch));
+ waddstr(win, unctrl(ch));
+ if (oldecho == TRUE) {
+ fputs(unctrl(ch), SP->_ofp);
+ fflush(SP->_ofp);
+ }
+ SP->_curscol++;
+ *str++ = ch;
+ }
+ }
+
+ win->_curx = 0;
+ if (win->_cury < win->_maxy)
+ win->_cury++;
+ wrefresh(win);
+
+ if (oldnl == FALSE)
+ nonl();
+
+ if (oldecho == TRUE)
+ echo();
+
+ if (oldraw == TRUE)
+ raw();
+
+ if (oldcbreak == FALSE)
+ nocbreak();
+
+ if (oldkeypad == FALSE)
+ keypad(win, FALSE);
+
+ if (ch == ERR) {
+ *str = '\0';
+ return ERR;
+ }
+ *str = '\0';
+
+ T(("wgetnstr returns \"%s\"", visbuf(oldstr)));
+
+ return(OK);
+}
diff --git a/lib/libncurses/lib_inchstr.c b/lib/libncurses/lib_inchstr.c
new file mode 100644
index 0000000..d0ad351
--- /dev/null
+++ b/lib/libncurses/lib_inchstr.c
@@ -0,0 +1,29 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_inchstr.c
+**
+** The routine winchnstr().
+**
+*/
+
+#include "curses.priv.h"
+
+int winchnstr(WINDOW *win, chtype *chstr, int i)
+{
+chtype *point, *end;
+
+ T(("winschnstr(%x,'%x',%d) called", win, chstr, i));
+
+ point = &win->_line[win->_cury][win->_curx];
+ end = &win->_line[win->_cury][win->_maxx];
+ if (point + i - 1 < end)
+ end = point + i - 1;
+
+ chstr = (chtype *)malloc((end - point + 1)*sizeof(chtype));
+ chstr[end - point] = '\0';
+ return OK;
+}
diff --git a/lib/libncurses/lib_initscr.c b/lib/libncurses/lib_initscr.c
new file mode 100644
index 0000000..5c9dfc3
--- /dev/null
+++ b/lib/libncurses/lib_initscr.c
@@ -0,0 +1,31 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_initscr.c
+**
+** The routine initscr().
+**
+*/
+
+#include <stdlib.h>
+#include "curses.priv.h"
+
+WINDOW *initscr()
+{
+#ifdef TRACE
+ _init_trace();
+
+ T(("initscr() called"));
+#endif
+
+ if (newterm(getenv("TERM"), stdout, stdin) == NULL)
+ return NULL;
+ else {
+ def_shell_mode();
+ def_prog_mode();
+ return(stdscr);
+ }
+}
diff --git a/lib/libncurses/lib_insch.c b/lib/libncurses/lib_insch.c
new file mode 100644
index 0000000..a86732d
--- /dev/null
+++ b/lib/libncurses/lib_insch.c
@@ -0,0 +1,36 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_insch.c
+**
+** The routine winsch().
+**
+*/
+
+#include "curses.priv.h"
+
+int winsch(WINDOW *win, chtype c)
+{
+chtype *temp1, *temp2;
+chtype *end;
+
+ T(("winsch(%x,'%x') called", win, c));
+
+ end = &win->_line[win->_cury][win->_curx];
+ temp1 = &win->_line[win->_cury][win->_maxx];
+ temp2 = temp1 - 1;
+
+ while (temp1 > end)
+ *temp1-- = *temp2--;
+
+ *temp1 = c | win->_attrs;
+
+ win->_lastchar[win->_cury] = win->_maxx;
+ if (win->_firstchar[win->_cury] == _NOCHANGE
+ || win->_firstchar[win->_cury] > win->_curx)
+ win->_firstchar[win->_cury] = win->_curx;
+ return OK;
+}
diff --git a/lib/libncurses/lib_insdel.c b/lib/libncurses/lib_insdel.c
new file mode 100644
index 0000000..aca7cc3
--- /dev/null
+++ b/lib/libncurses/lib_insdel.c
@@ -0,0 +1,49 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_insdel.c
+**
+** The routine winsdel(win, n).
+** positive n insert n lines above current line
+** negative n delete n lines starting from current line
+**
+*/
+
+#include <stdlib.h>
+#include "curses.priv.h"
+#include "terminfo.h"
+
+int
+winsdelln(WINDOW *win, int n)
+{
+ int ret, sscroll, stop, sbot;
+
+ T(("winsdel(%x,%d) called", win, n));
+
+ if (n == 0)
+ return OK;
+ if (n < 0 && win->_cury - n >= win->_maxy)
+ /* request to delete too many lines */
+ /* should we truncate to an appropriate number? */
+ return ERR;
+
+ sscroll = win->_scroll;
+ stop = win->_regtop;
+ sbot = win->_regbottom;
+
+ win->_scroll = TRUE;
+ win->_regtop = win->_cury;
+ if (win->_regtop > win->_regbottom)
+ win->_regbottom = win->_maxy;
+
+ ret = wscrl(win, -n);
+
+ win->_scroll = sscroll;
+ win->_regtop = stop;
+ win->_regbottom = sbot;
+
+ return ret;
+}
diff --git a/lib/libncurses/lib_insstr.c b/lib/libncurses/lib_insstr.c
new file mode 100644
index 0000000..6307662
--- /dev/null
+++ b/lib/libncurses/lib_insstr.c
@@ -0,0 +1,21 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_insstr.c
+**
+** The routine winsnstr().
+**
+*/
+
+#include "curses.priv.h"
+
+int winsnstr(WINDOW *win, char *str, int n)
+{
+
+ T(("winsstr(%x,'%x',%d) called", win, str, n));
+
+ return OK;
+}
diff --git a/lib/libncurses/lib_kernel.c b/lib/libncurses/lib_kernel.c
new file mode 100644
index 0000000..a96cbfc
--- /dev/null
+++ b/lib/libncurses/lib_kernel.c
@@ -0,0 +1,312 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+ * lib_kernel.c
+ *
+ * Misc. low-level routines:
+ * reset_prog_mode()
+ * reset_shell_mode()
+ * baudrate()
+ * erasechar()
+ * killchar()
+ * flushinp()
+ * savetty()
+ * resetty()
+ *
+ *
+ */
+
+#include "curses.priv.h"
+#include "terminfo.h"
+
+int wattron(WINDOW *win, chtype at)
+{
+ T(("wattron(%x,%s) current = %s", win, _traceattr(at), _traceattr(win->_attrs)));
+ if (PAIR_NUMBER(at) > 0x00) {
+ win->_attrs = (win->_attrs & ~A_COLOR) | at ;
+ T(("new attribute is %s", _traceattr(win->_attrs)));
+ } else {
+ win->_attrs |= at;
+ T(("new attribute is %s", _traceattr(win->_attrs)));
+ }
+ return OK;
+}
+
+int wattroff(WINDOW *win, chtype at)
+{
+#define IGNORE_COLOR_OFF FALSE
+
+ T(("wattroff(%x,%s) current = %s", win, _traceattr(at), _traceattr(win->_attrs)));
+ if (IGNORE_COLOR_OFF == TRUE) {
+ if (PAIR_NUMBER(at) == 0xff) /* turn off color */
+ win->_attrs &= ~at;
+ else /* leave color alone */
+ win->_attrs &= ~(at & ~A_COLOR);
+ } else {
+ if (PAIR_NUMBER(at) > 0x00) /* turn off color */
+ win->_attrs &= ~at;
+ else /* leave color alone */
+ win->_attrs &= ~(at & ~A_COLOR);
+ }
+ T(("new attribute is %s", _traceattr(win->_attrs)));
+ return OK;
+}
+
+#ifndef MYTINFO
+int reset_prog_mode()
+{
+ T(("reset_prog_mode() called"));
+
+#ifdef TERMIOS
+ tcsetattr(cur_term->Filedes, TCSANOW, &cur_term->Nttyb);
+#else
+ stty(cur_term->Filedes, &cur_term->Nttyb);
+#endif
+
+ return OK;
+}
+
+
+int reset_shell_mode()
+{
+ T(("reset_shell_mode() called"));
+
+#ifdef TERMIOS
+ tcsetattr(cur_term->Filedes, TCSANOW, &cur_term->Ottyb);
+#else
+ stty(cur_term->Filedes, &cur_term->Ottyb);
+#endif
+
+ return OK;
+}
+#endif
+
+int curs_set(int vis)
+{
+int cursor = SP->_cursor;
+
+ T(("curs_set(%d)", vis));
+
+ if (vis < 0 || vis > 2)
+ return ERR;
+
+ switch(vis) {
+ case 2:
+ if (cursor_visible)
+ putp(cursor_visible);
+ break;
+ case 1:
+ if (cursor_normal)
+ putp(cursor_normal);
+ break;
+ case 0:
+ if (cursor_invisible)
+ putp(cursor_invisible);
+ break;
+ }
+ SP->_cursor = vis;
+ return cursor;
+}
+
+int delay_output(int ms)
+{
+int speed;
+
+ T(("delay_output(%d) called", ms));
+
+ if (!no_pad_char && (speed = baudrate()) == ERR)
+ return(ERR);
+ else {
+ register int nullcount;
+
+ if (!no_pad_char)
+ for (nullcount = ms * 1000 / speed; nullcount > 0; nullcount--)
+ putc(*pad_char, SP->_ofp);
+ (void) fflush(SP->_ofp);
+ if (no_pad_char)
+ napms(ms);
+ }
+
+ return OK;
+}
+
+/*
+ * erasechar()
+ *
+ * Return erase character as given in cur_term->Ottyb.
+ *
+ */
+
+char
+erasechar()
+{
+ T(("erasechar() called"));
+
+#ifdef TERMIOS
+ return(cur_term->Ottyb.c_cc[VERASE]);
+#else
+ return(cur_term->Ottyb.sg_erase);
+#endif
+
+}
+
+
+
+/*
+ * killchar()
+ *
+ * Return kill character as given in cur_term->Ottyb.
+ *
+ */
+
+char
+killchar()
+{
+ T(("killchar() called"));
+
+#ifdef TERMIOS
+ return(cur_term->Ottyb.c_cc[VKILL]);
+#else
+ return(cur_term->Ottyb.sg_kill);
+#endif
+}
+
+
+
+/*
+ * flushinp()
+ *
+ * Flush any input on cur_term->Filedes
+ *
+ */
+
+int flushinp()
+{
+ T(("flushinp() called"));
+
+#ifdef TERMIOS
+ tcflush(cur_term->Filedes, TCIFLUSH);
+#else
+ ioctl(cur_term->Filedes, TIOCFLUSH, 0);
+#endif
+ if (SP) {
+ SP->_fifohead = -1;
+ SP->_fifotail = 0;
+ SP->_fifopeek = 0;
+ }
+ return OK;
+
+}
+
+
+
+/*
+ * int
+ * baudrate()
+ *
+ * Returns the current terminal's baud rate.
+ *
+ */
+
+#ifndef TERMIOS
+struct speed {
+ speed_t s;
+ int sp;
+};
+
+static struct speed speeds[] = {
+ {B0, 0},
+ {B50, 50},
+ {B75, 75},
+ {B110, 110},
+ {B134, 134},
+ {B150, 150},
+ {B200, 200},
+ {B300, 300},
+ {B600, 600},
+ {B1200, 1200},
+ {B1800, 1800},
+ {B2400, 2400},
+ {B4800, 4800},
+ {B9600, 9600}
+#define MAX_BAUD B9600
+#ifdef B19200
+#undef MAX_BAUD
+#define MAX_BAUD B19200
+ ,{B19200, 19200}
+#endif
+#ifdef B38400
+#undef MAX_BAUD
+#define MAX_BAUD B38400
+ ,{B38400, 38400}
+#endif
+#ifdef B57600
+#undef MAX_BAUD
+#define MAX_BAUD B57600
+ ,{B57600, 57600}
+#endif
+#ifdef B115200
+#undef MAX_BAUD
+#define MAX_BAUD B115200
+ ,{B115200, 115200}
+#endif
+};
+#endif
+
+int
+baudrate()
+{
+#ifndef TERMIOS
+int i, ret;
+#endif
+
+ T(("baudrate() called"));
+
+#ifdef TERMIOS
+ return cfgetospeed(&cur_term->Nttyb);
+#else
+ ret = cur_term->Nttyb.sg_ospeed;
+ if(ret < 0 || ret > MAX_BAUD)
+ return ERR;
+ for (i = 0; i < (sizeof(speeds) / sizeof(struct speed)); i++)
+ if (speeds[i].s == ret)
+ return speeds[i].sp;
+ return ERR;
+#endif
+}
+
+
+/*
+** savetty() and resetty()
+**
+*/
+
+static TTY buf;
+
+int savetty()
+{
+ T(("savetty() called"));
+
+#ifdef TERMIOS
+ tcgetattr(cur_term->Filedes, &buf);
+#else
+ gtty(cur_term->Filedes, &buf);
+#endif
+ return OK;
+}
+
+int resetty()
+{
+ T(("resetty() called"));
+
+#ifdef TERMIOS
+ tcsetattr(cur_term->Filedes, TCSANOW, &buf);
+#else
+ stty(cur_term->Filedes, &buf);
+#endif
+ return OK;
+}
+
diff --git a/lib/libncurses/lib_longname.c b/lib/libncurses/lib_longname.c
new file mode 100644
index 0000000..a8de085
--- /dev/null
+++ b/lib/libncurses/lib_longname.c
@@ -0,0 +1,35 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_longname.c
+**
+** The routine longname().
+**
+*/
+
+#include <string.h>
+#include "curses.priv.h"
+#include "terminfo.h"
+
+char *
+longname()
+{
+#ifndef MYTINFO
+char *ptr;
+#endif
+
+ T(("longname() called"));
+
+#ifdef MYTINFO
+ return cur_term->name_long;
+#else
+ for (ptr = ttytype + strlen(ttytype); ptr > ttytype; ptr--)
+ if (*ptr == '|')
+ return(ptr + 1);
+
+ return(ttytype);
+#endif
+}
diff --git a/lib/libncurses/lib_move.c b/lib/libncurses/lib_move.c
new file mode 100644
index 0000000..cf56fa0
--- /dev/null
+++ b/lib/libncurses/lib_move.c
@@ -0,0 +1,30 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_move.c
+**
+** The routine wmove().
+**
+*/
+
+#include "curses.priv.h"
+
+int
+wmove(WINDOW *win, int y, int x)
+{
+ T(("wmove(%x,%d,%d) called", win, y, x));
+
+ if (x >= 0 && x <= win->_maxx &&
+ y >= 0 && y <= win->_maxy)
+ {
+ win->_curx = x;
+ win->_cury = y;
+
+ win->_flags |= _HASMOVED;
+ return(OK);
+ } else
+ return(ERR);
+}
diff --git a/lib/libncurses/lib_mvcur.c b/lib/libncurses/lib_mvcur.c
new file mode 100644
index 0000000..388c680
--- /dev/null
+++ b/lib/libncurses/lib_mvcur.c
@@ -0,0 +1,700 @@
+/*---------------------------------------------------------------------------
+ *
+ * lib_mvcur.c
+ *
+ * The routine mvcur() etc.
+ *
+ * last edit-date: [Wed Jun 16 14:13:22 1993]
+ *
+ * -hm conversion from termcap -> terminfo
+ * -hm optimization debugging
+ * -hm zeyd's ncurses 0.7 update
+ * -hm eat_newline_glitch bugfix
+ * -hm hpux lint'ing ..
+ *
+ *---------------------------------------------------------------------------*/
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+#include <string.h>
+#include <stdlib.h>
+#include "terminfo.h"
+#include "curses.priv.h"
+
+#ifndef OPT_MVCUR
+/*
+**
+** mvcur(oldrow, oldcol, newrow, newcol)
+** A hack for terminals that are smart enough
+** to know how to move cursor.
+** There is still a bug in the alternative long-
+** winded code.
+**
+*/
+
+int mvcur(int oldrow, int oldcol, int newrow, int newcol)
+{
+ T(("mvcur(%d,%d,%d,%d) called", oldrow, oldcol, newrow, newcol));
+
+ if(!cursor_address)
+ return ERR;
+
+ newrow %= lines;
+ newcol %= columns;
+
+ if (cursor_address)
+ putp(tparm(cursor_address, newrow, newcol));
+ return OK;
+
+}
+
+#else
+
+#define BUFSIZE 128 /* size of strategy buffer */
+
+struct Sequence
+{
+ int vec[BUFSIZE]; /* vector of operations */
+ int *end; /* end of vector */
+ int cost; /* cost of vector */
+};
+
+static void row(struct Sequence *outseq, int orow, int nrow);
+static void column(struct Sequence *outseq, int ocol, int ncol);
+static void simp_col(struct Sequence *outseq, int oc, int nc);
+static void zero_seq(struct Sequence *seq);
+static void add_seq(struct Sequence *seq1, struct Sequence *seq2);
+static void out_seq(struct Sequence *seq);
+static void update_ops(void);
+static void init_costs(int costs[]);
+static int countc(char ch);
+static void add_op(struct Sequence *seq, int op, ...);
+static char *sequence(int op);
+
+static int c_count; /* used for counting tputs output */
+
+#define INFINITY 1000 /* biggest, impossible sequence cost */
+#define NUM_OPS 16 /* num. term. control sequences */
+#define NUM_NPARM 9 /* num. ops wo/ parameters */
+
+ /* operator indexes into op_info */
+
+#define CARRIAGE_RETURN 0 /* watch out for nl mapping */
+#define CURS_DOWN 1
+#define CURS_HOME 2
+#define CURS_LEFT 3
+#define CURS_RIGHT 4
+#define CURS_TO_LL 5
+#define CURS_UP 6
+#define TAB 7
+#define BACK_TAB 8
+#define ROW_ADDR 9
+#define COL_ADDR 10
+#define P_DOWN_CURS 11
+#define P_LEFT_CURS 12
+#define P_RIGHT_CURS 13
+#define P_UP_CURS 14
+#define CURS_ADDR 15
+
+static bool loc_init = FALSE; /* set if op_info is init'ed */
+
+static bool rel_ok; /* set if we really know where we are */
+
+/*
+ * op_info[NUM_OPS]
+ *
+ * op_info[] contains for operations with no parameters
+ * the cost of the operation. These ops should be first in the array.
+ * For operations with parameters, op_info[] contains
+ * the negative of the number of parameters.
+ */
+
+static int op_info[NUM_OPS] = {
+ 0, /* carriage_return */
+ 0, /* cursor_down */
+ 0, /* cursor_home */
+ 0, /* cursor_left */
+ 0, /* cursor_right */
+ 0, /* cursor_to_ll */
+ 0, /* cursor_up */
+ 0, /* tab */
+ 0, /* back_tab */
+ -1, /* row_address */
+ -1, /* column_address */
+ -1, /* parm_down_cursor */
+ -1, /* parm_left_cursor */
+ -1, /* parm_right_cursor */
+ -1, /* parm_up_cursor */
+ -2 /* cursor_address */
+};
+
+/*
+** Make_seq_best(best, try)
+**
+** Make_seq_best() copies try to best if try->cost < best->cost
+**
+** fixed the old version, now it really runs .. (-hm/08.04.93)
+**
+*/
+
+inline void Make_seq_best(struct Sequence *best, struct Sequence *try)
+{
+ if (best->cost > try->cost) {
+ register int *sptr;
+
+ sptr = try->vec; /* src ptr */
+ best->end = best->vec; /* dst ptr */
+ while(sptr != try->end) /* copy src -> dst */
+ *(best->end++) = *(sptr++);
+ best->cost = try->cost; /* copy cost */
+ }
+}
+
+
+/*
+**
+** mvcur(oldrow, oldcol, newrow, newcol)
+**
+** mvcur() optimally moves the cursor from the position
+** specified by (oldrow, oldcol) to (newrow, newcol). If
+** (oldrow, oldcol) == (-1, -1), mvcur() does not use relative
+** cursor motions. If the coordinates are otherwise
+** out of bounds, it mods them into range.
+**
+** Revisions needed:
+** eat_newline_glitch, auto_right_margin
+*/
+
+int mvcur(int oldrow, int oldcol, int newrow, int newcol)
+{
+struct Sequence seqA, seqB, /* allocate work structures */
+ col0seq, /* sequence to get from col0 to nc */
+ *best, /* best sequence so far */
+ *try; /* next try */
+bool nlstat = SP->_nl; /* nl-output-mapping in effect ?*/
+
+ T(("=============================\nmvcur(%d,%d,%d,%d) called",
+ oldrow, oldcol, newrow, newcol));
+
+ if ((oldrow == newrow) && (oldcol == newcol))
+ return OK;
+
+ if (oldcol == columns-1 && eat_newline_glitch && auto_right_margin) {
+ putp(tparm(cursor_address, newrow, newcol));
+ return OK;
+ }
+
+#if 0
+ if (nlstat)
+ nonl();
+#endif
+ update_ops(); /* make sure op_info[] is current */
+
+ if (oldrow < 0 || oldcol < 0 || (eat_newline_glitch && oldcol == 0 )) {
+ rel_ok = FALSE; /* relative ops ok? */
+ } else {
+ rel_ok = TRUE;
+ oldrow %= lines; /* mod values into range */
+ oldcol %= columns;
+ }
+
+ newrow %= lines;
+ newcol %= columns;
+
+ best = &seqA;
+ try = &seqB;
+
+ /* try out direct cursor addressing */
+
+ zero_seq(best);
+ add_op(best, CURS_ADDR, newrow, newcol);
+
+ /* try out independent row/column addressing */
+
+ if(rel_ok) {
+ zero_seq(try);
+ row(try, oldrow, newrow);
+ column(try, oldcol, newcol);
+ Make_seq_best(best, try);
+ }
+
+ zero_seq(&col0seq); /* store seq. to get from c0 to nc */
+ column(&col0seq, 0, newcol);
+
+ if(col0seq.cost < INFINITY) { /* can get from col0 to newcol */
+
+ /* try out homing and then row/column */
+
+ if (! rel_ok || newcol < oldcol || newrow < oldrow) {
+ zero_seq(try);
+ add_op(try, CURS_HOME, 1);
+ row(try, 0, newrow);
+ add_seq(try, &col0seq);
+ Make_seq_best(best, try);
+ }
+
+ /* try out homing to last line and then row/column */
+
+ if (! rel_ok || newcol < oldcol || newrow > oldrow) {
+ zero_seq(try);
+ add_op(try, CURS_TO_LL, 1);
+ row(try, lines - 1, newrow);
+ add_seq(try, &col0seq);
+ Make_seq_best(best, try);
+ }
+ }
+
+ out_seq(best);
+#if 0
+ if(nlstat)
+ nl();
+#endif
+
+ T(("==================================="));
+
+ return OK;
+}
+
+/*
+** row(outseq, oldrow, newrow)
+**
+** row() adds the best sequence for moving
+** the cursor from oldrow to newrow to seq.
+** row() considers row_address, parm_up/down_cursor
+** and cursor_up/down.
+*/
+
+static void
+row(struct Sequence *outseq, /* where to put the output */
+int orow, int nrow) /* old, new cursor locations */
+{
+struct Sequence seqA, seqB,
+ *best, /* best sequence so far */
+ *try; /* next try */
+
+int parm_cursor, one_step;
+
+ best = &seqA;
+ try = &seqB;
+
+ if (nrow == orow)
+ return;
+
+ if (nrow < orow) {
+ parm_cursor = P_UP_CURS;
+ one_step = CURS_UP;
+ } else {
+ parm_cursor = P_DOWN_CURS;
+ one_step = CURS_DOWN;
+ }
+
+ /* try out direct row addressing */
+
+ zero_seq(best);
+ add_op(best, ROW_ADDR, nrow);
+
+ /* try out paramaterized up or down motion */
+
+ if (rel_ok) {
+ zero_seq(try);
+ add_op(try, parm_cursor, abs(orow - nrow));
+ Make_seq_best(best, try);
+ }
+
+ /* try getting there one step at a time... */
+
+ if (rel_ok) {
+ zero_seq(try);
+ add_op(try, one_step, abs(orow-nrow));
+ Make_seq_best(best, try);
+ }
+
+ add_seq(outseq, best);
+}
+
+
+/*
+** column(outseq, oldcol, newcol)
+**
+** column() adds the best sequence for moving
+** the cursor from oldcol to newcol to outseq.
+** column() considers column_address, parm_left/right_cursor,
+** simp_col(), and carriage_return followed by simp_col().
+*/
+
+static void column(struct Sequence *outseq, /* where to put the output */
+int ocol, int ncol) /* old, new cursor column */
+{
+struct Sequence seqA, seqB,
+ *best, *try;
+int parm_cursor; /* set to either parm_up/down_cursor */
+
+ best = &seqA;
+ try = &seqB;
+
+ if (ncol == ocol)
+ return;
+
+ if (ncol < ocol)
+ parm_cursor = P_LEFT_CURS;
+ else
+ parm_cursor = P_RIGHT_CURS;
+
+ /* try out direct column addressing */
+
+ zero_seq(best);
+ add_op(best, COL_ADDR, ncol);
+
+ /* try carriage_return then simp_col() */
+
+ if(! rel_ok || (ncol < ocol)) {
+ zero_seq(try);
+ add_op(try, CARRIAGE_RETURN, 1);
+ simp_col(try, 0, ncol);
+ Make_seq_best(best, try);
+ }
+ if(rel_ok) {
+ /* try out paramaterized left or right motion */
+
+ zero_seq(try);
+ add_op(try, parm_cursor, abs(ocol - ncol));
+ Make_seq_best(best, try);
+
+ /* try getting there with simp_col() */
+
+ zero_seq(try);
+ simp_col(try, ocol, ncol);
+ Make_seq_best(best, try);
+ }
+
+ add_seq(outseq, best);
+}
+
+
+/*
+** simp_col(outseq, oldcol, newcol)
+**
+** simp_col() adds the best simple sequence for getting
+** from oldcol to newcol to outseq.
+** simp_col() considers (back_)tab and cursor_left/right.
+**
+** Revisions needed:
+** Simp_col asssumes that the cost of a (back_)tab
+** is less then the cost of one-stepping to get to the same column.
+** Should sometimes use overprinting instead of cursor_right.
+*/
+
+static void
+simp_col( struct Sequence *outseq, /* place to put sequence */
+int oc, int nc) /* old column, new column */
+{
+struct Sequence seqA, seqB, tabseq,
+ *best, *try;
+int mytab, tabs, onepast,
+ one_step, opp_step;
+
+ onepast = -1;
+
+ if (oc == nc)
+ return;
+
+ if(! rel_ok) {
+ outseq->cost = INFINITY;
+ return;
+ }
+
+ best = &seqA;
+ try = &seqB;
+
+ if(oc < nc) {
+ mytab = TAB;
+
+ if (init_tabs > 0 && op_info[TAB] < INFINITY) {
+ tabs = (nc / init_tabs) - (oc / init_tabs);
+ onepast = ((nc / init_tabs) + 1) * init_tabs;
+ if (tabs)
+ oc = onepast - init_tabs; /* consider it done */
+ } else {
+ tabs = 0;
+ }
+ one_step = CURS_RIGHT;
+ opp_step = CURS_LEFT;
+ } else {
+ mytab = BACK_TAB;
+ if (init_tabs > 0 && op_info[BACK_TAB] < INFINITY) {
+ tabs = (oc / init_tabs) - (nc / init_tabs);
+ onepast = ((nc - 1) / init_tabs) * init_tabs;
+ if (tabs)
+ oc = onepast + init_tabs; /* consider it done */
+ } else {
+ tabs = 0;
+ }
+ one_step = CURS_LEFT;
+ opp_step = CURS_RIGHT;
+ }
+
+ /* tab as close as possible to nc */
+
+ zero_seq(&tabseq);
+ add_op(&tabseq, mytab, tabs);
+
+ /* try extra tab and backing up */
+
+ zero_seq(best);
+
+ if (onepast >= 0 && onepast < columns) {
+ add_op(best, mytab, 1);
+ add_op(best, opp_step, abs(onepast - nc));
+ } else {
+ best->cost = INFINITY; /* make sure of next swap */
+ }
+
+ /* try stepping to nc */
+
+ zero_seq(try);
+ add_op(try, one_step, abs(nc - oc));
+ Make_seq_best(best, try);
+
+ if (tabseq.cost < INFINITY)
+ add_seq(outseq, &tabseq);
+ add_seq(outseq, best);
+}
+
+
+/*
+** zero_seq(seq) empties seq.
+** add_seq(seq1, seq2) adds seq1 to seq2.
+** out_seq(seq) outputs a sequence.
+*/
+
+static void
+zero_seq(seq)
+struct Sequence *seq;
+{
+ seq->end = seq->vec;
+ seq->cost = 0;
+}
+
+static void
+add_seq(struct Sequence *seq1, struct Sequence *seq2)
+{
+int *vptr;
+
+ T(("add_seq(%x, %x)", seq1, seq2));
+
+ if(seq1->cost >= INFINITY || seq2->cost >= INFINITY)
+ seq1->cost = INFINITY;
+ else {
+ vptr = seq2->vec;
+ while (vptr != seq2->end)
+ *(seq1->end++) = *(vptr++);
+ seq1->cost += seq2->cost;
+ }
+}
+
+
+static void
+out_seq(struct Sequence *seq)
+{
+int *opptr, prm[9], ps, p, op;
+int count;
+char *sequence();
+
+ T(("out_seq(%x)", seq));
+
+ if (seq->cost >= INFINITY)
+ return;
+
+ for (opptr = seq->vec; opptr < seq->end; opptr++) {
+ op = *opptr; /* grab operator */
+ ps = -op_info[op];
+ if(ps > 0) { /* parameterized */
+ for (p = 0; p < ps; p++) /* fill in needed parms */
+ prm[p] = *(++opptr);
+
+ putp(tparm(sequence(op),
+ prm[0], prm[1], prm[2], prm[3], prm[4],
+ prm[5], prm[6], prm[7], prm[8]));
+ } else {
+ count = *(++opptr);
+ /*rev should save tputs output instead of mult calls */
+ while (count--) /* do count times */
+ putp(sequence(op));
+ }
+ }
+}
+
+
+/*
+** update_ops()
+**
+** update_ops() makes sure that
+** the op_info[] array is updated and initializes
+** the cost array for SP if needed.
+*/
+
+static void
+update_ops()
+{
+ T(("update_ops()"));
+
+ if (SP) { /* SP structure exists */
+ int op;
+
+ if (! SP->_costinit) { /* this term not yet assigned costs */
+ loc_init = FALSE; /* if !SP in the future, new term */
+ init_costs(SP->_costs); /* fill term costs */
+ SP->_costinit = TRUE;
+ }
+
+ for (op = 0; op < NUM_NPARM; op++)
+ op_info[op] = SP->_costs[op]; /* set up op_info */
+
+ /* check for newline that might be mapped... */
+
+ if (SP->_nlmapping && index(sequence(CURS_DOWN), '\n'))
+ op_info[CURS_DOWN] = INFINITY;
+ } else {
+ if (! loc_init) { /* using local costs */
+ loc_init = TRUE;
+ init_costs(op_info); /* set up op_info */
+ }
+
+ /* check for newline that might be mapped... */
+
+ if (index(sequence(CURS_DOWN), '\n'))
+ op_info[CURS_DOWN] = INFINITY;
+ }
+}
+
+
+/*
+** init_costs(costs)
+**
+** init_costs() fills the array costs[NUM_NPARM]
+** with costs calculated by doing tputs() calls.
+*/
+
+static void
+init_costs(int costs[])
+{
+int i;
+
+ for (i = 0; i < NUM_NPARM; i++) {
+ if (sequence(i) != (char *) 0) {
+ c_count = 0;
+ tputs(sequence(i), 1, countc);
+ costs[i] = c_count;
+ } else
+ costs[i] = INFINITY;
+ }
+}
+
+
+/*
+** countc() increments global var c_count.
+*/
+
+static int countc(char ch)
+{
+ return(c_count++);
+}
+
+/*
+** add_op(seq, op, p0, p1, ... , p8)
+**
+** add_op() adds the operator op and the appropriate
+** number of paramaters to seq. It also increases the
+** cost appropriately.
+** if op has no parameters, p0 is taken to be a count.
+*/
+
+static void add_op(struct Sequence *seq, int op, ...)
+{
+va_list argp;
+int num_ps, p;
+
+ T(("adding op %d to sequence", op));
+
+ va_start(argp, op);
+
+ num_ps = - op_info[op]; /* get parms or -cost */
+
+ *(seq->end++) = op;
+
+ if (num_ps == (- INFINITY) || sequence(op) == (char *) 0) {
+ seq->cost = INFINITY;
+ } else if (num_ps <= 0) { /* no parms, -cost */
+ int i = va_arg(argp, int);
+ seq->cost -= i * num_ps; /* ADD count * cost */
+ *(seq->end++) = i;
+ } else {
+ int prm[9];
+
+ for (p = 0; p < num_ps; p++)
+ *(seq->end++) = prm[p] = va_arg(argp, int);
+
+ c_count = 0;
+
+ tputs(tparm(sequence(op), prm[0], prm[1], prm[2], prm[3], prm[4],
+ prm[5], prm[6], prm[7], prm[8]), 1, countc);
+
+ seq->cost += c_count;
+ }
+ va_end(argp);
+}
+
+
+/*
+** char *sequence(op)
+**
+** sequence() returns a pointer to the op's
+** terminal control sequence.
+*/
+
+static char *sequence(int op)
+{
+ T(("sequence(%d)", op));
+
+ switch(op) {
+ case CARRIAGE_RETURN:
+ return (carriage_return);
+ case CURS_DOWN:
+ return (cursor_down);
+ case CURS_HOME:
+ return (cursor_home);
+ case CURS_LEFT:
+ return (cursor_left);
+ case CURS_RIGHT:
+ return (cursor_right);
+ case CURS_TO_LL:
+ return (cursor_to_ll);
+ case CURS_UP:
+ return (cursor_up);
+ case TAB:
+ return (tab);
+ case BACK_TAB:
+ return (back_tab);
+ case ROW_ADDR:
+ return (row_address);
+ case COL_ADDR:
+ return (column_address);
+ case P_DOWN_CURS:
+ return (parm_down_cursor);
+ case P_LEFT_CURS:
+ return (parm_left_cursor);
+ case P_RIGHT_CURS:
+ return (parm_right_cursor);
+ case P_UP_CURS:
+ return (parm_up_cursor);
+ case CURS_ADDR:
+ return (cursor_address);
+ default:
+ return ((char *) 0);
+ }
+}
+
+#endif
+
diff --git a/lib/libncurses/lib_mvwin.c b/lib/libncurses/lib_mvwin.c
new file mode 100644
index 0000000..2e6159f
--- /dev/null
+++ b/lib/libncurses/lib_mvwin.c
@@ -0,0 +1,29 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_mvwin.c
+**
+** The routine mvwin().
+**
+*/
+
+#include "curses.priv.h"
+#include "terminfo.h"
+
+int mvwin(WINDOW *win, int by, int bx)
+{
+ T(("mvwin(%x,%d,%d) called", win, by, bx));
+
+ if (by + win->_maxy > lines - 1 || bx + win->_maxx > columns - 1)
+ return(ERR);
+
+ win->_begy = by;
+ win->_begx = bx;
+
+ touchwin(win);
+
+ return(OK);
+}
diff --git a/lib/libncurses/lib_newterm.c b/lib/libncurses/lib_newterm.c
new file mode 100644
index 0000000..95ef1eb
--- /dev/null
+++ b/lib/libncurses/lib_newterm.c
@@ -0,0 +1,176 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_newterm.c
+**
+** The newterm() function.
+**
+*/
+
+#include <stdlib.h>
+#include "curses.priv.h"
+#include "terminfo.h"
+#ifdef SVR4_ACTION
+#define _POSIX_SOURCE
+#endif
+#include <signal.h>
+
+#ifdef MYTINFO
+int LINES, COLS;
+#endif
+
+static void cleanup(int sig)
+{
+
+ if (sig == SIGSEGV)
+ fprintf(stderr, "Got a segmentation violation signal, cleaning up and exiting\n");
+ endwin();
+ exit(1);
+}
+
+static void
+size_change(int sig)
+{
+ struct ttysize ws;
+
+ if (ioctl(0, TIOCGSIZE, &ws) != -1) {
+ LINES = ws.ts_lines;
+ COLS = ws.ts_cols;
+ }
+}
+
+WINDOW *stdscr, *curscr, *newscr;
+SCREEN *SP;
+
+struct ripoff_t
+{
+ int line;
+ int (*hook)();
+}
+rippedoff[5], *rsp = rippedoff;
+
+SCREEN * newterm(char *term, FILE *ofp, FILE *ifp)
+{
+sigaction_t act;
+int errret;
+int stolen, topstolen;
+extern char _ncurses_copyright[];
+char *use_it = _ncurses_copyright;
+
+ use_it = use_it; /* shut up compiler */
+#ifdef TRACE
+ _init_trace();
+ T(("newterm(\"%s\",%x,%x) called", term, ofp, ifp));
+#endif
+
+#ifdef MYTINFO
+ if (setupterm(term, fileno(ofp), &errret) != OK)
+ return NULL;
+ COLS = columns;
+ LINES = lines;
+#else
+ if (setupterm(term, fileno(ofp), &errret) != 1)
+ return NULL;
+#endif
+
+ if ((SP = (SCREEN *) malloc(sizeof *SP)) == NULL)
+ return NULL;
+
+ if (ofp == stdout && ifp == stdin) {
+ SP->_ofp = stdout;
+ SP->_ifp = stdin;
+ } else {
+ SP->_ofp = ofp;
+ SP->_ifp = ofp;
+ }
+ SP->_term = cur_term;
+ SP->_cursrow = -1;
+ SP->_curscol = -1;
+ SP->_keytry = UNINITIALISED;
+ SP->_nl = TRUE;
+ SP->_raw = FALSE;
+ SP->_cbreak = FALSE;
+ SP->_echo = TRUE;
+ SP->_nlmapping = TRUE;
+ SP->_fifohead = -1;
+ SP->_fifotail = 0;
+ SP->_fifopeek = 0;
+ SP->_endwin = FALSE;
+ SP->_checkfd = fileno(ifp);
+ typeahead(fileno(ifp));
+
+ if (enter_ca_mode)
+ putp(enter_ca_mode);
+
+ init_acs();
+
+ T(("creating newscr"));
+ if ((newscr = newwin(lines, columns, 0, 0)) == (WINDOW *)NULL)
+ return(NULL);
+
+ T(("creating curscr"));
+ if ((curscr = newwin(lines, columns, 0, 0)) == (WINDOW *)NULL)
+ return(NULL);
+
+ SP->_newscr = newscr;
+ SP->_curscr = curscr;
+
+ newscr->_clear = TRUE;
+ curscr->_clear = FALSE;
+
+ stolen = topstolen = 0;
+ for (rsp = rippedoff; rsp->line; rsp++) {
+ if (rsp->hook)
+ if (rsp->line < 0)
+ rsp->hook(newwin(1,COLS, LINES-1,0), COLS);
+ else
+ rsp->hook(newwin(1,COLS, topstolen++,0), COLS);
+ --LINES;
+ stolen++;
+ }
+
+ act.sa_handler = tstp;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGTSTP, &act, NULL);
+ act.sa_handler = cleanup;
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+#if 0
+ sigaction(SIGSEGV, &act, NULL);
+#endif
+ act.sa_handler = size_change;
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGWINCH, &act, NULL); /* this must restart read() */
+ if ((stdscr = newwin(lines - stolen, columns, topstolen, 0)) == NULL)
+ return(NULL);
+
+ SP->_stdscr = stdscr;
+
+ def_shell_mode();
+ def_prog_mode();
+
+ T(("newterm returns %x", SP));
+
+ return(SP);
+}
+
+int
+ripoffline(int line, int (*init)(WINDOW *, int))
+{
+ if (line == 0)
+ return(OK);
+
+ if (rsp >= rippedoff + sizeof(rippedoff)/sizeof(rippedoff[0]))
+ return(ERR);
+
+ rsp->line = line;
+ rsp->hook = init;
+ rsp++;
+
+ return(OK);
+}
+
diff --git a/lib/libncurses/lib_newwin.c b/lib/libncurses/lib_newwin.c
new file mode 100644
index 0000000..793d06e
--- /dev/null
+++ b/lib/libncurses/lib_newwin.c
@@ -0,0 +1,185 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_newwin.c
+**
+** The routines newwin(), subwin() and their dependent
+**
+*/
+
+#include <stdlib.h>
+#include "terminfo.h"
+#include "curses.priv.h"
+
+WINDOW * newwin(int num_lines, int num_columns, int begy, int begx)
+{
+WINDOW *win;
+chtype *ptr;
+int i, j;
+
+ T(("newwin(%d,%d,%d,%d) called", num_lines, num_columns, begy, begx));
+
+ if (num_lines == 0)
+ num_lines = lines - begy;
+
+ if (num_columns == 0)
+ num_columns = columns - begx;
+
+ if (num_columns + begx > columns || num_lines + begy > lines)
+ return NULL;
+
+ if ((win = makenew(num_lines, num_columns, begy, begx)) == NULL)
+ return NULL;
+
+ for (i = 0; i < num_lines; i++) {
+ if ((win->_line[i] = (chtype *) calloc(num_columns, sizeof(chtype))) == NULL) {
+ for (j = 0; j < i; j++)
+ free(win->_line[j]);
+
+ free(win->_firstchar);
+ free(win->_lastchar);
+ free(win->_line);
+ free(win);
+
+ return NULL;
+ }
+ else
+ for (ptr = win->_line[i]; ptr < win->_line[i] + num_columns; )
+ *ptr++ = ' ';
+ }
+
+ T(("newwin: returned window is %x", win));
+
+ return(win);
+}
+
+WINDOW * derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx)
+{
+WINDOW *win;
+int i;
+
+ T(("derwin(%x, %d,%d,%d,%d) called", orig, num_lines, num_columns, begy, begx));
+
+ /*
+ ** make sure window fits inside the original one
+ */
+ if ( begy < 0 || begx < 0)
+ return NULL;
+ if ( begy + num_lines > orig->_maxy + 1
+ || begx + num_columns > orig->_maxx + 1)
+ return NULL;
+
+ if (num_lines == 0)
+ num_lines = orig->_maxy - orig->_begy - begy;
+
+ if (num_columns == 0)
+ num_columns = orig->_maxx - orig->_begx - begx;
+
+ if ((win = makenew(num_lines, num_columns, orig->_begy + begy, orig->_begx + begx)) == NULL)
+ return NULL;
+
+ win->_pary = begy;
+ win->_parx = begx;
+ win->_attrs = orig->_attrs;
+ win->_bkgd = orig->_bkgd;
+
+ for (i = 0; i < num_lines; i++)
+ win->_line[i] = &orig->_line[begy++][begx];
+
+ win->_flags = _SUBWIN;
+ win->_parent = orig;
+
+ T(("derwin: returned window is %x", win));
+
+ return(win);
+}
+
+
+WINDOW *subwin(WINDOW *w, int l, int c, int y, int x)
+{
+ T(("subwin(%x, %d, %d, %d, %d) called", w, l, c, y, x));
+ T(("parent has begy = %d, begx = %d", w->_begy, w->_begx));
+
+ return derwin(w, l, c, y - w->_begy, x - w->_begx);
+}
+
+WINDOW *
+makenew(int num_lines, int num_columns, int begy, int begx)
+{
+int i;
+WINDOW *win;
+
+ T(("makenew(%d,%d,%d,%d)", num_lines, num_columns, begy, begx));
+
+ if ((win = (WINDOW *) malloc(sizeof(WINDOW))) == NULL)
+ return NULL;
+
+ if ((win->_line = (chtype **) calloc(num_lines, sizeof (chtype *))) == NULL) {
+ free(win);
+ return NULL;
+ }
+
+ if ((win->_firstchar = calloc(num_lines, sizeof(short))) == NULL) {
+ free(win);
+ free(win->_line);
+ return NULL;
+ }
+
+ if ((win->_lastchar = calloc(num_lines, sizeof(short))) == NULL) {
+ free(win);
+ free(win->_line);
+ free(win->_firstchar);
+ return NULL;
+ }
+
+ win->_curx = 0;
+ win->_cury = 0;
+ win->_maxy = num_lines - 1;
+ win->_maxx = num_columns - 1;
+ win->_begy = begy;
+ win->_begx = begx;
+
+ win->_flags = 0;
+ win->_attrs = A_NORMAL;
+ win->_bkgd = ' ';
+
+ win->_clear = (num_lines == lines && num_columns == columns);
+ win->_idlok = FALSE;
+ win->_use_idc = TRUE;
+ win->_scroll = FALSE;
+ win->_leave = FALSE;
+ win->_use_keypad = FALSE;
+#ifdef TERMIOS
+ win->_use_meta = ((cur_term->Ottyb.c_cflag & CSIZE) == CS8 &&
+ !(cur_term->Ottyb.c_iflag & ISTRIP));
+#else
+ win->_use_meta = FALSE;
+#endif
+ win->_delay = -1;
+ win->_immed = FALSE;
+ win->_sync = 0;
+ win->_parx = 0;
+ win->_pary = 0;
+ win->_parent = (WINDOW *)NULL;
+
+ win->_regtop = 0;
+ win->_regbottom = num_lines - 1;
+
+ for (i = 0; i < num_lines; i++)
+ win->_firstchar[i] = win->_lastchar[i] = _NOCHANGE;
+
+ if (begx + num_columns == columns) {
+ win->_flags |= _ENDLINE;
+
+ if (begx == 0 && num_lines == lines && begy == 0)
+ win->_flags |= _FULLWIN;
+
+ if (begy + num_lines == lines)
+ win->_flags |= _SCROLLWIN;
+ }
+
+ return(win);
+}
diff --git a/lib/libncurses/lib_options.c b/lib/libncurses/lib_options.c
new file mode 100644
index 0000000..7aefe96
--- /dev/null
+++ b/lib/libncurses/lib_options.c
@@ -0,0 +1,252 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_options.c
+**
+** The routines to handle option setting.
+**
+*/
+
+#include <stdlib.h>
+#include "terminfo.h"
+#include "curses.priv.h"
+
+int idlok(WINDOW *win, int flag)
+{
+ T(("idlok(%x,%d) called", win, flag));
+
+ if (flag == FALSE) {
+ win->_idlok = FALSE;
+ return OK;
+ }
+
+ if ((insert_line || parm_insert_line) && (delete_line || parm_delete_line)) {
+ win->_idlok = TRUE;
+ }
+ return OK;
+}
+
+
+int clearok(WINDOW *win, int flag)
+{
+ T(("clearok(%x,%d) called", win, flag));
+
+ if (win == curscr)
+ newscr->_clear = flag;
+ else
+ win->_clear = flag;
+ return OK;
+}
+
+
+int leaveok(WINDOW *win, int flag)
+{
+ T(("leaveok(%x,%d) called", win, flag));
+
+ win->_leave = flag;
+ if (flag == TRUE)
+ curs_set(0);
+ else
+ curs_set(1);
+ return OK;
+}
+
+
+int scrollok(WINDOW *win, int flag)
+{
+ T(("scrollok(%x,%d) called", win, flag));
+
+ win->_scroll = flag;
+ return OK;
+}
+
+int halfdelay(int t)
+{
+ T(("halfdelay(%d) called", t));
+
+ if (t < 1 || t > 255)
+ return ERR;
+
+ cbreak();
+ SP->_cbreak = t+1;
+ return OK;
+}
+
+int nodelay(WINDOW *win, int flag)
+{
+ T(("nodelay(%x,%d) called", win, flag));
+
+ if (flag == TRUE)
+ win->_delay = 0;
+ else win->_delay = -1;
+ return OK;
+}
+
+int notimeout(WINDOW *win, bool f)
+{
+ T(("notimout(%x,%d) called", win, f));
+
+ win->_notimeout = f;
+ return OK;
+}
+
+int wtimeout(WINDOW *win, int delay)
+{
+ T(("wtimeout(%x,%d) called", win, delay));
+
+ win->_delay = delay;
+ return OK;
+}
+
+static void init_keytry();
+static void add_to_try(char *, short);
+
+int keypad(WINDOW *win, int flag)
+{
+ T(("keypad(%x,%d) called", win, flag));
+
+ win->_use_keypad = flag;
+
+ if (flag && keypad_xmit)
+ putp(keypad_xmit);
+ else if (! flag && keypad_local)
+ putp(keypad_local);
+
+ if (SP->_keytry == UNINITIALISED)
+ init_keytry();
+ return OK;
+}
+
+
+
+int meta(WINDOW *win, int flag)
+{
+ T(("meta(%x,%d) called", win, flag));
+
+ win->_use_meta = flag;
+
+ if (flag && meta_on)
+ putp(meta_on);
+ else if (! flag && meta_off)
+ putp(meta_off);
+ return OK;
+}
+
+/*
+** init_keytry()
+**
+** Construct the try for the current terminal's keypad keys.
+**
+*/
+
+
+static struct try *newtry;
+
+static void init_keytry()
+{
+ newtry = NULL;
+
+#include "keys.tries"
+
+ SP->_keytry = newtry;
+}
+
+
+static void add_to_try(char *str, short code)
+{
+static bool out_of_memory = FALSE;
+struct try *ptr, *savedptr;
+
+ if (! str || out_of_memory)
+ return;
+
+ if (newtry != NULL) {
+ ptr = savedptr = newtry;
+
+ for (;;) {
+ while (ptr->ch != (unsigned char) *str
+ && ptr->sibling != NULL)
+ ptr = ptr->sibling;
+
+ if (ptr->ch == (unsigned char) *str) {
+ if (*(++str)) {
+ if (ptr->child != NULL)
+ ptr = ptr->child;
+ else
+ break;
+ } else {
+ ptr->value = code;
+ return;
+ }
+ } else {
+ if ((ptr->sibling = (struct try *) malloc(sizeof *ptr)) == NULL) {
+ out_of_memory = TRUE;
+ return;
+ }
+
+ savedptr = ptr = ptr->sibling;
+ ptr->child = ptr->sibling = NULL;
+ ptr->ch = *str++;
+ ptr->value = (short) NULL;
+
+ break;
+ }
+ } /* end for (;;) */
+ } else { /* newtry == NULL :: First sequence to be added */
+ savedptr = ptr = newtry = (struct try *) malloc(sizeof *ptr);
+
+ if (ptr == NULL) {
+ out_of_memory = TRUE;
+ return;
+ }
+
+ ptr->child = ptr->sibling = NULL;
+ ptr->ch = *(str++);
+ ptr->value = (short) NULL;
+ }
+
+ /* at this point, we are adding to the try. ptr->child == NULL */
+
+ while (*str) {
+ ptr->child = (struct try *) malloc(sizeof *ptr);
+
+ ptr = ptr->child;
+
+ if (ptr == NULL) {
+ out_of_memory = TRUE;
+
+ ptr = savedptr;
+ while (ptr != NULL) {
+ savedptr = ptr->child;
+ free(ptr);
+ ptr = savedptr;
+ }
+
+ return;
+ }
+
+ ptr->child = ptr->sibling = NULL;
+ ptr->ch = *(str++);
+ ptr->value = (short) NULL;
+ }
+
+ ptr->value = code;
+ return;
+}
+
+int typeahead(int fd)
+{
+
+ T(("typeahead(%d) called", fd));
+ SP->_checkfd = fd;
+ return OK;
+}
+
+int intrflush(WINDOW *win, bool flag)
+{
+ T(("intrflush(%x, %d) called", win, flag));
+ return OK;
+}
diff --git a/lib/libncurses/lib_overlay.c b/lib/libncurses/lib_overlay.c
new file mode 100644
index 0000000..19e58f3
--- /dev/null
+++ b/lib/libncurses/lib_overlay.c
@@ -0,0 +1,110 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_overlay.c
+**
+** The routines overlay(), copywin(), and overwrite().
+**
+*/
+
+#include "curses.priv.h"
+
+static void overlap(WINDOW *s, WINDOW *d, int flag)
+{
+int sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol;
+
+ T(("overlap : sby %d, sbx %d, smy %d, smx %d, dby %d, dbx %d, dmy %d, dmx %d",
+ s->_begy, s->_begx, s->_maxy, s->_maxx,
+ d->_begy, d->_begx, d->_maxy, d->_maxx));
+ sminrow = max(s->_begy, d->_begy) - s->_begy;
+ smincol = max(s->_begx, d->_begx) - s->_begx;
+ dminrow = max(s->_begy, d->_begy) - d->_begy;
+ dmincol = max(s->_begx, d->_begx) - d->_begx;
+ dmaxrow = min(s->_maxy+s->_begy, d->_maxy+d->_begy) - d->_begy;
+ dmaxcol = min(s->_maxx+s->_begx, d->_maxx+d->_begx) - d->_begx;
+
+ copywin(s, d, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, flag);
+}
+
+/*
+**
+** overlay(win1, win2)
+**
+**
+** overlay() writes the overlapping area of win1 behind win2
+** on win2 non-destructively.
+**
+**/
+
+int overlay(WINDOW *win1, WINDOW *win2)
+{
+ overlap(win1, win2, TRUE);
+ return OK;
+}
+
+/*
+**
+** overwrite(win1, win2)
+**
+**
+** overwrite() writes the overlapping area of win1 behind win2
+** on win2 destructively.
+**
+**/
+
+int overwrite(WINDOW *win1, WINDOW *win2)
+{
+ overlap(win1, win2, FALSE);
+ return OK;
+}
+
+int copywin(WINDOW *src, WINDOW *dst,
+ int sminrow, int smincol,
+ int dminrow, int dmincol, int dmaxrow, int dmaxcol,
+ int over)
+{
+int sx, sy, dx, dy;
+
+ T(("copywin(%x, %x, %d, %d, %d, %d, %d, %d, %d)",
+ src, dst, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, over));
+
+ /* make sure rectangle exists in source */
+ if ((sminrow + dmaxrow - dminrow) > (src->_maxy + 1) ||
+ (smincol + dmaxcol - dmincol) > (src->_maxx + 1)) {
+ return ERR;
+ }
+
+ T(("rectangle exists in source"));
+
+ /* make sure rectangle fits in destination */
+ if (dmaxrow > dst->_maxy || dmaxcol > dst->_maxx) {
+ return ERR;
+ }
+
+ T(("rectangle fits in destination"));
+
+ for (dy = dminrow, sy = sminrow; dy <= dmaxrow; sy++, dy++) {
+ dst->_firstchar[dy] = dmincol;
+ dst->_lastchar[dy] = dmincol;
+ for (dx = dmincol, sx = smincol; dx <= dmaxcol; sx++, dx++) {
+ if (over == TRUE ) {
+ if (((src->_line[sy][sx] & A_CHARTEXT) != ' ') && (dst->_line[dy][dx] != src->_line[sy][sx])) {
+ dst->_line[dy][dx] = src->_line[sy][sx];
+ dst->_lastchar[dy] = dx;
+ } else
+ dst->_firstchar[dy]++;
+ } else {
+ if (dst->_line[dy][dx] != src->_line[sy][sx]) {
+ dst->_line[dy][dx] = src->_line[sy][sx];
+ dst->_lastchar[dy] = dx;
+ } else
+ dst->_firstchar[dy]++;
+ }
+ }
+ }
+ T(("finished copywin"));
+ return OK;
+}
diff --git a/lib/libncurses/lib_pad.c b/lib/libncurses/lib_pad.c
new file mode 100644
index 0000000..5b4aa99
--- /dev/null
+++ b/lib/libncurses/lib_pad.c
@@ -0,0 +1,143 @@
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+ * lib_pad.c
+ * newpad -- create a new pad
+ * pnoutrefresh -- refresh a pad, no update
+ * pechochar -- add a char to a pad and refresh
+ */
+
+#include <stdlib.h>
+#include "curses.priv.h"
+
+WINDOW *newpad(int l, int c)
+{
+WINDOW *win;
+chtype *ptr;
+int i, j;
+
+ T(("newpad(%d, %d) called", l, c));
+
+ if (l <= 0 || c <= 0)
+ return NULL;
+
+ if ((win = makenew(l,c,0,0)) == NULL)
+ return NULL;
+
+ win->_flags |= _ISPAD;
+
+ for (i = 0; i < l; i++) {
+ if ((win->_line[i] = (chtype *) calloc(c, sizeof(chtype))) == NULL) {
+ for (j = 0; j < i; j++)
+ free(win->_line[j]);
+
+ free(win->_firstchar);
+ free(win->_lastchar);
+ free(win->_line);
+ free(win);
+
+ return NULL;
+ }
+ else
+ for (ptr = win->_line[i]; ptr < win->_line[i] + c; )
+ *ptr++ = ' ';
+ }
+
+ T(("newpad: returned window is %x", win));
+
+ return(win);
+}
+
+int prefresh(WINDOW *win, int pminrow, int pmincol,
+ int sminrow, int smincol, int smaxrow, int smaxcol)
+{
+ T(("prefresh() called"));
+ if (pnoutrefresh(win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol) != ERR)
+ return (doupdate());
+ else
+ return ERR;
+
+}
+
+int pnoutrefresh(WINDOW *win, int pminrow, int pmincol,
+ int sminrow, int smincol, int smaxrow, int smaxcol)
+{
+int i, j;
+int m, n;
+
+ T(("pnoutrefresh(%x, %d, %d, %d, %d, %d, %d) called",
+ win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol));
+
+ if (!(win->_flags & _ISPAD))
+ return ERR;
+
+ T(("one"));
+ if (pminrow < 0) pminrow = 0;
+ if (pmincol < 0) pmincol = 0;
+ if (sminrow < 0) sminrow = 0;
+ if (smincol < 0) smincol = 0;
+
+ T(("two"));
+ if (smaxrow >= LINES || smaxcol >= COLS)
+ return ERR;
+
+ T(("three"));
+ if ((pminrow + smaxrow - sminrow > win->_maxy) ||
+ (pmincol + smaxcol - smincol > win->_maxx))
+ return ERR;
+
+ T(("pad being refreshed"));
+
+ for (i = pminrow, m = sminrow; i <= pminrow + smaxrow-sminrow;
+ i++, m++) {
+ for (j = pmincol, n = smincol; j <= pmincol + smaxcol-smincol;
+ j++, n++) {
+ if (win->_line[i][j] != newscr->_line[m][n]) {
+ newscr->_line[m][n] = win->_line[i][j];
+
+ if (newscr->_firstchar[m] == _NOCHANGE)
+ newscr->_firstchar[m] = newscr->_lastchar[m] = n;
+ else if (n < newscr->_firstchar[m])
+ newscr->_firstchar[m] = n;
+ else if (n > newscr->_lastchar[m])
+ newscr->_lastchar[m] = n;
+ }
+ }
+ }
+
+ win->_firstchar[i] = win->_lastchar[i] = _NOCHANGE;
+
+ win->_begx = smincol;
+ win->_begy = sminrow;
+
+ if (win->_clear) {
+ win->_clear = FALSE;
+ newscr->_clear = TRUE;
+ }
+
+ if (! win->_leave) {
+ newscr->_cury = win->_cury + win->_begy;
+ newscr->_curx = win->_curx + win->_begx;
+ }
+ return OK;
+}
+
+int pechochar(WINDOW *pad, chtype ch)
+{
+int x, y;
+
+ T(("echochar(%x, %x)", pad, ch));
+
+ if (pad->_flags & _ISPAD)
+ return ERR;
+
+ x = pad->_begx + pad->_curx;
+ y = pad->_begy + pad->_cury;
+
+ waddch(curscr, ch);
+ doupdate();
+ return OK;
+}
+
diff --git a/lib/libncurses/lib_printw.c b/lib/libncurses/lib_printw.c
new file mode 100644
index 0000000..236c29a
--- /dev/null
+++ b/lib/libncurses/lib_printw.c
@@ -0,0 +1,75 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_printw.c
+**
+** The routines printw(), wprintw() and friends.
+**
+*/
+
+#include "curses.priv.h"
+
+int printw(char *fmt, ...)
+{
+va_list argp;
+char buf[BUFSIZ];
+
+ T(("printw(\"%s\",...) called", fmt));
+
+ va_start(argp, fmt);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+ return(waddstr(stdscr, buf));
+}
+
+
+
+int wprintw(WINDOW *win, char *fmt, ...)
+{
+va_list argp;
+char buf[BUFSIZ];
+
+ T(("wprintw(%x,\"%s\",...) called", win, fmt));
+
+ va_start(argp, fmt);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+ return(waddstr(win, buf));
+}
+
+
+
+int mvprintw(int y, int x, char *fmt, ...)
+{
+va_list argp;
+char buf[BUFSIZ];
+
+ va_start(argp, fmt);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+ return(move(y, x) == OK ? waddstr(stdscr, buf) : ERR);
+}
+
+
+
+int mvwprintw(WINDOW *win, int y, int x, char *fmt, ...)
+{
+va_list argp;
+char buf[BUFSIZ];
+
+ va_start(argp, fmt);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+ return(wmove(win, y, x) == OK ? waddstr(win, buf) : ERR);
+}
+
+int vwprintw(WINDOW *win, char *fmt, va_list argp)
+{
+char buf[BUFSIZ];
+
+ vsprintf(buf, fmt, argp);
+ return(waddstr(win, buf));
+}
diff --git a/lib/libncurses/lib_raw.c b/lib/libncurses/lib_raw.c
new file mode 100644
index 0000000..fac726e
--- /dev/null
+++ b/lib/libncurses/lib_raw.c
@@ -0,0 +1,201 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+ * raw.c
+ *
+ * Routines:
+ * raw()
+ * echo()
+ * nl()
+ * cbreak()
+ * noraw()
+ * noecho()
+ * nonl()
+ * nocbreak()
+ *
+ */
+
+#include "curses.priv.h"
+#include "terminfo.h"
+
+#ifdef TERMIOS
+static tcflag_t iexten = 0;
+#endif
+
+int raw()
+{
+ T(("raw() called"));
+
+ SP->_raw = TRUE;
+ SP->_cbreak = TRUE;
+ SP->_nlmapping = TRUE;
+
+#ifdef TERMIOS
+ if(iexten == 0)
+ iexten = cur_term->Nttyb.c_lflag & IEXTEN;
+ cur_term->Nttyb.c_lflag &= ~(ICANON|ISIG|iexten);
+ cur_term->Nttyb.c_iflag &= ~(INPCK|ISTRIP|IXON);
+ cur_term->Nttyb.c_oflag &= ~(OPOST);
+ cur_term->Nttyb.c_cc[VMIN] = 1;
+ cur_term->Nttyb.c_cc[VTIME] = 0;
+ if((tcsetattr(cur_term->Filedes, TCSANOW, &cur_term->Nttyb)) == -1)
+ return ERR;
+ else
+ return OK;
+#else
+ cur_term->Nttyb.sg_flags |= RAW;
+ stty(cur_term->Filedes, &cur_term->Nttyb);
+ return OK;
+#endif
+}
+
+int cbreak()
+{
+ T(("cbreak() called"));
+
+ SP->_cbreak = 1;
+
+#ifdef TERMIOS
+ cur_term->Nttyb.c_lflag &= ~ICANON;
+ cur_term->Nttyb.c_lflag |= ISIG;
+ cur_term->Nttyb.c_cc[VMIN] = 1;
+ cur_term->Nttyb.c_cc[VTIME] = 0;
+ if((tcsetattr(cur_term->Filedes, TCSANOW, &cur_term->Nttyb)) == -1)
+ return ERR;
+ else
+ return OK;
+#else
+ cur_term->Nttyb.sg_flags |= CBREAK;
+ stty(cur_term->Filedes, &cur_term->Nttyb);
+ return OK;
+#endif
+}
+
+int echo()
+{
+ T(("echo() called"));
+
+ SP->_echo = TRUE;
+
+#ifdef TERMIOS
+ cur_term->Nttyb.c_lflag |= ECHO;
+ if((tcsetattr(cur_term->Filedes, TCSANOW, &cur_term->Nttyb)) == -1)
+ return ERR;
+ else
+ return OK;
+#else
+ cur_term->Nttyb.sg_flags |= ECHO;
+ stty(cur_term->Filedes, &cur_term->Nttyb);
+ return OK;
+#endif
+}
+
+
+int nl()
+{
+ T(("nl() called"));
+
+ SP->_nl = TRUE;
+ SP->_nlmapping = ! SP->_raw;
+
+#ifdef TERMIOS
+ cur_term->Nttyb.c_iflag |= IXON|ICRNL|IXOFF;
+ cur_term->Nttyb.c_oflag |= OPOST|ONLCR;
+ if((tcsetattr(cur_term->Filedes, TCSANOW, &cur_term->Nttyb)) == -1)
+ return ERR;
+ else
+ return OK;
+#else
+ cur_term->Nttyb.sg_flags |= CRMOD;
+ stty(cur_term->Filedes, &cur_term->Nttyb);
+ return OK;
+#endif
+}
+
+
+int noraw()
+{
+ T(("noraw() called"));
+
+ SP->_raw = FALSE;
+ SP->_cbreak = FALSE;
+ SP->_nlmapping = SP->_nl;
+
+#ifdef TERMIOS
+ cur_term->Nttyb.c_lflag |= ISIG|ICANON|iexten;
+ cur_term->Nttyb.c_iflag |= IXON;
+ cur_term->Nttyb.c_oflag |= OPOST;
+ if((tcsetattr(cur_term->Filedes, TCSANOW, &cur_term->Nttyb)) == -1)
+ return ERR;
+ else
+ return OK;
+#else
+ cur_term->Nttyb.sg_flags &= ~(RAW|CBREAK);
+ stty(cur_term->Filedes, &cur_term->Nttyb);
+ return OK;
+#endif
+
+}
+
+
+int nocbreak()
+{
+ T(("nocbreak() called"));
+
+ SP->_cbreak = 0;
+
+#ifdef TERMIOS
+ cur_term->Nttyb.c_lflag |= ICANON;
+ if((tcsetattr(cur_term->Filedes, TCSANOW, &cur_term->Nttyb)) == -1)
+ return ERR;
+ else
+ return OK;
+#else
+ cur_term->Nttyb.sg_flags &= ~CBREAK;
+ stty(cur_term->Filedes, &cur_term->Nttyb);
+ return OK;
+#endif
+}
+
+int noecho()
+{
+ T(("noecho() called"));
+
+ SP->_echo = FALSE;
+
+#ifdef TERMIOS
+ cur_term->Nttyb.c_lflag &= ~(ECHO);
+ if((tcsetattr(cur_term->Filedes, TCSANOW, &cur_term->Nttyb)) == -1)
+ return ERR;
+ else
+ return OK;
+#else
+ cur_term->Nttyb.sg_flags &= ~ECHO;
+ stty(cur_term->Filedes, &cur_term->Nttyb);
+ return OK;
+#endif
+}
+
+
+int nonl()
+{
+ T(("nonl() called"));
+
+ SP->_nl = SP->_nlmapping = FALSE;
+
+#ifdef TERMIOS
+ cur_term->Nttyb.c_iflag &= ~ICRNL;
+ cur_term->Nttyb.c_oflag &= ~ONLCR;
+ if((tcsetattr(cur_term->Filedes, TCSANOW, &cur_term->Nttyb)) == -1)
+ return ERR;
+ else
+ return OK;
+#else
+ cur_term->Nttyb.sg_flags &= ~CRMOD;
+ stty(cur_term->Filedes, &cur_term->Nttyb);
+ return OK;
+#endif
+}
diff --git a/lib/libncurses/lib_refresh.c b/lib/libncurses/lib_refresh.c
new file mode 100644
index 0000000..72ab095
--- /dev/null
+++ b/lib/libncurses/lib_refresh.c
@@ -0,0 +1,74 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+ * lib_refresh.c
+ *
+ * The routines wredrawln(), wrefresh() and wnoutrefresh().
+ *
+ */
+
+#include "curses.priv.h"
+
+int wredrawln(WINDOW *win, int beg, int num)
+{
+ T(("wredrawln(%x,%d,%d) called", win, beg, num));
+ touchline(win, beg, num);
+ wrefresh(win);
+ return OK;
+}
+
+int wrefresh(WINDOW *win)
+{
+ T(("wrefresh(%x) called", win));
+
+ if (win == curscr)
+ curscr->_clear = TRUE;
+ else
+ wnoutrefresh(win);
+ return(doupdate());
+}
+
+int wnoutrefresh(WINDOW *win)
+{
+int i, j;
+int begx = win->_begx;
+int begy = win->_begy;
+int m, n;
+
+ T(("wnoutrefresh(%x) called", win));
+
+ win->_flags &= ~_HASMOVED;
+ for (i = 0, m = begy; i <= win->_maxy; i++, m++) {
+ if (win->_firstchar[i] != _NOCHANGE) {
+ j = win->_firstchar[i];
+ n = j + begx;
+ for (; j <= win->_lastchar[i]; j++, n++) {
+ if (win->_line[i][j] != newscr->_line[m][n]) {
+ newscr->_line[m][n] = win->_line[i][j];
+
+ if (newscr->_firstchar[m] == _NOCHANGE)
+ newscr->_firstchar[m] = newscr->_lastchar[m] = n;
+ else if (n < newscr->_firstchar[m])
+ newscr->_firstchar[m] = n;
+ else if (n > newscr->_lastchar[m])
+ newscr->_lastchar[m] = n;
+ }
+ }
+ }
+ win->_firstchar[i] = win->_lastchar[i] = _NOCHANGE;
+ }
+
+ if (win->_clear) {
+ win->_clear = FALSE;
+ newscr->_clear = TRUE;
+ }
+
+ if (! win->_leave) {
+ newscr->_cury = win->_cury + win->_begy;
+ newscr->_curx = win->_curx + win->_begx;
+ }
+ return(OK);
+}
diff --git a/lib/libncurses/lib_scanw.c b/lib/libncurses/lib_scanw.c
new file mode 100644
index 0000000..69b5a33
--- /dev/null
+++ b/lib/libncurses/lib_scanw.c
@@ -0,0 +1,66 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_scanw.c
+**
+** The routines scanw(), wscanw() and friends.
+**
+*/
+
+#include <stdio.h>
+#include "curses.priv.h"
+
+int vwscanw(WINDOW *win, char *fmt, va_list argp)
+{
+char buf[BUFSIZ];
+
+ if (wgetstr(win, buf) == ERR)
+ return(ERR);
+
+ return(vsscanf(buf, fmt, argp));
+}
+
+int scanw(char *fmt, ...)
+{
+va_list ap;
+
+ T(("scanw(\"%s\",...) called", fmt));
+
+ va_start(ap, fmt);
+ return(vwscanw(stdscr, fmt, ap));
+}
+
+int wscanw(WINDOW *win, char *fmt, ...)
+{
+va_list ap;
+
+ T(("wscanw(%x,\"%s\",...) called", win, fmt));
+
+ va_start(ap, fmt);
+ return(vwscanw(win, fmt, ap));
+}
+
+
+
+int mvscanw(int y, int x, char *fmt, ...)
+{
+va_list ap;
+
+ va_start(ap, fmt);
+ return(move(y, x) == OK ? vwscanw(stdscr, fmt, ap) : ERR);
+}
+
+
+
+int mvwscanw(WINDOW *win, int y, int x, char *fmt, ...)
+{
+va_list ap;
+
+ va_start(ap, fmt);
+ return(wmove(win, y, x) == OK ? vwscanw(win, fmt, ap) : ERR);
+}
+
+
diff --git a/lib/libncurses/lib_screen.c b/lib/libncurses/lib_screen.c
new file mode 100644
index 0000000..382411b
--- /dev/null
+++ b/lib/libncurses/lib_screen.c
@@ -0,0 +1,58 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+#included "curses.priv.h"
+
+int putwin(WINDOW *win, char *file)
+{
+int fd, i;
+
+ fd = open(file, O_WRONLY);
+ if (fd < -1)
+ return ERR;
+ for (i = 0; i < lines; i++)
+ write(fd, win->_line[i], sizeof(chtype)*columns);
+ close(fd);
+ return OK;
+}
+
+int scr_restore(char *file)
+{
+int fd, i;
+
+ fd = open(file, O_RDONLY);
+ if (fd < -1)
+ return ERR;
+ for (i = 0; i < lines; i++)
+ read(fd, curscr->_line[i], sizeof(chtype)*columns);
+ touchwin(curscr);
+ close(fd);
+ return OK;
+}
+
+int scr_dump(char *file)
+{
+
+ putwin(curscr, file);
+}
+
+int scr_init(char *file)
+{
+
+ return ERR;
+}
+
+int scr_set(char *file)
+{
+
+ return ERR;
+}
+
+WINDOW *getwin(FILE *filep)
+{
+
+ return NULL;
+}
+
diff --git a/lib/libncurses/lib_scroll.c b/lib/libncurses/lib_scroll.c
new file mode 100644
index 0000000..1721a3f
--- /dev/null
+++ b/lib/libncurses/lib_scroll.c
@@ -0,0 +1,201 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_scroll.c
+**
+** The routine wscrl(win, n).
+** positive n scroll the window up (ie. move lines down)
+** negative n scroll the window down (ie. move lines up)
+**
+*/
+
+#include <stdlib.h>
+#include "curses.priv.h"
+#include "terminfo.h"
+
+void scroll_window(WINDOW *win, int n, int regtop, int regbottom)
+{
+int line, i;
+chtype *ptr, *temp;
+chtype **saved;
+chtype blank = ' ';
+
+ saved = (chtype **)malloc(sizeof(chtype *) * abs(n));
+
+ if (n < 0) {
+ /* save overwritten lines */
+
+ for (i = 0; i < -n; i++)
+ saved[i] = win->_line[regbottom-i];
+
+ /* shift n lines */
+
+ for (line = regbottom; line >= regtop-n; line--)
+ win->_line[line] = win->_line[line+n];
+
+ /* restore saved lines and blank them */
+
+ for (i = 0, line = regtop; line < regtop-n; line++, i++) {
+ win->_line[line] = saved[i];
+ temp = win->_line[line];
+ for (ptr = temp; ptr - temp <= win->_maxx; ptr++)
+ *ptr = blank;
+ }
+ } else {
+ /* save overwritten lines */
+
+ for (i = 0; i < n; i++)
+ saved[i] = win->_line[regtop+i];
+
+ /* shift n lines */
+
+ for (line = regtop; line <= regbottom-n; line++)
+ win->_line[line] = win->_line[line+n];
+
+ /* restore saved lines and blank them */
+
+ for (i = 0, line = regbottom; line > regbottom - n; line--, i++) {
+ win->_line[line] = saved[i];
+ temp = win->_line[line];
+ for (ptr = temp; ptr - temp <= win->_maxx; ptr++)
+ *ptr = blank;
+ }
+ }
+
+ free(saved);
+}
+
+int
+wscrl(WINDOW *win, int n)
+{
+int physical = FALSE;
+int i;
+
+ T(("wscrl(%x,%d) called", win, n));
+
+ if (! win->_scroll)
+ return ERR;
+
+ if (n == 0)
+ return OK;
+
+ /* as an optimization, if the scrolling region is the entire screen
+ scroll the physical screen */
+
+ if ( win->_begx == 0 && win->_maxx == columns - 1
+ && !memory_above && !memory_below
+ && ((((win->_begy+win->_regtop == 0 && win->_begy+win->_regbottom == lines - 1)
+ || change_scroll_region)
+ && ( (n < 0 && (parm_rindex || scroll_reverse))
+ || (n > 0 && (parm_index || scroll_forward))
+ )
+ ) || (win->_idlok && (parm_insert_line || insert_line)
+ && (parm_delete_line || delete_line)
+ )
+ )
+ )
+ physical = TRUE;
+
+ if (physical == TRUE) {
+ wrefresh(win);
+ scroll_window(curscr, n, win->_begy+win->_regtop, win->_begy+win->_regbottom);
+ scroll_window(newscr, n, win->_begy+win->_regtop, win->_begy+win->_regbottom);
+ }
+ scroll_window(win, n, win->_regtop, win->_regbottom);
+
+ if (physical == TRUE) {
+ if (n < 0) {
+ if ( (( win->_begy+win->_regtop == 0
+ && win->_begy+win->_regbottom == lines - 1)
+ || change_scroll_region)
+ && (parm_rindex || scroll_reverse)
+ ) {
+ if (change_scroll_region &&
+ (win->_begy+win->_regtop != 0 || win->_begy+win->_regbottom != lines - 1)
+ )
+ putp(tparm(change_scroll_region, win->_begy+win->_regtop, win->_begy+win->_regbottom));
+ i = abs(n);
+ mvcur(-1, -1, win->_begy+win->_regtop, 0);
+ if (parm_rindex) {
+ putp(tparm(parm_rindex, i));
+ } else if (scroll_reverse) {
+ while (i--)
+ putp(scroll_reverse);
+ }
+ if (change_scroll_region &&
+ (win->_begy+win->_regtop != 0 || win->_begy+win->_regbottom != lines - 1)
+ )
+ putp(tparm(change_scroll_region, 0, lines-1));
+ } else {
+ i = abs(n);
+ if (win->_begy+win->_regbottom < lines - 1) {
+ mvcur(-1, -1, win->_begy+win->_regbottom, 0);
+ if (parm_delete_line) {
+ putp(tparm(parm_delete_line, i));
+ } else if (delete_line) {
+ while (i--)
+ putp(delete_line);
+ i = abs(n);
+ }
+ }
+ mvcur(-1, -1, win->_begy+win->_regtop, 0);
+ if (parm_insert_line) {
+ putp(tparm(parm_insert_line, i));
+ } else if (insert_line) {
+ while (i--)
+ putp(insert_line);
+ }
+ }
+ } else {
+ if ( (( win->_begy+win->_regtop == 0
+ && win->_begy+win->_regbottom == lines - 1)
+ || change_scroll_region)
+ && (parm_index || scroll_forward)
+ ) {
+ if (change_scroll_region &&
+ (win->_begy+win->_regtop != 0 || win->_begy+win->_regbottom != lines - 1)
+ )
+ putp(tparm(change_scroll_region, win->_begy+win->_regtop, win->_begy+win->_regbottom));
+ mvcur(-1, -1, win->_begy+win->_regbottom, 0);
+ if (parm_index) {
+ putp(tparm(parm_index, n));
+ } else if (scroll_forward) {
+ i = n;
+ while (i--)
+ putp(scroll_forward);
+ }
+ if (change_scroll_region &&
+ (win->_begy+win->_regtop != 0 || win->_begy+win->_regbottom != lines - 1)
+ )
+ putp(tparm(change_scroll_region, 0, lines-1));
+ } else {
+ mvcur(-1, -1, win->_begy+win->_regtop, 0);
+ if (parm_delete_line) {
+ putp(tparm(parm_delete_line, n));
+ } else if (delete_line) {
+ i = n;
+ while (i--)
+ putp(delete_line);
+ }
+ if (win->_begy+win->_regbottom < lines - 1) {
+ mvcur(win->_begy+win->_regtop, 0, win->_begy+win->_regbottom, 0);
+ if (parm_insert_line) {
+ putp(tparm(parm_insert_line, n));
+ } else if (insert_line) {
+ i = n;
+ while (i--)
+ putp(insert_line);
+ }
+ }
+ }
+ }
+
+ mvcur(-1, -1, win->_begy+win->_cury, win->_begx+win->_curx);
+ } else
+ touchline(win, win->_regtop, win->_regbottom - win->_regtop + 1);
+
+ return OK;
+}
diff --git a/lib/libncurses/lib_scrreg.c b/lib/libncurses/lib_scrreg.c
new file mode 100644
index 0000000..31bab4f
--- /dev/null
+++ b/lib/libncurses/lib_scrreg.c
@@ -0,0 +1,32 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_scrreg.c
+**
+** The routine wsetscrreg().
+**
+*/
+
+#include "curses.priv.h"
+#include "terminfo.h"
+
+int wsetscrreg(WINDOW *win, int top, int bottom)
+{
+ T(("wsetscrreg(%x,%d,%d) called", win, top, bottom));
+
+ if (top >= 0 && top <= win->_maxy &&
+ bottom >= 0 && bottom <= win->_maxy &&
+ bottom > top)
+ {
+ win->_regtop = top;
+ win->_regbottom = bottom;
+
+ T(("correctly set scrolling region between %d and %d", top, bottom));
+
+ return(OK);
+ } else
+ return(ERR);
+}
diff --git a/lib/libncurses/lib_set_term.c b/lib/libncurses/lib_set_term.c
new file mode 100644
index 0000000..bc73ca3
--- /dev/null
+++ b/lib/libncurses/lib_set_term.c
@@ -0,0 +1,33 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_set_term.c
+**
+** The routine set_term().
+**
+*/
+
+#include "curses.priv.h"
+#include "terminfo.h"
+
+struct screen *
+set_term(screen)
+struct screen *screen;
+{
+struct screen *oldSP;
+
+ T(("set_term(%o) called", screen));
+
+ oldSP = SP;
+ SP = screen;
+
+ cur_term = SP->_term;
+ curscr = SP->_curscr;
+ newscr = SP->_newscr;
+ stdscr = SP->_stdscr;
+
+ return(oldSP);
+}
diff --git a/lib/libncurses/lib_slk.c b/lib/libncurses/lib_slk.c
new file mode 100644
index 0000000..5d59c69
--- /dev/null
+++ b/lib/libncurses/lib_slk.c
@@ -0,0 +1,251 @@
+
+/*
+ * lib_slk.c
+ * Soft key routines.
+ *
+ * Copyright (C) Gerhard Fuernkranz 1993
+ * Permisson is granted to redistribute this
+ * code under the terms of the GNU Copyleft.
+ */
+
+#include "terminfo.h"
+#include "curses.priv.h"
+#include <string.h>
+#include <stdlib.h>
+
+int _slk_format; /* format specified in slk_init() */
+
+#define MAXCOLUMNS 135
+#define MAXLINES 66
+#define UNINITIALISED ((struct try * ) -1)
+/*
+ * Retrieve label text.
+ */
+
+char *
+slk_label(int n)
+{
+SLK *slk = SP->_slk;
+
+ T(("slk_label(%d)", n));
+
+ if (slk == NULL || n < 1 || n > 8)
+ return NULL;
+ return slk->ent[n-1].text;
+}
+
+/*
+ * Write the soft lables to the slk window.
+ */
+
+static void
+slk_intern_refresh(SLK *slk)
+{
+int i;
+ T(("slk_intern_refresh(%x)", slk));
+
+ for (i = 0; i < 8; i++) {
+ if (slk->dirty || slk->ent[i].dirty) {
+ if (slk->ent[i].visible) {
+ wmove(slk->win,0,slk->ent[i].x);
+ wattrset(slk->win,A_REVERSE);
+ waddstr(slk->win,slk->ent[i].form_text);
+ wattrset(slk->win,A_NORMAL);
+ }
+ slk->ent[i].dirty = FALSE;
+ }
+ }
+ slk->dirty = FALSE;
+}
+
+/*
+ * Refresh the soft label window.
+ */
+
+int
+slk_noutrefresh(void)
+{
+SLK *slk = SP->_slk;
+
+ T(("slk_noutrefresh()"));
+
+ if (slk == NULL)
+ return ERR;
+ if (slk->hidden)
+ return OK;
+ slk_intern_refresh(slk);
+ return wnoutrefresh(slk->win);
+}
+
+/*
+ * Refresh the soft label window.
+ */
+
+int
+slk_refresh(void)
+{
+SLK *slk = SP->_slk;
+
+ T(("slk_refresh()"));
+
+ if (slk == NULL)
+ return ERR;
+ if (slk->hidden)
+ return OK;
+ slk_intern_refresh(slk);
+ return wrefresh(slk->win);
+}
+
+/*
+ * Restore the soft labels on the screen.
+ */
+
+int
+slk_restore(void)
+{
+SLK *slk = SP->_slk;
+
+ T(("slk_restore()"));
+
+ if (slk == NULL)
+ return ERR;
+ slk->hidden = FALSE;
+ slk->dirty = TRUE;
+ return slk_refresh();
+}
+
+/*
+ * Set soft label text.
+ */
+
+int
+slk_set(int i, char *str, int format)
+{
+SLK *slk = SP->_slk;
+int len;
+ T(("slk_set(%d, \"%s\", %d)", i, str, format));
+
+ if (slk == NULL || i < 1 || i > 8 || format < 0 || format > 2)
+ return ERR;
+ if (str == NULL)
+ str = "";
+ i--;
+ strncpy(slk->ent[i].text,str,8);
+ memset(slk->ent[i].form_text,' ',8);
+ slk->ent[i].text[8] = 0;
+ slk->ent[i].form_text[8] = 0;
+ len = strlen(slk->ent[i].text);
+ switch(format) {
+ case 0: /* left */
+ memcpy(slk->ent[i].form_text,slk->ent[i].text,len);
+ break;
+ case 1: /* center */
+ memcpy(slk->ent[i].form_text+(8-len)/2,slk->ent[i].text,len);
+ break;
+ case 2: /* right */
+ memcpy(slk->ent[i].form_text+8-len,slk->ent[i].text,len);
+ break;
+ }
+ slk->ent[i].dirty = TRUE;
+ return OK;
+}
+
+/*
+ * Pretend, that soft keys have been changed.
+ */
+
+int
+slk_touch(void)
+{
+SLK *slk = SP->_slk;
+ T(("slk_touch()"));
+
+ if (slk == NULL)
+ return ERR;
+ slk->dirty = TRUE;
+ return OK;
+}
+
+/*
+ * Remove soft labels from the screen.
+ */
+
+int
+slk_clear(void)
+{
+SLK *slk = SP->_slk;
+
+ T(("slk_clear()"));
+
+ if (slk == NULL)
+ return ERR;
+ slk->hidden = TRUE;
+ werase(slk->win);
+ return wrefresh(slk->win);
+}
+
+/*
+ * Initialize soft labels.
+ * Called from newterm()
+ */
+
+static int
+slk_initialize(WINDOW *stwin, int cols)
+{
+SLK *slk;
+int i, maxlab, x;
+
+ T(("slk_initialize()"));
+
+ if ((SP->_slk = slk = (SLK*) calloc(1,sizeof(SLK))) == NULL)
+ return OK;
+ maxlab = (cols+1)/9;
+ for (i = 0; i < 8; i++) {
+ memset(slk->ent[i].form_text,' ',8);
+ slk->ent[i].visible = i < maxlab;
+ }
+ if (_slk_format == 1) { /* 4-4 */
+ int gap = cols - 64 - 6;
+ if (gap < 1)
+ gap = 1;
+ for (i = x = 0; i < 8; i++) {
+ slk->ent[i].x = x;
+ x += 8;
+ x += (i == 3) ? gap : 1;
+ }
+ }
+ else { /* 0 -> 3-2-3 */
+ int gap = (cols - 64 - 5) / 2;
+ if (gap < 1)
+ gap = 1;
+ for (i = x = 0; i < 8; i++) {
+ slk->ent[i].x = x;
+ x += 8;
+ x += (i == 2 || i == 4) ? gap : 1;
+ }
+ }
+ slk->dirty = TRUE;
+ if ((slk->win = stwin) == NULL)
+ {
+ free(slk);
+ return ERR;
+ }
+
+ return OK;
+}
+
+/*
+ * Initialize soft labels.
+ * Called by the user.
+ */
+
+int
+slk_init(int format)
+{
+ if (format < 0 || format > 1)
+ return ERR;
+ _slk_format = format;
+ ripoffline(-1, slk_initialize);
+ return OK;
+}
+
diff --git a/lib/libncurses/lib_touch.c b/lib/libncurses/lib_touch.c
new file mode 100644
index 0000000..4d291b3
--- /dev/null
+++ b/lib/libncurses/lib_touch.c
@@ -0,0 +1,48 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_touch.c
+**
+** The routines untouchwin(),
+** wtouchln(),
+** is_linetouched()
+** is_wintouched().
+**
+*/
+
+#include "curses.priv.h"
+
+int is_linetouched(WINDOW *win, int line)
+{
+ if (line > win->_maxy || line < 0)
+ return ERR;
+ if (win->_firstchar[line] != _NOCHANGE) return TRUE;
+ return FALSE;
+}
+
+int is_wintouched(WINDOW *win)
+{
+int i;
+
+ for (i = 0; i <= win->_maxy; i++)
+ if (win->_firstchar[i] != _NOCHANGE)
+ return TRUE;
+ return FALSE;
+}
+
+int wtouchln(WINDOW *win, int y, int n, int changed)
+{
+int i;
+
+ T(("wtouchln(%x,%d,%d,%d)", win, y, n, changed));
+
+ for (i = y; i < y+n; i++) {
+ win->_firstchar[i] = changed ? 0 : _NOCHANGE;
+ win->_lastchar[i] = changed ? win->_maxx : _NOCHANGE;
+ }
+ return OK;
+}
+
diff --git a/lib/libncurses/lib_trace.c b/lib/libncurses/lib_trace.c
new file mode 100644
index 0000000..3a66467
--- /dev/null
+++ b/lib/libncurses/lib_trace.c
@@ -0,0 +1,179 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+ * lib_trace.c - Tracing/Debugging routines
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "curses.priv.h"
+#include "terminfo.h"
+
+#if defined(BRAINDEAD)
+extern int errno;
+#endif
+
+int _tracing = 0;
+
+static int tracefd;
+
+void _tracef(char *fmt, ...);
+
+void _init_trace()
+{
+static int been_here = 0;
+
+ if (! been_here) {
+ been_here = 1;
+
+ if ((tracefd = creat("trace", 0644)) < 0) {
+ write(2, "curses: Can't open 'trace' file: ", 33);
+ write(2, strerror(errno), strlen(strerror(errno)));
+ write(2, "\n", 1);
+ exit(1);
+ }
+ _tracef("TRACING NCURSES version %s", NCURSES_VERSION);
+ }
+}
+
+
+void trace(const unsigned int tracelevel)
+{
+ _tracing = tracelevel;
+}
+
+
+char *_traceattr(int newmode)
+{
+static char buf[BUFSIZ];
+struct {unsigned int val; char *name;}
+names[] =
+ {
+ {A_STANDOUT, "A_STANDOUT, ",},
+ {A_UNDERLINE, "A_UNDERLINE, ",},
+ {A_REVERSE, "A_REVERSE, ",},
+ {A_BLINK, "A_BLINK, ",},
+ {A_DIM, "A_DIM, ",},
+ {A_BOLD, "A_BOLD, ",},
+ {A_ALTCHARSET, "A_ALTCHARSET, ",},
+ {A_INVIS, "A_INVIS, ",},
+ {A_PROTECT, "A_PROTECT, ",},
+ {A_CHARTEXT, "A_CHARTEXT, ",},
+ {A_NORMAL, "A_NORMAL, ",},
+ },
+colors[] =
+ {
+ {COLOR_BLACK, "COLOR_BLACK",},
+ {COLOR_RED, "COLOR_RED",},
+ {COLOR_GREEN, "COLOR_GREEN",},
+ {COLOR_YELLOW, "COLOR_YELLOW",},
+ {COLOR_BLUE, "COLOR_BLUE",},
+ {COLOR_MAGENTA, "COLOR_MAGENTA",},
+ {COLOR_CYAN, "COLOR_CYAN",},
+ {COLOR_WHITE, "COLOR_WHITE",},
+ },
+ *sp;
+
+ strcpy(buf, "{");
+ for (sp = names; sp->val; sp++)
+ if (newmode & sp->val)
+ strcat(buf, sp->name);
+ if (newmode & A_COLOR)
+ {
+ int pairnum = PAIR_NUMBER(newmode);
+
+ (void) sprintf(buf + strlen(buf),
+ "COLOR_PAIR(%d) = (%s, %s), ",
+ pairnum,
+ colors[FG(color_pairs[pairnum])].name,
+ colors[BG(color_pairs[pairnum])].name
+ );
+ }
+ if ((newmode & A_ATTRIBUTES) == 0)
+ strcat(buf,"A_NORMAL, ");
+ if (buf[strlen(buf) - 2] == ',')
+ buf[strlen(buf) - 2] = '\0';
+ return(strcat(buf,"}"));
+}
+
+char *visbuf(const char *buf)
+/* visibilize a given string */
+{
+ static char vbuf[BUFSIZ];
+ char *tp = vbuf;
+
+ while (*buf)
+ {
+ if (isprint(*buf) || *buf == ' ')
+ *tp++ = *buf++;
+ else if (*buf == '\n')
+ {
+ *tp++ = '\\'; *tp++ = 'n';
+ buf++;
+ }
+ else if (*buf == '\r')
+ {
+ *tp++ = '\\'; *tp++ = 'r';
+ buf++;
+ }
+ else if (*buf == '\b')
+ {
+ *tp++ = '\\'; *tp++ = 'b';
+ buf++;
+ }
+ else if (*buf == '\033')
+ {
+ *tp++ = '\\'; *tp++ = 'e';
+ buf++;
+ }
+ else if (*buf < ' ')
+ {
+ *tp++ = '\\'; *tp++ = '^'; *tp++ = '@' + *buf;
+ buf++;
+ }
+ else
+ {
+ (void) sprintf(tp, "\\0x%02x", *buf++);
+ tp += strlen(tp);
+ }
+ }
+ *tp++ = '\0';
+ return(vbuf);
+}
+
+char *_tracechar(const unsigned char ch)
+{
+ static char crep[20];
+ /*
+ * We can show the actual character if it's either an ordinary printable
+ * or one of the high-half characters.
+ */
+ if (isprint(ch) || (ch & 0x80))
+ {
+ crep[0] = '\'';
+ crep[1] = ch; /* necessary; printf tries too hard on metachars */
+ (void) sprintf(crep + 2, "' = 0x%02x", ch);
+ }
+ else
+ (void) sprintf(crep, "0x%02x", ch);
+ return(crep);
+}
+
+void
+_tracef(char *fmt, ...)
+{
+va_list ap;
+char buffer[256];
+
+ va_start(ap, fmt);
+ vsprintf(buffer, fmt, ap);
+ write(tracefd, buffer, strlen(buffer));
+ write(tracefd, "\n", 1);
+}
+
diff --git a/lib/libncurses/lib_tstp.c b/lib/libncurses/lib_tstp.c
new file mode 100644
index 0000000..4412dcb
--- /dev/null
+++ b/lib/libncurses/lib_tstp.c
@@ -0,0 +1,50 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_tstp.c
+**
+** The routine tstp().
+**
+*/
+
+#include "curses.priv.h"
+#include "terminfo.h"
+#ifdef SVR4_ACTION
+#define _POSIX_SOURCE
+#endif
+#include <signal.h>
+
+void tstp(int dummy)
+{
+sigaction_t act, oact;
+sigset_t mask;
+
+ T(("tstp() called"));
+
+ endwin();
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGTSTP);
+ sigprocmask(SIG_UNBLOCK, &mask, NULL);
+
+ act.sa_handler = SIG_DFL;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+#ifdef SA_RESTART
+ act.sa_flags |= SA_RESTART;
+#endif
+ sigaction(SIGTSTP, &act, &oact);
+ kill(getpid(), SIGTSTP);
+
+ T(("SIGCONT received"));
+ sigaction(SIGTSTP, &oact, NULL);
+ reset_prog_mode();
+ flushinp();
+ if (enter_ca_mode)
+ putp(enter_ca_mode);
+ doupdate();
+}
+
diff --git a/lib/libncurses/lib_twait.c b/lib/libncurses/lib_twait.c
new file mode 100644
index 0000000..1b0fd1e
--- /dev/null
+++ b/lib/libncurses/lib_twait.c
@@ -0,0 +1,75 @@
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_twait.c
+**
+** The routine timed_wait().
+**
+*/
+
+#include <string.h>
+#include <sys/types.h> /* some systems can't live without this */
+#include <sys/time.h>
+#include <unistd.h>
+#if defined(SYS_SELECT)
+#include <sys/select.h>
+#endif
+#include "curses.priv.h"
+
+#if defined(NOUSLEEP)
+void usleep(unsigned int usec)
+{
+struct timeval tval;
+
+ tval.tv_sec = usec / 1000000;
+ tval.tv_usec = usec % 1000000;
+ select(0, NULL, NULL, NULL, &tval);
+
+}
+#endif
+
+int timed_wait(int fd, int wait, int *timeleft)
+{
+int result;
+struct timeval timeout;
+static fd_set set;
+#ifndef GOOD_SELECT
+struct timeval starttime, returntime;
+
+ gettimeofday(&starttime, NULL);
+#endif
+
+ FD_ZERO(&set);
+ FD_SET(fd, &set);
+
+ /* the units of wait are milliseconds */
+ timeout.tv_sec = wait / 1000;
+ timeout.tv_usec = (wait % 1000) * 1000;
+
+ T(("start twait: sec = %d, usec = %d", timeout.tv_sec, timeout.tv_usec));
+
+ result = select(fd+1, &set, NULL, NULL, &timeout);
+
+#ifndef GOOD_SELECT
+ gettimeofday(&returntime, NULL);
+ timeout.tv_sec -= (returntime.tv_sec - starttime.tv_sec);
+ timeout.tv_usec -= (returntime.tv_usec - starttime.tv_usec);
+ if (timeout.tv_usec < 0 && timeout.tv_sec > 0) {
+ timeout.tv_sec--;
+ timeout.tv_usec += 1000000;
+ }
+ if (timeout.tv_sec < 0)
+ timeout.tv_sec = timeout.tv_usec = 0;
+#endif
+
+ /* return approximate time left on the timeout, in milliseconds */
+ if (timeleft)
+ *timeleft = (timeout.tv_sec * 1000) + (timeout.tv_usec / 1000);
+
+ T(("end twait: returned %d, sec = %d, usec = %d (%d msec)",
+ result, timeout.tv_sec, timeout.tv_usec, *timeleft));
+
+ return(result);
+}
diff --git a/lib/libncurses/lib_unctrl.c b/lib/libncurses/lib_unctrl.c
new file mode 100644
index 0000000..b0f10c2
--- /dev/null
+++ b/lib/libncurses/lib_unctrl.c
@@ -0,0 +1,32 @@
+#ifdef __FreeBSD__
+#include <ctype.h>
+#endif
+#include <unctrl.h>
+
+char *
+ unctrl(register unsigned char uch)
+{
+ static char buffer[3] = "^x";
+
+#ifdef __FreeBSD__
+ if (isprint(uch)) {
+#else
+ if ((uch & 0x60) != 0 && uch != 0x7F) {
+#endif
+ /*
+ * Printable character. Simply return the character as a one-character
+ * string.
+ */
+ buffer[1] = uch;
+ return &buffer[1];
+ }
+ uch &= ~0x80;
+ /*
+ * It is a control character. DEL is handled specially (^?). All others
+ * use ^x notation, where x is the character code for the control character
+ * with 0x40 ORed in. (Control-A becomes ^A etc.).
+ */ buffer[1] = (uch == 0x7F ? '?' : (uch | 0x40));
+
+ return buffer;
+
+}
diff --git a/lib/libncurses/lib_vidattr.c b/lib/libncurses/lib_vidattr.c
new file mode 100644
index 0000000..eb796f4
--- /dev/null
+++ b/lib/libncurses/lib_vidattr.c
@@ -0,0 +1,181 @@
+
+/***************************************************************************
+* COPYRIGHT NOTICE *
+****************************************************************************
+* ncurses is copyright (C) 1992, 1993, 1994 *
+* by Zeyd M. Ben-Halim *
+* zmbenhal@netcom.com *
+* *
+* Permission is hereby granted to reproduce and distribute ncurses *
+* by any means and for any fee, whether alone or as part of a *
+* larger distribution, in source or in binary form, PROVIDED *
+* this notice is included with any such distribution, not removed *
+* from header files, and is reproduced in any documentation *
+* accompanying it or the applications linked with it. *
+* *
+* ncurses comes AS IS with no warranty, implied or expressed. *
+* *
+***************************************************************************/
+
+/*
+ * vidputs(newmode, outc)
+ *
+ * newmode is taken to be the logical 'or' of the symbols in curses.h
+ * representing graphic renditions. The teminal is set to be in all of
+ * the given modes, if possible.
+ *
+ * if set-attributes exists
+ * use it to set exactly what you want
+ * else
+ * if exit-attribute-mode exists
+ * turn off everything
+ * else
+ * turn off those which can be turned off and aren't in
+ * newmode.
+ * turn on each mode which should be on and isn't, one by one
+ *
+ * NOTE that this algorithm won't achieve the desired mix of attributes
+ * in some cases, but those are probably just those cases in which it is
+ * actually impossible, anyway, so...
+ *
+ */
+
+#include <string.h>
+#include "curses.priv.h"
+#include "terminfo.h"
+
+static void do_color(int pair, int (*outc)(int))
+{
+int fg, bg;
+
+ if ( pair == 0 ) {
+ tputs(orig_pair, 1, outc);
+ } else {
+ fg = FG(color_pairs[pair]);
+ bg = BG(color_pairs[pair]);
+
+ T(("setting colors: pair = %d, fg = %d, bg = %d\n", pair, fg, bg));
+
+ if (set_a_foreground)
+ tputs(tparm(set_a_foreground, fg), 1, outc);
+ else
+ tputs(tparm(set_foreground, fg), 1, outc);
+ if (set_a_background)
+ tputs(tparm(set_a_background, bg), 1, outc);
+ else
+ tputs(tparm(set_background, bg), 1, outc);
+ }
+}
+
+#define previous_attr SP->_current_attr
+
+int vidputs(chtype newmode, int (*outc)(int))
+{
+chtype turn_off = (~newmode & previous_attr) & ~A_COLOR;
+chtype turn_on = (newmode & ~previous_attr) & ~A_COLOR;
+
+ T(("vidputs(%x) called %s", newmode, _traceattr(newmode)));
+ T(("previous attribute was %s", _traceattr(previous_attr)));
+
+ if (newmode == previous_attr)
+ return OK;
+ if (newmode == A_NORMAL && exit_attribute_mode) {
+ if((previous_attr & A_ALTCHARSET) && exit_alt_charset_mode) {
+ tputs(exit_alt_charset_mode, 1, outc);
+ previous_attr &= ~A_ALTCHARSET;
+ }
+ if (previous_attr)
+ tputs(exit_attribute_mode, 1, outc);
+
+ } else if (set_attributes) {
+ if (turn_on || turn_off) {
+ tputs(tparm(set_attributes,
+ (newmode & A_STANDOUT) != 0,
+ (newmode & A_UNDERLINE) != 0,
+ (newmode & A_REVERSE) != 0,
+ (newmode & A_BLINK) != 0,
+ (newmode & A_DIM) != 0,
+ (newmode & A_BOLD) != 0,
+ (newmode & A_INVIS) != 0,
+ (newmode & A_PROTECT) != 0,
+ (newmode & A_ALTCHARSET) != 0), 1, outc);
+ }
+ } else {
+
+ T(("turning %x off", _traceattr(turn_off)));
+
+ if ((turn_off & A_ALTCHARSET) && exit_alt_charset_mode) {
+ tputs(exit_alt_charset_mode, 1, outc);
+ turn_off &= ~A_ALTCHARSET;
+ }
+
+ if ((turn_off & A_UNDERLINE) && exit_underline_mode) {
+ tputs(exit_underline_mode, 1, outc);
+ turn_off &= ~A_UNDERLINE;
+ }
+
+ if ((turn_off & A_STANDOUT) && exit_standout_mode) {
+ tputs(exit_standout_mode, 1, outc);
+ turn_off &= ~A_STANDOUT;
+ }
+
+ if (turn_off && exit_attribute_mode) {
+ tputs(exit_attribute_mode, 1, outc);
+ turn_on |= newmode & (A_UNDERLINE|A_REVERSE|A_BLINK|A_DIM|A_BOLD|A_INVIS|A_PROTECT);
+ }
+
+ T(("turning %x on", _traceattr(turn_on)));
+
+ if ((turn_on & A_ALTCHARSET) && enter_alt_charset_mode)
+ tputs(enter_alt_charset_mode, 1, outc);
+
+ if ((turn_on & A_BLINK) && enter_blink_mode)
+ tputs(enter_blink_mode, 1, outc);
+
+ if ((turn_on & A_BOLD) && enter_bold_mode)
+ tputs(enter_bold_mode, 1, outc);
+
+ if ((turn_on & A_DIM) && enter_dim_mode)
+ tputs(enter_dim_mode, 1, outc);
+
+ if ((turn_on & A_REVERSE) && enter_reverse_mode)
+ tputs(enter_reverse_mode, 1, outc);
+
+ if ((turn_on & A_STANDOUT) && enter_standout_mode)
+ tputs(enter_standout_mode, 1, outc);
+
+ if ((turn_on & A_PROTECT) && enter_protected_mode)
+ tputs(enter_protected_mode, 1, outc);
+
+ if ((turn_on & A_INVIS) && enter_secure_mode)
+ tputs(enter_secure_mode, 1, outc);
+
+ if ((turn_on & A_UNDERLINE) && enter_underline_mode)
+ tputs(enter_underline_mode, 1, outc);
+
+ }
+
+ if (SP->_coloron) {
+ int pair = PAIR_NUMBER(newmode);
+ int current_pair = PAIR_NUMBER(previous_attr);
+
+ T(("old pair = %d -- new pair = %d", current_pair, pair));
+ if (pair != current_pair || turn_off) {
+ do_color(pair, outc);
+ }
+ }
+
+ previous_attr = newmode;
+
+ T(("vidputs finished"));
+ return OK;
+}
+
+int vidattr(chtype newmode)
+{
+
+ T(("vidattr(%x) called", newmode));
+
+ return(vidputs(newmode, _outch));
+}
+
diff --git a/lib/libncurses/lib_window.c b/lib/libncurses/lib_window.c
new file mode 100644
index 0000000..699863c
--- /dev/null
+++ b/lib/libncurses/lib_window.c
@@ -0,0 +1,85 @@
+
+/* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for *
+* details. If they are missing then this copy is in violation of *
+* the copyright conditions. */
+
+/*
+** lib_window.c
+**
+**
+*/
+
+#include <string.h>
+#include "curses.priv.h"
+
+int mvder(WINDOW *win, int y, int x)
+{
+ return(ERR);
+}
+
+void wsyncup(WINDOW *win)
+{
+
+}
+
+int syncok(WINDOW *win, bool bf)
+{
+ return(ERR);
+}
+
+void wcursyncup(WINDOW *win)
+{
+
+}
+
+void wsyncdown(WINDOW *win)
+{
+
+}
+
+WINDOW *dupwin(WINDOW *win)
+{
+WINDOW *nwin;
+int linesize, i;
+
+ T(("dupwin(%x) called", win));
+
+ if ((nwin = newwin(win->_maxy + 1, win->_maxx + 1, win->_begy, win->_begx)) == NULL)
+ return NULL;
+
+ nwin->_curx = win->_curx;
+ nwin->_cury = win->_cury;
+ nwin->_maxy = win->_maxy;
+ nwin->_maxx = win->_maxx;
+ nwin->_begy = win->_begy;
+ nwin->_begx = win->_begx;
+
+ nwin->_flags = win->_flags;
+ nwin->_attrs = win->_attrs;
+ nwin->_bkgd = win->_bkgd;
+
+ nwin->_clear = win->_clear;
+ nwin->_scroll = win->_scroll;
+ nwin->_leave = win->_leave;
+ nwin->_use_keypad = win->_use_keypad;
+ nwin->_use_meta = win->_use_meta;
+ nwin->_delay = win->_delay;
+ nwin->_immed = win->_immed;
+ nwin->_sync = win->_sync;
+ nwin->_parx = win->_parx;
+ nwin->_pary = win->_pary;
+ nwin->_parent = win->_parent;
+
+ nwin->_regtop = win->_regtop;
+ nwin->_regbottom = win->_regbottom;
+
+ linesize = (win->_maxx + 1) * sizeof(chtype);
+ for (i = 0; i <= nwin->_maxy; i++) {
+ memcpy(nwin->_line[i], win->_line[i], linesize);
+ nwin->_firstchar[i] = win->_firstchar[i];
+ nwin->_lastchar[i] = win->_lastchar[i];
+ }
+
+ return nwin;
+}
+
diff --git a/lib/libncurses/ncurses.3 b/lib/libncurses/ncurses.3
new file mode 100644
index 0000000..09aa12d
--- /dev/null
+++ b/lib/libncurses/ncurses.3
@@ -0,0 +1,427 @@
+.TH ncurses 3 ""
+.ds n 5
+.ds d @TERMINFO@
+.SH NAME
+\fBncurses\fR - CRT screen handling and optimization package
+.SH SYNOPSIS
+\fB#include <ncurses.h>\fR
+.br
+.SH DESCRIPTION
+The \fBncurses\fR library routines give the user a terminal-independent
+method of updating character screens with reasonable optimization.
+
+The \fBncurses\fR routines emulate the \fBcurses\fR(3) library of System V
+Release 4 UNIX, but is freely redistributable in source form. Differences from
+the SVr4 curses are described in the BUGS sections of individual man pages.
+There are only few of these, and as ncurses matures they will become fewer
+still.
+
+A program using these routines must be linked with the \fB-lncurses\fR option,
+or (if they have been generated) with one of the debugging libraries
+\fB-ldcurses\fR or \fB-lpcurses\fR. The dcurses library generates trace logs
+that describe curses actions; the pcurses library supports profiling.
+
+The \fBncurses\fR package supports: overall screen, window and pad
+manipulation; output to windows and pads; reading terminal input; control over
+terminal and \fBncurses\fR input and output options; environment query
+routines; color manipulation; use of soft label keys; terminfo capabilities;
+and access to low-level \fBncurses\fR routines.
+
+To initialize the routines, the routine \fBinitscr\fR or \fBnewterm\fR
+must be called before any of the other routines that deal with windows
+and screens are used. The routine \fBendwin\fR must be called before
+exiting. To get character-at-a-time input without echoing (most
+interactive, screen oriented programs want this), the following
+sequence should be used:
+
+ \fBinitscr(); cbreak(); noecho();\fR
+
+Most programs would additionally use the sequence:
+
+ \fBnonl(); intrflush(stdscr,FALSE); keypad(stdscr,TRUE);\fR
+
+Before a \fBncurses\fR program is run, the tab stops of the terminal
+should be set and its initialization strings, if defined, must be
+output. This can be done by executing the \fBtput init\fR command
+after the shell environment variable \fBTERM\fR has been exported.
+[See \fBterminfo\fR(\*n) for further details.]
+
+The \fBncurses\fR library permits manipulation of data structures,
+called \fIwindows\fR, which can be thought of as two-dimensional
+arrays of characters representing all or part of a CRT screen. A
+default window called \fBstdscr\fR, which is the size of the terminal
+screen, is supplied. Others may be created with \fBnewwin\fR.
+
+Windows are referred to by variables declared as \fBWINDOW *\fR.
+These data structures are manipulated with routines described in manual section 3
+pages (whose names begin "curs_"). Among which the most basic
+routines are \fBmove\fR and \fBaddch\fR. More general versions of
+these routines are included with names beginning with \fBw\fR,
+allowing the user to specify a window. The routines not beginning
+with \fBw\fR affect \fBstdscr\fR.)
+
+After using routines to manipulate a window, \fBrefresh\fR is called,
+telling \fBncurses\fR to make the user's CRT screen look like
+\fBstdscr\fR. The characters in a window are actually of type
+\fBchtype\fR, (character and attribute data) so that other information
+about the character may also be stored with each character.
+
+Special windows called \fIpads\fR may also be manipulated. These are windows
+which are not constrained to the size of the screen and whose contents need not
+be completely displayed. See curs_pad(3) for more information.
+
+In addition to drawing characters on the screen, video attributes and colors
+may be supported, causing the characters to show up in such modes as
+underlined, in reverse video, or in color on terminals that support such
+display enhancements. Line drawing characters may be specified to be output.
+On input, \fBncurses\fR is also able to translate arrow and function keys that
+transmit escape sequences into single values. The video attributes, line
+drawing characters, and input values use names, defined in \fB<ncurses.h>\fR,
+such as \fBA_REVERSE\fR, \fBACS_HLINE\fR, and \fBKEY_LEFT\fR.
+
+If the environment variables \fBLINES\fR and \fBCOLUMNS\fR are set, or if the
+program is executing in a window environment, line and column information in
+the environment will override information read by \fIterminfo\fR. This would
+effect a program running in an AT&T 630 layer, for example, where the size of a
+screen is changeable.
+
+If the environment variable \fBTERMINFO\fR is defined, any program using
+\fBncurses\fR checks for a local terminal definition before checking in the
+standard place. For example, if \fBTERM\fR is set to \fBatt4424\fR, then the
+compiled terminal definition is found in
+
+ \fB\*d/a/att4424\fR.
+
+(The \fBa\fR is copied from the first letter of \fBatt4424\fR to avoid
+creation of huge directories.) However, if \fBTERMINFO\fR is set to
+\fB$HOME/myterms\fR, \fBncurses\fR first checks
+
+ \fB$HOME/myterms/a/att4424\fR,
+
+and if that fails, it then checks
+
+ \fB\*d/a/att4424\fR.
+
+This is useful for developing experimental definitions or when write
+permission in \fB\*d\fR is not available.
+
+The integer variables \fBLINES\fR and \fBCOLS\fR are defined in
+\fB<ncurses.h>\fR and will be filled in by \fBinitscr\fR with the size of the
+screen. The constants \fBTRUE\fR and \fBFALSE\fR have the values \fB1\fR and
+\fB0\fR, respectively.
+
+The \fBncurses\fR routines also define the \fBWINDOW *\fR variable \fBcurscr\fR
+which is used for certain low-level operations like clearing and redrawing a
+screen containing garbage. The \fBcurscr\fR can be used in only a few
+routines.
+
+.SS Routine and Argument Names
+Many \fBncurses\fR routines have two or more versions. The routines prefixed
+with \fBw\fR require a window argument. The routines prefixed with \fBp\fR
+require a pad argument. Those without a prefix generally use \fBstdscr\fR.
+
+The routines prefixed with \fBmv\fR require a \fIy\fR and \fIx\fR
+coordinate to move to before performing the appropriate action. The
+\fBmv\fR routines imply a call to \fBmove\fR before the call to the
+other routine. The coordinate \fIy\fR always refers to the row (of
+the window), and \fIx\fR always refers to the column. The upper
+left-hand corner is always (0,0), not (1,1).
+
+The routines prefixed with \fBmvw\fR take both a window argument and
+\fIx\fR and \fIy\fR coordinates. The window argument is always
+specified before the coordinates.
+
+In each case, \fIwin\fR is the window affected, and \fIpad\fR is the
+pad affected; \fIwin\fR and \fIpad\fR are always pointers to type
+\fBWINDOW\fR.
+
+Option setting routines require a Boolean flag \fIbf\fR with the value
+\fBTRUE\fR or \fBFALSE\fR; \fIbf\fR is always of type \fBbool\fR. The
+variables \fIch\fR and \fIattrs\fR below are always of type
+\fBchtype\fR. The types \fBWINDOW\fR, \fBSCREEN\fR, \fBbool\fR, and
+\fBchtype\fR are defined in \fB<ncurses.h>\fR. The type \fBTERMINAL\fR
+is defined in \fB<term.h>\fR. All other arguments are integers.
+
+.SS Routine Name Index
+The following table lists each \fBncurses\fR routine and the name of
+the manual page on which it is described.
+
+.nf
+\fBncurses\fR Routine Name Manual Page Name
+___________________________________________
+addch curs_addch(3)
+addchnstr curs_addchstr(3)
+addchstr curs_addchstr(3)
+addnstr curs_addstr(3)
+addstr curs_addstr(3)
+attroff curs_attr(3)
+attron curs_attr(3)
+attrset curs_attr(3)
+baudrate curs_termattrs(3)
+beep curs_beep(3)
+bkgd curs_bkgd(3)
+bkgdset curs_bkgd(3)
+border curs_border(3)
+box curs_border(3)
+can_change_color curs_color(3)
+cbreak curs_inopts(3)
+clear curs_clear(3)
+clearok curs_outopts(3)
+clrtobot curs_clear(3)
+clrtoeol curs_clear(3)
+color_content curs_color(3)
+copywin curs_overlay(3)
+curs_set curs_kernel(3)
+def_prog_mode curs_kernel(3)
+def_shell_mode curs_kernel(3)
+del_curterm curs_terminfo(\*n)
+delay_output curs_util(3)
+delch curs_delch(3)
+deleteln curs_deleteln(3)
+delscreen curs_initscr(3)
+delwin curs_window(3)
+derwin curs_window(3)
+doupdate curs_refresh(3)
+dupwin curs_window(3)
+echo curs_inopts(3)
+echochar curs_addch(3)
+endwin curs_initscr(3)
+erase curs_clear(3)
+erasechar curs_termattrs(3)
+filter curs_util(3)
+flash curs_beep(3)
+flushinp curs_util(3)
+getbegyx curs_getyx(3)
+getch curs_getch(3)
+getmaxyx curs_getyx(3)
+getparyx curs_getyx(3)
+getstr curs_getstr(3)
+getsyx curs_kernel(3)
+getwin curs_util(3)
+getyx curs_getyx(3)
+halfdelay curs_inopts(3)
+has_colors curs_color(3)
+has_ic curs_termattrs(3)
+has_il curs_termattrs(3)
+hline curs_border(3)
+idcok curs_outopts(3)
+idlok curs_outopts(3)
+immedok curs_outopts(3)
+inch curs_inch(3)
+inchnstr curs_inchstr(3)
+inchstr curs_inchstr(3)
+init_color curs_color(3)
+init_pair curs_color(3)
+initscr curs_initscr(3)
+innstr curs_instr(3)
+insch curs_insch(3)
+insdelln curs_deleteln(3)
+insertln curs_deleteln(3)
+insnstr curs_insstr(3)
+insstr curs_insstr(3)
+instr curs_instr(3)
+intrflush curs_inopts(3)
+is_linetouched curs_touch(3)
+is_wintouched curs_touch(3)
+isendwin curs_initscr(3)
+keyname curs_util(3)
+keypad curs_inopts(3)
+killchar curs_termattrs(3)
+leaveok curs_outopts(3)
+longname curs_termattrs(3)
+meta curs_inopts(3)
+move curs_move(3)
+mvaddch curs_addch(3)
+mvaddchnstr curs_addchstr(3)
+mvaddchstr curs_addchstr(3)
+mvaddnstr curs_addstr(3)
+mvaddstr curs_addstr(3)
+mvcur curs_terminfo(\*n)
+mvdelch curs_delch(3)
+mvderwin curs_window(3)
+mvgetch curs_getch(3)
+mvgetstr curs_getstr(3)
+mvinch curs_inch(3)
+mvinchnstr curs_inchstr(3)
+mvinchstr curs_inchstr(3)
+mvinnstr curs_instr(3)
+mvinsch curs_insch(3)
+mvinsnstr curs_insstr(3)
+mvinsstr curs_insstr(3)
+mvinstr curs_instr(3)
+mvprintw curs_printw(3)
+mvscanw curs_scanw(3)
+mvwaddch curs_addch(3)
+mvwaddchnstr curs_addchstr(3)
+mvwaddchstr curs_addchstr(3)
+mvwaddnstr curs_addstr(3)
+mvwaddstr curs_addstr(3)
+mvwdelch curs_delch(3)
+mvwgetch curs_getch(3)
+mvwgetstr curs_getstr(3)
+mvwin curs_window(3)
+mvwinch curs_inch(3)
+mvwinchnstr curs_inchstr(3)
+mvwinchstr curs_inchstr(3)
+mvwinnstr curs_instr(3)
+mvwinsch curs_insch(3)
+mvwinsnstr curs_insstr(3)
+mvwinsstr curs_insstr(3)
+mvwinstr curs_instr(3)
+mvwprintw curs_printw(3)
+mvwscanw curs_scanw(3)
+napms curs_kernel(3)
+newpad curs_pad(3)
+newterm curs_initscr(3)
+newwin curs_window(3)
+nl curs_outopts(3)
+nocbreak curs_inopts(3)
+nodelay curs_inopts(3)
+noecho curs_inopts(3)
+nonl curs_outopts(3)
+noqiflush curs_inopts(3)
+noraw curs_inopts(3)
+notimeout curs_inopts(3)
+overlay curs_overlay(3)
+overwrite curs_overlay(3)
+pair_content curs_color(3)
+pechochar curs_pad(3)
+pnoutrefresh curs_pad(3)
+prefresh curs_pad(3)
+printw curs_printw(3)
+putp curs_terminfo(\*n)
+putwin curs_util(3)
+qiflush curs_inopts(3)
+raw curs_inopts(3)
+redrawwin curs_refresh(3)
+refresh curs_refresh(3)
+reset_prog_mode curs_kernel(3)
+reset_shell_mode curs_kernel(3)
+resetty curs_kernel(3)
+restartterm curs_terminfo(\*n)
+ripoffline curs_kernel(3)
+savetty curs_kernel(3)
+scanw curs_scanw(3)
+scr_dump curs_scr_dmp(3)
+scr_init curs_scr_dmp(3)
+scr_restore curs_scr_dmp(3)
+scr_set curs_scr_dmp(3)
+scrl curs_scroll(3)
+scroll curs_scroll(3)
+scrollok curs_outopts(3)
+set_curterm curs_terminfo(\*n)
+set_term curs_initscr(3)
+setscrreg curs_outopts(3)
+setsyx curs_kernel(3)
+setterm curs_terminfo(\*n)
+setupterm curs_terminfo(\*n)
+slk_attroff curs_slk(3)
+slk_attron curs_slk(3)
+slk_attrset curs_slk(3)
+slk_clear curs_slk(3)
+slk_init curs_slk(3)
+slk_label curs_slk(3)
+slk_noutrefresh curs_slk(3)
+slk_refresh curs_slk(3)
+slk_restore curs_slk(3)
+slk_set curs_slk(3)
+slk_touch curs_slk(3)
+standend curs_attr(3)
+standout curs_attr(3)
+start_color curs_color(3)
+subpad curs_pad(3)
+subwin curs_window(3)
+syncok curs_window(3)
+termattrs curs_termattrs(3)
+termname curs_termattrs(3)
+tigetflag curs_terminfo(\*n)
+tigetnum curs_terminfo(\*n)
+tigetstr curs_terminfo(\*n)
+timeout curs_inopts(3)
+touchline curs_touch(3)
+touchwin curs_touch(3)
+tparm curs_terminfo(\*n)
+tputs curs_terminfo(\*n)
+typeahead curs_inopts(3)
+unctrl curs_util(3)
+ungetch curs_getch(3)
+untouchwin curs_touch(3)
+use_env curs_util(3)
+vidattr curs_terminfo(\*n)
+vidputs curs_terminfo(\*n)
+vline curs_border(3)
+vwprintw curs_printw(3)
+vwscanw curs_scanw(3)
+waddch curs_addch(3)
+waddchnstr curs_addchstr(3)
+waddchstr curs_addchstr(3)
+waddnstr curs_addstr(3)
+waddstr curs_addstr(3)
+wattroff curs_attr(3)
+wattron curs_attr(3)
+wattrset curs_attr(3)
+wbkgd curs_bkgd(3)
+wbkgdset curs_bkgd(3)
+wborder curs_border(3)
+wclear curs_clear(3)
+wclrtobot curs_clear(3)
+wclrtoeol curs_clear(3)
+wcursyncup curs_window(3)
+wdelch curs_delch(3)
+wdeleteln curs_deleteln(3)
+wechochar curs_addch(3)
+werase curs_clear(3)
+wgetch curs_getch(3)
+wgetnstr curs_getstr(3)
+wgetstr curs_getstr(3)
+whline curs_border(3)
+winch curs_inch(3)
+winchnstr curs_inchstr(3)
+winchstr curs_inchstr(3)
+winnstr curs_instr(3)
+winsch curs_insch(3)
+winsdelln curs_deleteln(3)
+winsertln curs_deleteln(3)
+winsnstr curs_insstr(3)
+winsstr curs_insstr(3)
+winstr curs_instr(3)
+wmove curs_move(3)
+wnoutrefresh curs_refresh(3)
+wprintw curs_printw(3)
+wredrawln curs_refresh(3)
+wrefresh curs_refresh(3)
+wscanw curs_scanw(3)
+wscrl curs_scroll(3)
+wsetscrreg curs_outopts(3)
+wstandend curs_attr(3)
+wstandout curs_attr(3)
+wsyncdown curs_window(3)
+wsyncup curs_window(3)
+wtimeout curs_inopts(3)
+wtouchln curs_touch(3)
+wvline curs_border(3)
+.fi
+.SH RETURN VALUE
+Routines that return an integer return \fBERR\fR upon failure and an
+integer value other than \fBERR\fR upon successful completion, unless
+otherwise noted in the routine descriptions.
+
+All macros return the value of the \fBw\fR version, except \fBsetscrreg\fR,
+\fBwsetscrreg\fR, \fBgetyx\fR, \fBgetbegyx\fR, \fBgetmaxyx\fR. The return
+values of \fBsetscrreg\fR, \fBwsetscrreg\fR, \fBgetyx\fR, \fBgetbegyx\fR, and
+\fBgetmaxyx\fR are undefined (\fIi\fR.\fIe\fR., these should not be used as the
+right-hand side of assignment statements).
+
+Routines that return pointers return \fBNULL\fR on error.
+.SH SEE ALSO
+\fBterminfo\fR(5) and section 3 pages whose names begin "curs_" for detailed routine
+descriptions.
+.SH NOTES
+The header file \fB<ncurses.h>\fR automatically includes the header files
+\fB<stdio.h>\fR and \fB<unctrl.h>\fR.
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/term.5 b/lib/libncurses/term.5
new file mode 100644
index 0000000..3fe30bd
--- /dev/null
+++ b/lib/libncurses/term.5
@@ -0,0 +1,153 @@
+.TH TERM 5
+.ds n 5
+.ds d /usr/lib/terminfo
+.SH NAME
+term \- format of compiled term file.
+.SH SYNOPSIS
+.B term
+.SH DESCRIPTION
+.PP
+Compiled terminfo descriptions are placed under the directory \fB\*d\fP.
+In order to avoid a linear search of a huge \s-1UNIX\s+1 system directory, a
+two-level scheme is used: \fB\*b/c/name\fP
+where
+.I name
+is the name of the terminal, and
+.I c
+is the first character of
+.IR name .
+Thus,
+.I act4
+can be found in the file \fB\*d/a/act4\fP.
+Synonyms for the same terminal are implemented by multiple
+links to the same compiled file.
+.PP
+The format has been chosen so that it will be the same on all hardware.
+An 8 or more bit byte is assumed, but no assumptions about byte ordering
+or sign extension are made.
+.PP
+The compiled file is created with the
+.I tic
+program, and read by the routine
+.IR setupterm .
+Both of these pieces of software are part of
+.IR ncurses (3).
+The file is divided into six parts:
+the header,
+terminal names,
+boolean flags,
+numbers,
+strings,
+and
+string table.
+.PP
+The header section begins the file.
+This section contains six short integers in the format
+described below.
+These integers are
+(1) the magic number (octal 0432);
+(2) the size, in bytes, of the names section;
+(3) the number of bytes in the boolean section;
+(4) the number of short integers in the numbers section;
+(5) the number of offsets (short integers) in the strings section;
+(6) the size, in bytes, of the string table.
+.PP
+Short integers are stored in two 8-bit bytes.
+The first byte contains the least significant 8 bits of the value,
+and the second byte contains the most significant 8 bits.
+(Thus, the value represented is 256*second+first.)
+The value \-1 is represented by 0377, 0377, other negative
+value are illegal.
+The
+\-1 generally means that a capability is missing from this terminal.
+Note that this format corresponds to the hardware of the \s-1VAX\s+1 and \s-1PDP\s+1-11.
+Machines where this does not correspond to the hardware read the
+integers as two bytes and compute the result.
+.PP
+The terminal names section comes next.
+It contains the first line of the terminfo description,
+listing the various names for the terminal,
+separated by the `|' character.
+The section is terminated with an \s-1ASCII NUL\s+1 character.
+.PP
+The boolean flags have one byte for each flag.
+This byte is either 0 or 1 as the flag is present or absent.
+The capabilities are in the same order as the file <term.h>.
+.PP
+Between the boolean section and the number section,
+a null byte will be inserted, if necessary,
+to ensure that the number section begins on an even byte.
+All short integers are aligned on a short word boundary.
+.PP
+The numbers section is similar to the flags section.
+Each capability takes up two bytes,
+and is stored as a short integer.
+If the value represented is \-1, the capability is taken to be missing.
+.PP
+The strings section is also similar.
+Each capability is stored as a short integer, in the format above.
+A value of \-1 means the capability is missing.
+Otherwise, the value is taken as an offset from the beginning
+of the string table.
+Special characters in ^X or \ec notation are stored in their
+interpreted form, not the printing representation.
+Padding information $<nn> and parameter information %x are
+stored intact in uninterpreted form.
+.PP
+The final section is the string table.
+It contains all the values of string capabilities referenced in
+the string section.
+Each string is null terminated.
+.PP
+Note that it is possible for
+.I setupterm
+to expect a different set of capabilities
+than are actually present in the file.
+Either the database may have been updated since
+.I setupterm
+has been recompiled
+(resulting in extra unrecognized entries in the file)
+or the program may have been recompiled more recently
+than the database was updated
+(resulting in missing entries).
+The routine
+.I setupterm
+must be prepared for both possibilities \-
+this is why the numbers and sizes are included.
+Also, new capabilities must always be added at the end of the lists
+of boolean, number, and string capabilities.
+.PP
+As an example, an octal dump of the description for the Microterm ACT 4
+is included:
+.nf
+.sp
+microterm|act4|microterm act iv,
+ cr=^M, cud1=^J, ind=^J, bel=^G, am, cub1=^H,
+ ed=^_, el=^^, clear=^L, cup=^T%p1%c%p2%c,
+ cols#80, lines#24, cuf1=^X, cuu1=^Z, home=^],
+.sp
+.ft CW
+\s-2000 032 001 \e0 025 \e0 \eb \e0 212 \e0 " \e0 m i c r
+020 o t e r m | a c t 4 | m i c r o
+040 t e r m a c t i v \e0 \e0 001 \e0 \e0
+060 \e0 \e0 \e0 \e0 \e0 \e0 \e0 \e0 \e0 \e0 \e0 \e0 \e0 \e0 \e0 \e0
+100 \e0 \e0 P \e0 377 377 030 \e0 377 377 377 377 377 377 377 377
+120 377 377 377 377 \e0 \e0 002 \e0 377 377 377 377 004 \e0 006 \e0
+140 \eb \e0 377 377 377 377 \en \e0 026 \e0 030 \e0 377 377 032 \e0
+160 377 377 377 377 034 \e0 377 377 036 \e0 377 377 377 377 377 377
+200 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377
+*
+520 377 377 377 377 \e0 377 377 377 377 377 377 377 377 377 377
+540 377 377 377 377 377 377 007 \e0 \er \e0 \ef \e0 036 \e0 037 \e0
+560 024 % p 1 % c % p 2 % c \e0 \en \e0 035 \e0
+600 \eb \e0 030 \e0 032 \e0 \en \e0\s+2
+.ft R
+.fi
+.sp
+.PP
+Some limitations: total compiled entries cannot exceed 4096 bytes.
+The name field cannot exceed 128 bytes.
+.SH FILES
+\*d/*/* compiled terminal capability data base
+.SH "SEE ALSO"
+ncurses(3), terminfo(5).
diff --git a/lib/libncurses/terminfo.5 b/lib/libncurses/terminfo.5
new file mode 100644
index 0000000..6810df6
--- /dev/null
+++ b/lib/libncurses/terminfo.5
@@ -0,0 +1,1656 @@
+.\" Note: this must be run through tbl befor nroff
+.TH TERMINFO 5
+.ds n 5
+.ds d /usr/lib/terminfo
+.SH NAME
+terminfo \- terminal capability data base
+.SH SYNOPSIS
+\*d/*/*
+.SH DESCRIPTION
+.I Terminfo
+is a data base describing terminals, used by screen-oriented programs such as
+.IR vi (1),
+.IR rogue (1)
+and
+.IR ncurses (3).
+.I Terminfo
+describes terminals by giving a set of capabilities which they
+have, by specifying how to perform screen operations, and by
+specifying padding requirements and initialization sequences.
+.PP
+Entries in
+.I terminfo
+consist of a number of `,' separated fields.
+White space after each `,' is ignored.
+The first entry for each terminal gives the names which are known for the
+terminal, separated by `|' characters.
+The first name given is the most common abbreviation for the terminal,
+the last name given should be a long name fully identifying the terminal,
+and all others are understood as synonyms for the terminal name.
+All names but the last should be in lower case and contain no blanks;
+the last name may well contain upper case and blanks for readability.
+.PP
+Terminal names (except for the last, verbose entry) should
+be chosen using the following conventions.
+The particular piece of hardware making up the terminal should
+have a root name chosen, thus ``hp2621''.
+This name should not contain hyphens, except that synonyms may
+be chosen that do not conflict with other names.
+Modes that the hardware can be in, or user preferences, should
+be indicated by appending a hyphen and an indicator of the mode.
+Thus, a vt100 in 132 column mode would be vt100-w.
+The following suffixes should be used where possible:
+.TS
+center;
+l c l
+l l l.
+\fBSuffix Meaning Example\fP
+-w Wide mode (more than 80 columns) vt100-w
+-am With auto. margins (usually default) vt100-am
+-nam Without automatic margins vt100-nam
+-\fIn\fP Number of lines on the screen aaa-60
+-na No arrow keys (leave them in local) c100-na
+-\fIn\fPp Number of pages of memory c100-4p
+-rv Reverse video c100-rv
+.TE
+.SH CAPABILITIES
+The variable is the name by which the programmer (at the terminfo level)
+accesses the capability.
+The capname is the short name used in the text of the database,
+and is used by a person updating the database.
+The i.code is the two letter internal code used in the compiled database,
+and always corresponds to the old
+.B termcap
+capability name.
+.P
+Capability names have no hard length limit, but an informal limit of 5
+characters has been adopted to keep them short and to allow the tabs in
+the source file
+.B caps
+to line up nicely.
+Whenever possible, names are chosen to be the same as or similar to
+the ANSI X3.64-1979 standard. Semantics are also intended to match
+those of the specification.
+.TP
+(P)
+indicates that padding may be specified
+.TP
+(G)
+indicates that the string is passed through tparm with
+parms as given (#\fIi\fP).
+.TP
+(*)
+indicates that padding may be based on the number of
+lines affected
+.TP
+(#\d\fIi\fP\u)
+indicates the \fIi\fP\uth\d parameter.
+
+.TS
+center;
+c c c c
+c c c c
+l l l l.
+\fBVariable Cap- I. Description\fR
+\f3Booleans name Code\fR
+\s-1auto_left_margin, bw bw cub1 wraps from column 0 to last
+ column\s+1
+\s-1auto_right_margin, am am Terminal has automatic margins\s+1
+\s-1back_color_erase, bce ut screen erased with background color\s+1
+\s-1can_change, ccc cc terminal can re-define exiting colors\s+1
+\s-1ceol_standout_glitch, xhp xs Standout not erased by overwriting
+ (hp)\s+1
+\s-1col_addr_glitch, xhpa YA only positive motion for hpa/mhpa caps\s+1
+\s-1cpi_changes_res, cpix YF changing character pitch changes resolution\s+1
+\s-1cr_cancels_micro_mode, crxm YB using cr turns off micro mode\s+1
+\s-1eat_newline_glitch, xenl xn newline ignored after 80 cols
+ (Concept)\s+1
+\s-1erase_overstrike, eo eo Can erase overstrikes with a blank\s+1
+\s-1generic_type, gn gn Generic line type (e.g.,, dialup,
+ switch).\s+1
+\s-1hard_copy, hc hc Hardcopy terminal\s+1
+\s-1hard_cursor, chts HC cursor is hard to see\s+1
+\s-1has_meta_key, km km Has a meta key (shift, sets parity
+ bit)\s+1
+\s-1has_print_wheel, daisy YC printer needs operator to change character set\s+1
+\s-1has_status_line, hs hs Has extra "status line"\s+1
+\s-1hue_lightness_saturation, hls hl terminal uses only HLS color notation (tektronix)\s+1
+\s-1insert_null_glitch, in in Insert mode distinguishes nulls\s+1
+\s-1lpi_changes_res, lpix YG changing line pitch changes resolution\s+1
+\s-1memory_above, da da Display may be retained above the
+ screen\s+1
+\s-1memory_below, db db Display may be retained below the
+ screen\s+1
+\s-1move_insert_mode, mir mi Safe to move while in insert mode\s+1
+\s-1move_standout_mode, msgr ms Safe to move in standout modes\s+1
+\s-1needs_xon_xoff, nxon nx padding won't work, xon/xoff required\s+1
+\s-1no_esc_ctl_c, xsb xb Beehive (f1=escape, f2=ctrl C)\s+1
+\s-1non_rev_rmcup, nrrmc NR smcup does not reverse rmcup\s+1
+\s-1no_pad_char, npc NP pad character does not exist\s+1
+\s-1non_dest_scroll_region, ndscr ND scrolling region is non-destructive\s+1
+\s-1over_strike, os os Terminal overstrikes\s+1
+\s-1prtr_silent, mc5i 5i printer won't echo on screen\s+1
+\s-1row_addr_glitch, xvpa YD only positive motion for vhp/mvpa caps\s+1
+\s-1semi_auto_right_margin, sam YE printing in last column causes cr\s+1
+\s-1status_line_esc_ok, eslok es Escape can be used on the status line\s+1
+\s-1dest_tabs_magic_smso, xt xt Tabs ruin, magic so char (Teleray
+ 1061)\s+1
+\s-1tilde_glitch, hz hz Hazeltine; can not print ~'s\s+1
+\s-1transparent_underline, ul ul underline character overstrikes\s+1
+\s-1xon_xoff, xon xo Terminal uses xon/xoff handshaking\s+1
+
+\s-1\f3Numbers:\fR\s+1
+\s-1bit_image_entwining, bitwin Yo Undocumented in SVr4.0\s+1
+\s-1buffer_capacity, bufsz Ya numbers of bytes buffered before printing\s+1
+\s-1columns, cols co Number of columns in a line\s+1
+\s-1dot_vert_spacing, spinv Yb spacing of dots horizontally in dots per inch\s+1
+\s-1dot_horz_spacing, spinh Yc spacing of pins vertically in pins per inch\s+1
+\s-1init_tabs, it it Tabs initially every # spaces\s+1
+\s-1label_height, lh lh rows in each label\s+1
+\s-1label_width, lw lw columns in each label\s+1
+\s-1lines, lines li Number of lines on screen or page\s+1
+\s-1lines_of_memory, lm lm Lines of memory if > lines. 0 means varies\s+1
+\s-1magic_cookie_glitch, xmc sg Number of blank chars left by smso or rmso\s+1
+\s-1max_colors, colors Co maximum numbers of colors on screen\s+1
+\s-1max_micro_address, maddr Yd maximum value in micro_..._address\s+1
+\s-1max_micro_jump, mjump Ye maximum value in parm_..._micro\s+1
+\s-1max_pairs, pairs pa maximum number of color-pairs on the screen\s+1
+\s-1micro_col_size, mcs Yf Character step size when in micro mode\s+1
+\s-1micro_line_size, mls Yg Line step size when in micro mode\s+1
+\s-1no_color_video, ncv NC video attributes that can't be used with colors\s+1
+\s-1number_of_pins, npins Yh numbers of pins in print-head\s+1
+\s-1num_labels, nlab Nl number of labels on screen\s+1
+\s-1output_res_char, orc Yi horizontal resolution in units per line\s+1
+\s-1output_res_line, orl Yj vertical resolution in units per line\s+1
+\s-1output_res_horz_inch, orhi Yk horizontal resolution in units per inch\s+1
+\s-1output_res_vert_inch, orvi Yl vertical resolution in units per inch\s+1
+\s-1padding_baud_rate, pb pb Lowest baud where cr/nl padding is needed\s+1
+\s-1virtual_terminal, vt vt Virtual terminal number (\s-1UNIX\s+1 system)\s+1
+\s-1width_status_line, wsl ws No. columns in status line\s+1
+.TE
+
+(The following numeric capabilities are present in the SVr4.0 term structure,
+but are not yet documented in the man page. Comments are from the term
+structure header.)
+
+.TS
+center;
+c c c c
+c c c c
+l l l l.
+\s-1bit_image_type, bitype Yp Type of bit-image device\s+1
+\s-1buttons, btns BT Number of mouse buttons\s+1
+\s-1max_attributes, ma ma Max combined attributes terminal can handle\s+1
+\s-1maximum_windows, wnum MW Max number of definable windows\s+1
+\s-1print_rate, cps Ym Print rate in chars per second\s+1
+\s-1wide_char_size, widcs Yn Char step size in double wide mode\s+1
+
+\s-1\f3Strings:\fR\s+1
+\s-1acs_chars, acsc ac Graphics charset pairs - def=vt100\s+1
+\s-1alt_scancode_esc, scesa S8 Alternate esc for scancode emulation (default is vt100)\s+1
+\s-1back_tab, cbt bt Back tab (P)\s+1
+\s-1bell, bel bl Audible signal (bell) (P)\s+1
+\s-1bit_image_repeat, birep Xy Repeat bit image cell #1 #2 times (use tparm)\s+1
+\s-1bit_image_newline, binel Zz Move to next row of the bit image (use tparm)\s+1
+\s-1bit_image_carriage_return, bicr Yv Move to beginning of same row (use tparm)\s+1
+\s-1carriage_return, cr cr Carriage return (P*)\s+1
+\s-1change_char_pitch, cpi ZA Change # chars per inch\s+1
+\s-1change_line_pitch, lpi ZB Change # lines per inch\s+1
+\s-1change_res_horz, chr ZC Change horizontal resolution\s+1
+\s-1change_res_vert, cvr ZD Change vertical resolution\s+1
+\s-1change_scroll_region, csr cs Change to lines #1 through #2 (vt100) (PG)\s+1
+\s-1char_padding, rmp rP Like ip but when in insert mode\s+1
+\s-1char_set_names, csnm Zy List of character set names\s+1
+\s-1clear_all_tabs, tbc ct Clear all tab stops (P)\s+1
+\s-1clear_margins, mgc MC Clear all margins (top, bottom, and sides)\s+1
+\s-1clear_screen, clear cl Clear screen and home cursor (P*)\s+1
+\s-1clr_bol. el1 cb Clear to beginning of line\s+1
+\s-1clr_eol, el ce Clear to end of line (P)\s+1
+\s-1clr_eos, ed cd Clear to end of display (P*)\s+1
+\s-1code_set_init, csin ci Init sequence for multiple code sets\s+1
+\s-1color_names, colornm Yw Give name for color #1\s+1
+\s-1column_address, hpa ch Set cursor column (PG)\s+1
+\s-1command_character, cmdch CC Term. settable cmd char in prototype\s+1
+\s-1cursor_address, cup cm Screen rel. cursor motion row #1
+ col #2 (PG)\s+1
+\s-1cursor_down, cud1 do Down one line\s+1
+\s-1cursor_home, home ho Home cursor (if no cup)\s+1
+\s-1cursor_invisible, civis vi Make cursor invisible\s+1
+\s-1cursor_left, cub1 le Move cursor left one space\s+1
+\s-1cursor_mem_address, mrcup CM Memory relative cursor addressing\s+1
+\s-1cursor_normal, cnorm ve Make cursor appear normal (undo vs/vi)\s+1
+\s-1cursor_right, cuf1 nd Non-destructive space (cursor right)\s+1
+\s-1cursor_to_ll, ll ll Last line, first column (if no cup)\s+1
+\s-1cursor_up, cuu1 up Upline (cursor up)\s+1
+\s-1cursor_visible, cvvis vs Make cursor very visible\s+1
+\s-1define_bit_image_region, defbi Yx Define rectangular bit image region (use tparm)\s+1
+\s-1define_char, defc ZE Define character in a character set\s+1
+\s-1delete_character, dch1 dc Delete character (P*)\s+1
+\s-1delete_line, dl1 dl Delete line (P*)\s+1
+\s-1device_type, devt dv Indicate language/codeset support\s+1
+\s-1dis_status_line, dsl ds Disable status line\s+1
+\s-1display_pc_char, dispc S1 Display PC character\s+1
+\s-1down_half_line, hd hd Half-line down (forward 1/2 linefeed)\s+1
+\s-1ena_acs, enacs eA enable alternate char set\s+1
+\s-1end_bit_image_region, endbi Yy End bit image region (use tparm)\s+1
+\s-1enter_alt_charset_mode, smacs as Start alternate character set (P)\s+1
+\s-1enter_am_mode, smam SA turn on automatic margins\s+1
+\s-1enter_blink_mode, blink mb Turn on blinking\s+1
+\s-1enter_bold_mode, bold md Turn on bold (extra bright) mode\s+1
+\s-1enter_ca_mode, smcup ti String to begin programs that use cup\s+1
+\s-1enter_delete_mode, smdc dm Delete mode (enter)\s+1
+\s-1enter_dim_mode, dim mh Turn on half-bright mode\s+1
+\s-1enter_doublewide_mode, swidm ZF Enable double-wide mode\s+1
+\s-1enter_draft_quality, sdrfq ZG Set draft-quality printing\s+1
+\s-1enter_insert_mode, smir im Insert mode (enter);\s+1
+\s-1enter_italics_mode, sitm ZH Enable italics mode\s+1
+\s-1enter_leftward_mode, slm ZI Enable leftward carriage motion\s+1
+\s-1enter_micro_mode, smicm ZJ Enable micro-motion capabilities\s+1
+\s-1enter_near_letter_quality, snlq ZK Set NLQ printing\s+1
+\s-1enter_normal_quality, snrmq ZL Set normal quality printing\s+1
+\s-1enter_pc_charset_mode, smpch S2 Enter PC character display mode\s+1
+\s-1enter_protected_mode, prot mp Turn on protected mode\s+1
+\s-1enter_reverse_mode, rev mr Turn on reverse video mode\s+1
+\s-1enter_scancode_mode, smsc S4 Enter PC scancode mode\s+1
+\s-1enter_secure_mode, invis mk Turn on blank mode (chars invisible)\s+1
+\s-1enter_shadow_mode, sshm ZM Enable shadow-mode printing\s+1
+\s-1enter_standout_mode, smso so Begin stand out mode\s+1
+\s-1enter_subscript_mode, ssubm ZN Enable subscript printing\s+1
+\s-1enter_superscript_mode, ssupm ZO Enable superscript printing\s+1
+\s-1enter_underline_mode, smul us Start underscore mode\s+1
+\s-1enter_upward_mode, sum ZP Enable upward carriage motion\s+1
+\s-1enter_xon_mode, smxon SX Turn on xon/xoff handshaking\s+1
+\s-1erase_chars, ech ec Erase #1 characters (PG)\s+1
+\s-1exit_alt_charset_mode, rmacs ae End alternate character set (P)\s+1
+\s-1exit_am_mode, rmam RA Turn off automatic margins\s+1
+\s-1exit_attribute_mode, sgr0 me Turn off all attributes\s+1
+\s-1exit_ca_mode, rmcup te String to end programs that use cup\s+1
+\s-1exit_delete_mode, rmdc ed End delete mode\s+1
+\s-1exit_doublewide_mode, rwidm ZQ Disable doublewide printing\s+1
+\s-1exit_insert_mode, rmir ei End insert mode\s+1
+\s-1exit_italics_mode, ritm ZR Disable italic printing\s+1
+\s-1exit_leftward_mode, rlm ZS Enable rightward (normal) carriage motion\s+1
+\s-1exit_micro_mode, rmicm ZT Disable micro motion capabilities\s+1
+\s-1exit_pc_charset_mode, rmpch S3 Disable PC character display\s+1
+\s-1exit_scancode_mode, rmsc S5 Disable PC scancode mode\s+1
+\s-1exit_shadow_mode, rshm ZU Disable shadow printing\s+1
+\s-1exit_standout_mode, rmso se End stand out mode\s+1
+\s-1exit_subscript_mode, rsubm ZV Disable subscript printing\s+1
+\s-1exit_superscript_mode, rsupm ZW Disable superscript printing\s+1
+\s-1exit_underline_mode, rmul ue End underscore mode\s+1
+\s-1exit_upward_mode, rum ZX Enable downward (normal) carriage motion\s+1
+\s-1exit_xon_mode, rmxon RX turn off xon/xoff handshaking\s+1
+\s-1flash_screen, flash vb Visible bell (may not move cursor)\s+1
+\s-1form_feed, ff ff Hardcopy terminal page eject (P*)\s+1
+\s-1from_status_line, fsl fs Return from status line\s+1
+\s-1init_1string, is1 i1 Terminal initialization string\s+1
+\s-1init_2string, is2 i2 Terminal initialization string\s+1
+\s-1init_3string, is3 i3 Terminal initialization string\s+1
+\s-1init_file, if if Name of file containing is\s+1
+\s-1init_prog, iprog iP Path name of program for init\s+1
+\s-1initialize_color, initc Ic Initialize the definition of color\s+1
+\s-1initialize_pair, initp Ip Initialize color-pair\s+1
+\s-1insert_character, ich1 ic Insert character (P)\s+1
+\s-1insert_line, il1 al Add new blank line (P*)\s+1
+\s-1insert_padding, ip ip Insert pad after character inserted
+ (p*)\s+1
+\s-1key_a1, ka1 K1 Upper left of keypad\s+1
+\s-1key_a3, ka3 K3 Upper right of keypad\s+1
+\s-1key_b2, kb2 K2 Center of keypad\s+1
+\s-1key_backspace, kbs kb Sent by backspace key\s+1
+\s-1key_beg, kbeg @1 begin key\s+1
+\s-1key_btab, kcbt kB back-tab key\s+1
+\s-1key_c1, kc1 K4 Lower left of keypad\s+1
+\s-1key_c3, kc3 K5 Lower right of keypad\s+1
+\s-1key_cancel, kcan @2 cancel key\s+1
+\s-1key_catab, ktbc ka Sent by clear-all-tabs key\s+1
+\s-1key_clear, kclr kC Sent by clear screen or erase key\s+1
+\s-1key_close, kclo @3 close key\s+1
+\s-1key_command, kcmd @4 command key\s+1
+\s-1key_copy, kcpy @5 copy key\s+1
+\s-1key_create, kcrt @6 create key\s+1
+\s-1key_ctab, kctab kt Sent by clear-tab key\s+1
+\s-1key_dc, kdch1 kD Sent by delete character key\s+1
+\s-1key_dl, kdl1 kL Sent by delete line key\s+1
+\s-1key_down, kcud1 kd Sent by terminal down arrow key\s+1
+\s-1key_eic, krmir kM Sent by rmir or smir in insert mode\s+1
+\s-1key_end, kend @7 end key\s+1
+\s-1key_enter, kent @8 enter/send key\s+1
+\s-1key_eol, kel kE Sent by clear-to-end-of-line key\s+1
+\s-1key_eos, ked kS Sent by clear-to-end-of-screen key\s+1
+\s-1key_exit, kext @9 exit key\s+1
+\s-1key_f0, kf0 k0 Sent by function key f0\s+1
+\s-1key_f1, kf1 k1 Sent by function key f1\s+1
+\s-1key_f2, kf2 k2 Sent by function key f2\s+1
+\s-1key_f3, kf3 k3 Sent by function key f3\s+1
+\s-1key_f4, kf4 k4 Sent by function key f4\s+1
+\s-1key_f5, kf5 k5 Sent by function key f5\s+1
+\s-1key_f6, kf6 k6 Sent by function key f6\s+1
+\s-1key_f7, kf7 k7 Sent by function key f7\s+1
+\s-1key_f8, kf8 k8 Sent by function key f8\s+1
+\s-1key_f9, kf9 k9 Sent by function key f9\s+1
+\s-1key_f10, kf10 k; Sent by function key f10\s+1
+\s-1key_f11, kf11 F1 F11 function key\s+1
+\s-1key_f12, kf12 F2 F12 function key\s+1
+\s-1key_f13, kf13 F3 F13 function key\s+1
+\s-1key_f14, kf14 F4 F14 function key\s+1
+\s-1key_f15, kf15 F5 F15 function key\s+1
+\s-1key_f16, kf16 F6 F16 function key\s+1
+\s-1key_f17, kf17 F7 F17 function key\s+1
+\s-1key_f18, kf18 F8 F18 function key\s+1
+\s-1key_f19, kf19 F9 F19 function key\s+1
+\s-1key_f20, kf20 FA F20 function key\s+1
+\s-1key_f21, kf21 FB F21 function key\s+1
+\s-1key_f22, kf22 FC F22 function key\s+1
+\s-1key_f23, kf23 FD F23 function key\s+1
+\s-1key_f24, kf24 FE F24 function key\s+1
+\s-1key_f25, kf25 FF F25 function key\s+1
+\s-1key_f26, kf26 FG F26 function key\s+1
+\s-1key_f27, kf27 FH F27 function key\s+1
+\s-1key_f28, kf28 FI F28 function key\s+1
+\s-1key_f29, kf29 FJ F29 function key\s+1
+\s-1key_f30, kf30 FK F30 function key\s+1
+\s-1key_f31, kf31 FL F31 function key\s+1
+\s-1key_f32, kf32 FM F32 function key\s+1
+\s-1key_f33, kf33 FN F33 function key\s+1
+\s-1key_f34, kf34 FO F34 function key\s+1
+\s-1key_f35, kf35 FP F35 function key\s+1
+\s-1key_f36, kf36 FQ F36 function key\s+1
+\s-1key_f37, kf37 FR F37 function key\s+1
+\s-1key_f38, kf38 FS F38 function key\s+1
+\s-1key_f39, kf39 FT F39 function key\s+1
+\s-1key_f40, kf40 FU F40 function key\s+1
+\s-1key_f41, kf41 FV F41 function key\s+1
+\s-1key_f42, kf42 FW F42 function key\s+1
+\s-1key_f43, kf43 FX F43 function key\s+1
+\s-1key_f44, kf44 FY F44 function key\s+1
+\s-1key_f45, kf45 FZ F45 function key\s+1
+\s-1key_f46, kf46 Fa F46 function key\s+1
+\s-1key_f47, kf47 Fb F47 function key\s+1
+\s-1key_f48, kf48 Fc F48 function key\s+1
+\s-1key_f49, kf49 Fd F49 function key\s+1
+\s-1key_f50, kf50 Fe F50 function key\s+1
+\s-1key_f51, kf51 Ff F51 function key\s+1
+\s-1key_f52, kf52 Fg F52 function key\s+1
+\s-1key_f53, kf53 Fh F53 function key\s+1
+\s-1key_f54, kf54 Fi F54 function key\s+1
+\s-1key_f55, kf55 Fj F55 function key\s+1
+\s-1key_f56, kf56 Fk F56 function key\s+1
+\s-1key_f57, kf57 Fl F57 function key\s+1
+\s-1key_f58, kf58 Fm F58 function key\s+1
+\s-1key_f59, kf59 Fn F59 function key\s+1
+\s-1key_f60, kf60 Fo F60 function key\s+1
+\s-1key_f61, kf61 Fp F61 function key\s+1
+\s-1key_f62, kf62 Fq F62 function key\s+1
+\s-1key_f63, kf63 Fr F63 function key\s+1
+\s-1key_find, kfnd @0 find key\s+1
+\s-1key_help, khlp %1 help key\s+1
+\s-1key_home, khome kh Sent by home key\s+1
+\s-1key_ic, kich1 kI Sent by ins char/enter ins mode key\s+1
+\s-1key_il, kil1 kA Sent by insert line\s+1
+\s-1key_left, kcub1 kl Sent by terminal left arrow key\s+1
+\s-1key_ll, kll kH Sent by home-down key\s+1
+\s-1key_mark, kmrk %2 mark key\s+1
+\s-1key_message, kmsg %3 message key\s+1
+\s-1key_move, kmov %4 move key\s+1
+\s-1key_next, knxt %5 next key\s+1
+\s-1key_npage, knp kN Sent by next-page key\s+1
+\s-1key_open, kopn %6 open key\s+1
+\s-1key_options, kopt %7 options key\s+1
+\s-1key_ppage, kpp kP Sent by previous-page key\s+1
+\s-1key_previous, kprv %8 previous key\s+1
+\s-1key_print, kprt %9 print key\s+1
+\s-1key_redo, krdo %0 redo key\s+1
+\s-1key_reference, kref &1 reference key\s+1
+\s-1key_refresh, krfr &2 refresh key\s+1
+\s-1key_replace, krpl &3 replace key\s+1
+\s-1key_restart, krst &4 restart key\s+1
+\s-1key_resume, kres &5 resume key\s+1
+\s-1key_right, kcuf1 kr Sent by terminal right arrow key\s+1
+\s-1key_save, ksav &6 save key\s+1
+\s-1key_sbeg, kBEG &9 shifted begin key\s+1
+\s-1key_scancel, kCAN &0 shifted cancel key\s+1
+\s-1key_scommand, kCMD *1 shifted command key\s+1
+\s-1key_scopy, kCPY *2 shifted copy key\s+1
+\s-1key_screate, kCRT *3 shifted create key\s+1
+\s-1key_sdc, kDC *4 shifted delete char key\s+1
+\s-1key_sdl, kDL *5 shifted delete line key\s+1
+\s-1key_select, kslt *6 select key\s+1
+\s-1key_send, kEND *7 shifted end key\s+1
+\s-1key_seol, kEOL *8 shifted end of line key\s+1
+\s-1key_sexit, kEXT *9 shifted exit key\s+1
+\s-1key_sf, kind kF Sent by scroll-forward/down key\s+1
+\s-1key_sfind, kFND *0 shifted find key\s+1
+\s-1key_shelp, kHLP #1 shifted help key\s+1
+\s-1key_shome, kHOM #2 shifted home key\s+1
+\s-1key_sic, kIC #3 shifted insert char key\s+1
+\s-1key_sleft, kLFT #4 shifted left key\s+1
+\s-1key_smessage, kMSG %a shifted message key\s+1
+\s-1key_smove, kMOV %b shifted move key\s+1
+\s-1key_snext, kNXT %c shifted next key\s+1
+\s-1key_soptions, kOPT %d shifted options key\s+1
+\s-1key_sprevious, kPRV %e shifted previous key\s+1
+\s-1key_sprint, kPRT %f shifted print key\s+1
+\s-1key_sr, kri kR Sent by scroll-backward/up key\s+1
+\s-1key_sredo, kRDO %g shifted redo key\s+1
+\s-1key_sreplace, kRPL %h shifted replace key\s+1
+\s-1key_sright, kRIT %i shifted right key\s+1
+\s-1key_srsume, kRES %j shifted resume key\s+1
+\s-1key_ssave, kSAV !1 shifted save key\s+1
+\s-1key_ssuspend, kSPD !2 shifted suspend key\s+1
+\s-1key_stab, khts kT Sent by set-tab key\s+1
+\s-1key_sundo, kUND !3 shifted undo key\s+1
+\s-1key_suspend, kspd &7 suspend key\s+1
+\s-1key_undo, kund &8 undo key\s+1
+\s-1key_up, kcuu1 ku Sent by terminal up arrow key\s+1
+\s-1keypad_local, rmkx ke Out of "keypad transmit" mode\s+1
+\s-1keypad_xmit, smkx ks Put terminal in "keypad transmit" mode\s+1
+\s-1lab_f0, lf0 l0 Labels on function key f0 if not f0\s+1
+\s-1lab_f1, lf1 l1 Labels on function key f1 if not f1\s+1
+\s-1lab_f2, lf2 l2 Labels on function key f2 if not f2\s+1
+\s-1lab_f3, lf3 l3 Labels on function key f3 if not f3\s+1
+\s-1lab_f4, lf4 l4 Labels on function key f4 if not f4\s+1
+\s-1lab_f5, lf5 l5 Labels on function key f5 if not f5\s+1
+\s-1lab_f6, lf6 l6 Labels on function key f6 if not f6\s+1
+\s-1lab_f7, lf7 l7 Labels on function key f7 if not f7\s+1
+\s-1lab_f8, lf8 l8 Labels on function key f8 if not f8\s+1
+\s-1lab_f9, lf9 l9 Labels on function key f9 if not f9\s+1
+\s-1lab_f10, lf10 la Labels on function key f10 if not f10\s+1
+\s-1label_on, smln LO turn on soft labels\s+1
+\s-1label_off, rmln LF turn off soft labels\s+1
+\s-1meta_off, rmm mo Turn off "meta mode"\s+1
+\s-1meta_on, smm mm Turn on "meta mode" (8th bit)\s+1
+\s-1micro_column_address, mhpa ZY Like column_address for micro adjustment\s+1
+\s-1micro_down, mcud1 ZZ Like cursor_down for micro adjustment\s+1
+\s-1micro_left, mcub1 Za Like cursor_left for micro adjustment\s+1
+\s-1micro_right, mcuf1 Zb Like cursor_right for micro adjustment\s+1
+\s-1micro_row_address, mvpa Zc Like row_address for micro adjustment\s+1
+\s-1micro_up, mcuu1 Zd Like cursor_up for micro adjustment\s+1
+\s-1newline, nel nw Newline (behaves like cr followed by lf)\s+1
+\s-1order_of_pins, porder Ze Matches software buts to print-head pins\s+1
+\s-1orig_colors, oc oc Reset all color pairs\s+1
+\s-1orig_pair, op op Set default color-pair to original one\s+1
+\s-1pad_char, pad pc Pad character (rather than null)\s+1
+\s-1parm_dch, dch DC Delete #1 chars (PG*)\s+1
+\s-1parm_delete_line, dl DL Delete #1 lines (PG*)\s+1
+\s-1parm_down_cursor, cud DO Move cursor down #1 lines (PG*)\s+1
+\s-1parm_down_micro, mcud Zf Like cud for micro adjust\s+1
+\s-1parm_ich, ich IC Insert #1 blank chars (PG*)\s+1
+\s-1parm_index, indn SF Scroll forward #1 lines (PG)\s+1
+\s-1parm_insert_line, il AL Add #1 new blank lines (PG*)\s+1
+\s-1parm_left_cursor, cub LE Move cursor left #1 spaces (PG)\s+1
+\s-1parm_left_micro, mcub Zg Like cul for micro adjust\s+1
+\s-1parm_right_cursor, cuf RI Move cursor right #1 spaces (PG*)\s+1
+\s-1parm_right_micro, mcuf Zh Likr cuf for micro adjust\s+1
+\s-1parm_rindex, rin SR Scroll backward #1 lines (PG)\s+1
+\s-1parm_up_cursor, cuu UP Move cursor up #1 lines (PG*)\s+1
+\s-1parm_up_micro, mcuu Zi Like cuu for micro adjust\s+1
+\s-1pkey_key, pfkey pk Prog funct key #1 to type string #2\s+1
+\s-1pkey_local, pfloc pl Prog funct key #1 to execute string #2\s+1
+\s-1pkey_xmit, pfx px Prog funct key #1 to xmit string #2\s+1
+\s-1pkey_plab, pfxl xl Program key #1 to xmit #2 and show #3\s+1
+\s-1plab_norm, pln pn program label #1 to show string #2\s+1
+\s-1print_screen, mc0 ps Print contents of the screen\s+1
+\s-1prtr_non, mc5p pO Turn on the printer for #1 bytes\s+1
+\s-1prtr_off, mc4 pf Turn off the printer\s+1
+\s-1prtr_on, mc5 po Turn on the printer\s+1
+\s-1repeat_char, rep rp Repeat char #1 #2 times. (PG*)\s+1
+\s-1req_for_input, rfi RF request for input\s+1
+\s-1reset_1string, rs1 r1 Reset terminal completely to sane modes.\s+1
+\s-1reset_2string, rs2 r2 Reset terminal completely to sane modes.\s+1
+\s-1reset_3string, rs3 r3 Reset terminal completely to sane modes.\s+1
+\s-1reset_file, rf rf Name of file containing reset string\s+1
+\s-1restore_cursor, rc rc Restore cursor to position of last sc\s+1
+\s-1row_address, vpa cv Vertical position absolute (set row) (PG)\s+1
+\s-1save_cursor, sc sc Save cursor position (P)\s+1
+\s-1scancode_escape, scesc S7 Escape for scancode emulation\s+1
+\s-1scroll_forward, ind sf Scroll text up (P)\s+1
+\s-1scroll_reverse, ri sr Scroll text down (P)\s+1
+\s-1select_char_set, scs Zj Select character set\s+1
+\s-1set0_des_seq, s0ds s0 Shift to codeset 0 (EUC set 0, ASCII)\s+1
+\s-1set1_des_seq, s1ds s1 Shift to codeset 1\s+1
+\s-1set2_des_seq, s2ds s2 Shift to codeset 2\s+1
+\s-1set3_des_seq, s3ds s3 Shift to codeset 3\s+1
+\s-1set_a_background, setab AB Set background color using ANSI escape\s+1
+\s-1set_a_foreground, setaf AF Set foreground color using ANSI escape\s+1
+\s-1set_attributes, sgr sa Define the video attributes (PG9)\s+1
+\s-1set_background, setb Sb Set current background color\s+1
+\s-1set_bottom_margin, smgb Zk Set bottom margin at current line\s+1
+\s-1set_bottom_margin_parm, smgbp Zl Set bottom line at line #1 or #2 lines from bottom\s+1
+\s-1set_color_band, setcolor Yz Change to ribbon color #1\s+1
+\s-1set_color_pair, scp sp Set current color pair\s+1
+\s-1set_foreground, setf Sf Set current foreground color\s+1
+\s-1set_left_margin, smgl ML Set left margin at current line\s+1
+\s-1set_left_margin_parm, smglp Zm Set left (right) margin at #1 (#2)\s+1
+\s-1set_lr_margin, smglr ML Set both left and right margins\s+1
+\s-1set_page_length, slines YZ Set page length to #1 lines (use tparm)\s+1
+\s-1set_right_margin, smgr MR Set right margin at current column\s+1
+\s-1set_right_margin_parm, smgrp Zn Set right margin at column #1\s+1
+\s-1set_tab, hts st Set a tab in all rows, current column\s+1
+\s-1set_tb_margin, smgtb MT Sets both top and bottom margins\s+1
+\s-1set_top_margin, smgt Zo Set top margin at current line\s+1
+\s-1set_top_margin_parm, smgtp Zp Set top margin at line #1\s+1
+\s-1set_window, wind wi Current window is lines #1-#2 cols #3-#4\s+1
+\s-1start_bit_image, sbim Zq Start printing bit image graphics\s+1
+\s-1start_char_set_def, scsd Zr Start definition of a character set\s+1
+\s-1stop_bit_image, rbim Zs End printing bit image graphics\s+1
+\s-1stop_char_set_def, rcsd Zt End definition of character set\s+1
+\s-1subscript_characters, subcs Zu List of subscriptable chars\s+1
+\s-1superscript_characters, supcs Zv List of superscriptable chars\s+1
+\s-1tab, ht ta Tab to next 8 space hardware tab stop\s+1
+\s-1these_cause_cr, docr Zw These characters cause a CR\s+1
+\s-1to_status_line, tsl ts Go to status line, column #1\s+1
+\s-1underline_char, uc uc Underscore one char and move past it\s+1
+\s-1up_half_line, hu hu Half-line up (reverse 1/2 linefeed)\s+1
+\s-1xoff_character, xoffc XF XON character\s+1
+\s-1xon_character, xonc XN XOFF character\s+1
+.TE
+
+(The following string capabilities are present in the SVr4.0 term structure,
+but are not documented in the man page. Comments are from the term
+structure header.)
+
+.TS
+center;
+c c c c
+c c c c
+l l l l.
+\s-1label_format, fln Lf ??\s+1
+\s-1set_clock, sclk SC Set time-of-day clock\s+1
+\s-1display_clock, dclk DK Display time-of-day clock\s+1
+\s-1remove_clock, rmclk RC Remove time-of-day clock??\s+1
+\s-1create_window, cwin CW Define win #1 to go from #2,#3 to #4,#5\s+1
+\s-1goto_window, wingo WG Goto window #1\s+1
+\s-1hangup, hup HU Hang up phone\s+1
+\s-1dial_phone, dial DI Dial phone number #1\s+1
+\s-1quick_dial, qdial QD Dial phone number #1, without progress detection\s+1
+\s-1tone, tone TO Select touch tone dialing\s+1
+\s-1pulse, pulse PU Select pulse dialing\s+1
+\s-1flash_hook, hook fh Flash the switch hook\s+1
+\s-1fixed_pause, pause PA Pause for 2-3 seconds\s+1
+\s-1wait_tone, wait WA Wait for dial tone\s+1
+\s-1user0, u0 u0 User string # 0\s+1
+\s-1user1, u1 u1 User string # 1\s+1
+\s-1user2, u2 u2 User string # 2\s+1
+\s-1user3, u3 u3 User string # 3\s+1
+\s-1user4, u4 u4 User string # 4\s+1
+\s-1user5, u5 u5 User string # 5\s+1
+\s-1user6, u6 u6 User string # 6\s+1
+\s-1user7, u7 u7 User string # 7\s+1
+\s-1user8, u8 u8 User string # 8\s+1
+\s-1user9, u9 u9 User string # 9\s+1
+\s-1get_mouse, getm Gm Curses should get button events\s+1
+\s-1key_mouse, kmous Km ??\s+1
+\s-1mouse_info, minfo Mi Mouse status information\s+1
+\s-1pc_term_options, pctrm S6 PC terminal options\s+1
+\s-1req_mouse_pos, reqmp RQ Request mouse position report\s+1
+\s-1zero_motion, zerom, Zx No motion for the subsequent character\s+1
+.TE
+.PP
+.B A Sample Entry
+.PP
+The following entry, which describes the Concept\-100, is among the more
+complex entries in the
+.I terminfo
+file as of this writing.
+.PP
+.nf
+.in -2
+.ta .3i
+.ft CW
+\s-2concept100\||\|c100|\|\|concept\||\|c104\||\|c100-4p\||\|concept 100,
+ am, bel=^G, blank=\eEH, blink=\eEC, clear=^L$<2*>, cnorm=\eEw,
+ cols#80, cr=^M$<9>, cub1=^H, cud1=^J, cuf1=\eE=,
+ cup=\eEa%p1%' '%+%c%p2%' '%+%c,
+ cuu1=\eE;, cvvis=\eEW, db, dch1=\eE^A$<16*>, dim=\eEE, dl1=\eE^B$<3*>,
+ ed=\eE^C$<16*>, el=\eE^U$<16>, eo, flash=\eEk$<20>\eEK, ht=\et$<8>,
+ il1=\eE^R$<3*>, in, ind=^J, .ind=^J$<9>, ip=$<16*>,
+ is2=\eEU\eEf\eE7\eE5\eE8\eEl\eENH\eEK\eE\e200\eEo&\e200\eEo\e47\eE,
+ kbs=^h, kcub1=\eE>, kcud1=\eE<, kcuf1=\eE=, kcuu1=\eE;,
+ kf1=\eE5, kf2=\eE6, kf3=\eE7, khome=\eE?,
+ lines#24, mir, pb#9600, prot=\eEI, rep=\eEr%p1%c%p2%' '%+%c$<.2*>,
+ rev=\eED, rmcup=\eEv $<6>\eEp\er\en, rmir=\eE\e200, rmkx=\eEx,
+ rmso=\eEd\eEe, rmul=\eEg, rmul=\eEg, sgr0=\eEN\e200,
+ smcup=\eEU\eEv 8p\eEp\er, smir=\eE^P, smkx=\eEX, smso=\eEE\eED,
+ smul=\eEG, tabs, ul, vt#8, xenl,\s+2
+.in +2
+.fi
+.ft R
+.PP
+Entries may continue onto multiple lines by placing white space at
+the beginning of each line except the first.
+Comments may be included on lines beginning with ``#''.
+Capabilities in
+.I terminfo
+are of three types:
+Boolean capabilities which indicate that the terminal has
+some particular feature, numeric capabilities giving the size of the terminal
+or the size of particular delays, and string
+capabilities, which give a sequence which can be used to perform particular
+terminal operations.
+.PP
+.B Types of Capabilities
+.PP
+All capabilities have names. For instance, the fact that
+the Concept has
+.I "automatic margins"
+(i.e., an automatic return and linefeed
+when the end of a line is reached) is indicated by the capability \fBam\fR.
+Hence the description of the Concept includes \fBam\fR.
+Numeric capabilities are followed by the character `#' and then the value.
+Thus \fBcols\fR, which indicates the number of columns the terminal has,
+gives the value `80' for the Concept.
+.PP
+Finally, string valued capabilities, such as \fBel\fR (clear to end of line
+sequence) are given by the two-character code, an `=', and then a string
+ending at the next following `,'. A delay in milliseconds may appear
+anywhere in such a capability, enclosed in $<..> brackets,
+as in \fBel\fP=\eEK$<3>,
+and padding characters are supplied by
+.I tputs
+to provide this delay.
+The delay can be either a number, e.g., `20', or a number followed by
+an `*', i.e., `3*'. A `*' indicates that the padding required is proportional
+to the number of lines affected by the operation, and the amount given is
+the per-affected-unit padding required.
+(In the case of insert character, the factor is still the number of
+.IR lines
+affected.
+This is always one unless the terminal has \fBxenl\fP and the software uses it.)
+When a `*' is specified, it is sometimes useful to give a delay of the form
+`3.5' to specify a delay per unit to tenths of milliseconds.
+(Only one decimal place is allowed.)
+.PP
+A number of escape sequences are provided in the string valued capabilities
+for easy encoding of characters there. Both \fB\eE\fR and \fB\ee\fR
+map to an \s-1ESCAPE\s0 character,
+\fB^x\fR maps to a control-x for any appropriate x, and the sequences
+\fB\en \el \er \et \eb \ef \es\fR give
+a newline, linefeed, return, tab, backspace, formfeed, and space.
+Other escapes include \e^ for ^, \e\e for \e, \e, for comma, \e: for :,
+and \e0 for null.
+(\e0 will produce \e200, which does not terminate a string but behaves
+as a null character on most terminals.)
+Finally, characters may be given as three octal digits after a \fB\e\fR.
+.PP
+Sometimes individual capabilities must be commented out.
+To do this, put a period before the capability name.
+For example, see the second
+.B ind
+in the example above.
+.br
+.ne 5
+.PP
+.B Preparing Descriptions
+.PP
+We now outline how to prepare descriptions of terminals.
+The most effective way to prepare a terminal description is by imitating
+the description of a similar terminal in
+.I terminfo
+and to build up a description gradually, using partial descriptions
+with
+.I vi
+or some other screen-oriented program to check that they are correct.
+Be aware that a very unusual terminal may expose deficiencies in
+the ability of the
+.I terminfo
+file to describe it
+or bugs in the screen-handling code of the test program.
+To easily test a new terminal description you can set the environment variable
+TERMINFO to a pathname of a directory containing the
+compiled description you are working
+on and programs will look there rather than in
+.IR \*d .
+To get the padding for insert line right (if the terminal manufacturer
+did not document it) a severe test is to edit /etc/passwd at 9600 baud,
+delete 16 or so lines from the middle of the screen, then hit the `u'
+key several times quickly.
+If the terminal messes up, more padding is usually needed.
+A similar test can be used for insert character.
+.PP
+.B Basic Capabilities
+.PP
+The number of columns on each line for the terminal is given by the
+\fBcols\fR numeric capability. If the terminal is a \s-1CRT\s0, then the
+number of lines on the screen is given by the \fBlines\fR capability.
+If the terminal wraps around to the beginning of the next line when
+it reaches the right margin, then it should have the \fBam\fR capability.
+If the terminal can clear its screen, leaving the cursor in the home
+position, then this is given by the \fBclear\fR string capability.
+If the terminal overstrikes
+(rather than clearing a position when a character is struck over)
+then it should have the \fBos\fR capability.
+If the terminal is a printing terminal, with no soft copy unit,
+give it both
+.B hc
+and
+.BR os .
+.RB ( os
+applies to storage scope terminals, such as \s-1TEKTRONIX\s+1 4010
+series, as well as hard copy and APL terminals.)
+If there is a code to move the cursor to the left edge of the current
+row, give this as
+.BR cr .
+(Normally this will be carriage return, control M.)
+If there is a code to produce an audible signal (bell, beep, etc)
+give this as
+.BR bel .
+.PP
+If there is a code to move the cursor one position to the left
+(such as backspace) that capability should be given as
+.BR cub1 .
+Similarly, codes to move to the right, up, and down should be
+given as
+.BR cuf1 ,
+.BR cuu1 ,
+and
+.BR cud1 .
+These local cursor motions should not alter the text they pass over,
+for example, you would not normally use `\fBcuf1\fP=\ ' because the
+space would erase the character moved over.
+.PP
+A very important point here is that the local cursor motions encoded
+in
+.I terminfo
+are undefined at the left and top edges of a \s-1CRT\s0 terminal.
+Programs should never attempt to backspace around the left edge,
+unless
+.B bw
+is given,
+and never attempt to go up locally off the top.
+In order to scroll text up, a program will go to the bottom left corner
+of the screen and send the
+.B ind
+(index) string.
+.PP
+To scroll text down, a program goes to the top left corner
+of the screen and sends the
+.B ri
+(reverse index) string.
+The strings
+.B ind
+and
+.B ri
+are undefined when not on their respective corners of the screen.
+.PP
+Parameterized versions of the scrolling sequences are
+.B indn
+and
+.B rin
+which have the same semantics as
+.B ind
+and
+.B ri
+except that they take one parameter, and scroll that many lines.
+They are also undefined except at the appropriate edge of the screen.
+.PP
+The \fBam\fR capability tells whether the cursor sticks at the right
+edge of the screen when text is output, but this does not necessarily
+apply to a
+.B cuf1
+from the last column.
+The only local motion which is defined from the left edge is if
+.B bw
+is given, then a
+.B cub1
+from the left edge will move to the right edge of the previous row.
+If
+.B bw
+is not given, the effect is undefined.
+This is useful for drawing a box around the edge of the screen, for example.
+If the terminal has switch selectable automatic margins,
+the
+.I terminfo
+file usually assumes that this is on; i.e., \fBam\fR.
+If the terminal has a command which moves to the first column of the next
+line, that command can be given as
+.B nel
+(newline).
+It does not matter if the command clears the remainder of the current line,
+so if the terminal has no
+.B cr
+and
+.B lf
+it may still be possible to craft a working
+.B nel
+out of one or both of them.
+.PP
+These capabilities suffice to describe hardcopy and \*(lqglass-tty\*(rq terminals.
+Thus the model 33 teletype is described as
+.PP
+.DT
+.nf
+.ft CW
+.in -7
+ \s-133\||\|tty33\||\|tty\||\|model 33 teletype,
+ bel=^G, cols#72, cr=^M, cud1=^J, hc, ind=^J, os,\s+1
+.in +7
+.ft R
+.PP
+while the Lear Siegler \s-1ADM\-3\s0 is described as
+.PP
+.DT
+.nf
+.ft CW
+.in -7
+ \s-1adm3\||\|3\||\|lsi adm3,
+ am, bel=^G, clear=^Z, cols#80, cr=^M, cub1=^H, cud1=^J,
+ ind=^J, lines#24,\s+1
+.in +7
+.ft R
+.fi
+.PP
+.B Parameterized Strings
+.PP
+Cursor addressing and other strings requiring parameters
+in the terminal are described by a
+parameterized string capability, with
+.IR printf (3S)
+like escapes \fB%x\fR in it.
+For example, to address the cursor, the
+.B cup
+capability is given, using two parameters:
+the row and column to address to.
+(Rows and columns are numbered from zero and refer to the
+physical screen visible to the user, not to any unseen memory.)
+If the terminal has memory relative cursor addressing,
+that can be indicated by
+.BR mrcup .
+.PP
+The parameter mechanism uses a stack and special \fB%\fP codes
+to manipulate it. Typically a sequence will push one of the
+parameters onto the stack and then print it in some format.
+Often more complex operations are necessary.
+.PP
+The \fB%\fR encodings have the following meanings:
+.PP
+.DT
+.nf
+.ta .5i 1.5i
+ \s-1%% outputs `%'
+ %d print pop() as in printf
+ %2d print pop() like %2d
+ %3d print pop() like %3d
+ %02d
+ %03d as in printf
+ %c print pop() gives %c
+ %s print pop() gives %s
+
+ %p[1-9] push ith parm
+ %P[a-z] set variable [a-z] to pop()
+ %g[a-z] get variable [a-z] and push it
+ %'c' char constant c
+ %{nn} integer constant nn
+
+ %+ %- %* %/ %m
+ arithmetic (%m is mod): push(pop() op pop())
+ %& %| %^ bit operations: push(pop() op pop())
+ %= %> %< logical operations: push(pop() op pop())
+ %! %~ unary operations push(op pop())
+ %i add 1 to first two parms (for ANSI terminals)
+
+ %? expr %t thenpart %e elsepart %;
+ if-then-else, %e elsepart is optional.
+ else-if's are possible ala Algol 68:
+ %? c\d1\u %t b\d1\u %e c\d2\u %t b\d2\u %e c\d3\u %t b\d3\u %e c\d4\u %t b\d4\u %e %;
+\s+1 c\di\u are conditions, b\di\u are bodies.
+.fi
+.PP
+Binary operations are in postfix form with the operands in the usual order.
+That is, to get x-5 one would use "%gx%{5}%-".
+.PP
+Consider the HP2645, which, to get to row 3 and column 12, needs
+to be sent \eE&a12c03Y padded for 6 milliseconds. Note that the order
+of the rows and columns is inverted here, and that the row and column
+are printed as two digits.
+Thus its \fBcup\fR capability is \*(lqcup=6\eE&%p2%2dc%p1%2dY\*(rq.
+.PP
+The Microterm \s-1ACT-IV\s0 needs the current row and column sent
+preceded by a \fB^T\fR, with the row and column simply encoded in binary,
+\*(lqcup=^T%p1%c%p2%c\*(rq.
+Terminals which use \*(lq%c\*(rq need to be able to
+backspace the cursor (\fBcub1\fR),
+and to move the cursor up one line on the screen (\fBcuu1\fR).
+This is necessary because it is not always safe to transmit \fB\en\fR
+\fB^D\fR and \fB\er\fR, as the system may change or discard them.
+(The library routines dealing with terminfo set tty modes so that
+tabs are never expanded, so \et is safe to send.
+This turns out to be essential for the Ann Arbor 4080.)
+.PP
+A final example is the \s-1LSI ADM\s0-3a, which uses row and column
+offset by a blank character, thus \*(lqcup=\eE=%p1%' '%+%c%p2%' '%+%c\*(rq.
+After sending `\eE=', this pushes the first parameter, pushes the
+ASCII value for a space (32), adds them (pushing the sum on the stack
+in place of the two previous values) and outputs that value as a character.
+Then the same is done for the second parameter.
+More complex arithmetic is possible using the stack.
+.PP
+If the terminal has row or column absolute cursor addressing,
+these can be given as single parameter capabilities
+.B hpa
+(horizontal position absolute)
+and
+.B vpa
+(vertical position absolute).
+Sometimes these are shorter than the more general two parameter
+sequence (as with the hp2645) and can be used in preference to
+.B cup .
+If there are parameterized local motions (e.g., move
+.I n
+spaces to the right) these can be given as
+.BR cud ,
+.BR cub ,
+.BR cuf ,
+and
+.BR cuu
+with a single parameter indicating how many spaces to move.
+These are primarily useful if the terminal does not have
+.BR cup ,
+such as the \s-1TEKTRONIX\s+1 4025.
+.PP
+.B Cursor Motions
+.PP
+If the terminal has a fast way to home the cursor
+(to very upper left corner of screen) then this can be given as
+\fBhome\fR; similarly a fast way of getting to the lower left-hand corner
+can be given as \fBll\fR; this may involve going up with \fBcuu1\fR
+from the home position,
+but a program should never do this itself (unless \fBll\fR does) because it
+can make no assumption about the effect of moving up from the home position.
+Note that the home position is the same as addressing to (0,0):
+to the top left corner of the screen, not of memory.
+(Thus, the \eEH sequence on HP terminals cannot be used for
+.BR home .)
+.PP
+.B Area Clears
+.PP
+If the terminal can clear from the current position to the end of the
+line, leaving the cursor where it is, this should be given as \fBel\fR.
+If the terminal can clear from the current position to the end of the
+display, then this should be given as \fBed\fR.
+\fBEd\fR is only defined from the first column of a line.
+(Thus, it can be simulated by a request to delete a large number of lines,
+if a true
+.B ed
+is not available.)
+.PP
+.B Insert/delete line
+.PP
+If the terminal can open a new blank line before the line where the cursor
+is, this should be given as \fBil1\fR; this is done only from the first
+position of a line. The cursor must then appear on the newly blank line.
+If the terminal can delete the line which the cursor is on, then this
+should be given as \fBdl1\fR; this is done only from the first position on
+the line to be deleted.
+Versions of
+.B il1
+and
+.B dl1
+which take a single parameter and insert or delete that many lines can
+be given as
+.B il
+and
+.BR dl .
+If the terminal has a settable scrolling region (like the vt100)
+the command to set this can be described with the
+.B csr
+capability, which takes two parameters:
+the top and bottom lines of the scrolling region.
+The cursor position is, alas, undefined after using this command.
+It is possible to get the effect of insert or delete line using
+this command \- the
+.B sc
+and
+.B rc
+(save and restore cursor) commands are also useful.
+Inserting lines at the top or bottom of the screen can also be
+done using
+.B ri
+or
+.B ind
+on many terminals without a true insert/delete line,
+and is often faster even on terminals with those features.
+.PP
+If the terminal has the ability to define a window as part of
+memory, which all commands affect,
+it should be given as the parameterized string
+.BR wind .
+The four parameters are the starting and ending lines in memory
+and the starting and ending columns in memory, in that order.
+.PP
+If the terminal can retain display memory above, then the
+\fBda\fR capability should be given; if display memory can be retained
+below, then \fBdb\fR should be given. These indicate
+that deleting a line or scrolling may bring non-blank lines up from below
+or that scrolling back with \fBri\fR may bring down non-blank lines.
+.PP
+.B Insert/Delete Character
+.PP
+There are two basic kinds of intelligent terminals with respect to
+insert/delete character which can be described using
+.I terminfo.
+The most common insert/delete character operations affect only the characters
+on the current line and shift characters off the end of the line rigidly.
+Other terminals, such as the Concept 100 and the Perkin Elmer Owl, make
+a distinction between typed and untyped blanks on the screen, shifting
+upon an insert or delete only to an untyped blank on the screen which is
+either eliminated, or expanded to two untyped blanks. You can determine the
+kind of terminal you have by clearing the screen and then typing
+text separated by cursor motions. Type \*(lqabc\ \ \ \ def\*(rq using local
+cursor motions (not spaces) between the \*(lqabc\*(rq and the \*(lqdef\*(rq.
+Then position the cursor before the \*(lqabc\*(rq and put the terminal in insert
+mode. If typing characters causes the rest of the line to shift
+rigidly and characters to fall off the end, then your terminal does
+not distinguish between blanks and untyped positions. If the \*(lqabc\*(rq
+shifts over to the \*(lqdef\*(rq which then move together around the end of the
+current line and onto the next as you insert, you have the second type of
+terminal, and should give the capability \fBin\fR, which stands for
+\*(lqinsert null\*(rq.
+While these are two logically separate attributes (one line vs. multiline
+insert mode, and special treatment of untyped spaces) we have seen no
+terminals whose insert mode cannot be described with the single attribute.
+.PP
+Terminfo can describe both terminals which have an insert mode, and terminals
+which send a simple sequence to open a blank position on the current line.
+Give as \fBsmir\fR the sequence to get into insert mode.
+Give as \fBrmir\fR the sequence to leave insert mode.
+Now give as \fBich1\fR any sequence needed to be sent just before sending
+the character to be inserted. Most terminals with a true insert mode
+will not give \fBich1\fR; terminals which send a sequence to open a screen
+position should give it here.
+(If your terminal has both, insert mode is usually preferable to \fBich1\fP.
+Do not give both unless the terminal actually requires both
+to be used in combination.)
+If post insert padding is needed, give this as a number of milliseconds
+in \fBip\fR (a string option). Any other sequence which may need to be
+sent after an insert of a single character may also be given in \fBip\fR.
+If your terminal needs both to be placed into an `insert mode' and
+a special code to precede each inserted character, then both
+.BR smir / rmir
+and
+.B ich1
+can be given, and both will be used.
+The
+.B ich
+capability, with one parameter,
+.IR n ,
+will repeat the effects of
+.B ich1
+.I n
+times.
+.PP
+It is occasionally necessary to move around while in insert mode
+to delete characters on the same line (e.g., if there is a tab after
+the insertion position). If your terminal allows motion while in
+insert mode you can give the capability \fBmir\fR to speed up inserting
+in this case. Omitting \fBmir\fR will affect only speed. Some terminals
+(notably Datamedia's) must not have \fBmir\fR because of the way their
+insert mode works.
+.PP
+Finally, you can specify
+.B dch1
+to delete a single character,
+.B dch
+with one parameter,
+.IR n ,
+to delete
+.I n characters,
+and delete mode by giving \fBsmdc\fR and \fBrmdc\fR
+to enter and exit delete mode (any mode the terminal needs to be placed
+in for
+.B dch1
+to work).
+.PP
+A command to erase
+.I n
+characters (equivalent to outputting
+.I n
+blanks without moving the cursor)
+can be given as
+.B ech
+with one parameter.
+.PP
+.B "Highlighting, Underlining, and Visible Bells"
+.PP
+If your terminal has one or more kinds of display attributes,
+these can be represented in a number of different ways.
+You should choose one display form as
+\f2standout mode\fR,
+representing a good, high contrast, easy-on-the-eyes,
+format for highlighting error messages and other attention getters.
+(If you have a choice, reverse video plus half-bright is good,
+or reverse video alone.)
+The sequences to enter and exit standout mode
+are given as \fBsmso\fR and \fBrmso\fR, respectively.
+If the code to change into or out of standout
+mode leaves one or even two blank spaces on the screen,
+as the TVI 912 and Teleray 1061 do,
+then \fBxmc\fR should be given to tell how many spaces are left.
+.PP
+Codes to begin underlining and end underlining can be given as \fBsmul\fR
+and \fBrmul\fR respectively.
+If the terminal has a code to underline the current character and move
+the cursor one space to the right,
+such as the Microterm Mime,
+this can be given as \fBuc\fR.
+.PP
+Other capabilities to enter various highlighting modes include
+.B blink
+(blinking)
+.B bold
+(bold or extra bright)
+.B dim
+(dim or half-bright)
+.B invis
+(blanking or invisible text)
+.B prot
+(protected)
+.B rev
+(reverse video)
+.B sgr0
+(turn off
+.I all
+attribute modes)
+.B smacs
+(enter alternate character set mode)
+and
+.B rmacs
+(exit alternate character set mode).
+Turning on any of these modes singly may or may not turn off other modes.
+.PP
+If there is a sequence to set arbitrary combinations of modes,
+this should be given as
+.B sgr
+(set attributes),
+taking 9 parameters.
+Each parameter is either 0 or 1, as the corresponding attribute is on or off.
+The 9 parameters are, in order:
+standout, underline, reverse, blink, dim, bold, blank, protect, alternate
+character set.
+Not all modes need be supported by
+.BR sgr ,
+only those for which corresponding separate attribute commands exist.
+.PP
+Terminals with the ``magic cookie'' glitch
+.RB ( xmc )
+deposit special ``cookies'' when they receive mode-setting sequences,
+which affect the display algorithm rather than having extra bits for
+each character.
+Some terminals, such as the HP 2621, automatically leave standout
+mode when they move to a new line or the cursor is addressed.
+Programs using standout mode should exit standout mode before
+moving the cursor or sending a newline,
+unless the
+.B msgr
+capability, asserting that it is safe to move in standout mode, is present.
+.PP
+If the terminal has
+a way of flashing the screen to indicate an error quietly (a bell replacement)
+then this can be given as \fBflash\fR; it must not move the cursor.
+.PP
+If the cursor needs to be made more visible than normal when it is
+not on the bottom line (to make, for example, a non-blinking underline into an
+easier to find block or blinking underline)
+give this sequence as
+.BR cvvis .
+If there is a way to make the cursor completely invisible, give that as
+.BR civis .
+The capability
+.BR cnorm
+should be given which undoes the effects of both of these modes.
+.PP
+If the terminal needs to be in a special mode when running
+a program that uses these capabilities,
+the codes to enter and exit this mode can be given as \fBsmcup\fR and \fBrmcup\fR.
+This arises, for example, from terminals like the Concept with more than
+one page of memory.
+If the terminal has only memory relative cursor addressing and not screen
+relative cursor addressing, a one screen-sized window must be fixed into
+the terminal for cursor addressing to work properly.
+This is also used for the \s-1TEKTRONIX\s+1 4025,
+where
+.B smcup
+sets the command character to be the one used by terminfo.
+.PP
+If your terminal correctly generates underlined characters
+(with no special codes needed)
+even though it does not overstrike,
+then you should give the capability \fBul\fR.
+If overstrikes are erasable with a blank,
+then this should be indicated by giving \fBeo\fR.
+.PP
+.B Keypad
+.PP
+If the terminal has a keypad that transmits codes when the keys are pressed,
+this information can be given. Note that it is not possible to handle
+terminals where the keypad only works in local (this applies, for example,
+to the unshifted HP 2621 keys).
+If the keypad can be set to transmit or not transmit,
+give these codes as \fBsmkx\fR and \fBrmkx\fR.
+Otherwise the keypad is assumed to always transmit.
+The codes sent by the left arrow, right arrow, up arrow, down arrow,
+and home keys can be given as \fBkcub1, kcuf1, kcuu1, kcud1,
+\fRand\fB khome\fR respectively.
+If there are function keys such as f0, f1, ..., f10, the codes they send
+can be given as \fBkf0, kf1, ..., kf10\fR.
+If these keys have labels other than the default f0 through f10, the labels
+can be given as \fBlf0, lf1, ..., lf10\fR.
+The codes transmitted by certain other special keys can be given:
+.B kll
+(home down),
+.B kbs
+(backspace),
+.B ktbc
+(clear all tabs),
+.B kctab
+(clear the tab stop in this column),
+.B kclr
+(clear screen or erase key),
+.B kdch1
+(delete character),
+.B kdl1
+(delete line),
+.B krmir
+(exit insert mode),
+.B kel
+(clear to end of line),
+.B ked
+(clear to end of screen),
+.B kich1
+(insert character or enter insert mode),
+.B kil1
+(insert line),
+.B knp
+(next page),
+.B kpp
+(previous page),
+.B kind
+(scroll forward/down),
+.B kri
+(scroll backward/up),
+.B khts
+(set a tab stop in this column).
+In addition, if the keypad has a 3 by 3 array of keys including the four
+arrow keys, the other five keys can be given as
+.BR ka1 ,
+.BR ka3 ,
+.BR kb2 ,
+.BR kc1 ,
+and
+.BR kc3 .
+These keys are useful when the effects of a 3 by 3 directional pad are needed.
+.PP
+.B Tabs and Initialization
+.PP
+If the terminal has hardware tabs, the command to advance to the next
+tab stop can be given as
+.B ht
+(usually control I).
+A ``backtab'' command which moves leftward to the next tab stop can
+be given as
+.BR cbt .
+By convention, if the teletype modes indicate that tabs are being
+expanded by the computer rather than being sent to the terminal,
+programs should not use
+.B ht
+or
+.B cbt
+even if they are present, since the user may not have the tab stops
+properly set.
+If the terminal has hardware tabs which are initially set every
+.I n
+spaces when the terminal is powered up,
+the numeric parameter
+.B it
+is given, showing the number of spaces the tabs are set to.
+This is normally used by the
+.IR tset
+command to determine whether to set the mode for hardware tab expansion,
+and whether to set the tab stops.
+If the terminal has tab stops that can be saved in nonvolatile memory,
+the terminfo description can assume that they are properly set.
+.PP
+Other capabilities
+include
+.BR is1 ,
+.BR is2 ,
+and
+.BR is3 ,
+initialization strings for the terminal,
+.BR iprog ,
+the path name of a program to be run to initialize the terminal,
+and \fBif\fR, the name of a file containing long initialization strings.
+These strings are expected to set the terminal into modes consistent
+with the rest of the terminfo description.
+They are normally sent to the terminal, by the
+.IR tset
+program, each time the user logs in.
+They will be printed in the following order:
+.BR is1 ;
+.BR is2 ;
+setting tabs using
+.B tbc
+and
+.BR hts ;
+.BR if ;
+running the program
+.BR iprog ;
+and finally
+.BR is3 .
+Most initialization is done with
+.BR is2 .
+Special terminal modes can be set up without duplicating strings
+by putting the common sequences in
+.B is2
+and special cases in
+.B is1
+and
+.BR is3 .
+A pair of sequences that does a harder reset from a totally unknown state
+can be analogously given as
+.BR rs1 ,
+.BR rs2 ,
+.BR rf ,
+and
+.BR rs3 ,
+analogous to
+.B is2
+and
+.BR if .
+These strings are output by the
+.IR reset
+program, which is used when the terminal gets into a wedged state.
+Commands are normally placed in
+.B rs2
+and
+.B rf
+only if they produce annoying effects on the screen and are not
+necessary when logging in.
+For example, the command to set the vt100 into 80-column mode would
+normally be part of
+.BR is2 ,
+but it causes an annoying glitch of the screen and is not normally
+needed since the terminal is usually already in 80 column mode.
+.PP
+If there are commands to set and clear tab stops, they can be given as
+.B tbc
+(clear all tab stops)
+and
+.B hts
+(set a tab stop in the current column of every row).
+If a more complex sequence is needed to set the tabs than can be
+described by this, the sequence can be placed in
+.B is2
+or
+.BR if .
+.PP
+Delays
+.PP
+Certain capabilities control padding in the teletype driver.
+These are primarily needed by hard copy terminals, and are used
+by the
+.IR tset
+program to set teletype modes appropriately.
+Delays embedded in the capabilities
+.BR cr ,
+.BR ind ,
+.BR cub1 ,
+.BR ff ,
+and
+.B tab
+will cause the appropriate delay bits to be set in the teletype driver.
+If
+.B pb
+(padding baud rate)
+is given,
+these values can be ignored at baud rates below the value of
+.BR pb .
+.PP
+.B Miscellaneous
+.PP
+If the terminal requires other than a null (zero) character as a pad,
+then this can be given as \fBpad\fR.
+Only the first character of the
+.B pad
+string is used.
+.PP
+If the terminal has an extra ``status line'' that is not normally
+used by software, this fact can be indicated.
+If the status line is viewed as an extra line below the bottom line,
+into which one can cursor address normally
+(such as the Heathkit h19's 25th line, or the 24th line of a vt100
+which is set to a 23-line scrolling region),
+the capability
+.B hs
+should be given.
+Special strings to go to the beginning of the status
+line and to return from the status line can be given as
+.B tsl
+and
+.BR fsl .
+.RB ( fsl
+must leave the cursor position in the same place it was before
+.BR tsl .
+If necessary, the
+.B sc
+and
+.B rc
+strings can be included in
+.B tsl
+and
+.B fsl
+to get this effect.)
+The parameter
+.B tsl
+takes one parameter, which is the column number of the status line
+the cursor is to be moved to.
+If escape sequences and other special commands, such as tab, work
+while in the status line, the flag
+.B eslok
+can be given.
+A string which turns off the status line (or otherwise erases its
+contents) should be given as
+.BR dsl .
+If the terminal has commands to save and restore the position of the cursor,
+give them as
+.B sc
+and
+.BR rc .
+The status line is normally assumed to be the same width as the rest
+of the screen, e.g.,
+.BR cols .
+If the status line is a different width (possibly because the terminal
+does not allow an entire line to be loaded) the width, in columns,
+can be indicated with the numeric parameter
+.BR wsl .
+.PP
+If the terminal can move up or down half a line,
+this can be indicated with
+.B hu
+(half-line up)
+and
+.B hd
+(half-line down).
+This is primarily useful for superscripts and subscripts on hardcopy terminals.
+If a hardcopy terminal can eject to the next page (form feed), give this as
+.B ff
+(usually control L).
+.PP
+If there is a command to repeat a given character a given number of
+times (to save time transmitting a large number of identical characters)
+this can be indicated with the parameterized string
+.BR rep .
+The first parameter is the character to be repeated and the second
+is the number of times to repeat it.
+Thus, tparm(repeat_char, 'x', 10) is the same as `xxxxxxxxxx'.
+.PP
+If the terminal has a settable command character, such as the \s-1TEKTRONIX\s+1 4025,
+this can be indicated with
+.BR cmdch .
+A prototype command character is chosen which is used in all capabilities.
+This character is given in the
+.B cmdch
+capability to identify it.
+The following convention is supported on some UNIX systems:
+The environment is to be searched for a
+.B CC
+variable, and if found, all
+occurrences of the prototype character are replaced with the character
+in the environment variable.
+.PP
+Terminal descriptions that do not represent a specific kind of known
+terminal, such as
+.IR switch ,
+.IR dialup ,
+.IR patch ,
+and
+.IR network ,
+should include the
+.B gn
+(generic) capability so that programs can complain that they do not know
+how to talk to the terminal.
+(This capability does not apply to
+.I virtual
+terminal descriptions for which the escape sequences are known.)
+.PP
+If the terminal uses xon/xoff handshaking for flow control, give
+.BR xon .
+Padding information should still be included so that routines can
+make better decisions about costs, but actual pad characters will
+not be transmitted.
+.PP
+If the terminal has a ``meta key'' which acts as a shift key,
+setting the 8th bit of any character transmitted, this fact can
+be indicated with
+.BR km .
+Otherwise, software will assume that the 8th bit is parity and it
+will usually be cleared.
+If strings exist to turn this ``meta mode'' on and off, they
+can be given as
+.B smm
+and
+.BR rmm .
+.PP
+If the terminal has more lines of memory than will fit on the screen
+at once, the number of lines of memory can be indicated with
+.BR lm .
+A value of
+.BR lm #0
+indicates that the number of lines is not fixed,
+but that there is still more memory than fits on the screen.
+.PP
+If the terminal is one of those supported by the \s-1UNIX\s+1 virtual
+terminal protocol, the terminal number can be given as
+.BR vt .
+.PP
+Media copy
+strings which control an auxiliary printer connected to the terminal
+can be given as
+.BR mc0 :
+print the contents of the screen,
+.BR mc4 :
+turn off the printer, and
+.BR mc5 :
+turn on the printer.
+When the printer is on, all text sent to the terminal will be sent
+to the printer.
+It is undefined whether the text is also displayed on the terminal screen
+when the printer is on.
+A variation
+.B mc5p
+takes one parameter, and leaves the printer on for as many characters
+as the value of the parameter, then turns the printer off.
+The parameter should not exceed 255.
+All text, including
+.BR mc4 ,
+is transparently passed to the printer while an
+.B mc5p
+is in effect.
+.PP
+Strings to program function keys can be given as
+.BR pfkey ,
+.BR pfloc ,
+and
+.BR pfx .
+Each of these strings takes two parameters: the function key number to
+program (from 0 to 10) and the string to program it with.
+Function key numbers out of this range may program undefined keys in
+a terminal dependent manner.
+The difference between the capabilities is that
+.B pfkey
+causes pressing the given key to be the same as the user typing the
+given string;
+.B pfloc
+causes the string to be executed by the terminal in local; and
+.B pfx
+causes the string to be transmitted to the computer.
+.PP
+.B Glitches and Braindamage
+.PP
+Hazeltine terminals, which do not allow `~' characters to be displayed should
+indicate \fBhz\fR.
+.PP
+Terminals which ignore a linefeed immediately after an \fBam\fR wrap,
+such as the Concept and vt100,
+should indicate \fBxenl\fR.
+.PP
+If
+.B el
+is required to get rid of standout
+(instead of merely writing normal text on top of it),
+\fBxhp\fP should be given.
+.PP
+Teleray terminals, where tabs turn all characters moved over to blanks,
+should indicate \fBxt\fR (destructive tabs).
+Note: the variable indicating this is now `dest_tabs_magic_smso'; in
+older versions, it was teleray_glitch.
+This glitch is also taken to mean that it is not possible to position
+the cursor on top of a ``magic cookie'',
+that to erase standout mode it is instead necessary to use
+delete and insert line.
+.PP
+The Beehive Superbee, which is unable to correctly transmit the escape
+or control C characters, has
+.BR xsb ,
+indicating that the f1 key is used for escape and f2 for control C.
+(Only certain Superbees have this problem, depending on the ROM.)
+Note that in older terminfo versions, this capability was called
+`beehive_glitch'; it is now `no_esc_ctl_c'.
+.PP
+Other specific terminal problems may be corrected by adding more
+capabilities of the form \fBx\fIx\fR.
+.PP
+.B Similar Terminals
+.PP
+If there are two very similar terminals,
+one can be defined as being just like the other with certain exceptions.
+The string capability \fBuse\fR can be given
+with the name of the similar terminal.
+The capabilities given before
+.B use
+override those in the terminal type invoked by
+.BR use .
+A capability can be canceled by placing \fBxx@\fR to the left of the
+capability definition, where xx is the capability.
+For example, the entry
+.PP
+ 2621-nl, smkx@, rmkx@, use=2621,
+.PP
+defines a 2621-nl that does not have the \fBsmkx\fR or \fBrmkx\fR capabilities,
+and hence does not turn on the function key labels when in visual mode.
+This is useful for different modes for a terminal, or for different
+user preferences.
+.SH FILES
+.TP 25
+\*d/?/*
+files containing terminal descriptions
+.SH "SEE ALSO"
+tic(1), curses(3), printf(3), term(5).
+.SH AUTHORS
+Pavel Curtis, Zeyd M. Ben-Halim
+.\"#
+.\"# The following sets edit modes for GNU EMACS
+.\"# Local Variables:
+.\"# mode:nroff
+.\"# fill-column:79
+.\"# End:
diff --git a/lib/libncurses/terminfo.h b/lib/libncurses/terminfo.h
new file mode 100644
index 0000000..c238040
--- /dev/null
+++ b/lib/libncurses/terminfo.h
@@ -0,0 +1,2 @@
+/* fake header for sources compatibility */
+#include <nterm.h>
diff --git a/lib/libncurses/unctrl.h b/lib/libncurses/unctrl.h
new file mode 100644
index 0000000..31205d3
--- /dev/null
+++ b/lib/libncurses/unctrl.h
@@ -0,0 +1,19 @@
+
+/*
+ * unctrl.h
+ *
+ * Display a printable version of a control character.
+ * Control characters are displayed in caret notation (^x), DELETE is displayed
+ * as ^?. Printable characters sre displatyed as is.
+ *
+ * The returned pointer points to a static buffer which gets overwritten by
+ * each call. Therefore, you must copy the resulting string to a safe place
+ * before calling unctrl() again.
+ *
+ */
+#ifndef _UNCTRL_H
+#define _UNCTRL_H 1
+
+extern char *unctrl(unsigned char);
+
+#endif /* _UNCTRL_H */
diff --git a/lib/libncurses/version.h b/lib/libncurses/version.h
new file mode 100644
index 0000000..45a8b46
--- /dev/null
+++ b/lib/libncurses/version.h
@@ -0,0 +1,3 @@
+
+#define NCURSES_VERSION "1.8.6"
+
diff --git a/lib/libopie/Makefile b/lib/libopie/Makefile
new file mode 100644
index 0000000..a65cb2c
--- /dev/null
+++ b/lib/libopie/Makefile
@@ -0,0 +1,31 @@
+# Makefile for libopie
+#
+# $Id: Makefile,v 1.2 1997/02/22 15:07:48 peter Exp $
+#
+OPIE_DIST?= ${.CURDIR}/../../contrib/opie
+DIST_DIR= ${OPIE_DIST}/${.CURDIR:T}
+
+KEYFILE?= \"/etc/opiekeys\"
+EXTFILE?= \"/etc/opiekeys.ext\"
+
+.PATH: ${DIST_DIR} ${OPIE_DIST}/libmissing
+
+LIB= opie
+SRCS= atob8.c btoa8.c btoh.c challenge.c getsequence.c hash.c hashlen.c \
+ keycrunch.c lock.c lookup.c newseed.c parsechallenge.c passcheck.c \
+ passwd.c randomchallenge.c readpass.c unlock.c verify.c version.c \
+ btoe.c accessfile.c generator.c insecure.c getutmpentry.c \
+ readrec.c writerec.c login.c open.c \
+ getutline.c pututline.c endutent.c # from libmissing
+
+CFLAGS+=-I${.CURDIR} -I${OPIE_DIST} -I${DIST_DIR} \
+ -DSTD_KEY_FILE=${KEYFILE} -DEXT_KEY_FILE=${EXTFILE}
+
+MAN4= ${OPIE_DIST}/opie.4
+MAN5= ${OPIE_DIST}/opiekeys.5 ${OPIE_DIST}/opieaccess.5
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${OPIE_DIST}/opie.h \
+ ${DESTDIR}/usr/include
+
+.include <bsd.lib.mk>
diff --git a/lib/libopie/config.h b/lib/libopie/config.h
new file mode 100644
index 0000000..b01598a
--- /dev/null
+++ b/lib/libopie/config.h
@@ -0,0 +1,322 @@
+/* Define if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
+#endif
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if on MINIX. */
+/* #undef _MINIX */
+
+/* Define if the system does not provide POSIX.1 features except
+ with this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you want the FTP daemon to support anonymous logins. */
+/* #undef DOANONYMOUS */
+
+/* The default value of the PATH environment variable */
+#define DEFAULT_PATH "/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin"
+
+/* Defined if the file /etc/default/login exists
+ (and, presumably, should be looked at by login) */
+/* #undef HAVE_ETC_DEFAULT_LOGIN */
+
+/* Defined to the name of a file that contains a list of files whose
+ permissions and ownerships should be changed on login. */
+/* #undef HAVE_LOGIN_PERMFILE */
+
+/* Defined to the name of a file that contains a list of environment
+ values that should be set on login. */
+/* #undef HAVE_LOGIN_ENVFILE */
+
+/* Defined if the file /etc/securetty exists
+ (and, presumably, should be looked at by login) */
+/* #undef HAVE_SECURETTY */
+
+/* Defined if the file /etc/shadow exists
+ (and, presumably, should be looked at for shadow passwords) */
+/* #undef HAVE_ETC_SHADOW */
+
+/* The path to the access file, if we're going to use it */
+/* #undef PATH_ACCESS_FILE */
+
+/* The path to the mail spool, if we know it */
+#define PATH_MAIL "/var/mail"
+
+/* Defined if the system's profile (/etc/profile) displays
+ the motd file */
+/* #undef HAVE_MOTD_IN_PROFILE */
+
+/* Defined if the system's profile (/etc/profile) informs the
+ user of new mail */
+/* #undef HAVE_MAILCHECK_IN_PROFILE */
+
+/* Define if you have a nonstandard gettimeofday() that takes one argument
+ instead of two. */
+/* #undef HAVE_ONE_ARG_GETTIMEOFDAY */
+
+/* Define if the system has the getenv function */
+#define HAVE_GETENV 1
+
+/* Define if the system has the setenv function */
+#define HAVE_SETENV 1
+
+/* Define if the system has the /var/adm/sulog file */
+/* #undef HAVE_SULOG */
+
+/* Define if the system has the unsetenv function */
+#define HAVE_UNSETENV 1
+
+/* Define if the compiler can handle ANSI-style argument lists */
+#define HAVE_ANSIDECL 1
+
+/* Define if the compiler can handle ANSI-style prototypes */
+#define HAVE_ANSIPROTO 1
+
+/* Define if the system has an ANSI-style printf (returns int instead of char *) */
+#define HAVE_ANSISPRINTF 1
+
+/* Define if the compiler can handle ANSI-style variable argument lists */
+#define HAVE_ANSISTDARG 1
+
+/* Define if the compiler can handle void argument lists to functions */
+#define HAVE_VOIDARG 1
+
+/* Define if the compiler can handle void return "values" from functions */
+#define HAVE_VOIDRET 1
+
+/* Define if the compiler can handle void pointers to our liking */
+#define HAVE_VOIDPTR 1
+
+/* Define if the /bin/ls command seems to support the -g flag */
+/* #undef HAVE_LS_G_FLAG */
+
+/* Define if there is a ut_pid field in struct utmp */
+/* #undef HAVE_UT_PID */
+
+/* Define if there is a ut_type field in struct utmp */
+/* #undef HAVE_UT_TYPE */
+
+/* Define if there is a ut_name field in struct utmp */
+#define HAVE_UT_NAME 1
+
+/* Define if there is a ut_host field in struct utmp */
+#define HAVE_UT_HOST 1
+
+/* Define if you have the bcopy function. */
+/* #undef HAVE_BCOPY */
+
+/* Define if you have the bzero function. */
+/* #undef HAVE_BZERO */
+
+/* Define if you have the endspent function. */
+/* #undef HAVE_ENDSPENT */
+
+/* Define if you have the fpurge function. */
+#define HAVE_FPURGE 1
+
+/* Define if you have the getdtablesize function. */
+/* #undef HAVE_GETDTABLESIZE */
+
+/* Define if you have the getgroups function. */
+#define HAVE_GETGROUPS 1
+
+/* Define if you have the gethostname function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define if you have the getspent function. */
+/* #undef HAVE_GETSPENT */
+
+/* Define if you have the gettimeofday function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if you have the getttynam function. */
+#define HAVE_GETTTYNAM 1
+
+/* Define if you have the getutxline function. */
+/* #undef HAVE_GETUTXLINE */
+
+/* Define if you have the getwd function. */
+/* #undef HAVE_GETWD */
+
+/* Define if you have the index function. */
+/* #undef HAVE_INDEX */
+
+/* Define if you have the lstat function. */
+#define HAVE_LSTAT 1
+
+/* Define if you have the pututxline function. */
+/* #undef HAVE_PUTUTXLINE */
+
+/* Define if you have the rindex function. */
+/* #undef HAVE_RINDEX */
+
+/* Define if you have the setegid function. */
+#define HAVE_SETEGID 1
+
+/* Define if you have the seteuid function. */
+#define HAVE_SETEUID 1
+
+/* Define if you have the setgroups function. */
+#define HAVE_SETGROUPS 1
+
+/* Define if you have the setlogin function. */
+#define HAVE_SETLOGIN 1
+
+/* Define if you have the setpriority function. */
+#define HAVE_SETPRIORITY 1
+
+/* Define if you have the setregid function. */
+#define HAVE_SETREGID 1
+
+/* Define if you have the setresgid function. */
+/* #undef HAVE_SETRESGID */
+
+/* Define if you have the setresuid function. */
+/* #undef HAVE_SETRESUID */
+
+/* Define if you have the setreuid function. */
+#define HAVE_SETREUID 1
+
+/* Define if you have the setvbuf function. */
+#define HAVE_SETVBUF 1
+
+/* Define if you have the sigblock function. */
+/* #undef HAVE_SIGBLOCK */
+
+/* Define if you have the sigsetmask function. */
+/* #undef HAVE_SIGSETMASK */
+
+/* Define if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define if you have the strftime function. */
+#define HAVE_STRFTIME 1
+
+/* Define if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define if you have the sysconf function. */
+#define HAVE_SYSCONF 1
+
+/* Define if you have the ttyslot function. */
+#define HAVE_TTYSLOT 1
+
+/* Define if you have the <crypt.h> header file. */
+/* #undef HAVE_CRYPT_H */
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <lastlog.h> header file. */
+/* #undef HAVE_LASTLOG_H */
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <ndir.h> header file. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <shadow.h> header file. */
+/* #undef HAVE_SHADOW_H */
+
+/* Define if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/dir.h> header file. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/ndir.h> header file. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/signal.h> header file. */
+#define HAVE_SYS_SIGNAL_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <utmpx.h> header file. */
+/* #undef HAVE_UTMPX_H */
+
+/* Define if you have the crypt library (-lcrypt). */
+#define HAVE_LIBCRYPT 1
+
+/* Define if you have the nsl library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define if you have the posix library (-lposix). */
+/* #undef HAVE_LIBPOSIX */
+
+/* Define if you have the socket library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
diff --git a/lib/libpam/modules/pam_kerberosIV/klogin.c b/lib/libpam/modules/pam_kerberosIV/klogin.c
new file mode 100644
index 0000000..4263786
--- /dev/null
+++ b/lib/libpam/modules/pam_kerberosIV/klogin.c
@@ -0,0 +1,204 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)klogin.c 8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+
+#ifdef KERBEROS
+#include <sys/param.h>
+#include <sys/syslog.h>
+#include <des.h>
+#include <kerberosIV/krb.h>
+
+#include <err.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define INITIAL_TICKET "krbtgt"
+#define VERIFY_SERVICE "rcmd"
+
+extern int notickets;
+extern char *krbtkfile_env;
+
+/*
+ * Attempt to log the user in using Kerberos authentication
+ *
+ * return 0 on success (will be logged in)
+ * 1 if Kerberos failed (try local password in login)
+ */
+int
+klogin(pw, instance, localhost, password)
+ struct passwd *pw;
+ char *instance, *localhost, *password;
+{
+ int kerror;
+ char realm[REALM_SZ], savehost[MAXHOSTNAMELEN];
+ char tkt_location[MAXPATHLEN];
+ char *krb_get_phost();
+ extern int noticketsdontcomplain;
+
+#ifdef KLOGIN_PARANOID
+ AUTH_DAT authdata;
+ KTEXT_ST ticket;
+ struct hostent *hp;
+ unsigned long faddr;
+
+ noticketsdontcomplain = 0; /* enable warning message */
+#endif
+
+ /*
+ * Root logins don't use Kerberos.
+ * If we have a realm, try getting a ticket-granting ticket
+ * and using it to authenticate. Otherwise, return
+ * failure so that we can try the normal passwd file
+ * for a password. If that's ok, log the user in
+ * without issuing any tickets.
+ */
+ if (strcmp(pw->pw_name, "root") == 0 ||
+ krb_get_lrealm(realm, 0) != KSUCCESS)
+ return (1);
+
+ noticketsdontcomplain = 0; /* enable warning message */
+
+ /*
+ * get TGT for local realm
+ * tickets are stored in a file named TKT_ROOT plus uid
+ * except for user.root tickets.
+ */
+
+ if (strcmp(instance, "root") != 0)
+ (void)sprintf(tkt_location, "%s%d", TKT_ROOT, pw->pw_uid);
+ else {
+ (void)sprintf(tkt_location, "%s_root_%d", TKT_ROOT, pw->pw_uid);
+ krbtkfile_env = tkt_location;
+ }
+ (void)krb_set_tkt_string(tkt_location);
+
+ /*
+ * Set real as well as effective ID to 0 for the moment,
+ * to make the kerberos library do the right thing.
+ */
+ if (setuid(0) < 0) {
+ warnx("setuid");
+ return (1);
+ }
+ kerror = krb_get_pw_in_tkt(pw->pw_name, instance,
+ realm, INITIAL_TICKET, realm, DEFAULT_TKT_LIFE, password);
+
+ /*
+ * If we got a TGT, get a local "rcmd" ticket and check it so as to
+ * ensure that we are not talking to a bogus Kerberos server.
+ *
+ * There are 2 cases where we still allow a login:
+ * 1: the VERIFY_SERVICE doesn't exist in the KDC
+ * 2: local host has no srvtab, as (hopefully) indicated by a
+ * return value of RD_AP_UNDEC from krb_rd_req().
+ */
+ if (kerror != INTK_OK) {
+ if (kerror != INTK_BADPW && kerror != KDC_PR_UNKNOWN) {
+ syslog(LOG_ERR, "Kerberos intkt error: %s",
+ krb_err_txt[kerror]);
+ dest_tkt();
+ }
+ return (1);
+ }
+
+ if (chown(TKT_FILE, pw->pw_uid, pw->pw_gid) < 0)
+ syslog(LOG_ERR, "chown tkfile (%s): %m", TKT_FILE);
+
+ (void)strncpy(savehost, krb_get_phost(localhost), sizeof(savehost));
+ savehost[sizeof(savehost)-1] = NULL;
+
+#ifdef KLOGIN_PARANOID
+ /*
+ * if the "VERIFY_SERVICE" doesn't exist in the KDC for this host,
+ * still allow login with tickets, but log the error condition.
+ */
+
+ kerror = krb_mk_req(&ticket, VERIFY_SERVICE, savehost, realm, 33);
+ if (kerror == KDC_PR_UNKNOWN) {
+ syslog(LOG_NOTICE,
+ "warning: TGT not verified (%s); %s.%s not registered, or srvtab is wrong?",
+ krb_err_txt[kerror], VERIFY_SERVICE, savehost);
+ notickets = 0;
+ return (0);
+ }
+
+ if (kerror != KSUCCESS) {
+ warnx("unable to use TGT: (%s)", krb_err_txt[kerror]);
+ syslog(LOG_NOTICE, "unable to use TGT: (%s)",
+ krb_err_txt[kerror]);
+ dest_tkt();
+ return (1);
+ }
+
+ if (!(hp = gethostbyname(localhost))) {
+ syslog(LOG_ERR, "couldn't get local host address");
+ dest_tkt();
+ return (1);
+ }
+
+ memmove((void *)&faddr, (void *)hp->h_addr, sizeof(faddr));
+
+ kerror = krb_rd_req(&ticket, VERIFY_SERVICE, savehost, faddr,
+ &authdata, "");
+
+ if (kerror == KSUCCESS) {
+ notickets = 0;
+ return (0);
+ }
+
+ /* undecipherable: probably didn't have a srvtab on the local host */
+ if (kerror = RD_AP_UNDEC) {
+ syslog(LOG_NOTICE, "krb_rd_req: (%s)\n", krb_err_txt[kerror]);
+ dest_tkt();
+ return (1);
+ }
+ /* failed for some other reason */
+ warnx("unable to verify %s ticket: (%s)", VERIFY_SERVICE,
+ krb_err_txt[kerror]);
+ syslog(LOG_NOTICE, "couldn't verify %s ticket: %s", VERIFY_SERVICE,
+ krb_err_txt[kerror]);
+ dest_tkt();
+ return (1);
+#else
+ notickets = 0;
+ return (0);
+#endif
+}
+#endif
diff --git a/lib/libpam/modules/pam_login_access/login.access.5 b/lib/libpam/modules/pam_login_access/login.access.5
new file mode 100644
index 0000000..201c185
--- /dev/null
+++ b/lib/libpam/modules/pam_login_access/login.access.5
@@ -0,0 +1,50 @@
+.\" this is comment
+.Dd April 30, 1994
+.Dt LOGIN.ACCESS 5
+.Os FreeBSD 1.2
+.Sh NAME
+.Nm login.access
+.Nd Login access control table
+.Sh DESCRIPTION
+The
+.Nm login.access
+file specifies (user, host) combinations and/or (user, tty)
+combinations for which a login will be either accepted or refused.
+.Pp
+When someone logs in, the
+.Nm login.access
+is scanned for the first entry that
+matches the (user, host) combination, or, in case of non-networked
+logins, the first entry that matches the (user, tty) combination. The
+permissions field of that table entry determines whether the login will
+be accepted or refused.
+.Pp
+Each line of the login access control table has three fields separated by a
+":" character: permission : users : origins
+
+The first field should be a "+" (access granted) or "-" (access denied)
+character. The second field should be a list of one or more login names,
+group names, or ALL (always matches). The third field should be a list
+of one or more tty names (for non-networked logins), host names, domain
+names (begin with "."), host addresses, internet network numbers (end
+with "."), ALL (always matches) or LOCAL (matches any string that does
+not contain a "." character). If you run NIS you can use @netgroupname
+in host or user patterns.
+
+The EXCEPT operator makes it possible to write very compact rules.
+
+The group file is searched only when a name does not match that of the
+logged-in user. Only groups are matched in which users are explicitly
+listed: the program does not look at a user's primary group id value.
+.Sh FILES
+.Bl -tag -width /etc/login.access -compact
+.It Pa /etc/login.access
+The
+.Nm login.access
+file resides in
+.Pa /etc .
+.El
+.Sh SEE ALSO
+.Xr login 1
+.Sh AUTHOR
+Guido van Rooij
diff --git a/lib/libpam/modules/pam_login_access/login_access.c b/lib/libpam/modules/pam_login_access/login_access.c
new file mode 100644
index 0000000..b5003c7
--- /dev/null
+++ b/lib/libpam/modules/pam_login_access/login_access.c
@@ -0,0 +1,239 @@
+ /*
+ * This module implements a simple but effective form of login access
+ * control based on login names and on host (or domain) names, internet
+ * addresses (or network numbers), or on terminal line names in case of
+ * non-networked logins. Diagnostics are reported through syslog(3).
+ *
+ * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
+ */
+
+#ifdef LOGIN_ACCESS
+#ifndef lint
+static char sccsid[] = "%Z% %M% %I% %E% %U%";
+#endif
+
+#include <stdio.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <grp.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "pathnames.h"
+
+ /* Delimiters for fields and for lists of users, ttys or hosts. */
+
+static char fs[] = ":"; /* field separator */
+static char sep[] = ", \t"; /* list-element separator */
+
+ /* Constants to be used in assignments only, not in comparisons... */
+
+#define YES 1
+#define NO 0
+
+static int list_match();
+static int user_match();
+static int from_match();
+static int string_match();
+
+/* login_access - match username/group and host/tty with access control file */
+
+int
+login_access(user, from)
+char *user;
+char *from;
+{
+ FILE *fp;
+ char line[BUFSIZ];
+ char *perm; /* becomes permission field */
+ char *users; /* becomes list of login names */
+ char *froms; /* becomes list of terminals or hosts */
+ int match = NO;
+ int end;
+ int lineno = 0; /* for diagnostics */
+
+ /*
+ * Process the table one line at a time and stop at the first match.
+ * Blank lines and lines that begin with a '#' character are ignored.
+ * Non-comment lines are broken at the ':' character. All fields are
+ * mandatory. The first field should be a "+" or "-" character. A
+ * non-existing table means no access control.
+ */
+
+ if ((fp = fopen(_PATH_LOGACCESS, "r")) != NULL) {
+ while (!match && fgets(line, sizeof(line), fp)) {
+ lineno++;
+ if (line[end = strlen(line) - 1] != '\n') {
+ syslog(LOG_ERR, "%s: line %d: missing newline or line too long",
+ _PATH_LOGACCESS, lineno);
+ continue;
+ }
+ if (line[0] == '#')
+ continue; /* comment line */
+ while (end > 0 && isspace(line[end - 1]))
+ end--;
+ line[end] = 0; /* strip trailing whitespace */
+ if (line[0] == 0) /* skip blank lines */
+ continue;
+ if (!(perm = strtok(line, fs))
+ || !(users = strtok((char *) 0, fs))
+ || !(froms = strtok((char *) 0, fs))
+ || strtok((char *) 0, fs)) {
+ syslog(LOG_ERR, "%s: line %d: bad field count", _PATH_LOGACCESS,
+ lineno);
+ continue;
+ }
+ if (perm[0] != '+' && perm[0] != '-') {
+ syslog(LOG_ERR, "%s: line %d: bad first field", _PATH_LOGACCESS,
+ lineno);
+ continue;
+ }
+ match = (list_match(froms, from, from_match)
+ && list_match(users, user, user_match));
+ }
+ (void) fclose(fp);
+ } else if (errno != ENOENT) {
+ syslog(LOG_ERR, "cannot open %s: %m", _PATH_LOGACCESS);
+ }
+ return (match == 0 || (line[0] == '+'));
+}
+
+/* list_match - match an item against a list of tokens with exceptions */
+
+static int list_match(list, item, match_fn)
+char *list;
+char *item;
+int (*match_fn) ();
+{
+ char *tok;
+ int match = NO;
+
+ /*
+ * Process tokens one at a time. We have exhausted all possible matches
+ * when we reach an "EXCEPT" token or the end of the list. If we do find
+ * a match, look for an "EXCEPT" list and recurse to determine whether
+ * the match is affected by any exceptions.
+ */
+
+ for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) {
+ if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */
+ break;
+ if ((match = (*match_fn)(tok, item)) != NULL) /* YES */
+ break;
+ }
+ /* Process exceptions to matches. */
+
+ if (match != NO) {
+ while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT"))
+ /* VOID */ ;
+ if (tok == 0 || list_match((char *) 0, item, match_fn) == NO)
+ return (match);
+ }
+ return (NO);
+}
+
+/* netgroup_match - match group against machine or user */
+
+static int netgroup_match(group, machine, user)
+gid_t group;
+char *machine;
+char *user;
+{
+#ifdef NIS
+ static char *mydomain = 0;
+
+ if (mydomain == 0)
+ yp_get_default_domain(&mydomain);
+ return (innetgr(group, machine, user, mydomain));
+#else
+ syslog(LOG_ERR, "NIS netgroup support not configured");
+ return 0;
+#endif
+}
+
+/* user_match - match a username against one token */
+
+static int user_match(tok, string)
+char *tok;
+char *string;
+{
+ struct group *group;
+ int i;
+
+ /*
+ * If a token has the magic value "ALL" the match always succeeds.
+ * Otherwise, return YES if the token fully matches the username, or if
+ * the token is a group that contains the username.
+ */
+
+ if (tok[0] == '@') { /* netgroup */
+ return (netgroup_match(tok + 1, (char *) 0, string));
+ } else if (string_match(tok, string)) { /* ALL or exact match */
+ return (YES);
+ } else if ((group = getgrnam(tok)) != NULL) {/* try group membership */
+ for (i = 0; group->gr_mem[i]; i++)
+ if (strcasecmp(string, group->gr_mem[i]) == 0)
+ return (YES);
+ }
+ return (NO);
+}
+
+/* from_match - match a host or tty against a list of tokens */
+
+static int from_match(tok, string)
+char *tok;
+char *string;
+{
+ int tok_len;
+ int str_len;
+
+ /*
+ * If a token has the magic value "ALL" the match always succeeds. Return
+ * YES if the token fully matches the string. If the token is a domain
+ * name, return YES if it matches the last fields of the string. If the
+ * token has the magic value "LOCAL", return YES if the string does not
+ * contain a "." character. If the token is a network number, return YES
+ * if it matches the head of the string.
+ */
+
+ if (tok[0] == '@') { /* netgroup */
+ return (netgroup_match(tok + 1, string, (char *) 0));
+ } else if (string_match(tok, string)) { /* ALL or exact match */
+ return (YES);
+ } else if (tok[0] == '.') { /* domain: match last fields */
+ if ((str_len = strlen(string)) > (tok_len = strlen(tok))
+ && strcasecmp(tok, string + str_len - tok_len) == 0)
+ return (YES);
+ } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */
+ if (strchr(string, '.') == 0)
+ return (YES);
+ } else if (tok[(tok_len = strlen(tok)) - 1] == '.' /* network */
+ && strncmp(tok, string, tok_len) == 0) {
+ return (YES);
+ }
+ return (NO);
+}
+
+/* string_match - match a string against one token */
+
+static int string_match(tok, string)
+char *tok;
+char *string;
+{
+
+ /*
+ * If the token has the magic value "ALL" the match always succeeds.
+ * Otherwise, return YES if the token fully matches the string.
+ */
+
+ if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */
+ return (YES);
+ } else if (strcasecmp(tok, string) == 0) { /* try exact match */
+ return (YES);
+ }
+ return (NO);
+}
+#endif /* LOGIN_ACCES */
diff --git a/lib/libpcap/Makefile b/lib/libpcap/Makefile
new file mode 100644
index 0000000..9256d62
--- /dev/null
+++ b/lib/libpcap/Makefile
@@ -0,0 +1,40 @@
+# Makefile for libpcap
+# $Id: Makefile,v 1.15 1997/02/22 15:07:50 peter Exp $
+
+LIB= pcap
+SRCS= grammar.c tokdefs.h pcap-bpf.c \
+ pcap.c inet.c gencode.c optimize.c nametoaddr.c \
+ etherent.c savefile.c bpf_filter.c bpf_image.c \
+ scanner.c
+MAN3= pcap.3
+CLEANFILES+= tokdefs.h grammar.c scanner.c y.tab.c y.tab.h
+
+DEFS= -DHAVE_SYS_IOCCOM_H=1 -DHAVE_SYS_SOCKIO_H=1 \
+ -DHAVE_ETHER_HOSTTON=1 -DHAVE_STRERROR=1 \
+ -DHAVE_SOCKADDR_SA_LEN=1 -DLBL_ALIGN=1
+
+CFLAGS+=-I. -Dyylval=pcap_lval ${DEFS}
+
+SHLIB_MAJOR=2
+SHLIB_MINOR=2
+
+#
+# Magic to grab sources out of src/contrib
+#
+PCAP_DISTDIR?=${.CURDIR}/../../contrib/libpcap
+CFLAGS+=-I${PCAP_DISTDIR} -I${PCAP_DISTDIR}/lbl -I${PCAP_DISTDIR}/bpf
+.PATH: ${PCAP_DISTDIR}
+.PATH: ${PCAP_DISTDIR}/bpf/net
+
+beforeinstall:
+.for i in pcap.h pcap-namedb.h
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${PCAP_DISTDIR}/$i \
+ ${DESTDIR}/usr/include
+.endfor
+
+tokdefs.h grammar.c: grammar.y
+ ${YACC} ${YACCFLAGS} -d ${PCAP_DISTDIR}/grammar.y
+ mv y.tab.c grammar.c
+ mv y.tab.h tokdefs.h
+
+.include <bsd.lib.mk>
diff --git a/lib/libpthread/Makefile b/lib/libpthread/Makefile
new file mode 100644
index 0000000..363f308
--- /dev/null
+++ b/lib/libpthread/Makefile
@@ -0,0 +1,21 @@
+# $Id$
+#
+# All library objects contain rcsid strings by default; they may be
+# excluded as a space-saving measure. To produce a library that does
+# not contain these strings, delete -DLIBC_RCS and -DSYSLIBC_RCS
+# from CFLAGS below. To remove these strings from just the system call
+# stubs, remove just -DSYSLIBC_RCS from CFLAGS.
+LIB=c_r
+SHLIB_MAJOR= 3
+SHLIB_MINOR= 0
+CFLAGS+=-DLIBC_RCS -DSYSLIBC_RCS
+CFLAGS+=-DPTHREAD_KERNEL -D_THREAD_SAFE -I${.CURDIR}/uthread
+AINC= -I${.CURDIR}/../libc/${MACHINE} -I${.CURDIR}/uthread
+PRECIOUSLIB= yes
+
+.include "${.CURDIR}/../libc/Makefile.inc"
+.include "${.CURDIR}/man/Makefile.inc"
+.include "${.CURDIR}/uthread/Makefile.inc"
+.include "${.CURDIR}/sys/Makefile.inc"
+
+.include <bsd.lib.mk>
diff --git a/lib/libpthread/man/Makefile.inc b/lib/libpthread/man/Makefile.inc
new file mode 100644
index 0000000..7d67fb8
--- /dev/null
+++ b/lib/libpthread/man/Makefile.inc
@@ -0,0 +1,17 @@
+# $Id$
+
+# POSIX thread man files
+
+.PATH: ${.CURDIR}/man
+
+MAN3+= pthread_create.3 \
+ pthread_detach.3 \
+ pthread_equal.3 \
+ pthread_exit.3 \
+ pthread_getspecific.3 \
+ pthread_join.3 \
+ pthread_key_create.3 \
+ pthread_key_delete.3 \
+ pthread_once.3 \
+ pthread_self.3 \
+ pthread_setspecific.3
diff --git a/lib/libpthread/man/pthread_create.3 b/lib/libpthread/man/pthread_create.3
new file mode 100644
index 0000000..aa81588
--- /dev/null
+++ b/lib/libpthread/man/pthread_create.3
@@ -0,0 +1,109 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_CREATE 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_create
+.Nd create a new thread
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_create "pthread_t *thread" "const pthread_attr_t *attr" "void *(*start_routine)(void *)" "void *arg"
+.Sh DESCRIPTION
+The
+.Fn pthread_create
+function is used to create a new thread, with attributes specified by
+.Fa attr ,
+within a process. If
+.Fa attr
+is NULL, the default attributes are used. If the attributes specified by
+.Fa attr
+are modified later, the thread's attributes are not affected. Upon
+successful completion
+.Fn pthread_create
+will store the ID of the created thread in the location specified by
+.Fa thread .
+.Pp
+The thread is created executing
+.Fa start_routine
+with
+.Fa arg
+as its sole argument. If the
+.Fa start_routine
+returns, the effect is as if there was an implicit call to
+.Fn pthread_exit
+using the return value of
+.Fa start_toutine
+as the exit status. Note that the thread in which
+.Fn main
+was originally invoked differs from this. When it returns from
+.Fn main ,
+the effect is as if there was an implicit call to
+.Fn exit using the return value of
+.Fn main
+as the exit status.
+.Pp
+The signal state of the new thread is initialized as:
+.Bl -bullet -offset indent
+.It
+The signal mask is inherited from the creating thread.
+.It
+The set of signals pending for the new thread is empty.
+.El
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_create
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+.Fn pthread_create
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EAGAIN
+The system lacked the necessary resources to create another thread, or
+the system-imposed limit on the total number of threads in a process
+[PTHREAD_THREADS_MAX] would be exceeded.
+.It Bq Er EINVAL
+The value specified by
+.Fa attr
+is invalid.
+.El
+.Pp
+.Sh SEE ALSO
+.Xr fork 2 ,
+.Xr pthread_exit 3 ,
+.Xr pthread_join 3
+.Sh STANDARDS
+.Fn pthread_create
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libpthread/man/pthread_detach.3 b/lib/libpthread/man/pthread_detach.3
new file mode 100644
index 0000000..d2a60dd
--- /dev/null
+++ b/lib/libpthread/man/pthread_detach.3
@@ -0,0 +1,79 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_DETACH 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_detach
+.Nd detach a thread
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_detach "pthread_t thread"
+.Sh DESCRIPTION
+The
+.Fn pthread_detach
+function is used to indicate to the implementation that storage for the
+thread
+.Fa thread
+can be reclaimed when the thread terminates. If
+.Fa thread
+has not terminated,
+.Fn pthread_detach
+will not cause it to terminate. The effect of multiple
+.Fn pthread_detach
+calls on the same target thread is unspecified.
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_detach
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+.Fn pthread_detach
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The implementation has detected that the value specified by
+.Fa thread
+does not refer to a joinable thread.
+.It Bq Er ESRCH
+No thread could be found corresponding to that specified by the given
+thread ID,
+.Fa thread .
+.El
+.Pp
+.Sh SEE ALSO
+.Xr pthread_join 3
+.Sh STANDARDS
+.Fn pthread_detach
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libpthread/man/pthread_equal.3 b/lib/libpthread/man/pthread_equal.3
new file mode 100644
index 0000000..3324855
--- /dev/null
+++ b/lib/libpthread/man/pthread_equal.3
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_EQUAL 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_equal
+.Nd compare thread IDs
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_equal "pthread_t t1" "pthread_t t2"
+.Sh DESCRIPTION
+The
+.Fn pthread_equal
+function compares the thread IDs
+.Fa t1
+and
+.Fa t2 .
+.Sh RETURN VALUES
+The
+.Fn pthread_equal
+function will non-zero if the thread IDs
+.Fa t1
+and
+.Fa t2
+correspond to the same thread, otherwise it will return zero.
+.Sh ERRORS
+None.
+.Pp
+.Sh SEE ALSO
+.Xr pthread_create 3 ,
+.Xr pthread_exit 3
+.Sh STANDARDS
+.Fn pthread_equal
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libpthread/man/pthread_exit.3 b/lib/libpthread/man/pthread_exit.3
new file mode 100644
index 0000000..aad365e
--- /dev/null
+++ b/lib/libpthread/man/pthread_exit.3
@@ -0,0 +1,99 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_EXIT 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_exit
+.Nd terminate the calling thread
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft void
+.Fn pthread_exit "void *value_ptr"
+.Sh DESCRIPTION
+The
+.Fn pthread_exit
+function terminates the calling thread and makes the value
+.Fa value_ptr
+available to any successful join with the terminating thread. Any
+cancellation cleanup handlers that have been pushed and are not yet popped
+are popped in the reverse order that they were pushed and then executed.
+After all cancellation handlers have been executed, if the thread has any
+thread-specific data, appropriate destructor functions are called in an
+unspecified order. Thread termination does not release any application
+visible process resources, including, but not limited to, mutexes and
+file descriptors, nor does it perform any process level cleanup
+actions, including, but not limited to, calling
+.Fn atexit
+routines that may exist.
+.Pp
+An implicit call to
+.Fn pthread_exit
+is made when a thread other than the thread in which
+.Fn main
+was first invoked returns from the start routine that was used to create
+it. The function's return value serves as the thread's exit status.
+.Pp
+The behavior of
+.Fn pthread_exit
+is undefied if called from a cancellation handler or destructor function
+that was invoked as the result of an implicit or explicit call to
+.Fn pthread_exit .
+.Pp
+After a thread has terminated, the result of access to local (auto)
+variables of the thread is undefined. Thus, references to local variables
+of the exiting thread should not be used for the
+.Fn pthread_exit
+.Fa value_ptr
+parameter value.
+.Pp
+The process will exit with an exit status of 0 after the last thread has
+been terminated. The behavior is as if the implementation called
+.Fn exit
+with a zero argument at thread termination time.
+.Pp
+.Sh RETURN VALUES
+The
+.Fn pthread_exit
+function cannot return to its caller.
+.Sh ERRORS
+None.
+.Pp
+.Sh SEE ALSO
+.Xr _exit 2 ,
+.Xr exit 2 ,
+.Xr pthread_create 3 ,
+.Xr pthread_join 3
+.Sh STANDARDS
+.Fn pthread_exit
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libpthread/man/pthread_getspecific.3 b/lib/libpthread/man/pthread_getspecific.3
new file mode 100644
index 0000000..b53841e
--- /dev/null
+++ b/lib/libpthread/man/pthread_getspecific.3
@@ -0,0 +1,82 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.\" $Id$
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_GETSPECIFIC 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_getspecific
+.Nd get a thread-specific data value
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft void *
+.Fn pthread_getspecific "pthread_key_t key"
+.Sh DESCRIPTION
+The
+.Fn pthread_getspecific
+function returns the value currently bound to the specified
+.Fa key
+on behalf of the calling thread.
+.Pp
+The effect of calling
+.Fn pthread_getspecific
+with a
+.Fa key
+value not obtained from
+.Fn pthread_key_create
+or after
+.Fa key
+has been deleted with
+.Fn pthread_key_delete
+is undefined.
+.Pp
+.Fn pthread_getspecific
+may be called from a thread-specific data destructor function.
+.Sh RETURN VALUES
+The
+.Fn pthread_getspecific
+function will return the thread-specific data value associated with the given
+.Fa key .
+If no thread-specific data value is associated with
+.Fa key ,
+then the value NULL is returned.
+.Sh ERRORS
+None.
+.Sh SEE ALSO
+.Xr pthread_key_create 3 ,
+.Xr pthread_key_delete 3 ,
+.Xr pthread_setspecific 3
+.Sh STANDARDS
+.Fn pthread_getspecific
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libpthread/man/pthread_join.3 b/lib/libpthread/man/pthread_join.3
new file mode 100644
index 0000000..cabf319
--- /dev/null
+++ b/lib/libpthread/man/pthread_join.3
@@ -0,0 +1,100 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_JOIN 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_join
+.Nd wait for thread termination
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_join "pthread_t thread" "void **value_ptr"
+.Sh DESCRIPTION
+The
+.Fn pthread_join
+function suspends execution of the calling thread until the target
+.Fa thread
+terminates unless the target
+.Fa thread
+has already terminated.
+.Pp
+On return from a successful
+.Fn pthread_join
+call with a non-NULL
+.Fa value_ptr
+argument, the value passed to
+.Fn pthread_exit
+by the terminating thread is stored in the location referenced by
+.Fa value_ptr .
+When a
+.Fn pthread_join
+returns successfully, the target thread has been terminated. The results
+of multiple simultaneous calls to
+.Fn pthread_join
+specifying the same target thread are undefined. If the thread calling
+.Fn pthread_join
+is cancelled, then the target thread is not detached.
+.Pp
+A thread that has exited but remains unjoined counts against
+[_POSIX_THREAD_THREADS_MAX].
+.Pp
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_join
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+.Fn pthread_join
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The implementation has detected that the value specified by
+.Fa thread
+does not refer to a joinable thread.
+.It Bq Er ESRCH
+No thread could be found corresponding to that specified by the given
+thread ID,
+.Fa thread .
+.It Bq Er EDEADLK
+A deadlock was detected or the value of
+.Fa thread
+specifies the calling thread.
+.El
+.Pp
+.Sh SEE ALSO
+.Xr wait 2 ,
+.Xr pthread_create 3
+.Sh STANDARDS
+.Fn pthread_join
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libpthread/man/pthread_key_create.3 b/lib/libpthread/man/pthread_key_create.3
new file mode 100644
index 0000000..25165ce
--- /dev/null
+++ b/lib/libpthread/man/pthread_key_create.3
@@ -0,0 +1,98 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_KEY_CREATE 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_key_create
+.Nd thread-specific data key creation
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_key_create "pthread_key_t *key" "void (*destructor)(void *)"
+.Sh DESCRIPTION
+The
+.Fn pthread_key_create
+function creates a thread-specific data key visible to all threads in the
+process. Key values provided by
+.Fn pthread_key_create
+are opaque objects used to locate thread-specific data. Although the same
+key value may be used by different threads, the values bound to the key
+by
+.Fn pthread_setspecific
+are maintained on a per-thread basis and persist for the life of the calling
+thread.
+.Pp
+Upon key creation, the value NULL is associated with the new key in all
+active threads. Upon thread creation, the value NULL is associated with all
+defined keys in the new thread.
+.Pp
+An optional destructor function may be associated with each key value. At
+thread exit, if a key value has a non-NULL destructor pointer, and the
+thread has a non-NULL value associated with the key, the function pointed
+to is called with the current associated value as its sole argument. The
+order of destructor calls is unspecified if more than one destructor exists
+for a thread when it exits.
+.Pp
+If, after all the destructors have been called for all non-NULL values
+with associated destructors, there are still some non-NULL values with
+associated destructors, then the process is repeated. If, after at least
+[PTHREAD_DESTRUCTOR_ITERATIONS] iterations of destructor calls for
+outstanding non-NULL values, there are still some non-NULL values with
+associated destructors, the implementation stops calling destructors.
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_key_create
+function will store the newly created key value at the location specified by
+.Fa key
+and returns zero. Otherwise an error number will be returned to indicate
+the error.
+.Sh ERRORS
+.Fn pthread_key_create
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EAGAIN
+The system lacked the necessary resources to create another thread-specific
+data key, or the system-imposed limit on the total number of keys per process
+[PTHREAD_KEYS_MAX] would be exceeded.
+.It Bq Er ENOMEM
+Insufficient memory exists to create the key.
+.El
+.Pp
+.Sh SEE ALSO
+.Xr pthread_getspecific 3 ,
+.Xr pthread_key_delete 3 ,
+.Xr pthread_setspecific 3
+.Sh STANDARDS
+.Fn pthread_key_create
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libpthread/man/pthread_key_delete.3 b/lib/libpthread/man/pthread_key_delete.3
new file mode 100644
index 0000000..badfa8c
--- /dev/null
+++ b/lib/libpthread/man/pthread_key_delete.3
@@ -0,0 +1,92 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_KEY_DELETE 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_key_delete
+.Nd delete a thread-specific data key
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_key_delete "pthread_key_t key"
+.Sh DESCRIPTION
+The
+.Fn pthread_key_delete
+function deletes a thread-specific data key previously returned by
+.Fn pthread_key_create .
+The thread-specific data values associated with
+.Fa key
+need not be NULL at the time that
+.Fn pthread_key_delete
+is called. It is the responsibility of the application to free any
+application storage or perform any cleanup actions for data structures
+related to the deleted key or associated thread-specific data in any threads;
+this cleanup can be done either before or after
+.Fn pthread_key_delete
+is called. Any attempt to use
+.Fa key
+following the call to
+.Fn pthread_key_delete
+results in undefined behavior.
+.Pp
+The
+.Fn pthread_key_delete
+function is callable from within destructor functions. Destructor functions
+are not invoked by
+.Fn pthread_key_delete .
+Any destructor function that may have been associated with
+.Fa key
+will no longer be called upon thread exit.
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_key_delete
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+.Fn pthread_key_delete
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa key
+value is invalid.
+.El
+.Pp
+.Sh SEE ALSO
+.Xr pthread_getspecific 3 ,
+.Xr pthread_key_create 3 ,
+.Xr pthread_setspecific 3
+.Sh STANDARDS
+.Fn pthread_key_delete
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libpthread/man/pthread_once.3 b/lib/libpthread/man/pthread_once.3
new file mode 100644
index 0000000..9ade42f
--- /dev/null
+++ b/lib/libpthread/man/pthread_once.3
@@ -0,0 +1,100 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_ONCE 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_once
+.Nd dynamic package initialization
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Pp
+pthread_once
+.Fa once_control
+= PTHREAD_ONCE_INIT;
+.Ft int
+.Fn pthread_once "pthread_once_t *once_control" "void *(*init_routine)(void)"
+.Sh DESCRIPTION
+The first call to
+.Fn pthread_once
+by any thread in a process, with a given
+.Fa once_control ,
+will call the
+.Fn init_routine
+with no arguments. Subsequent calls to
+.Fn pthread_once
+with the same
+.Fa once_control
+will not call the
+.Fn init_routine .
+On return from
+.Fn pthread_once ,
+it is guaranteed that
+.Fn init_routine
+has completed. The
+.Fa once_control
+parameter is used to determine whether the associated initialization
+routine has been called.
+.Pp
+The function
+.Fn pthread_once
+is not a cancellation point. However, if
+.Fn init_routine
+is a cancellation point and is cancelled, the effect on
+.Fa once_control is as if
+.Fn pthread_once
+was never called.
+.Pp
+The constant
+.Fa PTHREAD_ONCE_INIT
+is defined by header
+.Aq Pa pthread.h .
+.Pp
+The behavior of
+.Fn pthread_once
+is undefined if
+.Fa once_control
+has automatic storage duration or is not initialized by
+.Fa PTHREAD_ONCE_INIT .
+.Pp
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_once
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+None.
+.Pp
+.Sh STANDARDS
+.Fn pthread_once
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libpthread/man/pthread_self.3 b/lib/libpthread/man/pthread_self.3
new file mode 100644
index 0000000..9ba0ee6
--- /dev/null
+++ b/lib/libpthread/man/pthread_self.3
@@ -0,0 +1,59 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_SELF 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_self
+.Nd get the calling thread's ID
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft pthread_t
+.Fn pthread_self "void"
+.Sh DESCRIPTION
+The
+.Fn pthread_self
+function returns the thread ID of the calling thread.
+.Sh RETURN VALUES
+The
+.Fn pthread_self
+function returns the thread ID of the calling thread.
+.Sh ERRORS
+None.
+.Pp
+.Sh SEE ALSO
+.Xr pthread_create 3 ,
+.Xr pthread_equal 3
+.Sh STANDARDS
+.Fn pthread_self
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libpthread/man/pthread_setspecific.3 b/lib/libpthread/man/pthread_setspecific.3
new file mode 100644
index 0000000..838b587
--- /dev/null
+++ b/lib/libpthread/man/pthread_setspecific.3
@@ -0,0 +1,91 @@
+.\" Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by John Birrell.
+.\" 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 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.
+.\"
+.Dd April 4, 1996
+.Dt PTHREAD_SETSPECIFIC 3
+.Os BSD 4
+.Sh NAME
+.Nm pthread_setspecific
+.Nd set a thread-specific data value
+.Sh SYNOPSIS
+.Fd #include <pthread.h>
+.Ft int
+.Fn pthread_setspecific "pthread_key_t key" "const void *value"
+.Sh DESCRIPTION
+The
+.Fn pthread_setspecific
+function associates a thread-specific value with a
+.Fa key
+obtained via a previous call to
+.Fn pthread_key_create .
+Different threads man bind different values to the same key. These values are
+typically pointers to blocks of dynamically allocated memory that have been
+reserved for use by the calling thread.
+.Pp
+The effect of calling
+.Fn pthread_setspecific
+with a key value not obtained from
+.Fn pthread_key_create
+or after
+.Fa key
+has been deleted with
+.Fn pthread_key_delete
+is undefined.
+.Pp
+.Fn pthread_setspecific
+may be called from a thread-specific data destructor function, however this
+may result in lost storage or infinite loops.
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_setspecific
+function will return zero. Otherwise an error number will be returned to
+indicate the error.
+.Sh ERRORS
+.Fn pthread_setspecific
+will fail if:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+Insufficient memory exists to associate the value with the
+.Fa key .
+.It Bq Er EINVAL
+The
+.Fa key
+value is invalid.
+.El
+.Pp
+.Sh SEE ALSO
+.Xr pthread_getspecific 3 ,
+.Xr pthread_key_create 3 ,
+.Xr pthread_key_delete 3
+.Sh STANDARDS
+.Fn pthread_setspecific
+is expected to conform to IEEE
+.Pq Dq Tn POSIX
+Std 1003.1c when it is published.
diff --git a/lib/libpthread/sys/Makefile.inc b/lib/libpthread/sys/Makefile.inc
new file mode 100644
index 0000000..16fd33d
--- /dev/null
+++ b/lib/libpthread/sys/Makefile.inc
@@ -0,0 +1,5 @@
+# $Id$
+
+.PATH: ${.CURDIR}/sys
+
+SRCS+= __error.c
diff --git a/lib/libpthread/thread/Makefile.inc b/lib/libpthread/thread/Makefile.inc
new file mode 100644
index 0000000..3fbc97b
--- /dev/null
+++ b/lib/libpthread/thread/Makefile.inc
@@ -0,0 +1,93 @@
+# $Id: Makefile.inc,v 1.8 1997/02/22 15:05:31 peter Exp $
+
+# uthread sources
+.PATH: ${.CURDIR}/uthread
+
+SRCS+= \
+ uthread_accept.c \
+ uthread_attr_destroy.c \
+ uthread_attr_init.c \
+ uthread_attr_getdetachstate.c \
+ uthread_attr_getstackaddr.c \
+ uthread_attr_getstacksize.c \
+ uthread_attr_setcreatesuspend_np.c \
+ uthread_attr_setdetachstate.c \
+ uthread_attr_setstackaddr.c \
+ uthread_attr_setstacksize.c \
+ uthread_autoinit.cc \
+ uthread_bind.c \
+ uthread_clean.c \
+ uthread_close.c \
+ uthread_cond.c \
+ uthread_condattr_destroy.c \
+ uthread_condattr_init.c \
+ uthread_connect.c \
+ uthread_create.c \
+ uthread_detach.c \
+ uthread_dup.c \
+ uthread_dup2.c \
+ uthread_equal.c \
+ uthread_execve.c \
+ uthread_exit.c \
+ uthread_fchmod.c \
+ uthread_fchown.c \
+ uthread_fcntl.c \
+ uthread_fd.c \
+ uthread_file.c \
+ uthread_flock.c \
+ uthread_fork.c \
+ uthread_fstat.c \
+ uthread_fstatfs.c \
+ uthread_fsync.c \
+ uthread_getdirentries.c \
+ uthread_getpeername.c \
+ uthread_getprio.c \
+ uthread_getsockname.c \
+ uthread_getsockopt.c \
+ uthread_info.c \
+ uthread_init.c \
+ uthread_ioctl.c \
+ uthread_join.c \
+ uthread_kern.c \
+ uthread_kill.c \
+ uthread_listen.c \
+ uthread_longjmp.c \
+ uthread_mattr_init.c \
+ uthread_mattr_kind_np.c \
+ uthread_multi_np.c \
+ uthread_mutex.c \
+ uthread_mutexattr_destroy.c \
+ uthread_nanosleep.c \
+ uthread_once.c \
+ uthread_open.c \
+ uthread_pipe.c \
+ uthread_queue.c \
+ uthread_read.c \
+ uthread_readv.c \
+ uthread_recvfrom.c \
+ uthread_resume_np.c \
+ uthread_select.c \
+ uthread_self.c \
+ uthread_sendto.c \
+ uthread_seterrno.c \
+ uthread_setjmp.c \
+ uthread_setprio.c \
+ uthread_setsockopt.c \
+ uthread_shutdown.c \
+ uthread_sig.c \
+ uthread_sigaction.c \
+ uthread_sigblock.c \
+ uthread_single_np.c \
+ uthread_sigmask.c \
+ uthread_signal.c \
+ uthread_sigprocmask.c \
+ uthread_sigsetmask.c \
+ uthread_sigsuspend.c \
+ uthread_socket.c \
+ uthread_socketpair.c \
+ uthread_spec.c \
+ uthread_suspend_np.c \
+ uthread_wait4.c \
+ uthread_write.c \
+ uthread_writev.c \
+ uthread_yield.c
diff --git a/lib/libpthread/thread/thr_attr_destroy.c b/lib/libpthread/thread/thr_attr_destroy.c
new file mode 100644
index 0000000..1f4b2c8
--- /dev/null
+++ b/lib/libpthread/thread/thr_attr_destroy.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_destroy(pthread_attr_t *attr)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL)
+ /* Invalid argument: */
+ ret = EINVAL;
+ else {
+ /* Free the memory allocated to the attribute object: */
+ free(*attr);
+
+ /*
+ * Leave the attribute pointer NULL now that the memory
+ * has been freed:
+ */
+ *attr = NULL;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_attr_getdetachstate.c b/lib/libpthread/thread/thr_attr_getdetachstate.c
new file mode 100644
index 0000000..4715cb6
--- /dev/null
+++ b/lib/libpthread/thread/thr_attr_getdetachstate.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || detachstate == NULL)
+ ret = EINVAL;
+ else {
+ /* Check if the detached flag is set: */
+ if ((*attr)->flags & PTHREAD_DETACHED)
+ /* Return detached: */
+ *detachstate = PTHREAD_CREATE_DETACHED;
+ else
+ /* Return joinable: */
+ *detachstate = PTHREAD_CREATE_JOINABLE;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_attr_getstackaddr.c b/lib/libpthread/thread/thr_attr_getstackaddr.c
new file mode 100644
index 0000000..1850a32
--- /dev/null
+++ b/lib/libpthread/thread/thr_attr_getstackaddr.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stackaddr)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stackaddr == NULL)
+ ret = EINVAL;
+ else {
+ /* Return the stack address: */
+ *stackaddr = (*attr)->stackaddr_attr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_attr_getstacksize.c b/lib/libpthread/thread/thr_attr_getstacksize.c
new file mode 100644
index 0000000..de81106
--- /dev/null
+++ b/lib/libpthread/thread/thr_attr_getstacksize.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stacksize == NULL)
+ ret = EINVAL;
+ else {
+ /* Return the stack size: */
+ *stacksize = (*attr)->stacksize_attr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_attr_init.c b/lib/libpthread/thread/thr_attr_init.c
new file mode 100644
index 0000000..c64e29f
--- /dev/null
+++ b/lib/libpthread/thread/thr_attr_init.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_init(pthread_attr_t *attr)
+{
+ int ret;
+ pthread_attr_t pattr;
+
+ /* Allocate memory for the attribute object: */
+ if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL)
+ /* Insufficient memory: */
+ ret = ENOMEM;
+ else {
+ /* Initialise the attribute object with the defaults: */
+ memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr));
+
+ /* Return a pointer to the attribute object: */
+ *attr = pattr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_attr_setcreatesuspend_np.c b/lib/libpthread/thread/thr_attr_setcreatesuspend_np.c
new file mode 100644
index 0000000..afe6b23
--- /dev/null
+++ b/lib/libpthread/thread/thr_attr_setcreatesuspend_np.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ (*attr)->suspend = PTHREAD_CREATE_SUSPENDED;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_attr_setdetachstate.c b/lib/libpthread/thread/thr_attr_setdetachstate.c
new file mode 100644
index 0000000..6ec0dbc
--- /dev/null
+++ b/lib/libpthread/thread/thr_attr_setdetachstate.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL ||
+ (detachstate != PTHREAD_CREATE_DETACHED &&
+ detachstate != PTHREAD_CREATE_JOINABLE))
+ ret = EINVAL;
+ else {
+ /* Check if detached state: */
+ if (detachstate == PTHREAD_CREATE_DETACHED)
+ /* Set the detached flag: */
+ (*attr)->flags |= PTHREAD_DETACHED;
+ else
+ /* Reset the detached flag: */
+ (*attr)->flags &= ~PTHREAD_DETACHED;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_attr_setstackaddr.c b/lib/libpthread/thread/thr_attr_setstackaddr.c
new file mode 100644
index 0000000..ce54915
--- /dev/null
+++ b/lib/libpthread/thread/thr_attr_setstackaddr.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stackaddr == NULL)
+ ret = EINVAL;
+ else {
+ /* Save the stack address: */
+ (*attr)->stackaddr_attr = stackaddr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_attr_setstacksize.c b/lib/libpthread/thread/thr_attr_setstacksize.c
new file mode 100644
index 0000000..94e575e
--- /dev/null
+++ b/lib/libpthread/thread/thr_attr_setstacksize.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
+{
+ int ret;
+
+ /* Check for invalid arguments: */
+ if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN)
+ ret = EINVAL;
+ else {
+ /* Save the stack size: */
+ (*attr)->stacksize_attr = stacksize;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_clean.c b/lib/libpthread/thread/thr_clean.c
new file mode 100644
index 0000000..9319f85
--- /dev/null
+++ b/lib/libpthread/thread/thr_clean.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+pthread_cleanup_push(void (*routine) (void *), void *routine_arg)
+{
+ struct pthread_cleanup *new;
+
+ if ((new = (struct pthread_cleanup *) malloc(sizeof(struct pthread_cleanup))) != NULL) {
+ new->routine = routine;
+ new->routine_arg = routine_arg;
+ new->next = _thread_run->cleanup;
+
+ _thread_run->cleanup = new;
+ }
+}
+
+void
+pthread_cleanup_pop(int execute)
+{
+ struct pthread_cleanup *old;
+
+ if ((old = _thread_run->cleanup) != NULL) {
+ _thread_run->cleanup = old->next;
+ if (execute) {
+ old->routine(old->routine_arg);
+ }
+ free(old);
+ }
+}
+
+#endif
diff --git a/lib/libpthread/thread/thr_close.c b/lib/libpthread/thread/thr_close.c
new file mode 100644
index 0000000..26a8fbf
--- /dev/null
+++ b/lib/libpthread/thread/thr_close.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+close(int fd)
+{
+ int flags;
+ int ret;
+ int status;
+ struct stat sb;
+
+ /* Lock the file descriptor while the file is closed: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Get file descriptor status. */
+ fstat(fd, &sb);
+
+ /*
+ * Check if the file should be left as blocking.
+ *
+ * This is so that the file descriptors shared with a parent
+ * process aren't left set to non-blocking if the child
+ * closes them prior to exit. An example where this causes
+ * problems with /bin/sh is when a child closes stdin.
+ *
+ * Setting a file as blocking causes problems if a threaded
+ * parent accesses the file descriptor before the child exits.
+ * Once the threaded parent receives a SIGCHLD then it resets
+ * all of its files to non-blocking, and so it is then safe
+ * to access them.
+ *
+ * Pipes are not set to blocking when they are closed, as
+ * the parent and child will normally close the file
+ * descriptor of the end of the pipe that they are not
+ * using, which would then cause any reads to block
+ * indefinitely.
+ */
+ if ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) && (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0) {
+ /* Get the current flags: */
+ flags = _thread_sys_fcntl(fd, F_GETFL, NULL);
+ /* Clear the nonblocking file descriptor flag: */
+ _thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+ }
+
+ /* Close the file descriptor: */
+ ret = _thread_sys_close(fd);
+
+ /* Free the file descriptor table entry: */
+ free(_thread_fd_table[fd]);
+ _thread_fd_table[fd] = NULL;
+
+ /* Unblock signals again: */
+ _thread_kern_sig_unblock(status);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_cond.c b/lib/libpthread/thread/thr_cond.c
new file mode 100644
index 0000000..09ebb4e
--- /dev/null
+++ b/lib/libpthread/thread/thr_cond.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * cond_attr)
+{
+ enum pthread_cond_type type;
+ pthread_cond_t pcond;
+ int rval = 0;
+
+ if (cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /*
+ * Check if a pointer to a condition variable attribute
+ * structure was passed by the caller:
+ */
+ if (cond_attr != NULL && *cond_attr != NULL) {
+ /* Default to a fast condition variable: */
+ type = (*cond_attr)->c_type;
+ } else {
+ /* Default to a fast condition variable: */
+ type = COND_TYPE_FAST;
+ }
+
+ /* Process according to condition variable type: */
+ switch (type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Check for no errors: */
+ if (rval == 0) {
+ if ((pcond = (pthread_cond_t)
+ malloc(sizeof(struct pthread_cond))) == NULL) {
+ errno = ENOMEM;
+ rval = -1;
+ } else {
+ /*
+ * Initialise the condition variable
+ * structure:
+ */
+ _thread_queue_init(&pcond->c_queue);
+ pcond->c_flags |= COND_FLAGS_INITED;
+ pcond->c_type = type;
+ *cond = pcond;
+ }
+ }
+ }
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_destroy(pthread_cond_t * cond)
+{
+ int rval = 0;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Check for errors: */
+ if (rval == 0) {
+ /* Destroy the contents of the condition structure: */
+ _thread_queue_init(&(*cond)->c_queue);
+ (*cond)->c_flags = 0;
+ free(*cond);
+ *cond = NULL;
+ }
+ }
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
+{
+ int rval = 0;
+ int status;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /*
+ * Queue the running thread for the condition
+ * variable:
+ */
+ _thread_queue_enq(&(*cond)->c_queue, _thread_run);
+
+ /* Unlock the mutex: */
+ pthread_mutex_unlock(mutex);
+
+ /* Wait forever: */
+ _thread_run->wakeup_time.tv_sec = -1;
+
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_COND_WAIT,
+ __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Lock the mutex: */
+ rval = pthread_mutex_lock(mutex);
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
+ const struct timespec * abstime)
+{
+ int rval = 0;
+ int status;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Set the wakeup time: */
+ _thread_run->wakeup_time.tv_sec = abstime->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = abstime->tv_nsec;
+
+ /* Reset the timeout flag: */
+ _thread_run->timeout = 0;
+
+ /*
+ * Queue the running thread for the condition
+ * variable:
+ */
+ _thread_queue_enq(&(*cond)->c_queue, _thread_run);
+
+ /* Unlock the mutex: */
+ if ((rval = pthread_mutex_unlock(mutex)) != 0) {
+ /*
+ * Cannot unlock the mutex, so remove the
+ * running thread from the condition
+ * variable queue:
+ */
+ _thread_queue_deq(&(*cond)->c_queue);
+ } else {
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_COND_WAIT,
+ __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Lock the mutex: */
+ if ((rval = pthread_mutex_lock(mutex)) != 0) {
+ }
+ /* Check if the wait timed out: */
+ else if (_thread_run->timeout) {
+ /* Return a timeout error: */
+ errno = EAGAIN;
+ rval = -1;
+ }
+ }
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_signal(pthread_cond_t * cond)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread;
+
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Bring the next thread off the condition queue: */
+ if ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
+ /* Allow the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_broadcast(pthread_cond_t * cond)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /*
+ * Enter a loop to bring all threads off the
+ * condition queue:
+ */
+ while ((pthread =
+ _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
+ /* Allow the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_condattr_destroy.c b/lib/libpthread/thread/thr_condattr_destroy.c
new file mode 100644
index 0000000..b20f183
--- /dev/null
+++ b/lib/libpthread/thread/thr_condattr_destroy.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_condattr_destroy(pthread_condattr_t *attr)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ free(*attr);
+ *attr = NULL;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_condattr_init.c b/lib/libpthread/thread/thr_condattr_init.c
new file mode 100644
index 0000000..f94e438
--- /dev/null
+++ b/lib/libpthread/thread/thr_condattr_init.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_condattr_init(pthread_condattr_t *attr)
+{
+ int ret;
+ pthread_condattr_t pattr;
+
+ if ((pattr = (pthread_condattr_t)
+ malloc(sizeof(struct pthread_cond_attr))) == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ memcpy(pattr, &pthread_condattr_default,
+ sizeof(struct pthread_cond_attr));
+ *attr = pattr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_create.c b/lib/libpthread/thread/thr_create.c
new file mode 100644
index 0000000..e4925a9
--- /dev/null
+++ b/lib/libpthread/thread/thr_create.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <machine/reg.h>
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+_thread_create(pthread_t * thread, const pthread_attr_t * attr,
+ void *(*start_routine) (void *), void *arg, pthread_t parent)
+{
+ int i;
+ int ret = 0;
+ int status;
+ pthread_t new_thread;
+ pthread_attr_t pattr;
+ void *stack;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Allocate memory for the thread structure: */
+ if ((new_thread = (pthread_t) malloc(sizeof(struct pthread))) == NULL) {
+ /* Insufficient memory to create a thread: */
+ ret = EAGAIN;
+ } else {
+ /* Check if default thread attributes are required: */
+ if (attr == NULL || *attr == NULL) {
+ /* Use the default thread attributes: */
+ pattr = &pthread_attr_default;
+ } else {
+ pattr = *attr;
+ }
+ /* Check if a stack was specified in the thread attributes: */
+ if ((stack = pattr->stackaddr_attr) != NULL) {
+ }
+ /* Allocate memory for the stack: */
+ else if ((stack = (void *) malloc(pattr->stacksize_attr)) == NULL) {
+ /* Insufficient memory to create a thread: */
+ ret = EAGAIN;
+ free(new_thread);
+ }
+ /* Check for errors: */
+ if (ret != 0) {
+ } else {
+ /* Initialise the thread structure: */
+ memset(new_thread, 0, sizeof(struct pthread));
+ new_thread->slice_usec = -1;
+ new_thread->sig_saved = 0;
+ new_thread->stack = stack;
+ new_thread->start_routine = start_routine;
+ new_thread->arg = arg;
+ if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) {
+ PTHREAD_NEW_STATE(new_thread,PS_SUSPENDED);
+ } else {
+ PTHREAD_NEW_STATE(new_thread,PS_RUNNING);
+ }
+
+ /* Initialise the thread for signals: */
+ new_thread->sigmask = _thread_run->sigmask;
+
+ /*
+ * Enter a loop to initialise the signal handler
+ * array:
+ */
+ for (i = 1; i < NSIG; i++) {
+ /* Default the signal handler: */
+ sigfillset(&new_thread->act[i - 1].sa_mask);
+ new_thread->act[i - 1].sa_handler = _thread_run->act[i - 1].sa_handler;
+ new_thread->act[i - 1].sa_flags = _thread_run->act[i - 1].sa_flags;
+ }
+
+ /* Initialise the jump buffer: */
+ _thread_sys_setjmp(new_thread->saved_jmp_buf);
+
+ /*
+ * Set up new stack frame so that it looks like it
+ * returned from a longjmp() to the beginning of
+ * _thread_start(). Check if this is a user thread:
+ */
+ if (parent == NULL) {
+ /* Use the user start function: */
+#if defined(__FreeBSD__)
+ new_thread->saved_jmp_buf[0]._jb[0] = (long) _thread_start;
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[2] = (long) _thread_start;
+ new_thread->saved_jmp_buf[4 + R_RA] = 0;
+ new_thread->saved_jmp_buf[4 + R_T12] = (long) _thread_start;
+#else
+ new_thread->saved_jmp_buf[0] = (long) _thread_start;
+#endif
+#else
+#error "Don't recognize this operating system!"
+#endif
+ } else {
+ /*
+ * Use the (funny) signal handler start
+ * function:
+ */
+#if defined(__FreeBSD__)
+ new_thread->saved_jmp_buf[0]._jb[0] = (int) _thread_start_sig_handler;
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[2] = (long) _thread_start_sig_handler;
+ new_thread->saved_jmp_buf[4 + R_RA] = 0;
+ new_thread->saved_jmp_buf[4 + R_T12] = (long) _thread_start_sig_handler;
+#else
+ new_thread->saved_jmp_buf[0] = (long) _thread_start_sig_handler;
+#endif
+#else
+#error "Don't recognize this operating system!"
+#endif
+ }
+
+ /* The stack starts high and builds down: */
+#if defined(__FreeBSD__)
+ new_thread->saved_jmp_buf[0]._jb[2] = (int) (new_thread->stack + pattr->stacksize_attr - sizeof(double));
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[4 + R_SP] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
+#else
+ new_thread->saved_jmp_buf[2] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
+#endif
+#else
+#error "Don't recognize this operating system!"
+#endif
+
+ /* Copy the thread attributes: */
+ memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr));
+
+ /*
+ * Check if this thread is to inherit the scheduling
+ * attributes from its parent:
+ */
+ if (new_thread->attr.flags & PTHREAD_INHERIT_SCHED) {
+ /* Copy the scheduling attributes: */
+ new_thread->pthread_priority = _thread_run->pthread_priority;
+ new_thread->attr.prio = _thread_run->pthread_priority;
+ new_thread->attr.schedparam_policy = _thread_run->attr.schedparam_policy;
+ } else {
+ /*
+ * Use just the thread priority, leaving the
+ * other scheduling attributes as their
+ * default values:
+ */
+ new_thread->pthread_priority = new_thread->attr.prio;
+ }
+
+ /* Initialise the join queue for the new thread: */
+ _thread_queue_init(&(new_thread->join_queue));
+
+ /* Initialise hooks in the thread structure: */
+ new_thread->specific_data = NULL;
+ new_thread->cleanup = NULL;
+ new_thread->queue = NULL;
+ new_thread->qnxt = NULL;
+ new_thread->parent_thread = parent;
+ new_thread->flags = 0;
+
+ /* Add the thread to the linked list of all threads: */
+ new_thread->nxt = _thread_link_list;
+ _thread_link_list = new_thread;
+
+ /* Return a pointer to the thread structure: */
+ (*thread) = new_thread;
+
+ /* Check if a parent thread was specified: */
+ if (parent != NULL) {
+ /*
+ * A parent thread was specified, so this is
+ * a signal handler thread which must now
+ * wait for the signal handler to complete:
+ */
+ PTHREAD_NEW_STATE(parent,PS_SIGTHREAD);
+ } else {
+ /* Schedule the new user thread: */
+ _thread_kern_sched(NULL);
+ }
+ }
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the status: */
+ return (ret);
+}
+
+int
+pthread_create(pthread_t * thread, const pthread_attr_t * attr,
+ void *(*start_routine) (void *), void *arg)
+{
+ int ret = 0;
+
+ /*
+ * Call the low level thread creation function which allows a parent
+ * thread to be specified:
+ */
+ ret = _thread_create(thread, attr, start_routine, arg, NULL);
+
+ /* Return the status: */
+ return (ret);
+}
+
+void
+_thread_start(void)
+{
+ /* Run the current thread's start routine with argument: */
+ pthread_exit(_thread_run->start_routine(_thread_run->arg));
+
+ /* This point should never be reached. */
+ PANIC("Thread has resumed after exit");
+}
+
+void
+_thread_start_sig_handler(void)
+{
+ int sig;
+ long arg;
+ void (*sig_routine) (int);
+
+ /*
+ * Cast the argument from 'void *' to a variable that is NO SMALLER
+ * than a pointer (otherwise gcc under NetBSD/Alpha will complain):
+ */
+ arg = (long) _thread_run->arg;
+
+ /* Cast the argument as a signal number: */
+ sig = (int) arg;
+
+ /* Cast a pointer to the signal handler function: */
+ sig_routine = (void (*) (int)) _thread_run->start_routine;
+
+ /* Call the signal handler function: */
+ (*sig_routine) (sig);
+
+ /* Exit the signal handler thread: */
+ pthread_exit(&arg);
+
+ /* This point should never be reached. */
+ PANIC("Signal handler thread has resumed after exit");
+}
+#endif
diff --git a/lib/libpthread/thread/thr_detach.c b/lib/libpthread/thread/thr_detach.c
new file mode 100644
index 0000000..08cace4
--- /dev/null
+++ b/lib/libpthread/thread/thr_detach.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_detach(pthread_t * p_pthread)
+{
+ int rval = 0;
+ int status;
+ pthread_t next_thread;
+ pthread_t pthread;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Check for invalid calling parameters: */
+ if (p_pthread == NULL || (pthread = *p_pthread) == NULL) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ }
+ /* Check if the thread has not been detached: */
+ else if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) {
+ /* Flag the thread as detached: */
+ pthread->attr.flags |= PTHREAD_DETACHED;
+
+ /* Enter a loop to bring all threads off the join queue: */
+ while ((next_thread = _thread_queue_deq(&pthread->join_queue)) != NULL) {
+ /* Make the thread run: */
+ PTHREAD_NEW_STATE(next_thread,PS_RUNNING);
+ }
+
+ /*
+ * NULL the thread pointer now that the thread has been
+ * detached:
+ */
+ *p_pthread = NULL;
+ } else {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_equal.c b/lib/libpthread/thread/thr_equal.c
new file mode 100644
index 0000000..99ffb5d
--- /dev/null
+++ b/lib/libpthread/thread/thr_equal.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_equal(pthread_t t1, pthread_t t2)
+{
+ /* Compare the two thread pointers: */
+ return (t1 == t2);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_exit.c b/lib/libpthread/thread/thr_exit.c
new file mode 100644
index 0000000..15bcfa3
--- /dev/null
+++ b/lib/libpthread/thread/thr_exit.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void _exit(int status)
+{
+ int flags;
+ int i;
+ struct itimerval itimer;
+
+ /* Disable the interval timer: */
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+ itimer.it_value.tv_sec = 0;
+ itimer.it_value.tv_usec = 0;
+ setitimer(ITIMER_VIRTUAL, &itimer, NULL);
+
+ /* Close the pthread kernel pipe: */
+ _thread_sys_close(_thread_kern_pipe[0]);
+ _thread_sys_close(_thread_kern_pipe[1]);
+
+ /*
+ * Enter a loop to set all file descriptors to blocking
+ * if they were not created as non-blocking:
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Check if this file descriptor is in use: */
+ if (_thread_fd_table[i] != NULL &&
+ !(_thread_fd_table[i]->flags & O_NONBLOCK)) {
+ /* Get the current flags: */
+ flags = _thread_sys_fcntl(i, F_GETFL, NULL);
+ /* Clear the nonblocking file descriptor flag: */
+ _thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+
+ /* Call the _exit syscall: */
+ _thread_sys__exit(status);
+}
+
+void
+_thread_exit(char *fname, int lineno, char *string)
+{
+ char s[256];
+
+ /* Prepare an error message string: */
+ strcpy(s, "Fatal error '");
+ strcat(s, string);
+ strcat(s, "' at line ? ");
+ strcat(s, "in file ");
+ strcat(s, fname);
+ strcat(s, " (errno = ?");
+ strcat(s, ")\n");
+
+ /* Write the string to the standard error file descriptor: */
+ _thread_sys_write(2, s, strlen(s));
+
+ /* Force this process to exit: */
+ _exit(1);
+}
+
+void
+pthread_exit(void *status)
+{
+ int sig;
+ long l;
+ pthread_t pthread;
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Save the return value: */
+ _thread_run->ret = status;
+
+ while (_thread_run->cleanup != NULL) {
+ pthread_cleanup_pop(1);
+ }
+
+ if (_thread_run->attr.cleanup_attr != NULL) {
+ _thread_run->attr.cleanup_attr(_thread_run->attr.arg_attr);
+ }
+ /* Check if there is thread specific data: */
+ if (_thread_run->specific_data != NULL) {
+ /* Run the thread-specific data destructors: */
+ _thread_cleanupspecific();
+ }
+ /* Check if there are any threads joined to this one: */
+ while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) {
+ /* Wake the joined thread and let it detach this thread: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+
+ /* Check if the running thread is at the head of the linked list: */
+ if (_thread_link_list == _thread_run) {
+ /* There is no previous thread: */
+ _thread_link_list = _thread_run->nxt;
+ } else {
+ /* Point to the first thread in the list: */
+ pthread = _thread_link_list;
+
+ /*
+ * Enter a loop to find the thread in the linked list before
+ * the running thread:
+ */
+ while (pthread != NULL && pthread->nxt != _thread_run) {
+ /* Point to the next thread: */
+ pthread = pthread->nxt;
+ }
+
+ /* Check that a previous thread was found: */
+ if (pthread != NULL) {
+ /*
+ * Point the previous thread to the one after the
+ * running thread:
+ */
+ pthread->nxt = _thread_run->nxt;
+ }
+ }
+
+ /* Check if this is a signal handler thread: */
+ if (_thread_run->parent_thread != NULL) {
+ /*
+ * Enter a loop to search for other threads with the same
+ * parent:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Compare the parent thread pointers: */
+ if (pthread->parent_thread == _thread_run->parent_thread) {
+ /*
+ * The parent thread is waiting on at least
+ * one other signal handler. Exit the loop
+ * now that this is known.
+ */
+ break;
+ }
+ }
+
+ /*
+ * Check if the parent is not waiting on any other signal
+ * handler threads and if it hasn't died in the meantime:
+ */
+ if (pthread == NULL && _thread_run->parent_thread->state != PS_DEAD) {
+ /* Allow the parent thread to run again: */
+ PTHREAD_NEW_STATE(_thread_run->parent_thread,PS_RUNNING);
+ }
+ /* Get the signal number: */
+ l = (long) _thread_run->arg;
+ sig = (int) l;
+
+ /* Unblock the signal from the parent thread: */
+ sigdelset(&_thread_run->parent_thread->sigmask, sig);
+ }
+ /*
+ * This thread will never run again. Add it to the list of dead
+ * threads:
+ */
+ _thread_run->nxt = _thread_dead;
+ _thread_dead = _thread_run;
+
+ /*
+ * The running thread is no longer in the thread link list so it will
+ * now die:
+ */
+ _thread_kern_sched_state(PS_DEAD, __FILE__, __LINE__);
+
+ /* This point should not be reached. */
+ PANIC("Dead thread has resumed");
+}
+#endif
diff --git a/lib/libpthread/thread/thr_fcntl.c b/lib/libpthread/thread/thr_fcntl.c
new file mode 100644
index 0000000..f83ee50
--- /dev/null
+++ b/lib/libpthread/thread/thr_fcntl.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fcntl(int fd, int cmd,...)
+{
+ int flags = 0;
+ int oldfd;
+ int ret;
+ int status;
+ va_list ap;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Lock the file descriptor: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Initialise the variable argument list: */
+ va_start(ap, cmd);
+
+ /* Process according to file control command type: */
+ switch (cmd) {
+ /* Duplicate a file descriptor: */
+ case F_DUPFD:
+ /*
+ * Get the file descriptor that the caller wants to
+ * use:
+ */
+ oldfd = va_arg(ap, int);
+
+ /* Initialise the file descriptor table entry: */
+ if ((ret = _thread_sys_fcntl(fd, cmd, oldfd)) < 0) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(ret);
+
+ /* Reset the file descriptor: */
+ ret = -1;
+ } else {
+ /*
+ * Save the file open flags so that they can
+ * be checked later:
+ */
+ _thread_fd_table[ret]->flags = _thread_fd_table[fd]->flags;
+ }
+ break;
+ case F_SETFD:
+ break;
+ case F_GETFD:
+ break;
+ case F_GETFL:
+ ret = _thread_fd_table[fd]->flags;
+ break;
+ case F_SETFL:
+ flags = va_arg(ap, int);
+ if ((ret = _thread_sys_fcntl(fd, cmd, flags | O_NONBLOCK)) == 0) {
+ _thread_fd_table[fd]->flags = flags;
+ }
+ break;
+ default:
+ /* Might want to make va_arg use a union */
+ ret = _thread_sys_fcntl(fd, cmd, va_arg(ap, void *));
+ break;
+ }
+
+ /* Free variable arguments: */
+ va_end(ap);
+
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_fork.c b/lib/libpthread/thread/thr_fork.c
new file mode 100644
index 0000000..19f674d
--- /dev/null
+++ b/lib/libpthread/thread/thr_fork.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pid_t
+fork(void)
+{
+ int flags;
+ pid_t ret;
+
+ /* Fork a new process: */
+ if ((ret = _thread_sys_fork()) <= 0) {
+ /* Parent process or error. Nothing to do here. */
+ } else {
+ /* Close the pthread kernel pipe: */
+ _thread_sys_close(_thread_kern_pipe[0]);
+ _thread_sys_close(_thread_kern_pipe[1]);
+
+ /* Reset signals pending for the running thread: */
+ memset(_thread_run->sigpend, 0, sizeof(_thread_run->sigpend));
+
+ /*
+ * Create a pipe that is written to by the signal handler to
+ * prevent signals being missed in calls to
+ * _thread_sys_select:
+ */
+ if (_thread_sys_pipe(_thread_kern_pipe) != 0) {
+ /* Cannot create pipe, so abort: */
+ PANIC("Cannot create pthread kernel pipe for forked process");
+ }
+ /* Get the flags for the read pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Make the read pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Get the flags for the write pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Make the write pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ }
+
+ /* Return the process ID: */
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_fsync.c b/lib/libpthread/thread/thr_fsync.c
new file mode 100644
index 0000000..51078e5
--- /dev/null
+++ b/lib/libpthread/thread/thr_fsync.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fsync(int fd)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_fsync(fd);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_getprio.c b/lib/libpthread/thread/thr_getprio.c
new file mode 100644
index 0000000..85bd261
--- /dev/null
+++ b/lib/libpthread/thread/thr_getprio.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_getprio(pthread_t pthread)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread_p;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the first thread in the list: */
+ pthread_p = _thread_link_list;
+
+ /* Enter a loop to search for the thread: */
+ while (pthread_p != NULL && pthread_p != pthread) {
+ /* Point to the next thread: */
+ pthread_p = pthread_p->nxt;
+ }
+
+ /* Check if the thread pointer is NULL: */
+ if (pthread == NULL || pthread_p == NULL) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Get the thread priority: */
+ rval = pthread->pthread_priority;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the thread priority or an error status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_info.c b/lib/libpthread/thread/thr_info.c
new file mode 100644
index 0000000..be25d45
--- /dev/null
+++ b/lib/libpthread/thread/thr_info.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+struct s_thread_info {
+ enum pthread_state state;
+ char *name;
+};
+
+/* Static variables: */
+static const struct s_thread_info thread_info[] = {
+ {PS_RUNNING , "Running"},
+ {PS_SIGTHREAD , "Waiting on signal thread"},
+ {PS_MUTEX_WAIT , "Waiting on a mutex"},
+ {PS_COND_WAIT , "Waiting on a condition variable"},
+ {PS_FDLR_WAIT , "Waiting for a file read lock"},
+ {PS_FDLW_WAIT , "Waiting for a file write lock"},
+ {PS_FDR_WAIT , "Waiting for read"},
+ {PS_FDW_WAIT , "Waitingfor write"},
+ {PS_SELECT_WAIT , "Waiting on select"},
+ {PS_SLEEP_WAIT , "Sleeping"},
+ {PS_WAIT_WAIT , "Waiting process"},
+ {PS_SIGWAIT , "Waiting for a signal"},
+ {PS_JOIN , "Waiting to join"},
+ {PS_SUSPENDED , "Suspended"},
+ {PS_DEAD , "Dead"},
+ {PS_STATE_MAX , "Not a real state!"}
+};
+
+void
+_thread_dump_info(void)
+{
+ char s[128];
+ int fd;
+ int i;
+ int j;
+ pthread_t pthread;
+
+ /* Open the dump file for append and create it if necessary: */
+ if ((fd = _thread_sys_open("/tmp/uthread.dump", O_RDWR | O_CREAT | O_APPEND, 0666)) < 0) {
+ /* Can't open the dump file. */
+ } else {
+ /* Output a header for active threads: */
+ strcpy(s, "\n\n=============\nACTIVE THREADS\n\n");
+ _thread_sys_write(fd, s, strlen(s));
+
+ /* Enter a loop to report each thread in the global list: */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Find the state: */
+ for (j = 0; j < (sizeof(thread_info) / sizeof(struct s_thread_info)) - 1; j++)
+ if (thread_info[j].state == pthread->state)
+ break;
+ /* Output a record for the current thread: */
+ sprintf(s, "--------------------\nThread %p prio %3d state %s [%s:%d]\n",
+ pthread, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno);
+ _thread_sys_write(fd, s, strlen(s));
+
+ /* Check if this is the running thread: */
+ if (pthread == _thread_run) {
+ /* Output a record for the running thread: */
+ strcpy(s, "This is the running thread\n");
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ /* Check if this is the initial thread: */
+ if (pthread == _thread_initial) {
+ /* Output a record for the initial thread: */
+ strcpy(s, "This is the initial thread\n");
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /* File descriptor read lock wait: */
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_FDR_WAIT:
+ case PS_FDW_WAIT:
+ /* Write the lock details: */
+ sprintf(s, "fd %d[%s:%d]", pthread->data.fd.fd, pthread->data.fd.fname, pthread->data.fd.branch);
+ _thread_sys_write(fd, s, strlen(s));
+ sprintf(s, "owner %pr/%pw\n", _thread_fd_table[pthread->data.fd.fd]->r_owner, _thread_fd_table[pthread->data.fd.fd]->w_owner);
+ _thread_sys_write(fd, s, strlen(s));
+ break;
+
+ /*
+ * Trap other states that are not explicitly
+ * coded to dump information:
+ */
+ default:
+ /* Nothing to do here. */
+ break;
+ }
+ }
+
+ /* Check if there are no dead threads: */
+ if (_thread_dead == NULL) {
+ /* Output a record: */
+ strcpy(s, "\n\nTHERE ARE NO DEAD THREADS\n");
+ _thread_sys_write(fd, s, strlen(s));
+ } else {
+ /* Output a header for dead threads: */
+ strcpy(s, "\n\nDEAD THREADS\n\n");
+ _thread_sys_write(fd, s, strlen(s));
+
+ /*
+ * Enter a loop to report each thread in the global
+ * dead thread list:
+ */
+ for (pthread = _thread_dead; pthread != NULL; pthread = pthread->nxt) {
+ /* Output a record for the current thread: */
+ sprintf(s, "Thread %p prio %3d [%s:%d]\n", pthread, pthread->pthread_priority,pthread->fname,pthread->lineno);
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ }
+
+ /* Output a header for file descriptors: */
+ strcpy(s, "\n\n=============\nFILE DESCRIPTOR TABLE\n\n");
+ _thread_sys_write(fd, s, strlen(s));
+
+ /* Enter a loop to report file descriptor lock usage: */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /*
+ * Check if memory is allocated for this file
+ * descriptor:
+ */
+ if (_thread_fd_table[i] != NULL) {
+ /* Report the file descriptor lock status: */
+ sprintf(s, "fd[%3d] read owner %p count %d [%s:%d]\n write owner %p count %d [%s:%d]\n",
+ i,
+ _thread_fd_table[i]->r_owner,
+ _thread_fd_table[i]->r_lockcount,
+ _thread_fd_table[i]->r_fname,
+ _thread_fd_table[i]->r_lineno,
+ _thread_fd_table[i]->w_owner,
+ _thread_fd_table[i]->w_lockcount,
+ _thread_fd_table[i]->w_fname,
+ _thread_fd_table[i]->w_lineno);
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ }
+
+ /* Close the dump file: */
+ _thread_sys_close(fd);
+ }
+ return;
+}
+#endif
diff --git a/lib/libpthread/thread/thr_init.c b/lib/libpthread/thread/thr_init.c
new file mode 100644
index 0000000..5833cdf
--- /dev/null
+++ b/lib/libpthread/thread/thr_init.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+
+/* Allocate space for global thread variables here: */
+#define GLOBAL_PTHREAD_PRIVATE
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <machine/reg.h>
+#include <pthread.h>
+#include "pthread_private.h"
+extern int _thread_autoinit_dummy_decl;
+
+/*
+ * Threaded process initialization
+ */
+void
+_thread_init(void)
+{
+ int flags;
+ int i;
+ struct sigaction act;
+
+ /* Ensure that the auto-initialization routine is linked in: */
+ _thread_autoinit_dummy_decl = 1;
+
+ /* Check if this function has already been called: */
+ if (_thread_initial)
+ /* Only initialise the threaded application once. */
+ return;
+
+ /* Get the standard I/O flags before messing with them : */
+ for (i = 0; i < 3; i++)
+ if ((_pthread_stdio_flags[i] =
+ _thread_sys_fcntl(i,F_GETFL, NULL)) == -1)
+ PANIC("Cannot get stdio flags");
+
+ /*
+ * Create a pipe that is written to by the signal handler to prevent
+ * signals being missed in calls to _thread_sys_select:
+ */
+ if (_thread_sys_pipe(_thread_kern_pipe) != 0) {
+ /* Cannot create pipe, so abort: */
+ PANIC("Cannot create kernel pipe");
+ }
+ /* Get the flags for the read pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel read pipe flags");
+ }
+ /* Make the read pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot make kernel read pipe non-blocking");
+ }
+ /* Get the flags for the write pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel write pipe flags");
+ }
+ /* Make the write pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel write pipe flags");
+ }
+ /* Allocate memory for the thread structure of the initial thread: */
+ else if ((_thread_initial = (pthread_t) malloc(sizeof(struct pthread))) == NULL) {
+ /*
+ * Insufficient memory to initialise this application, so
+ * abort:
+ */
+ PANIC("Cannot allocate memory for initial thread");
+ } else {
+ /* Zero the global kernel thread structure: */
+ memset(&_thread_kern_thread, 0, sizeof(struct pthread));
+ memset(_thread_initial, 0, sizeof(struct pthread));
+
+ /* Default the priority of the initial thread: */
+ _thread_initial->pthread_priority = PTHREAD_DEFAULT_PRIORITY;
+
+ /* Initialise the state of the initial thread: */
+ _thread_initial->state = PS_RUNNING;
+
+ /* Initialise the queue: */
+ _thread_queue_init(&(_thread_initial->join_queue));
+
+ /* Initialise the rest of the fields: */
+ _thread_initial->parent_thread = NULL;
+ _thread_initial->specific_data = NULL;
+ _thread_initial->cleanup = NULL;
+ _thread_initial->queue = NULL;
+ _thread_initial->qnxt = NULL;
+ _thread_initial->nxt = NULL;
+ _thread_initial->flags = 0;
+ _thread_initial->error = 0;
+ _thread_link_list = _thread_initial;
+ _thread_run = _thread_initial;
+
+ /* Enter a loop to get the existing signal status: */
+ for (i = 1; i < NSIG; i++) {
+ /* Check for signals which cannot be trapped: */
+ if (i == SIGKILL || i == SIGSTOP) {
+ }
+ /* Get the signal handler details: */
+ else if (_thread_sys_sigaction(i, NULL, &act) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot read signal handler info");
+ }
+ /* Set the signal handler for the initial thread: */
+ else if (sigaction(i, &act, NULL) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot initialise signal handler for initial thread");
+ }
+ }
+
+ /* Initialise the global signal action structure: */
+ sigfillset(&act.sa_mask);
+ act.sa_handler = (void (*) ()) _thread_sig_handler;
+ act.sa_flags = SA_RESTART;
+
+ /* Enter a loop to initialise the rest of the signals: */
+ for (i = 1; i < NSIG; i++) {
+ /* Check for signals which cannot be trapped: */
+ if (i == SIGKILL || i == SIGSTOP) {
+ }
+ /* Initialise the signal for default handling: */
+ else if (_thread_sys_sigaction(i, &act, NULL) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot initialise signal handler");
+ }
+ }
+
+ /* Get the table size: */
+ if ((_thread_dtablesize = getdtablesize()) < 0) {
+ /*
+ * Cannot get the system defined table size, so abort
+ * this process.
+ */
+ PANIC("Cannot get dtablesize");
+ }
+ /* Allocate memory for the file descriptor table: */
+ if ((_thread_fd_table = (struct fd_table_entry **) malloc(sizeof(struct fd_table_entry *) * _thread_dtablesize)) == NULL) {
+ /*
+ * Cannot allocate memory for the file descriptor
+ * table, so abort this process.
+ */
+ PANIC("Cannot allocate memory for file descriptor table");
+ } else {
+ /*
+ * Enter a loop to initialise the file descriptor
+ * table:
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Initialise the file descriptor table: */
+ _thread_fd_table[i] = NULL;
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * Special start up code for NetBSD/Alpha
+ */
+#if defined(__NetBSD__) && defined(__alpha__)
+int
+main(int argc, char *argv[], char *env);
+
+int
+_thread_main(int argc, char *argv[], char *env)
+{
+ _thread_init();
+ return (main(argc, argv, env));
+}
+#endif
+#else
+/*
+ * A stub for non-threaded programs.
+ */
+void
+_thread_init(void)
+{
+}
+#endif
diff --git a/lib/libpthread/thread/thr_join.c b/lib/libpthread/thread/thr_join.c
new file mode 100644
index 0000000..161482e
--- /dev/null
+++ b/lib/libpthread/thread/thr_join.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_join(pthread_t pthread, void **thread_return)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread1;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the first thread in the list: */
+ pthread1 = _thread_link_list;
+
+ /* Search for the thread to join to: */
+ while (pthread1 != NULL && pthread1 != pthread) {
+ /* Point to the next thread: */
+ pthread1 = pthread1->nxt;
+ }
+
+ if (pthread1 == NULL) {
+ /* Point to the first thread in the dead thread list: */
+ pthread1 = _thread_dead;
+
+ /* Search for the thread to join to: */
+ while (pthread1 != NULL && pthread1 != pthread) {
+ /* Point to the next thread: */
+ pthread1 = pthread1->nxt;
+ }
+ }
+
+ if (pthread1 == NULL) {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+
+ /* Check if this thread has been detached: */
+ } else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+ }
+ /* Check if the thread is not dead: */
+ else if (pthread->state != PS_DEAD) {
+ /* Add the running thread to the join queue: */
+ _thread_queue_enq(&(pthread->join_queue), _thread_run);
+
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__);
+
+ /* Block signals again: */
+ _thread_kern_sig_block(NULL);
+
+ /* Check if the thread is not detached: */
+ if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) {
+ /* Check if the return value is required: */
+ if (thread_return) {
+ /* Return the thread's return value: */
+ *thread_return = pthread->ret;
+ }
+ } else {
+ /* Return an error: */
+ errno = ESRCH;
+ rval = -1;
+ }
+ } else {
+ /* Check if the return value is required: */
+ if (thread_return != NULL) {
+ /* Return the thread's return value: */
+ *thread_return = pthread->ret;
+ }
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_kern.c b/lib/libpthread/thread/thr_kern.c
new file mode 100644
index 0000000..ba8e250
--- /dev/null
+++ b/lib/libpthread/thread/thr_kern.c
@@ -0,0 +1,1739 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/syscall.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* Static variables: */
+static sigset_t sig_to_block = 0xffffffff;
+static sigset_t sig_to_unblock = 0;
+
+/* Static function prototype definitions: */
+static void
+_thread_kern_select(int wait_reqd);
+static void
+_thread_signal(pthread_t pthread, int sig);
+
+void
+_thread_kern_sched(struct sigcontext * scp)
+{
+#ifndef __alpha
+ char *fdata;
+#endif
+ int i;
+ int prio = -1;
+ pthread_t pthread;
+ pthread_t pthread_h = NULL;
+ pthread_t pthread_nxt = NULL;
+ pthread_t pthread_prv = NULL;
+ pthread_t pthread_s = NULL;
+ struct itimerval itimer;
+ struct timespec ts;
+ struct timespec ts1;
+ struct timeval tv;
+ struct timeval tv1;
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Check if this function was called from the signal handler: */
+ if (scp != NULL) {
+ /*
+ * Copy the signal context to the current thread's jump
+ * buffer:
+ */
+ memcpy(&_thread_run->saved_sigcontext, scp, sizeof(_thread_run->saved_sigcontext));
+
+#ifndef __alpha
+ /* Point to the floating point data in the running thread: */
+ fdata = _thread_run->saved_fp;
+
+ /* Save the floating point data: */
+__asm__("fnsave %0": :"m"(*fdata));
+#endif
+
+ /* Flag the signal context as the last state saved: */
+ _thread_run->sig_saved = 1;
+ }
+ /* Save the state of the current thread: */
+ else if (_thread_sys_setjmp(_thread_run->saved_jmp_buf) != 0) {
+ /* Unblock signals (just in case): */
+ _thread_kern_sig_unblock(0);
+
+ /*
+ * This point is reached when a longjmp() is called to
+ * restore the state of a thread.
+ */
+ return;
+ } else {
+ /* Flag the jump buffer was the last state saved: */
+ _thread_run->sig_saved = 0;
+ }
+
+ /* Point to the first dead thread (if there are any): */
+ pthread = _thread_dead;
+
+ /* There is no previous dead thread: */
+ pthread_prv = NULL;
+
+ /* Enter a loop to cleanup after dead threads: */
+ while (pthread != NULL) {
+ /* Save a pointer to the next thread: */
+ pthread_nxt = pthread->nxt;
+
+ /* Check if this thread is one which is running: */
+ if (pthread == _thread_run || pthread == _thread_initial) {
+ /*
+ * Don't destroy the running thread or the initial
+ * thread.
+ */
+ pthread_prv = pthread;
+ }
+ /*
+ * Check if this thread has detached or if it is a signal
+ * handler thread:
+ */
+ else if (((pthread->attr.flags & PTHREAD_DETACHED) != 0) || pthread->parent_thread != NULL) {
+ /* Check if there is no previous dead thread: */
+ if (pthread_prv == NULL) {
+ /*
+ * The dead thread is at the head of the
+ * list:
+ */
+ _thread_dead = pthread_nxt;
+ } else {
+ /*
+ * The dead thread is not at the head of the
+ * list:
+ */
+ pthread_prv->nxt = pthread->nxt;
+ }
+
+ /*
+ * Check if the stack was not specified by the caller
+ * to pthread_create and has not been destroyed yet:
+ */
+ if (pthread->attr.stackaddr_attr == NULL && pthread->stack != NULL) {
+ /* Free the stack of the dead thread: */
+ free(pthread->stack);
+ }
+ /* Free the memory allocated to the thread structure: */
+ free(pthread);
+ } else {
+ /*
+ * This thread has not detached, so do not destroy
+ * it:
+ */
+ pthread_prv = pthread;
+
+ /*
+ * Check if the stack was not specified by the caller
+ * to pthread_create and has not been destroyed yet:
+ */
+ if (pthread->attr.stackaddr_attr == NULL && pthread->stack != NULL) {
+ /* Free the stack of the dead thread: */
+ free(pthread->stack);
+
+ /*
+ * NULL the stack pointer now that the memory
+ * has been freed:
+ */
+ pthread->stack = NULL;
+ }
+ }
+
+ /* Point to the next thread: */
+ pthread = pthread_nxt;
+ }
+
+ /*
+ * Enter a the scheduling loop that finds the next thread that is
+ * ready to run. This loop completes when there are no more threads
+ * in the global list or when a thread has its state restored by
+ * either a sigreturn (if the state was saved as a sigcontext) or a
+ * longjmp (if the state was saved by a setjmp).
+ */
+ while (_thread_link_list != NULL) {
+ /* Get the current time of day: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+
+ /*
+ * Poll file descriptors to update the state of threads
+ * waiting on file I/O where data may be available:
+ */
+ _thread_kern_select(0);
+
+ /*
+ * Enter a loop to look for sleeping threads that are ready
+ * or threads with pending signals that are no longer
+ * blocked:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Enter a loop to process the sending signals: */
+ for (i = 1; i < NSIG; i++) {
+ /*
+ * Check if there are no pending signals of
+ * this type:
+ */
+ if (pthread->sigpend[i] == 0) {
+ }
+ /* Check if this signal type is not masked: */
+ else if (sigismember(&pthread->sigmask, i) == 0) {
+ /*
+ * Delete the signal from the set of
+ * pending signals for this thread:
+ */
+ pthread->sigpend[i] -= 1;
+
+ /*
+ * Act on the signal for the current
+ * thread:
+ */
+ _thread_signal(pthread, i);
+ } else {
+ /*
+ * This signal is masked, so make
+ * sure the count does not exceed 1:
+ */
+ pthread->sigpend[i] = 1;
+ }
+ }
+
+ /* Check if this thread is to timeout: */
+ if (pthread->state == PS_COND_WAIT ||
+ pthread->state == PS_SLEEP_WAIT ||
+ pthread->state == PS_FDR_WAIT ||
+ pthread->state == PS_FDW_WAIT ||
+ pthread->state == PS_SELECT_WAIT) {
+ /* Check if this thread is to wait forever: */
+ if (pthread->wakeup_time.tv_sec == -1) {
+ }
+ /*
+ * Check if this thread is to wakeup
+ * immediately or if it is past its wakeup
+ * time:
+ */
+ else if ((pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) ||
+ (ts.tv_sec > pthread->wakeup_time.tv_sec) ||
+ ((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
+ (ts.tv_nsec >= pthread->wakeup_time.tv_nsec))) {
+ /*
+ * Check if this thread is waiting on
+ * select:
+ */
+ if (pthread->state == PS_SELECT_WAIT) {
+ /*
+ * The select has timed out,
+ * so zero the file
+ * descriptor sets:
+ */
+ FD_ZERO(&pthread->data.select_data->readfds);
+ FD_ZERO(&pthread->data.select_data->writefds);
+ FD_ZERO(&pthread->data.select_data->exceptfds);
+ pthread->data.select_data->nfds = 0;
+ }
+ /*
+ * Return an error as an interrupted
+ * wait:
+ */
+ _thread_seterrno(pthread, EINTR);
+
+ /*
+ * Flag the timeout in the thread
+ * structure:
+ */
+ pthread->timeout = 1;
+
+ /*
+ * Change the threads state to allow
+ * it to be restarted:
+ */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ }
+ }
+
+ /* Check if there is a current thread: */
+ if (_thread_run != &_thread_kern_thread) {
+ /*
+ * Save the current time as the time that the thread
+ * became inactive:
+ */
+ _thread_run->last_inactive.tv_sec = tv.tv_sec;
+ _thread_run->last_inactive.tv_usec = tv.tv_usec;
+
+ /*
+ * Accumulate the number of microseconds that this
+ * thread has run for:
+ */
+ _thread_run->slice_usec += (_thread_run->last_inactive.tv_sec -
+ _thread_run->last_active.tv_sec) * 1000000 +
+ _thread_run->last_inactive.tv_usec -
+ _thread_run->last_active.tv_usec;
+
+ /*
+ * Check if this thread has reached its allocated
+ * time slice period:
+ */
+ if (_thread_run->slice_usec > TIMESLICE_USEC) {
+ /*
+ * Flag the allocated time slice period as
+ * up:
+ */
+ _thread_run->slice_usec = -1;
+ }
+ }
+ /* Check if an incremental priority update is required: */
+ if (((tv.tv_sec - kern_inc_prio_time.tv_sec) * 1000000 +
+ tv.tv_usec - kern_inc_prio_time.tv_usec) > INC_PRIO_USEC) {
+ /*
+ * Enter a loop to look for run-enabled threads that
+ * have not run since the last time that an
+ * incremental priority update was performed:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if this thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ }
+ /*
+ * Check if the last time that this thread
+ * was run (as indicated by the last time it
+ * became inactive) is before the time that
+ * the last incremental priority check was
+ * made:
+ */
+ else if (timercmp(&_thread_run->last_inactive, &kern_inc_prio_time, >)) {
+ /*
+ * Increment the incremental priority
+ * for this thread in the hope that
+ * it will eventually get a chance to
+ * run:
+ */
+ (pthread->inc_prio)++;
+ }
+ }
+
+ /* Save the new incremental priority update time: */
+ kern_inc_prio_time.tv_sec = tv.tv_sec;
+ kern_inc_prio_time.tv_usec = tv.tv_usec;
+ }
+ /*
+ * Enter a loop to look for the first thread of the highest
+ * priority that is ready to run:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
+ /* Check if the current thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ }
+ /*
+ * Check if no run-enabled thread has been seen or if
+ * the current thread has a priority higher than the
+ * highest seen so far:
+ */
+ else if (pthread_h == NULL || (pthread->pthread_priority + pthread->inc_prio) > prio) {
+ /*
+ * Save this thread as the highest priority
+ * thread seen so far:
+ */
+ pthread_h = pthread;
+ prio = pthread->pthread_priority + pthread->inc_prio;
+ }
+ }
+
+ /*
+ * Enter a loop to look for a thread that: 1. Is run-enabled.
+ * 2. Has the required agregate priority. 3. Has not been
+ * allocated its allocated time slice. 4. Became inactive
+ * least recently.
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
+ /* Check if the current thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ /* Ignore threads that are not ready to run. */
+ }
+ /*
+ * Check if the current thread as an agregate
+ * priority not equal to the highest priority found
+ * above:
+ */
+ else if ((pthread->pthread_priority + pthread->inc_prio) != prio) {
+ /*
+ * Ignore threads which have lower agregate
+ * priority.
+ */
+ }
+ /*
+ * Check if the current thread reached its time slice
+ * allocation last time it ran (or if it has not run
+ * yet):
+ */
+ else if (pthread->slice_usec == -1) {
+ }
+ /*
+ * Check if an eligible thread has not been found
+ * yet, or if the current thread has an inactive time
+ * earlier than the last one seen:
+ */
+ else if (pthread_s == NULL || timercmp(&pthread->last_inactive, &tv1, <)) {
+ /*
+ * Save the pointer to the current thread as
+ * the most eligible thread seen so far:
+ */
+ pthread_s = pthread;
+
+ /*
+ * Save the time that the selected thread
+ * became inactive:
+ */
+ tv1.tv_sec = pthread->last_inactive.tv_sec;
+ tv1.tv_usec = pthread->last_inactive.tv_usec;
+ }
+ }
+
+ /*
+ * Check if no thread was selected according to incomplete
+ * time slice allocation:
+ */
+ if (pthread_s == NULL) {
+ /*
+ * Enter a loop to look for any other thread that: 1.
+ * Is run-enabled. 2. Has the required agregate
+ * priority. 3. Became inactive least recently.
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
+ /*
+ * Check if the current thread is unable to
+ * run:
+ */
+ if (pthread->state != PS_RUNNING) {
+ /*
+ * Ignore threads that are not ready
+ * to run.
+ */
+ }
+ /*
+ * Check if the current thread as an agregate
+ * priority not equal to the highest priority
+ * found above:
+ */
+ else if ((pthread->pthread_priority + pthread->inc_prio) != prio) {
+ /*
+ * Ignore threads which have lower
+ * agregate priority.
+ */
+ }
+ /*
+ * Check if an eligible thread has not been
+ * found yet, or if the current thread has an
+ * inactive time earlier than the last one
+ * seen:
+ */
+ else if (pthread_s == NULL || timercmp(&pthread->last_inactive, &tv1, <)) {
+ /*
+ * Save the pointer to the current
+ * thread as the most eligible thread
+ * seen so far:
+ */
+ pthread_s = pthread;
+
+ /*
+ * Save the time that the selected
+ * thread became inactive:
+ */
+ tv1.tv_sec = pthread->last_inactive.tv_sec;
+ tv1.tv_usec = pthread->last_inactive.tv_usec;
+ }
+ }
+ }
+ /* Check if there are no threads ready to run: */
+ if (pthread_s == NULL) {
+ /*
+ * Lock the pthread kernel by changing the pointer to
+ * the running thread to point to the global kernel
+ * thread structure:
+ */
+ _thread_run = &_thread_kern_thread;
+
+ /*
+ * There are no threads ready to run, so wait until
+ * something happens that changes this condition:
+ */
+ _thread_kern_select(1);
+ } else {
+ /* Make the selected thread the current thread: */
+ _thread_run = pthread_s;
+
+ /*
+ * Save the current time as the time that the thread
+ * became active:
+ */
+ _thread_run->last_active.tv_sec = tv.tv_sec;
+ _thread_run->last_active.tv_usec = tv.tv_usec;
+
+ /*
+ * Check if this thread is running for the first time
+ * or running again after using its full time slice
+ * allocation:
+ */
+ if (_thread_run->slice_usec == -1) {
+ /* Reset the accumulated time slice period: */
+ _thread_run->slice_usec = 0;
+ }
+ /*
+ * Reset the incremental priority now that this
+ * thread has been given the chance to run:
+ */
+ _thread_run->inc_prio = 0;
+
+ /* Check if there is more than one thread: */
+ if (_thread_run != _thread_link_list || _thread_run->nxt != NULL) {
+ /*
+ * Define the maximum time before a SIGVTALRM
+ * is required:
+ */
+ itimer.it_value.tv_sec = 0;
+ itimer.it_value.tv_usec = TIMESLICE_USEC;
+
+ /*
+ * The interval timer is not reloaded when it
+ * times out. The interval time needs to be
+ * calculated every time.
+ */
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+
+ /*
+ * Enter a loop to look for threads waiting
+ * for a time:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /*
+ * Check if this thread is to
+ * timeout:
+ */
+ if (pthread->state == PS_COND_WAIT ||
+ pthread->state == PS_SLEEP_WAIT ||
+ pthread->state == PS_FDR_WAIT ||
+ pthread->state == PS_FDW_WAIT ||
+ pthread->state == PS_SELECT_WAIT) {
+ /*
+ * Check if this thread is to
+ * wait forever:
+ */
+ if (pthread->wakeup_time.tv_sec == -1) {
+ }
+ /*
+ * Check if this thread is to
+ * wakeup immediately:
+ */
+ else if (pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) {
+ }
+ /*
+ * Check if the current time
+ * is after the wakeup time:
+ */
+ else if ((ts.tv_sec > pthread->wakeup_time.tv_sec) ||
+ ((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
+ (ts.tv_nsec > pthread->wakeup_time.tv_nsec))) {
+ } else {
+ /*
+ * Calculate the time
+ * until this thread
+ * is ready, allowing
+ * for the clock
+ * resolution:
+ */
+ ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
+ ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
+ CLOCK_RES_NSEC;
+
+ /*
+ * Check for
+ * underflow of the
+ * nanosecond field:
+ */
+ if (ts1.tv_nsec < 0) {
+ /*
+ * Allow for
+ * the
+ * underflow
+ * of the
+ * nanosecond
+ * field:
+ */
+ ts1.tv_sec--;
+ ts1.tv_nsec += 1000000000;
+ }
+ /*
+ * Check for overflow
+ * of the nanosecond
+ * field:
+ */
+ if (ts1.tv_nsec >= 1000000000) {
+ /*
+ * Allow for
+ * the
+ * overflow
+ * of the
+ * nanosecond
+ * field:
+ */
+ ts1.tv_sec++;
+ ts1.tv_nsec -= 1000000000;
+ }
+ /*
+ * Convert the
+ * timespec structure
+ * to a timeval
+ * structure:
+ */
+ TIMESPEC_TO_TIMEVAL(&tv, &ts1);
+
+ /*
+ * Check if the
+ * thread will be
+ * ready sooner than
+ * the earliest one
+ * found so far:
+ */
+ if (timercmp(&tv, &itimer.it_value, <)) {
+ /*
+ * Update the
+ * time
+ * value:
+ */
+ itimer.it_value.tv_sec = tv.tv_sec;
+ itimer.it_value.tv_usec = tv.tv_usec;
+ }
+ }
+ }
+ }
+
+ /*
+ * Start the interval timer for the
+ * calculated time interval:
+ */
+ if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) != 0) {
+ /*
+ * Cannot initialise the timer, so
+ * abort this process:
+ */
+ PANIC("Cannot set virtual timer");
+ }
+ }
+ /* Check if a signal context was saved: */
+ if (_thread_run->sig_saved == 1) {
+#ifndef __alpha
+ /*
+ * Point to the floating point data in the
+ * running thread:
+ */
+ fdata = _thread_run->saved_fp;
+
+ /* Restore the floating point state: */
+ __asm__("frstor %0": :"m"(*fdata));
+#endif
+
+ /*
+ * Do a sigreturn to restart the thread that
+ * was interrupted by a signal:
+ */
+ _thread_sys_sigreturn(&_thread_run->saved_sigcontext);
+ } else {
+ /*
+ * Do a longjmp to restart the thread that
+ * was context switched out (by a longjmp to
+ * a different thread):
+ */
+ _thread_sys_longjmp(_thread_run->saved_jmp_buf, 1);
+ }
+
+ /* This point should not be reached. */
+ PANIC("Thread has returned from sigreturn or longjmp");
+ }
+ }
+
+ /* There are no more threads, so exit this process: */
+ exit(0);
+}
+
+static void
+_thread_signal(pthread_t pthread, int sig)
+{
+ int done;
+ long l;
+ pthread_t new_pthread;
+ struct sigaction act;
+ void *arg;
+
+ /*
+ * Assume that the signal will not be dealt with according
+ * to the thread state:
+ */
+ done = 0;
+
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /* States which do not change when a signal is trapped: */
+ case PS_COND_WAIT:
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_RUNNING:
+ case PS_STATE_MAX:
+ case PS_SIGTHREAD:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* Wait for child: */
+ case PS_WAIT_WAIT:
+ /* Check if the signal is from a child exiting: */
+ if (sig == SIGCHLD) {
+ /* Reset the error: */
+ _thread_seterrno(pthread, 0);
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ } else {
+ /* Return the 'interrupted' error: */
+ _thread_seterrno(pthread, EINTR);
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ pthread->interrupted = 1;
+ break;
+
+ /* Waiting on I/O for zero or more file descriptors: */
+ case PS_SELECT_WAIT:
+ pthread->data.select_data->nfds = -1;
+
+ /* Return the 'interrupted' error: */
+ _thread_seterrno(pthread, EINTR);
+ pthread->interrupted = 1;
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ break;
+
+ /*
+ * States that are interrupted by the occurrence of a signal
+ * other than the scheduling alarm:
+ */
+ case PS_FDR_WAIT:
+ case PS_FDW_WAIT:
+ case PS_SLEEP_WAIT:
+ /* Return the 'interrupted' error: */
+ _thread_seterrno(pthread, EINTR);
+ pthread->interrupted = 1;
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+
+ /* Return the signal number: */
+ pthread->signo = sig;
+ break;
+
+ /* Waiting on a signal: */
+ case PS_SIGWAIT:
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+
+ /* Return the signal number: */
+ pthread->signo = sig;
+
+ /* Flag the signal as dealt with: */
+ done = 1;
+ break;
+ }
+
+ /*
+ * Check if this signal has been dealt with, or is being
+ * ignored:
+ */
+ if (done || pthread->act[sig - 1].sa_handler == SIG_IGN) {
+ /* Ignore the signal for this thread. */
+ }
+ /* Check if this signal is to use the default handler: */
+ else if (pthread->act[sig - 1].sa_handler == SIG_DFL) {
+ /* Process according to signal type: */
+ switch (sig) {
+ /* Signals which cause core dumps: */
+ case SIGQUIT:
+ case SIGILL:
+ case SIGTRAP:
+ case SIGABRT:
+ case SIGEMT:
+ case SIGFPE:
+ case SIGBUS:
+ case SIGSEGV:
+ case SIGSYS:
+ /* Clear the signal action: */
+ sigfillset(&act.sa_mask);
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = SA_RESTART;
+ _thread_sys_sigaction(sig, &act, NULL);
+
+ /*
+ * Do a sigreturn back to where the signal was
+ * detected and a core dump should occur:
+ */
+ _thread_sys_sigreturn(&pthread->saved_sigcontext);
+ break;
+
+ /* Default processing for other signals: */
+ default:
+ /*
+ * ### Default processing is a problem to resolve!
+ * ###
+ */
+ break;
+ }
+ } else {
+ /*
+ * Cast the signal number as a long and then to a void
+ * pointer. Sigh. This is POSIX.
+ */
+ l = (long) sig;
+ arg = (void *) l;
+
+ /* Create a signal handler thread, but don't run it yet: */
+ if (_thread_create(&new_pthread, NULL, (void *) pthread->act[sig - 1].sa_handler, arg, pthread) != 0) {
+ /*
+ * Error creating signal handler thread, so abort
+ * this process:
+ */
+ PANIC("Cannot create signal handler thread");
+ }
+ }
+
+ /* Nothing to return. */
+ return;
+}
+
+void
+_thread_kern_sig_block(int *status)
+{
+ sigset_t oset;
+
+ /*
+ * Block all signals so that the process will not be interrupted by
+ * signals:
+ */
+ _thread_sys_sigprocmask(SIG_SETMASK, &sig_to_block, &oset);
+
+ /* Check if the caller wants the current block status returned: */
+ if (status != NULL) {
+ /* Return the previous signal block status: */
+ *status = (oset != 0);
+ }
+ return;
+}
+
+void
+_thread_kern_sig_unblock(int status)
+{
+ sigset_t oset;
+
+ /*
+ * Check if the caller thinks that signals weren't blocked when it
+ * called _thread_kern_sig_block:
+ */
+ if (status == 0) {
+ /*
+ * Unblock all signals so that the process will be
+ * interrupted when a signal occurs:
+ */
+ _thread_sys_sigprocmask(SIG_SETMASK, &sig_to_unblock, &oset);
+ }
+ return;
+}
+
+void
+_thread_kern_sched_state(enum pthread_state state, char *fname, int lineno)
+{
+ /* Change the state of the current thread: */
+ _thread_run->state = state;
+ _thread_run->fname = fname;
+ _thread_run->lineno = lineno;
+
+ /* Schedule the next thread that is ready: */
+ _thread_kern_sched(NULL);
+ return;
+}
+
+static void
+_thread_kern_select(int wait_reqd)
+{
+ char bufr[128];
+ fd_set fd_set_except;
+ fd_set fd_set_read;
+ fd_set fd_set_write;
+ int count = 0;
+ int count_dec;
+ int found_one;
+ int i;
+ int nfds = -1;
+ int settimeout;
+ pthread_t pthread;
+ ssize_t num;
+ struct timespec ts;
+ struct timespec ts1;
+ struct timeval *p_tv;
+ struct timeval tv;
+ struct timeval tv1;
+
+ /* Zero the file descriptor sets: */
+ FD_ZERO(&fd_set_read);
+ FD_ZERO(&fd_set_write);
+ FD_ZERO(&fd_set_except);
+
+ /* Check if the caller wants to wait: */
+ if (wait_reqd) {
+ /*
+ * Add the pthread kernel pipe file descriptor to the read
+ * set:
+ */
+ FD_SET(_thread_kern_pipe[0], &fd_set_read);
+ nfds = _thread_kern_pipe[0];
+
+ /* Get the current time of day: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+ }
+ /* Initialise the time value structure: */
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ /*
+ * Enter a loop to process threads waiting on either file descriptors
+ * or times:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Assume that this state does not time out: */
+ settimeout = 0;
+
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /*
+ * States which do not depend on file descriptor I/O
+ * operations or timeouts:
+ */
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_RUNNING:
+ case PS_SIGTHREAD:
+ case PS_SIGWAIT:
+ case PS_STATE_MAX:
+ case PS_WAIT_WAIT:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* File descriptor read wait: */
+ case PS_FDR_WAIT:
+ /* Add the file descriptor to the read set: */
+ FD_SET(pthread->data.fd.fd, &fd_set_read);
+
+ /*
+ * Check if this file descriptor is greater than any
+ * of those seen so far:
+ */
+ if (pthread->data.fd.fd > nfds) {
+ /* Remember this file descriptor: */
+ nfds = pthread->data.fd.fd;
+ }
+ /* Increment the file descriptor count: */
+ count++;
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+
+ /* File descriptor write wait: */
+ case PS_FDW_WAIT:
+ /* Add the file descriptor to the write set: */
+ FD_SET(pthread->data.fd.fd, &fd_set_write);
+
+ /*
+ * Check if this file descriptor is greater than any
+ * of those seen so far:
+ */
+ if (pthread->data.fd.fd > nfds) {
+ /* Remember this file descriptor: */
+ nfds = pthread->data.fd.fd;
+ }
+ /* Increment the file descriptor count: */
+ count++;
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+
+ /* States that time out: */
+ case PS_SLEEP_WAIT:
+ case PS_COND_WAIT:
+ /* Flag a timeout as required: */
+ settimeout = 1;
+ break;
+
+ /* Select wait: */
+ case PS_SELECT_WAIT:
+ /*
+ * Enter a loop to process each file descriptor in
+ * the thread-specific file descriptor sets:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ /*
+ * Check if this file descriptor is set for
+ * exceptions:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
+ /*
+ * Add the file descriptor to the
+ * exception set:
+ */
+ FD_SET(i, &fd_set_except);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ /*
+ * Check if this file descriptor is set for
+ * write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
+ /*
+ * Add the file descriptor to the
+ * write set:
+ */
+ FD_SET(i, &fd_set_write);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ /*
+ * Check if this file descriptor is set for
+ * read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
+ /*
+ * Add the file descriptor to the
+ * read set:
+ */
+ FD_SET(i, &fd_set_read);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ }
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+ }
+
+ /*
+ * Check if the caller wants to wait and if the thread state
+ * is one that times out:
+ */
+ if (wait_reqd && settimeout) {
+ /* Check if this thread wants to wait forever: */
+ if (pthread->wakeup_time.tv_sec == -1) {
+ }
+ /* Check if this thread doesn't want to wait at all: */
+ else if (pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) {
+ /* Override the caller's request to wait: */
+ wait_reqd = 0;
+ } else {
+ /*
+ * Calculate the time until this thread is
+ * ready, allowing for the clock resolution:
+ */
+ ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
+ ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
+ CLOCK_RES_NSEC;
+
+ /*
+ * Check for underflow of the nanosecond
+ * field:
+ */
+ if (ts1.tv_nsec < 0) {
+ /*
+ * Allow for the underflow of the
+ * nanosecond field:
+ */
+ ts1.tv_sec--;
+ ts1.tv_nsec += 1000000000;
+ }
+ /*
+ * Check for overflow of the nanosecond
+ * field:
+ */
+ if (ts1.tv_nsec >= 1000000000) {
+ /*
+ * Allow for the overflow of the
+ * nanosecond field:
+ */
+ ts1.tv_sec++;
+ ts1.tv_nsec -= 1000000000;
+ }
+ /*
+ * Convert the timespec structure to a
+ * timeval structure:
+ */
+ TIMESPEC_TO_TIMEVAL(&tv1, &ts1);
+
+ /*
+ * Check if no time value has been found yet,
+ * or if the thread will be ready sooner that
+ * the earliest one found so far:
+ */
+ if ((tv.tv_sec == 0 && tv.tv_usec == 0) || timercmp(&tv1, &tv, <)) {
+ /* Update the time value: */
+ tv.tv_sec = tv1.tv_sec;
+ tv.tv_usec = tv1.tv_usec;
+ }
+ }
+ }
+ }
+
+ /* Check if the caller wants to wait: */
+ if (wait_reqd) {
+ /* Check if no threads were found with timeouts: */
+ if (tv.tv_sec == 0 && tv.tv_usec == 0) {
+ /* Wait forever: */
+ p_tv = NULL;
+ } else {
+ /*
+ * Point to the time value structure which contains
+ * the earliest time that a thread will be ready:
+ */
+ p_tv = &tv;
+ }
+
+ /*
+ * Flag the pthread kernel as in a select. This is to avoid
+ * the window between the next statement that unblocks
+ * signals and the select statement which follows.
+ */
+ _thread_kern_in_select = 1;
+
+ /* Unblock all signals: */
+ _thread_kern_sig_unblock(0);
+
+ /*
+ * Wait for a file descriptor to be ready for read, write, or
+ * an exception, or a timeout to occur:
+ */
+ count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
+
+ /* Block all signals again: */
+ _thread_kern_sig_block(NULL);
+
+ /* Reset the kernel in select flag: */
+ _thread_kern_in_select = 0;
+
+ /*
+ * Check if it is possible that there are bytes in the kernel
+ * read pipe waiting to be read:
+ */
+ if (count < 0 || FD_ISSET(_thread_kern_pipe[0], &fd_set_read)) {
+ /*
+ * Check if the kernel read pipe was included in the
+ * count:
+ */
+ if (count > 0) {
+ /*
+ * Remove the kernel read pipe from the
+ * count:
+ */
+ FD_CLR(_thread_kern_pipe[0], &fd_set_read);
+
+ /* Decrement the count of file descriptors: */
+ count--;
+ }
+ /*
+ * Enter a loop to read (and trash) bytes from the
+ * pthread kernel pipe:
+ */
+ while ((num = _thread_sys_read(_thread_kern_pipe[0], bufr, sizeof(bufr))) > 0) {
+ /*
+ * The buffer read contains one byte per
+ * signal and each byte is the signal number.
+ * This data is not used, but the fact that
+ * the signal handler wrote to the pipe *is*
+ * used to cause the _thread_sys_select call
+ * to complete if the signal occurred between
+ * the time when signals were unblocked and
+ * the _thread_sys_select select call being
+ * made.
+ */
+ }
+ }
+ }
+ /* Check if there are file descriptors to poll: */
+ else if (count > 0) {
+ /*
+ * Point to the time value structure which has been zeroed so
+ * that the call to _thread_sys_select will not wait:
+ */
+ p_tv = &tv;
+
+ /* Poll file descrptors without wait: */
+ count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
+ }
+ /*
+ * Check if the select call was interrupted, or some other error
+ * occurred:
+ */
+ if (count < 0) {
+ /* Check if the select call was interrupted: */
+ if (errno == EINTR) {
+ /*
+ * Interrupted calls are expected. The interrupting
+ * signal will be in the sigpend array.
+ */
+ } else {
+ /* This should not occur: */
+ }
+ }
+ /* Check if no file descriptors are ready: */
+ else if (count == 0) {
+ /* Nothing to do here. */
+ } else {
+ /*
+ * Enter a loop to look for threads waiting on file
+ * descriptors that are flagged as available by the
+ * _thread_sys_select syscall:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /*
+ * States which do not depend on file
+ * descriptor I/O operations:
+ */
+ case PS_RUNNING:
+ case PS_COND_WAIT:
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_SIGWAIT:
+ case PS_SLEEP_WAIT:
+ case PS_WAIT_WAIT:
+ case PS_SIGTHREAD:
+ case PS_STATE_MAX:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* File descriptor read wait: */
+ case PS_FDR_WAIT:
+ /*
+ * Check if the file descriptor is available
+ * for read:
+ */
+ if (FD_ISSET(pthread->data.fd.fd, &fd_set_read)) {
+ /*
+ * Change the thread state to allow
+ * it to read from the file when it
+ * is scheduled next:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+
+ /* File descriptor write wait: */
+ case PS_FDW_WAIT:
+ /*
+ * Check if the file descriptor is available
+ * for write:
+ */
+ if (FD_ISSET(pthread->data.fd.fd, &fd_set_write)) {
+ /*
+ * Change the thread state to allow
+ * it to write to the file when it is
+ * scheduled next:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+
+ /* Select wait: */
+ case PS_SELECT_WAIT:
+ /*
+ * Reset the flag that indicates if a file
+ * descriptor is ready for some type of
+ * operation:
+ */
+ count_dec = 0;
+
+ /*
+ * Enter a loop to search though the
+ * thread-specific select file descriptors
+ * for the first descriptor that is ready:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds && count_dec == 0; i++) {
+ /*
+ * Check if this file descriptor does
+ * not have an exception:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds) && FD_ISSET(i, &fd_set_except)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ /*
+ * Check if this file descriptor is
+ * not ready for write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds) && FD_ISSET(i, &fd_set_write)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ /*
+ * Check if this file descriptor is
+ * not ready for read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds) && FD_ISSET(i, &fd_set_read)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ }
+
+ /*
+ * Check if any file descriptors are ready
+ * for the current thread:
+ */
+ if (count_dec) {
+ /*
+ * Reset the count of file
+ * descriptors that are ready for
+ * this thread:
+ */
+ found_one = 0;
+
+ /*
+ * Enter a loop to search though the
+ * thread-specific select file
+ * descriptors:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ /*
+ * Reset the count of
+ * operations for which the
+ * current file descriptor is
+ * ready:
+ */
+ count_dec = 0;
+
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * exceptions:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
+ /*
+ * Check if this file
+ * descriptor has an
+ * exception:
+ */
+ if (FD_ISSET(i, &fd_set_except)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->exceptfds);
+ }
+ }
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
+ /*
+ * Check if this file
+ * descriptor is
+ * ready for write:
+ */
+ if (FD_ISSET(i, &fd_set_write)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->writefds);
+ }
+ }
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
+ /*
+ * Check if this file
+ * descriptor is
+ * ready for read:
+ */
+ if (FD_ISSET(i, &fd_set_read)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->readfds);
+ }
+ }
+ /*
+ * Check if the current file
+ * descriptor is ready for
+ * any one of the operations:
+ */
+ if (count_dec > 0) {
+ /*
+ * Increment the
+ * count of file
+ * descriptors that
+ * are ready for the
+ * current thread:
+ */
+ found_one++;
+ }
+ }
+
+ /*
+ * Return the number of file
+ * descriptors that are ready:
+ */
+ pthread->data.select_data->nfds = found_one;
+
+ /*
+ * Change the state of the current
+ * thread to run:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+ }
+ }
+ }
+
+ /* Nothing to return. */
+ return;
+}
+
+void
+_thread_kern_set_timeout(struct timespec * timeout)
+{
+ struct timespec current_time;
+ struct timeval tv;
+
+ /* Reset the timeout flag for the running thread: */
+ _thread_run->timeout = 0;
+
+ /* Check if the thread is to wait forever: */
+ if (timeout == NULL) {
+ /*
+ * Set the wakeup time to something that can be recognised as
+ * different to an actual time of day:
+ */
+ _thread_run->wakeup_time.tv_sec = -1;
+ _thread_run->wakeup_time.tv_nsec = -1;
+ }
+ /* Check if no waiting is required: */
+ else if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
+ /* Set the wake up time to 'immediately': */
+ _thread_run->wakeup_time.tv_sec = 0;
+ _thread_run->wakeup_time.tv_nsec = 0;
+ } else {
+ /* Get the current time: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &current_time);
+
+ /* Calculate the time for the current thread to wake up: */
+ _thread_run->wakeup_time.tv_sec = current_time.tv_sec + timeout->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + timeout->tv_nsec;
+
+ /* Check if the nanosecond field needs to wrap: */
+ if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
+ /* Wrap the nanosecond field: */
+ _thread_run->wakeup_time.tv_sec += 1;
+ _thread_run->wakeup_time.tv_nsec -= 1000000000;
+ }
+ }
+ return;
+}
+#endif
diff --git a/lib/libpthread/thread/thr_kill.c b/lib/libpthread/thread/thr_kill.c
new file mode 100644
index 0000000..eb2c6b7
--- /dev/null
+++ b/lib/libpthread/thread/thr_kill.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_kill(pthread_t pthread, int sig)
+{
+ int rval = 0;
+ int status;
+ pthread_t p_pthread;
+
+ /* Check for invalid signal numbers: */
+ if (sig < 0 || sig >= NSIG)
+ /* Invalid signal: */
+ rval = EINVAL;
+ else {
+ /* Assume that the search will succeed: */
+ rval = 0;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Search for the thread: */
+ p_pthread = _thread_link_list;
+ while (p_pthread != NULL && p_pthread != pthread) {
+ p_pthread = p_pthread->nxt;
+ }
+
+ /* Check if the thread was not found: */
+ if (p_pthread == NULL)
+ /* Can't find the thread: */
+ rval = ESRCH;
+ else
+ /* Increment the pending signal count: */
+ p_pthread->sigpend[sig] += 1;
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_mattr_init.c b/lib/libpthread/thread/thr_mattr_init.c
new file mode 100644
index 0000000..323c982
--- /dev/null
+++ b/lib/libpthread/thread/thr_mattr_init.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1996 Jeffrey Hsu <hsu@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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_mutexattr_init(pthread_mutexattr_t *attr)
+{
+ int ret;
+ pthread_mutexattr_t pattr;
+
+ if ((pattr = (pthread_mutexattr_t)
+ malloc(sizeof(struct pthread_mutex_attr))) == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ memcpy(pattr, &pthread_mutexattr_default,
+ sizeof(struct pthread_mutex_attr));
+ *attr = pattr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_mattr_kind_np.c b/lib/libpthread/thread/thr_mattr_kind_np.c
new file mode 100644
index 0000000..3eeabff
--- /dev/null
+++ b/lib/libpthread/thread/thr_mattr_kind_np.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1996 Jeffrey Hsu <hsu@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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ (*attr)->m_type = kind;
+ ret = 0;
+ }
+ return(ret);
+}
+
+int
+pthread_mutexattr_getkind_np(pthread_mutexattr_t attr)
+{
+ int ret;
+ if (attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ ret = attr->m_type;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_multi_np.c b/lib/libpthread/thread/thr_multi_np.c
new file mode 100644
index 0000000..64f360f
--- /dev/null
+++ b/lib/libpthread/thread/thr_multi_np.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_multi_np()
+{
+ /* Return to multi-threaded scheduling mode: */
+ _thread_single = NULL;
+ return(0);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_mutex.c b/lib/libpthread/thread/thr_mutex.c
new file mode 100644
index 0000000..82a26e8
--- /dev/null
+++ b/lib/libpthread/thread/thr_mutex.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_mutex_init(pthread_mutex_t * mutex,
+ const pthread_mutexattr_t * mutex_attr)
+{
+ enum pthread_mutextype type;
+ pthread_mutex_t pmutex;
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Check if default mutex attributes: */
+ if (mutex_attr == NULL || *mutex_attr == NULL) {
+ /* Default to a fast mutex: */
+ type = MUTEX_TYPE_FAST;
+ } else if ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Use the requested mutex type: */
+ type = (*mutex_attr)->m_type;
+ }
+
+ /* Check no errors so far: */
+ if (ret == 0) {
+ if ((pmutex = (pthread_mutex_t) malloc(sizeof(struct pthread_mutex))) == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ /* Reset the mutex flags: */
+ pmutex->m_flags = 0;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch (type) {
+ /* Fast mutex: */
+ case MUTEX_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Reset the mutex count: */
+ pmutex->m_data.m_count = 0;
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+ if (ret == 0) {
+ /* Initialise the rest of the mutex: */
+ _thread_queue_init(&pmutex->m_queue);
+ pmutex->m_flags |= MUTEX_FLAGS_INITED;
+ pmutex->m_owner = NULL;
+ pmutex->m_type = type;
+ *mutex = pmutex;
+ } else {
+ free(pmutex);
+ *mutex = NULL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+ }
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_destroy(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutex: */
+ case MUTEX_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Reset the mutex count: */
+ (*mutex)->m_data.m_count = 0;
+ break;
+
+ /* Trap undefined mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Clean up the mutex in case that others want to use it: */
+ _thread_queue_init(&(*mutex)->m_queue);
+ (*mutex)->m_owner = NULL;
+ (*mutex)->m_flags = 0;
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_trylock(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutex: */
+ case MUTEX_TYPE_FAST:
+ /* Check if this mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for the running thread: */
+ (*mutex)->m_owner = _thread_run;
+ } else {
+ /* Return a busy error: */
+ errno = EBUSY;
+ ret = -1;
+ }
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Check if this mutex is locked: */
+ if ((*mutex)->m_owner != NULL) {
+ /*
+ * Check if the mutex is locked by the running
+ * thread:
+ */
+ if ((*mutex)->m_owner == _thread_run) {
+ /* Increment the lock count: */
+ (*mutex)->m_data.m_count++;
+ } else {
+ /* Return a busy error: */
+ errno = EBUSY;
+ ret = -1;
+ }
+ } else {
+ /* Lock the mutex for the running thread: */
+ (*mutex)->m_owner = _thread_run;
+ }
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_lock(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutexes do not check for any error conditions: */
+ case MUTEX_TYPE_FAST:
+ /*
+ * Enter a loop to wait for the mutex to be locked by the
+ * current thread:
+ */
+ while ((*mutex)->m_owner != _thread_run) {
+ /* Check if the mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for this thread: */
+ (*mutex)->m_owner = _thread_run;
+ } else {
+ /*
+ * Join the queue of threads waiting to lock
+ * the mutex:
+ */
+ _thread_queue_enq(&(*mutex)->m_queue, _thread_run);
+
+ /* Block signals: */
+ _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+ }
+ }
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /*
+ * Enter a loop to wait for the mutex to be locked by the
+ * current thread:
+ */
+ while ((*mutex)->m_owner != _thread_run) {
+ /* Check if the mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for this thread: */
+ (*mutex)->m_owner = _thread_run;
+
+ /* Reset the lock count for this mutex: */
+ (*mutex)->m_data.m_count = 0;
+ } else {
+ /*
+ * Join the queue of threads waiting to lock
+ * the mutex:
+ */
+ _thread_queue_enq(&(*mutex)->m_queue, _thread_run);
+
+ /* Block signals: */
+ _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+ }
+ }
+
+ /* Increment the lock count for this mutex: */
+ (*mutex)->m_data.m_count++;
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_unlock(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
+ /* Fast mutexes do not check for any error conditions: */
+ case MUTEX_TYPE_FAST:
+ /* Check if the running thread is not the owner of the mutex: */
+ if ((*mutex)->m_owner != _thread_run) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ }
+ /*
+ * Get the next thread from the queue of threads waiting on
+ * the mutex:
+ */
+ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
+ /* Allow the new owner of the mutex to run: */
+ PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING);
+ }
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Check if the running thread is not the owner of the mutex: */
+ if ((*mutex)->m_owner != _thread_run) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ }
+ /* Check if there are still counts: */
+ else if ((*mutex)->m_data.m_count) {
+ /* Decrement the count: */
+ (*mutex)->m_data.m_count--;
+ }
+ /*
+ * Get the next thread from the queue of threads waiting on
+ * the mutex:
+ */
+ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
+ /* Allow the new owner of the mutex to run: */
+ PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING);
+ }
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_mutexattr_destroy.c b/lib/libpthread/thread/thr_mutexattr_destroy.c
new file mode 100644
index 0000000..cf2e09f
--- /dev/null
+++ b/lib/libpthread/thread/thr_mutexattr_destroy.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ free(*attr);
+ *attr = NULL;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_nanosleep.c b/lib/libpthread/thread/thr_nanosleep.c
new file mode 100644
index 0000000..39c7dad
--- /dev/null
+++ b/lib/libpthread/thread/thr_nanosleep.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <stdio.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+nanosleep(const struct timespec * time_to_sleep,
+ struct timespec * time_remaining)
+{
+ int ret = 0;
+ struct timespec current_time;
+ struct timespec current_time1;
+ struct timespec remaining_time;
+ struct timeval tv;
+
+ /* Check if the time to sleep is legal: */
+ if (time_to_sleep == NULL || time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec > 1000000000) {
+ /* Return an EINVAL error : */
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Get the current time: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &current_time);
+
+ /* Calculate the time for the current thread to wake up: */
+ _thread_run->wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec;
+
+ /* Check if the nanosecond field has overflowed: */
+ if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
+ /* Wrap the nanosecond field: */
+ _thread_run->wakeup_time.tv_sec += 1;
+ _thread_run->wakeup_time.tv_nsec -= 1000000000;
+ }
+
+ /* Reschedule the current thread to sleep: */
+ _thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__);
+
+ /* Get the current time: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &current_time1);
+
+ /* Calculate the remaining time to sleep: */
+ remaining_time.tv_sec = time_to_sleep->tv_sec + current_time.tv_sec - current_time1.tv_sec;
+ remaining_time.tv_nsec = time_to_sleep->tv_nsec + current_time.tv_nsec - current_time1.tv_nsec;
+
+ /* Check if the nanosecond field has underflowed: */
+ if (remaining_time.tv_nsec < 0) {
+ /* Handle the underflow: */
+ remaining_time.tv_sec -= 1;
+ remaining_time.tv_nsec += 1000000000;
+ }
+
+ /* Check if the nanosecond field has overflowed: */
+ if (remaining_time.tv_nsec >= 1000000000) {
+ /* Handle the overflow: */
+ remaining_time.tv_sec += 1;
+ remaining_time.tv_nsec -= 1000000000;
+ }
+
+ /* Check if the sleep was longer than the required time: */
+ if (remaining_time.tv_sec < 0) {
+ /* Reset the time left: */
+ remaining_time.tv_sec = 0;
+ remaining_time.tv_nsec = 0;
+ }
+
+ /* Check if the time remaining is to be returned: */
+ if (time_remaining != NULL) {
+ /* Return the actual time slept: */
+ time_remaining->tv_sec = remaining_time.tv_sec;
+ time_remaining->tv_nsec = remaining_time.tv_nsec;
+ }
+
+ /* Check if the entire sleep was not completed: */
+ if (remaining_time.tv_nsec != 0 || remaining_time.tv_sec != 0) {
+ /* Return an EINTR error : */
+ errno = EINTR;
+ ret = -1;
+ }
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_once.c b/lib/libpthread/thread/thr_once.c
new file mode 100644
index 0000000..c55ba9e
--- /dev/null
+++ b/lib/libpthread/thread/thr_once.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_once(pthread_once_t * once_control, void (*init_routine) (void))
+{
+ if (once_control->state == PTHREAD_NEEDS_INIT) {
+ pthread_mutex_lock(&(once_control->mutex));
+ if (once_control->state == PTHREAD_NEEDS_INIT) {
+ init_routine();
+ once_control->state = PTHREAD_DONE_INIT;
+ }
+ pthread_mutex_unlock(&(once_control->mutex));
+ }
+ return (0);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_open.c b/lib/libpthread/thread/thr_open.c
new file mode 100644
index 0000000..ef7a504
--- /dev/null
+++ b/lib/libpthread/thread/thr_open.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+open(const char *path, int flags,...)
+{
+ int fd;
+ int mode = 0;
+ int status;
+ va_list ap;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Check if the file is being created: */
+ if (flags & O_CREAT) {
+ /* Get the creation mode: */
+ va_start(ap, flags);
+ mode = va_arg(ap, int);
+ va_end(ap);
+ }
+ /* Open the file: */
+ if ((fd = _thread_sys_open(path, flags, mode)) < 0) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(fd) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(fd);
+
+ /* Reset the file descriptor: */
+ fd = -1;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the file descriptor or -1 on error: */
+ return (fd);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h
new file mode 100644
index 0000000..e0a0511
--- /dev/null
+++ b/lib/libpthread/thread/thr_private.h
@@ -0,0 +1,783 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * Private thread definitions for the uthread kernel.
+ *
+ */
+
+#ifndef _PTHREAD_PRIVATE_H
+#define _PTHREAD_PRIVATE_H
+
+/*
+ * Evaluate the storage class specifier.
+ */
+#ifdef GLOBAL_PTHREAD_PRIVATE
+#define SCLASS
+#else
+#define SCLASS extern
+#endif
+
+/*
+ * Include files.
+ */
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+/*
+ * Kernel fatal error handler macro.
+ */
+#define PANIC(string) _thread_exit(__FILE__,__LINE__,string)
+
+/*
+ * State change macro:
+ */
+#define PTHREAD_NEW_STATE(thrd, newstate) { \
+ (thrd)->state = newstate; \
+ (thrd)->fname = __FILE__; \
+ (thrd)->lineno = __LINE__; \
+}
+
+/*
+ * Queue definitions.
+ */
+struct pthread_queue {
+ struct pthread *q_next;
+ struct pthread *q_last;
+ void *q_data;
+};
+
+/*
+ * Static queue initialization values.
+ */
+#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL }
+
+/*
+ * Mutex definitions.
+ */
+union pthread_mutex_data {
+ void *m_ptr;
+ int m_count;
+};
+
+struct pthread_mutex {
+ enum pthread_mutextype m_type;
+ struct pthread_queue m_queue;
+ struct pthread *m_owner;
+ union pthread_mutex_data m_data;
+ long m_flags;
+};
+
+/*
+ * Flags for mutexes.
+ */
+#define MUTEX_FLAGS_PRIVATE 0x01
+#define MUTEX_FLAGS_INITED 0x02
+#define MUTEX_FLAGS_BUSY 0x04
+
+/*
+ * Static mutex initialization values.
+ */
+#define PTHREAD_MUTEX_INITIALIZER \
+ { MUTEX_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, \
+ NULL, { NULL }, MUTEX_FLAGS_INITED }
+
+struct pthread_mutex_attr {
+ enum pthread_mutextype m_type;
+ long m_flags;
+};
+
+/*
+ * Condition variable definitions.
+ */
+enum pthread_cond_type {
+ COND_TYPE_FAST,
+ COND_TYPE_MAX
+};
+
+struct pthread_cond {
+ enum pthread_cond_type c_type;
+ struct pthread_queue c_queue;
+ void *c_data;
+ long c_flags;
+};
+
+struct pthread_cond_attr {
+ enum pthread_cond_type c_type;
+ long c_flags;
+};
+
+/*
+ * Flags for condition variables.
+ */
+#define COND_FLAGS_PRIVATE 0x01
+#define COND_FLAGS_INITED 0x02
+#define COND_FLAGS_BUSY 0x04
+
+/*
+ * Static cond initialization values.
+ */
+#define PTHREAD_COND_INITIALIZER \
+ { COND_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, NULL, COND_FLAGS_INITED }
+
+/*
+ * Cleanup definitions.
+ */
+struct pthread_cleanup {
+ struct pthread_cleanup *next;
+ void (*routine) ();
+ void *routine_arg;
+};
+
+/*
+ * Scheduling definitions.
+ */
+enum schedparam_policy {
+ SCHED_RR,
+ SCHED_IO,
+ SCHED_FIFO,
+ SCHED_OTHER
+};
+
+struct pthread_attr {
+ enum schedparam_policy schedparam_policy;
+ int prio;
+ int suspend;
+ int flags;
+ void *arg_attr;
+ void (*cleanup_attr) ();
+ void *stackaddr_attr;
+ size_t stacksize_attr;
+};
+
+struct sched_param {
+ int prio;
+ void *no_data;
+};
+
+/*
+ * Thread creation state attributes.
+ */
+#define PTHREAD_CREATE_RUNNING 0
+#define PTHREAD_CREATE_SUSPENDED 1
+
+/*
+ * Miscellaneous definitions.
+ */
+#define PTHREAD_STACK_DEFAULT 65536
+#define PTHREAD_DEFAULT_PRIORITY 64
+#define PTHREAD_MAX_PRIORITY 126
+#define PTHREAD_MIN_PRIORITY 0
+#define _POSIX_THREAD_ATTR_STACKSIZE
+
+/*
+ * Clock resolution in nanoseconds.
+ */
+#define CLOCK_RES_NSEC 10000000
+
+/*
+ * Number of microseconds between incremental priority updates for
+ * threads that are ready to run, but denied being run.
+ */
+#define INC_PRIO_USEC 500000
+
+/*
+ * Time slice period in microseconds.
+ */
+#define TIMESLICE_USEC 100000
+
+struct pthread_key {
+ pthread_mutex_t mutex;
+ long count;
+ void (*destructor) ();
+};
+
+/*
+ * Thread states.
+ */
+enum pthread_state {
+ PS_RUNNING,
+ PS_SIGTHREAD,
+ PS_MUTEX_WAIT,
+ PS_COND_WAIT,
+ PS_FDLR_WAIT,
+ PS_FDLW_WAIT,
+ PS_FDR_WAIT,
+ PS_FDW_WAIT,
+ PS_SELECT_WAIT,
+ PS_SLEEP_WAIT,
+ PS_WAIT_WAIT,
+ PS_SIGWAIT,
+ PS_JOIN,
+ PS_SUSPENDED,
+ PS_DEAD,
+ PS_STATE_MAX
+};
+
+
+/*
+ * File descriptor locking definitions.
+ */
+#define FD_READ 0x1
+#define FD_WRITE 0x2
+#define FD_RDWR (FD_READ | FD_WRITE)
+
+/*
+ * File descriptor table structure.
+ */
+struct fd_table_entry {
+ struct pthread_queue r_queue; /* Read queue. */
+ struct pthread_queue w_queue; /* Write queue. */
+ struct pthread *r_owner; /* Ptr to thread owning read lock. */
+ struct pthread *w_owner; /* Ptr to thread owning write lock. */
+ char *r_fname; /* Ptr to read lock source file name */
+ int r_lineno; /* Read lock source line number. */
+ char *w_fname; /* Ptr to write lock source file name */
+ int w_lineno; /* Write lock source line number. */
+ int r_lockcount; /* Count for FILE read locks. */
+ int w_lockcount; /* Count for FILE write locks. */
+ int flags; /* Flags used in open. */
+};
+
+struct pthread_select_data {
+ int nfds;
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+};
+
+union pthread_wait_data {
+ pthread_mutex_t *mutex;
+ pthread_cond_t *cond;
+ const sigset_t *sigwait; /* Waiting on a signal in sigwait */
+ struct {
+ short fd; /* Used when thread waiting on fd */
+ short branch; /* Line number, for debugging. */
+ char *fname; /* Source file name for debugging.*/
+ } fd;
+ struct pthread_select_data * select_data;
+};
+
+/*
+ * Thread structure.
+ */
+struct pthread {
+ /*
+ * Pointer to the next thread in the thread linked list.
+ */
+ struct pthread *nxt;
+
+ /*
+ * Thread start routine, argument, stack pointer and thread
+ * attributes.
+ */
+ void *(*start_routine)(void *);
+ void *arg;
+ void *stack;
+ struct pthread_attr attr;
+
+ /*
+ * Thread-specific signal handler interface:
+ *
+ * Array of signal actions for this thread.
+ */
+ struct sigaction act[NSIG];
+
+#if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(__i386__)
+ /*
+ * Saved floating point registers on systems where they are not
+ * saved in the signal context.
+ */
+ char saved_fp[108];
+#endif
+
+ /*
+ * Saved signal context used in call to sigreturn by
+ * _thread_kern_sched if sig_saved is TRUE.
+ */
+ struct sigcontext saved_sigcontext;
+
+ /*
+ * Saved jump buffer used in call to longjmp by _thread_kern_sched
+ * if sig_saved is FALSE.
+ */
+ jmp_buf saved_jmp_buf;
+
+ /*
+ * TRUE if the last state saved was a signal context. FALSE if the
+ * last state saved was a jump buffer.
+ */
+ int sig_saved;
+
+ /*
+ * Current signal mask and array of pending signals.
+ */
+ sigset_t sigmask;
+ int sigpend[NSIG];
+
+ /*
+ * Pointer to the parent thread for which the current thread is
+ * a signal handler thread, otherwise NULL if the current thread
+ * is not a signal handler thread.
+ */
+ struct pthread *parent_thread;
+
+ /* Thread state: */
+ enum pthread_state state;
+
+ /* Time that this thread was last made active. */
+ struct timeval last_active;
+
+ /* Time that this thread was last made inactive. */
+ struct timeval last_inactive;
+
+ /*
+ * Number of microseconds accumulated by this thread when
+ * time slicing is active.
+ */
+ long slice_usec;
+
+ /*
+ * Incremental priority accumulated by thread while it is ready to
+ * run but is denied being run.
+ */
+ int inc_prio;
+
+ /*
+ * Time to wake up thread. This is used for sleeping threads and
+ * for any operation which may time out (such as select).
+ */
+ struct timespec wakeup_time;
+
+ /* TRUE if operation has timed out. */
+ int timeout;
+
+ /*
+ * Error variable used instead of errno. The function __error()
+ * returns a pointer to this.
+ */
+ int error;
+
+ /* Join queue for waiting threads: */
+ struct pthread_queue join_queue;
+
+ /*
+ * The current thread can belong to only one queue at a time.
+ *
+ * Pointer to queue (if any) on which the current thread is waiting.
+ */
+ struct pthread_queue *queue;
+
+ /* Pointer to next element in queue. */
+ struct pthread *qnxt;
+
+ /* Wait data. */
+ union pthread_wait_data data;
+
+ /*
+ * Set to TRUE if a blocking operation was
+ * interrupted by a signal:
+ */
+ int interrupted;
+
+ /* Signal number when in state PS_SIGWAIT: */
+ int signo;
+
+ /* Miscellaneous data. */
+ char flags;
+ char pthread_priority;
+ void *ret;
+ const void **specific_data;
+ int specific_data_count;
+
+ /* Cleanup handlers Link List */
+ struct pthread_cleanup *cleanup;
+ char *fname; /* Ptr to source file name */
+ int lineno; /* Source line number. */
+};
+
+/*
+ * Global variables for the uthread kernel.
+ */
+
+/* Kernel thread structure used when there are no running threads: */
+SCLASS struct pthread _thread_kern_thread;
+
+/* Ptr to the thread structure for the running thread: */
+SCLASS struct pthread * volatile _thread_run
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= &_thread_kern_thread;
+#else
+;
+#endif
+
+/*
+ * Ptr to the thread running in single-threaded mode or NULL if
+ * running multi-threaded (default POSIX behaviour).
+ */
+SCLASS struct pthread * volatile _thread_single
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/* Ptr to the first thread in the thread linked list: */
+SCLASS struct pthread * volatile _thread_link_list
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/*
+ * Array of kernel pipe file descriptors that are used to ensure that
+ * no signals are missed in calls to _thread_sys_select.
+ */
+SCLASS int _thread_kern_pipe[2]
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= {
+ -1,
+ -1
+};
+#else
+;
+#endif
+SCLASS int _thread_kern_in_select
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 0;
+#else
+;
+#endif
+
+/* Last time that an incremental priority update was performed: */
+SCLASS struct timeval kern_inc_prio_time
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { 0, 0 };
+#else
+;
+#endif
+
+/* Dead threads: */
+SCLASS struct pthread * volatile _thread_dead
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/* Initial thread: */
+SCLASS struct pthread *_thread_initial
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/* Default thread attributes: */
+SCLASS struct pthread_attr pthread_attr_default
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { SCHED_RR, PTHREAD_DEFAULT_PRIORITY, PTHREAD_CREATE_RUNNING,
+ PTHREAD_CREATE_JOINABLE, NULL, NULL, NULL, PTHREAD_STACK_DEFAULT };
+#else
+;
+#endif
+
+/* Default mutex attributes: */
+SCLASS struct pthread_mutex_attr pthread_mutexattr_default
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { MUTEX_TYPE_FAST, 0 };
+#else
+;
+#endif
+
+/* Default condition variable attributes: */
+SCLASS struct pthread_cond_attr pthread_condattr_default
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { COND_TYPE_FAST, 0 };
+#else
+;
+#endif
+
+/*
+ * Standard I/O file descriptors need special flag treatment since
+ * setting one to non-blocking does all on *BSD. Sigh. This array
+ * is used to store the initial flag settings.
+ */
+SCLASS int _pthread_stdio_flags[3];
+
+/* File table information: */
+SCLASS struct fd_table_entry **_thread_fd_table
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+SCLASS const int dtablecount
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 4096/sizeof(struct fd_table_entry);
+#else
+;
+#endif
+SCLASS int _thread_dtablesize /* Descriptor table size. */
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 1024;
+#else
+;
+#endif
+
+/* Undefine the storage class specifier: */
+#undef SCLASS
+
+/*
+ * Function prototype definitions.
+ */
+__BEGIN_DECLS
+char *__ttyname_basic(int);
+char *__ttyname_r_basic(int, char *, size_t);
+char *ttyname_r(int, char *, size_t);
+int _thread_create(pthread_t *,const pthread_attr_t *,void *(*start_routine)(void *),void *,pthread_t);
+int _thread_fd_lock(int, int, struct timespec *,char *fname,int lineno);
+void _thread_exit(char *, int, char *);
+void _thread_fd_unlock(int, int);
+void *_thread_cleanup(pthread_t);
+void _thread_cleanupspecific(void);
+void _thread_dump_info(void);
+void _thread_init(void);
+void _thread_kern_sched(struct sigcontext *);
+void _thread_kern_sched_state(enum pthread_state,char *fname,int lineno);
+void _thread_kern_set_timeout(struct timespec *);
+void _thread_kern_sig_block(int *);
+void _thread_kern_sig_unblock(int);
+void _thread_sig_handler(int, int, struct sigcontext *);
+void _thread_start(void);
+void _thread_start_sig_handler(void);
+void _thread_seterrno(pthread_t,int);
+void _thread_queue_init(struct pthread_queue *);
+void _thread_queue_enq(struct pthread_queue *, struct pthread *);
+int _thread_queue_remove(struct pthread_queue *, struct pthread *);
+int _thread_fd_table_init(int fd);
+struct pthread *_thread_queue_get(struct pthread_queue *);
+struct pthread *_thread_queue_deq(struct pthread_queue *);
+
+/* #include <signal.h> */
+int _thread_sys_sigaction(int, const struct sigaction *, struct sigaction *);
+int _thread_sys_sigpending(sigset_t *);
+int _thread_sys_sigprocmask(int, const sigset_t *, sigset_t *);
+int _thread_sys_sigsuspend(const sigset_t *);
+int _thread_sys_sigblock(int);
+int _thread_sys_siginterrupt(int, int);
+int _thread_sys_sigpause(int);
+int _thread_sys_sigreturn(struct sigcontext *);
+int _thread_sys_sigsetmask(int);
+int _thread_sys_sigstack(const struct sigstack *, struct sigstack *);
+int _thread_sys_sigvec(int, struct sigvec *, struct sigvec *);
+void _thread_sys_psignal(unsigned int, const char *);
+void (*_thread_sys_signal(int, void (*)(int)))(int);
+
+/* #include <sys/stat.h> */
+#ifdef _SYS_STAT_H_
+int _thread_sys_fchmod(int, mode_t);
+int _thread_sys_fstat(int, struct stat *);
+int _thread_sys_fchflags(int, u_long);
+#endif
+
+/* #include <sys/mount.h> */
+#ifdef _SYS_MOUNT_H_
+int _thread_sys_fstatfs(int, struct statfs *);
+#endif
+int _thread_sys_pipe(int *);
+
+/* #include <sys/socket.h> */
+#ifdef _SYS_SOCKET_H_
+int _thread_sys_accept(int, struct sockaddr *, int *);
+int _thread_sys_bind(int, const struct sockaddr *, int);
+int _thread_sys_connect(int, const struct sockaddr *, int);
+int _thread_sys_getpeername(int, struct sockaddr *, int *);
+int _thread_sys_getsockname(int, struct sockaddr *, int *);
+int _thread_sys_getsockopt(int, int, int, void *, int *);
+int _thread_sys_listen(int, int);
+int _thread_sys_setsockopt(int, int, int, const void *, int);
+int _thread_sys_shutdown(int, int);
+int _thread_sys_socket(int, int, int);
+int _thread_sys_socketpair(int, int, int, int *);
+ssize_t _thread_sys_recv(int, void *, size_t, int);
+ssize_t _thread_sys_recvfrom(int, void *, size_t, int, struct sockaddr *, int *);
+ssize_t _thread_sys_recvmsg(int, struct msghdr *, int);
+ssize_t _thread_sys_send(int, const void *, size_t, int);
+ssize_t _thread_sys_sendmsg(int, const struct msghdr *, int);
+ssize_t _thread_sys_sendto(int, const void *,size_t, int, const struct sockaddr *, int);
+#endif
+
+/* #include <stdio.h> */
+#ifdef _STDIO_H_
+void _thread_flockfile(FILE *fp,char *fname,int lineno);
+void _thread_funlockfile(FILE *fp);
+FILE *_thread_sys_fdopen(int, const char *);
+FILE *_thread_sys_fopen(const char *, const char *);
+FILE *_thread_sys_freopen(const char *, const char *, FILE *);
+FILE *_thread_sys_popen(const char *, const char *);
+FILE *_thread_sys_tmpfile(void);
+char *_thread_sys_ctermid(char *);
+char *_thread_sys_cuserid(char *);
+char *_thread_sys_fgetln(FILE *, size_t *);
+char *_thread_sys_fgets(char *, int, FILE *);
+char *_thread_sys_gets(char *);
+char *_thread_sys_tempnam(const char *, const char *);
+char *_thread_sys_tmpnam(char *);
+int _thread_sys_fclose(FILE *);
+int _thread_sys_feof(FILE *);
+int _thread_sys_ferror(FILE *);
+int _thread_sys_fflush(FILE *);
+int _thread_sys_fgetc(FILE *);
+int _thread_sys_fgetpos(FILE *, fpos_t *);
+int _thread_sys_fileno(FILE *);
+int _thread_sys_fprintf(FILE *, const char *, ...);
+int _thread_sys_fpurge(FILE *);
+int _thread_sys_fputc(int, FILE *);
+int _thread_sys_fputs(const char *, FILE *);
+int _thread_sys_fscanf(FILE *, const char *, ...);
+int _thread_sys_fseek(FILE *, long, int);
+int _thread_sys_fsetpos(FILE *, const fpos_t *);
+int _thread_sys_getc(FILE *);
+int _thread_sys_getchar(void);
+int _thread_sys_getw(FILE *);
+int _thread_sys_pclose(FILE *);
+int _thread_sys_printf(const char *, ...);
+int _thread_sys_putc(int, FILE *);
+int _thread_sys_putchar(int);
+int _thread_sys_puts(const char *);
+int _thread_sys_putw(int, FILE *);
+int _thread_sys_remove(const char *);
+int _thread_sys_rename (const char *, const char *);
+int _thread_sys_scanf(const char *, ...);
+int _thread_sys_setlinebuf(FILE *);
+int _thread_sys_setvbuf(FILE *, char *, int, size_t);
+int _thread_sys_snprintf(char *, size_t, const char *, ...);
+int _thread_sys_sprintf(char *, const char *, ...);
+int _thread_sys_sscanf(const char *, const char *, ...);
+int _thread_sys_ungetc(int, FILE *);
+int _thread_sys_vfprintf(FILE *, const char *, _BSD_VA_LIST_);
+int _thread_sys_vprintf(const char *, _BSD_VA_LIST_);
+int _thread_sys_vscanf(const char *, _BSD_VA_LIST_);
+int _thread_sys_vsnprintf(char *, size_t, const char *, _BSD_VA_LIST_);
+int _thread_sys_vsprintf(char *, const char *, _BSD_VA_LIST_);
+int _thread_sys_vsscanf(const char *, const char *, _BSD_VA_LIST_);
+long _thread_sys_ftell(FILE *);
+size_t _thread_sys_fread(void *, size_t, size_t, FILE *);
+size_t _thread_sys_fwrite(const void *, size_t, size_t, FILE *);
+void _thread_sys_clearerr(FILE *);
+void _thread_sys_perror(const char *);
+void _thread_sys_rewind(FILE *);
+void _thread_sys_setbuf(FILE *, char *);
+void _thread_sys_setbuffer(FILE *, char *, int);
+#endif
+
+/* #include <unistd.h> */
+#ifdef _UNISTD_H_
+char *_thread_sys_ttyname(int);
+int _thread_sys_close(int);
+int _thread_sys_dup(int);
+int _thread_sys_dup2(int, int);
+int _thread_sys_exect(const char *, char * const *, char * const *);
+int _thread_sys_execve(const char *, char * const *, char * const *);
+int _thread_sys_fchdir(int);
+int _thread_sys_fchown(int, uid_t, gid_t);
+int _thread_sys_fsync(int);
+int _thread_sys_ftruncate(int, off_t);
+int _thread_sys_pause(void);
+int _thread_sys_pipe(int *);
+int _thread_sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+off_t _thread_sys_lseek(int, off_t, int);
+pid_t _thread_sys_fork(void);
+pid_t _thread_sys_tcgetpgrp(int);
+ssize_t _thread_sys_read(int, void *, size_t);
+ssize_t _thread_sys_write(int, const void *, size_t);
+void _thread_sys__exit(int);
+#endif
+
+/* #include <fcntl.h> */
+#ifdef _SYS_FCNTL_H_
+int _thread_sys_creat(const char *, mode_t);
+int _thread_sys_fcntl(int, int, ...);
+int _thread_sys_flock(int, int);
+int _thread_sys_open(const char *, int, ...);
+#endif
+
+/* #include <setjmp.h> */
+#ifdef _SETJMP_H_
+int __thread_sys_setjmp(jmp_buf);
+int _thread_sys_setjmp(jmp_buf);
+int _thread_sys_sigsetjmp(sigjmp_buf, int);
+void __thread_sys_longjmp(jmp_buf, int);
+void _thread_sys_longjmp(jmp_buf, int);
+void _thread_sys_longjmperror(void);
+void _thread_sys_siglongjmp(sigjmp_buf, int);
+#endif
+
+/* #include <sys/ioctl.h> */
+#ifdef _SYS_IOCTL_H_
+int _thread_sys_ioctl(int, unsigned long, ...);
+#endif
+
+/* #include <dirent.h> */
+#ifdef _DIRENT_H_
+DIR *___thread_sys_opendir2(const char *, int);
+DIR *_thread_sys_opendir(const char *);
+int _thread_sys_alphasort(const void *, const void *);
+int _thread_sys_scandir(const char *, struct dirent ***,
+ int (*)(struct dirent *), int (*)(const void *, const void *));
+int _thread_sys_closedir(DIR *);
+int _thread_sys_getdirentries(int, char *, int, long *);
+long _thread_sys_telldir(const DIR *);
+struct dirent *_thread_sys_readdir(DIR *);
+void _thread_sys_rewinddir(DIR *);
+void _thread_sys_seekdir(DIR *, long);
+#endif
+
+/* #include <sys/uio.h> */
+#ifdef _SYS_UIO_H_
+ssize_t _thread_sys_readv(int, const struct iovec *, int);
+ssize_t _thread_sys_writev(int, const struct iovec *, int);
+#endif
+
+/* #include <sys/wait.h> */
+#ifdef WNOHANG
+pid_t _thread_sys_wait(int *);
+pid_t _thread_sys_waitpid(pid_t, int *, int);
+pid_t _thread_sys_wait3(int *, int, struct rusage *);
+pid_t _thread_sys_wait4(pid_t, int *, int, struct rusage *);
+#endif
+__END_DECLS
+
+#endif /* !_PTHREAD_PRIVATE_H */
diff --git a/lib/libpthread/thread/thr_read.c b/lib/libpthread/thread/thr_read.c
new file mode 100644
index 0000000..242014e
--- /dev/null
+++ b/lib/libpthread/thread/thr_read.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+read(int fd, void *buf, size_t nbytes)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read: */
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking read syscall: */
+ while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDR_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_readv.c b/lib/libpthread/thread/thr_readv.c
new file mode 100644
index 0000000..3ea065e
--- /dev/null
+++ b/lib/libpthread/thread/thr_readv.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+readv(int fd, const struct iovec * iov, int iovcnt)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read: */
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking readv syscall: */
+ while ((ret = _thread_sys_readv(fd, iov, iovcnt)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDR_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_resume_np.c b/lib/libpthread/thread/thr_resume_np.c
new file mode 100644
index 0000000..934df58
--- /dev/null
+++ b/lib/libpthread/thread/thr_resume_np.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_resume_np(pthread_t thread)
+{
+ int ret = -1;
+ pthread_t pthread;
+ /*
+ * Search for the thread in the linked list.
+ */
+ for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
+ /* Is this the thread? */
+ if (pthread == thread) {
+ /* Found the thread. Is it suspended? */
+ if (pthread->state == PS_SUSPENDED) {
+ /* Allow the thread to run. */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ ret = 0;
+ } else if (pthread->state == PS_RUNNING) {
+ /* Thread is already running. */
+ ret = 0;
+ } else {
+ /* Thread is in some other state. */
+ errno = EINVAL;
+ }
+ }
+ }
+ /* Check if thread was not found. */
+ if (ret == -1) {
+ /* No such thread */
+ errno = ESRCH;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_select.c b/lib/libpthread/thread/thr_select.c
new file mode 100644
index 0000000..7db3ed2
--- /dev/null
+++ b/lib/libpthread/thread/thr_select.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+select(int numfds, fd_set * readfds, fd_set * writefds,
+ fd_set * exceptfds, struct timeval * timeout)
+{
+ fd_set read_locks, write_locks, rdwr_locks;
+ struct timespec ts;
+ struct timeval zero_timeout = {0, 0};
+ int i, ret = 0, got_all_locks = 1;
+ struct pthread_select_data data;
+
+ if (numfds > _thread_dtablesize) {
+ numfds = _thread_dtablesize;
+ }
+ /* Check if a timeout was specified: */
+ if (timeout) {
+ /* Convert the timeval to a timespec: */
+ TIMEVAL_TO_TIMESPEC(timeout, &ts);
+
+ /* Set the wake up time: */
+ _thread_kern_set_timeout(&ts);
+ } else {
+ /* Wait for ever: */
+ _thread_kern_set_timeout(NULL);
+ }
+
+ FD_ZERO(&read_locks);
+ FD_ZERO(&write_locks);
+ FD_ZERO(&rdwr_locks);
+
+ /* lock readfds */
+ if (readfds || writefds || exceptfds) {
+ for (i = 0; i < numfds; i++) {
+ if ((readfds && (FD_ISSET(i, readfds))) || (exceptfds && FD_ISSET(i, exceptfds))) {
+ if (writefds && FD_ISSET(i, writefds)) {
+ if ((ret = _thread_fd_lock(i, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &rdwr_locks);
+ } else {
+ if ((ret = _thread_fd_lock(i, FD_READ, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &read_locks);
+ }
+ } else {
+ if (writefds && FD_ISSET(i, writefds)) {
+ if ((ret = _thread_fd_lock(i, FD_WRITE, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &write_locks);
+ }
+ }
+ }
+ }
+ if (got_all_locks) {
+ data.nfds = numfds;
+ FD_ZERO(&data.readfds);
+ FD_ZERO(&data.writefds);
+ FD_ZERO(&data.exceptfds);
+ if (readfds != NULL) {
+ memcpy(&data.readfds, readfds, sizeof(data.readfds));
+ }
+ if (writefds != NULL) {
+ memcpy(&data.writefds, writefds, sizeof(data.writefds));
+ }
+ if (exceptfds != NULL) {
+ memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds));
+ }
+ if ((ret = _thread_sys_select(data.nfds, &data.readfds, &data.writefds, &data.exceptfds, &zero_timeout)) == 0) {
+ data.nfds = numfds;
+ FD_ZERO(&data.readfds);
+ FD_ZERO(&data.writefds);
+ FD_ZERO(&data.exceptfds);
+ if (readfds != NULL) {
+ memcpy(&data.readfds, readfds, sizeof(data.readfds));
+ }
+ if (writefds != NULL) {
+ memcpy(&data.writefds, writefds, sizeof(data.writefds));
+ }
+ if (exceptfds != NULL) {
+ memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds));
+ }
+ _thread_run->data.select_data = &data;
+ _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__);
+ ret = data.nfds;
+ }
+ }
+ /* clean up the locks */
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &read_locks))
+ _thread_fd_unlock(i, FD_READ);
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &rdwr_locks))
+ _thread_fd_unlock(i, FD_RDWR);
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &write_locks))
+ _thread_fd_unlock(i, FD_WRITE);
+
+ if (ret > 0) {
+ if (readfds != NULL) {
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, readfds) &&
+ !FD_ISSET(i, &data.readfds)) {
+ FD_CLR(i, readfds);
+ }
+ }
+ }
+ if (writefds != NULL) {
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, writefds) &&
+ !FD_ISSET(i, &data.writefds)) {
+ FD_CLR(i, writefds);
+ }
+ }
+ }
+ if (exceptfds != NULL) {
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, exceptfds) &&
+ !FD_ISSET(i, &data.exceptfds)) {
+ FD_CLR(i, exceptfds);
+ }
+ }
+ }
+ }
+
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_self.c b/lib/libpthread/thread/thr_self.c
new file mode 100644
index 0000000..a0a2d2a
--- /dev/null
+++ b/lib/libpthread/thread/thr_self.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pthread_t
+pthread_self(void)
+{
+ /* Return the running thread pointer: */
+ return (_thread_run);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_seterrno.c b/lib/libpthread/thread/thr_seterrno.c
new file mode 100644
index 0000000..c4fe08b6
--- /dev/null
+++ b/lib/libpthread/thread/thr_seterrno.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/*
+ * This function needs to reference the global error variable which is
+ * normally hidden from the user.
+ */
+#ifdef errno
+#undef errno;
+#endif
+extern int errno;
+
+void
+_thread_seterrno(pthread_t thread, int error)
+{
+ /* Check for the initial thread: */
+ if (thread == _thread_initial) {
+ /* The initial thread always uses the global error variable: */
+ errno = error;
+ } else {
+ /*
+ * Threads other than the initial thread always use the error
+ * field in the thread structureL
+ */
+ thread->error = error;
+ }
+}
+#endif
diff --git a/lib/libpthread/thread/thr_setprio.c b/lib/libpthread/thread/thr_setprio.c
new file mode 100644
index 0000000..4b49ed0
--- /dev/null
+++ b/lib/libpthread/thread/thr_setprio.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_setprio(pthread_t pthread, int prio)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread_p;
+
+ /* Check if the priority is invalid: */
+ if (prio < PTHREAD_MIN_PRIORITY || prio > PTHREAD_MAX_PRIORITY) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the first thread in the list: */
+ pthread_p = _thread_link_list;
+
+ /* Enter a loop to search for the thread: */
+ while (pthread_p != NULL && pthread_p != pthread) {
+ /* Point to the next thread: */
+ pthread_p = pthread_p->nxt;
+ }
+
+ /* Check if the thread pointer is NULL: */
+ if (pthread == NULL || pthread_p == NULL) {
+ /* Return a 'search' error: */
+ errno = ESRCH;
+ rval = -1;
+ } else {
+ /* Set the thread priority: */
+ pthread->pthread_priority = prio;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the error status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_sig.c b/lib/libpthread/thread/thr_sig.c
new file mode 100644
index 0000000..e73d5a2
--- /dev/null
+++ b/lib/libpthread/thread/thr_sig.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+_thread_sig_handler(int sig, int code, struct sigcontext * scp)
+{
+ char c;
+ int i;
+ pthread_t pthread;
+
+ /*
+ * Check if the pthread kernel has unblocked signals (or is about to)
+ * and was on its way into a _thread_sys_select when the current
+ * signal interrupted it:
+ */
+ if (_thread_kern_in_select) {
+ /* Cast the signal number to a character variable: */
+ c = sig;
+
+ /*
+ * Write the signal number to the kernel pipe so that it will
+ * be ready to read when this signal handler returns. This
+ * means that the _thread_sys_select call will complete
+ * immediately.
+ */
+ if (_thread_sys_write(_thread_kern_pipe[1], &c, 1) != 1) {
+ }
+ }
+ /* Check if the signal requires a dump of thread information: */
+ if (sig == SIGINFO) {
+ /* Dump thread information to file: */
+ _thread_dump_info();
+ } else {
+ /* Handle depending on signal type: */
+ switch (sig) {
+ /* Interval timer used for timeslicing: */
+ case SIGVTALRM:
+ /*
+ * Don't add the signal to any thread. Just want to
+ * call the scheduler:
+ */
+ break;
+
+ /* Child termination: */
+ case SIGCHLD:
+ /*
+ * Enter a loop to process each thread in the linked
+ * list:
+ */
+ for (pthread = _thread_link_list; pthread != NULL;
+ pthread = pthread->nxt) {
+ /*
+ * Add the signal to the set of pending
+ * signals:
+ */
+ pthread->sigpend[sig] += 1;
+ if (pthread->state == PS_WAIT_WAIT) {
+ /* Reset the error: */
+ /* There should be another flag so that this is not required! ### */
+ _thread_seterrno(pthread, 0);
+
+ /* Change the state of the thread to run: */
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ }
+ }
+
+ /*
+ * Go through the file list and set all files
+ * to non-blocking again in case the child
+ * set some of them to block. Sigh.
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Check if this file is used: */
+ if (_thread_fd_table[i] != NULL) {
+ /* Set the file descriptor to non-blocking: */
+ _thread_sys_fcntl(i, F_SETFL, _thread_fd_table[i]->flags | O_NONBLOCK);
+ }
+ }
+ break;
+
+ /* Signals specific to the running thread: */
+ case SIGBUS:
+ case SIGEMT:
+ case SIGFPE:
+ case SIGILL:
+ case SIGPIPE:
+ case SIGSEGV:
+ case SIGSYS:
+ /* Add the signal to the set of pending signals: */
+ _thread_run->sigpend[sig] += 1;
+ break;
+
+ /* Signals to send to all threads: */
+ default:
+ /*
+ * Enter a loop to process each thread in the linked
+ * list:
+ */
+ for (pthread = _thread_link_list; pthread != NULL;
+ pthread = pthread->nxt) {
+ /*
+ * Add the signal to the set of pending
+ * signals:
+ */
+ pthread->sigpend[sig] += 1;
+ }
+ break;
+ }
+
+ /* Check if the kernel is not locked: */
+ if (_thread_run != &_thread_kern_thread) {
+ /*
+ * Schedule the next thread. This function is not
+ * expected to return because it will do a longjmp
+ * instead.
+ */
+ _thread_kern_sched(scp);
+
+ /*
+ * This point should not be reached, so abort the
+ * process:
+ */
+ PANIC("Returned to signal function from scheduler");
+ }
+ }
+
+ /* Returns nothing. */
+ return;
+}
+#endif
diff --git a/lib/libpthread/thread/thr_sigaction.c b/lib/libpthread/thread/thr_sigaction.c
new file mode 100644
index 0000000..dd08405
--- /dev/null
+++ b/lib/libpthread/thread/thr_sigaction.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
+{
+ int ret = 0;
+ int status;
+
+ /* Check if the signal number is out of range: */
+ if (sig < 1 || sig > NSIG) {
+ /* Return an invalid argument: */
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /*
+ * Check if the existing signal action structure contents are
+ * to be returned:
+ */
+ if (oact != NULL) {
+ /* Return the existing signal action contents: */
+ oact->sa_handler = _thread_run->act[sig - 1].sa_handler;
+ oact->sa_mask = _thread_run->act[sig - 1].sa_mask;
+ oact->sa_flags = _thread_run->act[sig - 1].sa_flags;
+ }
+ /* Check if a signal action was supplied: */
+ if (act != NULL) {
+ /* Block signals while the signal handler is changed: */
+ _thread_kern_sig_block(&status);
+
+ /* Set the new signal handler: */
+ _thread_run->act[sig - 1].sa_handler = act->sa_handler;
+ _thread_run->act[sig - 1].sa_mask = act->sa_mask;
+ _thread_run->act[sig - 1].sa_flags = act->sa_flags;
+
+ /*
+ * Unblock signals to allow the new signal handler to
+ * take effect:
+ */
+ _thread_kern_sig_unblock(status);
+ }
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_sigmask.c b/lib/libpthread/thread/thr_sigmask.c
new file mode 100644
index 0000000..94f64cb
--- /dev/null
+++ b/lib/libpthread/thread/thr_sigmask.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
+{
+ int ret = 0;
+ int status;
+
+ /* Check if the existing signal process mask is to be returned: */
+ if (oset != NULL) {
+ /* Return the current mask: */
+ *oset = _thread_run->sigmask;
+ }
+ /* Check if a new signal set was provided by the caller: */
+ if (set != NULL) {
+ /* Block signals while the signal mask is changed: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to what to do: */
+ switch (how) {
+ /* Block signals: */
+ case SIG_BLOCK:
+ /* Add signals to the existing mask: */
+ _thread_run->sigmask |= *set;
+ break;
+
+ /* Unblock signals: */
+ case SIG_UNBLOCK:
+ /* Clear signals from the existing mask: */
+ _thread_run->sigmask &= ~(*set);
+ break;
+
+ /* Set the signal process mask: */
+ case SIG_SETMASK:
+ /* Set the new mask: */
+ _thread_run->sigmask = *set;
+ break;
+
+ /* Trap invalid actions: */
+ default:
+ /* Return an invalid argument: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /*
+ * Schedule the next thread in case there are signals that
+ * now need to be acted on:
+ */
+ _thread_kern_sched(NULL);
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_sigprocmask.c b/lib/libpthread/thread/thr_sigprocmask.c
new file mode 100644
index 0000000..b4a8d84
--- /dev/null
+++ b/lib/libpthread/thread/thr_sigprocmask.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigprocmask(int how, const sigset_t * set, sigset_t * oset)
+{
+ int ret = 0;
+ int status;
+
+ /* Check if the existing signal process mask is to be returned: */
+ if (oset != NULL) {
+ /* Return the current mask: */
+ *oset = _thread_run->sigmask;
+ }
+ /* Check if a new signal set was provided by the caller: */
+ if (set != NULL) {
+ /* Block signals while the signal mask is changed: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to what to do: */
+ switch (how) {
+ /* Block signals: */
+ case SIG_BLOCK:
+ /* Add signals to the existing mask: */
+ _thread_run->sigmask |= *set;
+ break;
+
+ /* Unblock signals: */
+ case SIG_UNBLOCK:
+ /* Clear signals from the existing mask: */
+ _thread_run->sigmask &= ~(*set);
+ break;
+
+ /* Set the signal process mask: */
+ case SIG_SETMASK:
+ /* Set the new mask: */
+ _thread_run->sigmask = *set;
+ break;
+
+ /* Trap invalid actions: */
+ default:
+ /* Return an invalid argument: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /*
+ * Schedule the next thread in case there are signals that
+ * now need to be acted on:
+ */
+ _thread_kern_sched(NULL);
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_sigsuspend.c b/lib/libpthread/thread/thr_sigsuspend.c
new file mode 100644
index 0000000..14cf74b
--- /dev/null
+++ b/lib/libpthread/thread/thr_sigsuspend.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigsuspend(const sigset_t * set)
+{
+ int ret = -1;
+ sigset_t oset;
+
+ /* Check if a new signal set was provided by the caller: */
+ if (set != NULL) {
+ /* Save the current sigmal mask: */
+ oset = _thread_run->sigmask;
+
+ /* Combine the caller's mask with the current one: */
+ _thread_run->sigmask |= *set;
+
+ /* Wait for a signal: */
+ _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__);
+
+ /* Restore the signal mask: */
+ _thread_run->sigmask = oset;
+ } else {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_sigwait.c b/lib/libpthread/thread/thr_sigwait.c
new file mode 100644
index 0000000..4f95190
--- /dev/null
+++ b/lib/libpthread/thread/thr_sigwait.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigwait(const sigset_t * set, int *sig)
+{
+ int ret;
+ int status;
+ sigset_t oset;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Save the current sigmal mask: */
+ oset = _thread_run->sigmask;
+
+ /* Combine the caller's mask with the current one: */
+ _thread_run->sigmask |= *set;
+
+ /* Wait for a signal: */
+ _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__);
+
+ /* Block signals again: */
+ _thread_kern_sig_block(NULL);
+
+ /* Return the signal number to the caller: */
+ *sig = _thread_run->signo;
+
+ /* Restore the signal mask: */
+ _thread_run->sigmask = oset;
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_single_np.c b/lib/libpthread/thread/thr_single_np.c
new file mode 100644
index 0000000..e36c856
--- /dev/null
+++ b/lib/libpthread/thread/thr_single_np.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_single_np()
+{
+ /* Enter single-threaded (non-POSIX) scheduling mode: */
+ _thread_single = _thread_run;
+ return(0);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_spec.c b/lib/libpthread/thread/thr_spec.c
new file mode 100644
index 0000000..8d06c52
--- /dev/null
+++ b/lib/libpthread/thread/thr_spec.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* Static variables: */
+static struct pthread_key key_table[PTHREAD_KEYS_MAX];
+
+int
+pthread_key_create(pthread_key_t * key, void (*destructor) (void *))
+{
+ for ((*key) = 0; (*key) < PTHREAD_KEYS_MAX; (*key)++) {
+ if (key_table[(*key)].count == 0) {
+ key_table[(*key)].count++;
+ key_table[(*key)].destructor = destructor;
+ return (0);
+ }
+ }
+ return (EAGAIN);
+}
+
+int
+pthread_key_delete(pthread_key_t key)
+{
+ int ret;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ if (key < PTHREAD_KEYS_MAX) {
+ switch (key_table[key].count) {
+ case 1:
+ key_table[key].destructor = NULL;
+ key_table[key].count = 0;
+ case 0:
+ ret = 0;
+ break;
+ default:
+ ret = EBUSY;
+ }
+ } else {
+ ret = EINVAL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+
+void
+_thread_cleanupspecific(void)
+{
+ void *data;
+ int key;
+ int itr;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ for (itr = 0; itr < PTHREAD_DESTRUCTOR_ITERATIONS; itr++) {
+ for (key = 0; key < PTHREAD_KEYS_MAX; key++) {
+ if (_thread_run->specific_data_count) {
+ if (_thread_run->specific_data[key]) {
+ data = (void *) _thread_run->specific_data[key];
+ _thread_run->specific_data[key] = NULL;
+ _thread_run->specific_data_count--;
+ if (key_table[key].destructor) {
+ key_table[key].destructor(data);
+ }
+ key_table[key].count--;
+ }
+ } else {
+ free(_thread_run->specific_data);
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return;
+ }
+ }
+ }
+ free(_thread_run->specific_data);
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+}
+
+static inline const void **
+pthread_key_allocate_data(void)
+{
+ const void **new_data;
+ if ((new_data = (const void **) malloc(sizeof(void *) * PTHREAD_KEYS_MAX)) != NULL) {
+ memset((void *) new_data, 0, sizeof(void *) * PTHREAD_KEYS_MAX);
+ }
+ return (new_data);
+}
+
+int
+pthread_setspecific(pthread_key_t key, const void *value)
+{
+ pthread_t pthread;
+ int ret = 0;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the running thread: */
+ pthread = _thread_run;
+
+ /*
+ * Enter a loop for signal handler threads to find the parent thread
+ * which has the specific data associated with it:
+ */
+ while (pthread->parent_thread != NULL) {
+ /* Point to the parent thread: */
+ pthread = pthread->parent_thread;
+ }
+
+ if ((pthread->specific_data) || (pthread->specific_data = pthread_key_allocate_data())) {
+ if ((key < PTHREAD_KEYS_MAX) && (key_table)) {
+ if (key_table[key].count) {
+ if (pthread->specific_data[key] == NULL) {
+ if (value != NULL) {
+ pthread->specific_data_count++;
+ key_table[key].count++;
+ }
+ } else {
+ if (value == NULL) {
+ pthread->specific_data_count--;
+ key_table[key].count--;
+ }
+ }
+ pthread->specific_data[key] = value;
+ ret = 0;
+ } else {
+ ret = EINVAL;
+ }
+ } else {
+ ret = EINVAL;
+ }
+ } else {
+ ret = ENOMEM;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+
+void *
+pthread_getspecific(pthread_key_t key)
+{
+ pthread_t pthread;
+ int status;
+ void *data;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the running thread: */
+ pthread = _thread_run;
+
+ /*
+ * Enter a loop for signal handler threads to find the parent thread
+ * which has the specific data associated with it:
+ */
+ while (pthread->parent_thread != NULL) {
+ /* Point to the parent thread: */
+ pthread = pthread->parent_thread;
+ }
+
+ /* Check for errors: */
+ if (pthread == NULL) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ data = NULL;
+ }
+ /* Check if there is specific data: */
+ else if (pthread->specific_data != NULL && (key < PTHREAD_KEYS_MAX) && (key_table)) {
+ /* Check if this key has been used before: */
+ if (key_table[key].count) {
+ /* Return the value: */
+ data = (void *) pthread->specific_data[key];
+ } else {
+ /*
+ * This key has not been used before, so return NULL
+ * instead:
+ */
+ data = NULL;
+ }
+ } else {
+ /* No specific data has been created, so just return NULL: */
+ data = NULL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (data);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_suspend_np.c b/lib/libpthread/thread/thr_suspend_np.c
new file mode 100644
index 0000000..d065b73
--- /dev/null
+++ b/lib/libpthread/thread/thr_suspend_np.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_suspend_np(pthread_t thread)
+{
+ int ret = -1;
+ pthread_t pthread;
+ /*
+ * Search for the thread in the linked list.
+ */
+ for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
+ /* Is this the thread? */
+ if (pthread == thread) {
+ /* Found the thread. Is it running? */
+ if (pthread->state != PS_RUNNING &&
+ pthread->state != PS_SUSPENDED) {
+ /* The thread operation has been interrupted */
+ _thread_seterrno(pthread,EINTR);
+ }
+ /* Suspend the thread. */
+ PTHREAD_NEW_STATE(pthread,PS_SUSPENDED);
+ ret = 0;
+ }
+ }
+ /* Check if thread was not found. */
+ if (ret == -1) {
+ /* No such thread */
+ errno = ESRCH;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_wait4.c b/lib/libpthread/thread/thr_wait4.c
new file mode 100644
index 0000000..0a721af4f
--- /dev/null
+++ b/lib/libpthread/thread/thr_wait4.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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 <errno.h>
+#include <sys/wait.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pid_t
+wait4(pid_t pid, int *istat, int options, struct rusage * rusage)
+{
+ int status;
+ pid_t ret;
+ _thread_kern_sig_block(&status);
+
+ /* Perform a non-blocking wait4 syscall: */
+ while ((ret = _thread_sys_wait4(pid, istat, options | WNOHANG, rusage)) == 0 && (options & WNOHANG) == 0) {
+ /* Schedule the next thread while this one waits: */
+ _thread_kern_sched_state(PS_WAIT_WAIT, __FILE__, __LINE__);
+
+ /* Check if this call was interrupted by a signal: */
+ if (errno == EINTR) {
+ ret = -1;
+ break;
+ }
+ _thread_kern_sig_block(NULL);
+ }
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_write.c b/lib/libpthread/thread/thr_write.c
new file mode 100644
index 0000000..eab105d
--- /dev/null
+++ b/lib/libpthread/thread/thr_write.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+write(int fd, const void *buf, size_t nbytes)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read and write: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking write syscall: */
+ while ((ret = _thread_sys_write(fd, buf, nbytes)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDW_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_writev.c b/lib/libpthread/thread/thr_writev.c
new file mode 100644
index 0000000..5ad1ce9
--- /dev/null
+++ b/lib/libpthread/thread/thr_writev.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ * $Id$
+ *
+ */
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+writev(int fd, const struct iovec * iov, int iovcnt)
+{
+ int ret;
+ int status;
+
+ /* Lock the file descriptor for read and write: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL,
+ __FILE__, __LINE__)) == 0) {
+ /* Perform a non-blocking writev syscall: */
+ while ((ret = _thread_sys_writev(fd, iov, iovcnt)) < 0) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+
+ /* Reset the interrupted operation flag: */
+ _thread_run->interrupted = 0;
+
+ _thread_kern_sched_state(PS_FDW_WAIT,
+ __FILE__, __LINE__);
+
+ /*
+ * Check if the operation was
+ * interrupted by a signal
+ */
+ if (_thread_run->interrupted) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libpthread/thread/thr_yield.c b/lib/libpthread/thread/thr_yield.c
new file mode 100644
index 0000000..a88a948
--- /dev/null
+++ b/lib/libpthread/thread/thr_yield.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 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 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+pthread_yield(void)
+{
+ /* Reset the accumulated time slice value for the current thread: */
+ _thread_run->slice_usec = -1;
+
+ /* Schedule the next thread: */
+ _thread_kern_sched(NULL);
+
+ /* Nothing to return. */
+ return;
+}
+#endif
diff --git a/lib/libresolv/Makefile b/lib/libresolv/Makefile
index 699c54c..69dcbe8 100644
--- a/lib/libresolv/Makefile
+++ b/lib/libresolv/Makefile
@@ -1,10 +1,32 @@
# @(#)Makefile 8.1 (Berkeley) 6/4/93
-LIB=resolv
-CFLAGS+=-DDEBUG -DLIBC_SCCS
+LIB= resolv
+INTERNALLIB= yes # Do not build or install ${LIB}*.a
+SHLIB_MAJOR= 2
+SHLIB_MINOR= 0
-.PATH: ${.CURDIR}/../libc/net
+SRCS= fakelib.c
-SRCS=gethostnamadr.c res_mkquery.c res_query.c res_send.c
+#
+# Before complaining about this, please *double-check* that you have
+# updated the ldconfig path in /etc/rc to include /usr/lib/compat that
+# was added in src/etc/rc rev 1.98.
+# This is so that programs that use autoconf will not "detect" -lresolv
+# and continue to propagate the bogosity. The ldconfig path fix will
+# enable you to run programs that were linked with -lresolv.
+#
+# libresolv on FreeBSD-2.x **never did anything**!!
+#
+beforeinstall:
+ rm -f ${DESTDIR}${LIBDIR}/lib${LIB}.a \
+ ${DESTDIR}${LIBDIR}/lib${LIB}_p.a \
+ ${DESTDIR}${ORIG_SHLIBDIR}/lib${LIB}.so.${SHLIB_MAJOR}.${SHLIB_MINOR}
.include <bsd.lib.mk>
+
+# This must follow the .include in case SHLIBDIR is defined there.
+ORIG_SHLIBDIR:= ${SHLIBDIR}
+
+# The ldconfig line in/etc/rc doesn't depend on ${LIBDIR} or ${SHLIBDIR},
+# so neither does this.
+SHLIBDIR= /usr/lib/compat
diff --git a/lib/libresolv/fakelib.c b/lib/libresolv/fakelib.c
new file mode 100644
index 0000000..0f7b46f
--- /dev/null
+++ b/lib/libresolv/fakelib.c
@@ -0,0 +1 @@
+static int ___fake_library___;
diff --git a/lib/librpc/rpc/Makefile b/lib/librpc/rpc/Makefile
deleted file mode 100644
index e949583..0000000
--- a/lib/librpc/rpc/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-# @(#)Makefile 5.12 (Berkeley) 7/15/92
-
-LIB= rpc
-CFLAGS+=-I${.CURDIR}/..
-SRCS= auth_none.c auth_unix.c authunix_prot.c bindresvport.c \
- clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \
- clnt_udp.c rpc_dtablesize.c get_myaddress.c getrpcent.c getrpcport.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 \
- svc.c svc_auth.c svc_auth_unix.c svc_raw.c svc_run.c svc_simple.c \
- svc_tcp.c svc_udp.c xdr.c xdr_array.c xdr_mem.c \
- xdr_rec.c xdr_reference.c xdr_stdio.c
-
-UNSUPPORTED= xdr_float.c
-
-HDRS= auth.h auth_unix.h clnt.h pmap_clnt.h \
- pmap_prot.h pmap_rmt.h rpc.h rpc_msg.h svc.h svc_auth.h types.h xdr.h
-
-all: librpc.a
-
-beforeinstall: ${HDRS}
- rm -rf ${DESTDIR}/usr/include/rpc
- mkdir ${DESTDIR}/usr/include/rpc
- chown bin.bin ${DESTDIR}/usr/include/rpc
- chmod 755 ${DESTDIR}/usr/include/rpc
- cd ${.CURDIR}; install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${HDRS} \
- ${DESTDIR}/usr/include/rpc
-
-.include <bsd.lib.mk>
diff --git a/lib/librpcsvc/Makefile b/lib/librpcsvc/Makefile
new file mode 100644
index 0000000..44c2384
--- /dev/null
+++ b/lib/librpcsvc/Makefile
@@ -0,0 +1,36 @@
+# from: @(#)Makefile 5.10 (Berkeley) 6/24/90
+# $Id: Makefile,v 1.6 1996/08/30 02:02:09 peter Exp $
+
+.PATH: ${DESTDIR}/usr/include/rpcsvc
+
+LIB= rpcsvc
+
+RPCSRCS= klm_prot.x mount.x nfs_prot.x nlm_prot.x rex.x rnusers.x \
+ rquota.x rstat.x rwall.x sm_inter.x spray.x yppasswd.x ypxfrd.x \
+ ypupdate_prot.x
+
+OTHERSRCS= rnusers.c rstat.c rwall.c yp_passwd.c yp_update.c
+SECRPCSRCS= publickey.c secretkey.c xcrypt.c
+
+RPCCOM = rpcgen -C
+
+INCDIRS= -I${DESTDIR}/usr/include/rpcsvc -I${DESTDIR}/usr/include
+
+CFLAGS+= -DYP ${INCDIRS}
+
+GENSRCS= ${RPCSRCS:R:S/$/_xdr.c/g}
+SRCS+= ${GENSRCS} ${OTHERSRCS} ${SECRPCSRCS}
+
+CLEANFILES+= ${GENSRCS} ${RPCSRCS}
+
+NOMAN= noman
+
+.include <bsd.lib.mk>
+
+.SUFFIXES: .x _xdr.c
+
+.x_xdr.c:
+ ${RPCCOM} -c ${.IMPSRC} -o ${.TARGET}
+
+OBJS= ${RPCSRCS:R:S/$/_xdr.o/g} ${SECRPCSRCS:R:S/$/.o/g} \
+ ${OTHERSRCS:R:S/$/.o/g}
diff --git a/lib/librpcsvc/publickey.c b/lib/librpcsvc/publickey.c
new file mode 100644
index 0000000..e1c34d9
--- /dev/null
+++ b/lib/librpcsvc/publickey.c
@@ -0,0 +1,172 @@
+/*
+ * 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(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)publickey.c 1.10 91/03/11 Copyr 1986 Sun Micro";
+#endif
+
+/*
+ * publickey.c
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+/*
+ * Public key lookup routines
+ */
+#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>
+
+#define PKFILE "/etc/publickey"
+
+/*
+ * Hack to let ypserv/rpc.nisd use AUTH_DES.
+ */
+int (*__getpublickey_LOCAL)() = 0;
+
+/*
+ * Get somebody's public key
+ */
+int
+__getpublickey_real(netname, publickey)
+ 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)
+ char *key;
+ char *ret;
+{
+ char buf[1024]; /* big enough */
+ char *res;
+ FILE *fd;
+ char *mkey;
+ char *mval;
+
+ fd = fopen(PKFILE, "r");
+ if (fd == (FILE *) 0)
+ return (0);
+ for (;;) {
+ res = fgets(buf, 1024, fd);
+ if (res == 0) {
+ 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 = strtok(buf, "\t ");
+ if (mkey == NULL) {
+ fprintf(stderr,
+ "Bad record in %s -- %s", PKFILE, buf);
+ continue;
+ }
+ mval = strtok((char *)NULL, " \t#\n");
+ 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)
+ char *netname;
+ char *publickey;
+{
+ if (__getpublickey_LOCAL != NULL)
+ return(__getpublickey_LOCAL(netname, publickey));
+ else
+ return(__getpublickey_real(netname, publickey));
+}
diff --git a/lib/librpcsvc/rnusers.c b/lib/librpcsvc/rnusers.c
new file mode 100644
index 0000000..3a4629f
--- /dev/null
+++ b/lib/librpcsvc/rnusers.c
@@ -0,0 +1,68 @@
+/*
+ * 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(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rnusers.c 1.2 91/03/11 TIRPC 1.0; from 1.7 89/03/24 SMI";
+#endif
+
+/*
+ * rnusers.c
+ *
+ * "High" level programmatic interface to rnusers RPC service.
+ *
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <rpcsvc/rnusers.h>
+
+int
+rusers(host, up)
+ char *host;
+ struct utmpidlearr *up;
+{
+ return (callrpc(host, RUSERSPROG, RUSERSVERS_IDLE, RUSERSPROC_NAMES,
+ xdr_void, (char *) NULL,
+ xdr_utmpidlearr, (char *) up));
+}
+
+int
+rnusers(host)
+ char *host;
+{
+ int nusers;
+
+ if (callrpc(host, RUSERSPROG, RUSERSVERS_ORIG, RUSERSPROC_NUM,
+ xdr_void, (char *) NULL,
+ xdr_u_long, (char *) &nusers) != 0)
+ return (-1);
+ else
+ return (nusers);
+}
+
diff --git a/lib/librpcsvc/rstat.c b/lib/librpcsvc/rstat.c
new file mode 100644
index 0000000..6851c75
--- /dev/null
+++ b/lib/librpcsvc/rstat.c
@@ -0,0 +1,67 @@
+/*
+ * 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(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rstat.c 1.2 91/03/11 TIRPC 1.0; from 1.6 89/03/24 SMI";
+#endif
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+/*
+ * "High" level programmatic interface to rstat RPC service.
+ */
+#include <rpc/rpc.h>
+#include <rpcsvc/rstat.h>
+
+int
+rstat(host, statp)
+ char *host;
+ struct statstime *statp;
+{
+ return (callrpc(host, RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS,
+ xdr_void, (char *) NULL,
+ xdr_statstime, (char *) statp));
+}
+
+int
+havedisk(host)
+ char *host;
+{
+ long have;
+
+ if (callrpc(host, RSTATPROG, RSTATVERS_SWTCH, RSTATPROC_HAVEDISK,
+ xdr_void, (char *) NULL,
+ xdr_long, (char *) &have) != 0)
+ return (-1);
+ else
+ return (have);
+}
+
diff --git a/lib/librpcsvc/rwall.c b/lib/librpcsvc/rwall.c
new file mode 100644
index 0000000..97de86e
--- /dev/null
+++ b/lib/librpcsvc/rwall.c
@@ -0,0 +1,52 @@
+/*
+ * 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(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rwall.c 1.2 91/03/11 TIRPC 1.0; from 1.3 89/03/24 SMI";
+#endif
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+/*
+ * "High" level programmatic interface to rwall RPC service.
+ */
+#include <rpc/rpc.h>
+#include <rpcsvc/rwall.h>
+
+int
+rwall(host, msg)
+ char *host;
+ char *msg;
+{
+ return (callrpc(host, WALLPROG, WALLVERS, WALLPROC_WALL,
+ xdr_wrapstring, (char *) &msg,
+ xdr_void, (char *) NULL));
+}
diff --git a/lib/librpcsvc/secretkey.c b/lib/librpcsvc/secretkey.c
new file mode 100644
index 0000000..374372b
--- /dev/null
+++ b/lib/librpcsvc/secretkey.c
@@ -0,0 +1,85 @@
+/*
+ * 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(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)secretkey.c 1.8 91/03/11 Copyr 1986 Sun Micro";
+#endif
+
+/*
+ * secretkey.c
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+/*
+ * Secret key lookup routines
+ */
+#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>
+
+extern int xdecrypt __P(( char *, char * ));
+
+/*
+ * Get somebody's encrypted secret key from the database, using the given
+ * passwd to decrypt it.
+ */
+int
+getsecretkey(netname, secretkey, passwd)
+ char *netname;
+ char *secretkey;
+ char *passwd;
+{
+ char lookup[3 * HEXKEYBYTES];
+ char *p;
+
+ if (secretkey == NULL)
+ return (0);
+ if (!getpublicandprivatekey(netname, lookup))
+ return (0);
+ p = strchr(lookup, ':');
+ if (p == NULL) {
+ return (0);
+ }
+ p++;
+ if (!xdecrypt(p, passwd)) {
+ return (0);
+ }
+ if (memcmp(p, p + HEXKEYBYTES, KEYCHECKSUMSIZE) != 0) {
+ secretkey[0] = '\0';
+ return (1);
+ }
+ p[HEXKEYBYTES] = '\0';
+ (void) strncpy(secretkey, p, HEXKEYBYTES);
+ secretkey[HEXKEYBYTES] = '\0';
+ return (1);
+}
diff --git a/lib/librpcsvc/xcrypt.c b/lib/librpcsvc/xcrypt.c
new file mode 100644
index 0000000..3635bd8
--- /dev/null
+++ b/lib/librpcsvc/xcrypt.c
@@ -0,0 +1,192 @@
+/*
+ * 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
+ */
+/*
+ * Hex encryption/decryption and utility routines
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/cdefs.h>
+#include <rpc/des_crypt.h>
+
+#ifndef lint
+/*from: static char sccsid[] = "@(#)xcrypt.c 2.2 88/08/10 4.0 RPCSRC"; */
+static const char rcsid[] = "$Id: xcrypt.c,v 1.1 1996/11/12 02:36:12 wpaul Exp $";
+#endif
+
+static char hex[]; /* forward */
+static char hexval __P(( char ));
+static void bin2hex __P(( int, unsigned char *, char * ));
+static void hex2bin __P(( int, char *, char * ));
+void passwd2des __P(( char *, char * ));
+
+/*
+ * Encrypt a secret key given passwd
+ * The secret key is passed and returned in hex notation.
+ * Its length must be a multiple of 16 hex digits (64 bits).
+ */
+int
+xencrypt(secret, passwd)
+ char *secret;
+ char *passwd;
+{
+ char key[8];
+ char ivec[8];
+ char *buf;
+ int err;
+ int len;
+
+ len = strlen(secret) / 2;
+ buf = malloc((unsigned)len);
+
+ hex2bin(len, secret, buf);
+ passwd2des(passwd, key);
+ bzero(ivec, 8);
+
+ err = cbc_crypt(key, buf, len, DES_ENCRYPT | DES_HW, ivec);
+ if (DES_FAILED(err)) {
+ free(buf);
+ return (0);
+ }
+ bin2hex(len, (unsigned char *) buf, secret);
+ free(buf);
+ return (1);
+}
+
+/*
+ * Decrypt secret key using passwd
+ * The secret key is passed and returned in hex notation.
+ * Once again, the length is a multiple of 16 hex digits
+ */
+int
+xdecrypt(secret, passwd)
+ char *secret;
+ char *passwd;
+{
+ char key[8];
+ char ivec[8];
+ char *buf;
+ int err;
+ int len;
+
+ len = strlen(secret) / 2;
+ buf = malloc((unsigned)len);
+
+ hex2bin(len, secret, buf);
+ passwd2des(passwd, key);
+ bzero(ivec, 8);
+
+ err = cbc_crypt(key, buf, len, DES_DECRYPT | DES_HW, ivec);
+ if (DES_FAILED(err)) {
+ free(buf);
+ return (0);
+ }
+ bin2hex(len, (unsigned char *) buf, secret);
+ free(buf);
+ return (1);
+}
+
+
+/*
+ * Turn password into DES key
+ */
+void
+passwd2des(pw, key)
+ char *pw;
+ char *key;
+{
+ int i;
+
+ bzero(key, 8);
+ for (i = 0; *pw; i = (i+1)%8) {
+ key[i] ^= *pw++ << 1;
+ }
+ des_setparity(key);
+}
+
+
+
+/*
+ * Hex to binary conversion
+ */
+static void
+hex2bin(len, hexnum, binnum)
+ int len;
+ char *hexnum;
+ char *binnum;
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ *binnum++ = 16 * hexval(hexnum[2*i]) + hexval(hexnum[2*i+1]);
+ }
+}
+
+/*
+ * Binary to hex conversion
+ */
+static void
+bin2hex(len, binnum, hexnum)
+ int len;
+ unsigned char *binnum;
+ char *hexnum;
+{
+ int i;
+ unsigned val;
+
+ for (i = 0; i < len; i++) {
+ val = binnum[i];
+ hexnum[i*2] = hex[val >> 4];
+ hexnum[i*2+1] = hex[val & 0xf];
+ }
+ hexnum[len*2] = 0;
+}
+
+static char hex[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
+};
+
+static char
+hexval(c)
+ char c;
+{
+ if (c >= '0' && c <= '9') {
+ return (c - '0');
+ } else if (c >= 'a' && c <= 'z') {
+ return (c - 'a' + 10);
+ } else if (c >= 'A' && c <= 'Z') {
+ return (c - 'A' + 10);
+ } else {
+ return (-1);
+ }
+}
diff --git a/lib/librpcsvc/yp_passwd.c b/lib/librpcsvc/yp_passwd.c
new file mode 100644
index 0000000..253291a
--- /dev/null
+++ b/lib/librpcsvc/yp_passwd.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1995, 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.
+ *
+ * $Id: yp_passwd.c,v 1.1 1996/11/16 20:52:13 wpaul Exp $
+ */
+
+#include <stdlib.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yppasswd.h>
+#include <netinet/in.h>
+
+#ifndef LINT
+static const char rcsid[] = "$Id: yp_passwd.c,v 1.1 1996/11/16 20:52:13 wpaul Exp $";
+#endif
+
+/*
+ * XXX <rpcsvc/yppasswd.h> does a typedef that makes 'yppasswd'
+ * a type of struct yppasswd. This leads to a namespace collision:
+ * gcc will not let you have a type called yppasswd and a function
+ * called yppasswd(). In order to get around this, we call the
+ * actual function _yppasswd() and put a macro called yppasswd()
+ * in yppasswd.h which calls the underlying function, thereby
+ * fooling gcc.
+ */
+
+int _yppasswd(oldpass, newpw)
+ char *oldpass;
+ struct x_passwd *newpw;
+{
+ char *server;
+ char *domain;
+ int rval, result;
+ struct yppasswd yppasswd;
+
+ yppasswd.newpw = *newpw;
+ yppasswd.oldpass = oldpass;
+
+ if (yp_get_default_domain(&domain))
+ return (-1);
+
+ if (yp_master(domain, "passwd.byname", &server))
+ return(-1);
+
+ rval = getrpcport(server, YPPASSWDPROG,
+ YPPASSWDPROC_UPDATE, IPPROTO_UDP);
+
+ if (rval == 0 || rval >= IPPORT_RESERVED) {
+ free(server);
+ return(-1);
+ }
+
+ rval = callrpc(server, YPPASSWDPROG, YPPASSWDVERS, YPPASSWDPROC_UPDATE,
+ xdr_yppasswd, (char *)&yppasswd, xdr_int, &result);
+
+ free(server);
+ if (rval || result)
+ return(-1);
+ else
+ return(0);
+}
diff --git a/lib/librpcsvc/yp_update.c b/lib/librpcsvc/yp_update.c
new file mode 100644
index 0000000..cbaa0fd
--- /dev/null
+++ b/lib/librpcsvc/yp_update.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 1995, 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.
+ *
+ * ypupdate client-side library function.
+ *
+ * Written by Bill Paul <wpaul@ctr.columbia.edu>
+ * Center for Telecommunications Research
+ * Columbia University, New York City
+ *
+ * $Id: yp_update.c,v 1.1 1996/11/16 20:54:57 wpaul Exp $
+ */
+
+#include <stdlib.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/ypupdate_prot.h>
+#include <rpc/key_prot.h>
+
+#ifndef lint
+static const char rcsid[] = "$Id: yp_update.c,v 1.1 1996/11/16 20:54:57 wpaul Exp $";
+#endif
+
+#ifndef WINDOW
+#define WINDOW (60*60)
+#endif
+
+#ifndef TIMEOUT
+#define TIMEOUT 300
+#endif
+
+int
+yp_update(domain, map, ypop, key, keylen, data, datalen)
+ char *domain;
+ char *map;
+ unsigned int ypop;
+ char *key;
+ int keylen;
+ char *data;
+ int datalen;
+{
+ char *master;
+ int rval;
+ unsigned int res;
+ struct ypupdate_args upargs;
+ struct ypdelete_args delargs;
+ CLIENT *clnt;
+ char netname[MAXNETNAMELEN+1];
+ des_block des_key;
+ struct timeval timeout;
+
+ /* Get the master server name for 'domain.' */
+ if ((rval = yp_master(domain, map, &master)))
+ return(rval);
+
+ /* Check that ypupdated is running there. */
+ if (getrpcport(master, YPU_PROG, YPU_VERS, ypop))
+ return(YPERR_DOMAIN);
+
+ /* Get a handle. */
+ if ((clnt = clnt_create(master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
+ return(YPERR_RPC);
+
+ /*
+ * Assemble netname of server.
+ * NOTE: It's difficult to discern from the documentation, but
+ * when you make a Secure RPC call, the netname you pass should
+ * be the netname of the guy on the other side, not your own
+ * netname. This is how the client side knows what public key
+ * to use for the initial exchange. Passing your own netname
+ * only works if the server on the other side is running under
+ * your UID.
+ */
+ if (!host2netname(netname, master, domain)) {
+ clnt_destroy(clnt);
+ return(YPERR_BADARGS);
+ }
+
+ /* Make up a DES session key. */
+ key_gendes(&des_key);
+
+ /* Set up DES authentication. */
+ if ((clnt->cl_auth = (AUTH *)authdes_create(netname, WINDOW, NULL,
+ &des_key)) == NULL) {
+ clnt_destroy(clnt);
+ return(YPERR_RESRC);
+ }
+
+ /* Set a timeout for clnt_call(). */
+ timeout.tv_usec = 0;
+ timeout.tv_sec = TIMEOUT;
+
+ /*
+ * Make the call. Note that we use clnt_call() here rather than
+ * the rpcgen-erated client stubs. We could use those stubs, but
+ * then we'd have to do some gymnastics to get at the error
+ * information to figure out what error code to send back to the
+ * caller. With clnt_call(), we get the error status returned to
+ * us right away, and we only have to exert a small amount of
+ * extra effort.
+ */
+ switch(ypop) {
+ case YPOP_CHANGE:
+ upargs.mapname = map;
+ upargs.key.yp_buf_len = keylen;
+ upargs.key.yp_buf_val = key;
+ upargs.datum.yp_buf_len = datalen;
+ upargs.datum.yp_buf_val = data;
+
+ if ((rval = clnt_call(clnt, YPU_CHANGE, xdr_ypupdate_args,
+ &upargs, xdr_u_int, &res, timeout)) != RPC_SUCCESS) {
+ if (rval == RPC_AUTHERROR)
+ res = YPERR_ACCESS;
+ else
+ res = YPERR_RPC;
+ }
+
+ break;
+ case YPOP_INSERT:
+ upargs.mapname = map;
+ upargs.key.yp_buf_len = keylen;
+ upargs.key.yp_buf_val = key;
+ upargs.datum.yp_buf_len = datalen;
+ upargs.datum.yp_buf_val = data;
+
+ if ((rval = clnt_call(clnt, YPU_INSERT, xdr_ypupdate_args,
+ &upargs, xdr_u_int, &res, timeout)) != RPC_SUCCESS) {
+ if (rval == RPC_AUTHERROR)
+ res = YPERR_ACCESS;
+ else
+ res = YPERR_RPC;
+ }
+
+ break;
+ case YPOP_DELETE:
+ delargs.mapname = map;
+ delargs.key.yp_buf_len = keylen;
+ delargs.key.yp_buf_val = key;
+
+ if ((rval = clnt_call(clnt, YPU_DELETE, xdr_ypdelete_args,
+ &delargs, xdr_u_int, &res, timeout)) != RPC_SUCCESS) {
+ if (rval == RPC_AUTHERROR)
+ res = YPERR_ACCESS;
+ else
+ res = YPERR_RPC;
+ }
+
+ break;
+ case YPOP_STORE:
+ upargs.mapname = map;
+ upargs.key.yp_buf_len = keylen;
+ upargs.key.yp_buf_val = key;
+ upargs.datum.yp_buf_len = datalen;
+ upargs.datum.yp_buf_val = data;
+
+ if ((rval = clnt_call(clnt, YPU_STORE, xdr_ypupdate_args,
+ &upargs, xdr_u_int, &res, timeout)) != RPC_SUCCESS) {
+ if (rval == RPC_AUTHERROR)
+ res = YPERR_ACCESS;
+ else
+ res = YPERR_RPC;
+ }
+
+ break;
+ default:
+ res = YPERR_BADARGS;
+ break;
+ }
+
+ /* All done: tear down the connection. */
+ auth_destroy(clnt->cl_auth);
+ clnt_destroy(clnt);
+ free(master);
+
+ return(res);
+}
diff --git a/lib/libscsi/Makefile b/lib/libscsi/Makefile
new file mode 100644
index 0000000..a056258
--- /dev/null
+++ b/lib/libscsi/Makefile
@@ -0,0 +1,21 @@
+# @(#)Makefile 8.1 (Berkeley) 6/4/93
+
+LIB= scsi
+#CFLAGS+=-DLIBC_SCCS -I/sys
+SRCS= scsi.c
+
+MAN3= scsi.3
+
+MLINKS+=scsi.3 scsireq_buff_decode.3 scsi.3 scsireq_build.3 \
+ scsi.3 scsireq_decode.3 scsi.3 scsireq_encode.3 \
+ scsi.3 scsireq_enter.3 scsi.3 scsireq_new.3 \
+ scsi.3 scsireq_reset.3 scsi.3 SCSIREQ_ERROR.3 \
+ scsi.3 scsi_open.3 scsi.3 scsi_debug.3 \
+ scsi.3 scsi_debug_output.3
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/scsi.h \
+ ${DESTDIR}/usr/include
+
+
+.include <bsd.lib.mk>
diff --git a/lib/libscsi/scsi.3 b/lib/libscsi/scsi.3
new file mode 100644
index 0000000..a61166b
--- /dev/null
+++ b/lib/libscsi/scsi.3
@@ -0,0 +1,350 @@
+.\" Copyright (c) 1994 HD Associates (hd@world.std.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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by HD Associates
+.\" 4. Neither the name of the HD Associates nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (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 November 20, 1994
+.Dt SCSI 3
+.Os
+.Sh NAME
+.Nm scsireq_buff_decode ,
+.Nm scsireq_build ,
+.Nm scsireq_decode ,
+.Nm scsireq_encode ,
+.Nm scsireq_enter ,
+.Nm scsireq_new ,
+.Nm scsireq_reset ,
+.Nm SCSIREQ_ERROR ,
+.Nm scsi_open ,
+.Nm scsi_debug ,
+.Nm scsi_debug_output
+.Nd SCSI User library
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/scsiio.h>
+.Fd #include <scsi.h>
+.Ft int
+.Fn scsireq_buff_decode "u_char *ptr" "size_t len" "char *fmt" ...
+.Ft struct scsireq *
+.Fn scsireq_build "struct scsireq *s" "u_long len" "caddr_t buf" "u_long flags" "char *fmt" ...
+.Ft int
+.Fn scsireq_decode "struct scsireq *" "char *fmt" ...
+.Ft int
+.Fn scsireq_encode "struct scsireq *" "char *fmt" ...
+.Ft int
+.Fn scsireq_enter "int fid" "struct scsireq *s"
+.Ft struct scsireq *
+.Fn scsireq_new void
+.Ft struct scsireq *
+.Fn scsireq_reset "struct scsireq *"
+.Ft int
+.Fn SCSIREQ_ERROR "struct scsireq *"
+.Ft int
+.Fn scsi_open "const char *path" "int flags"
+.Ft int
+.Fn scsi_debug "FILE *f" "int ret" "struct scsireq *s"
+.Ft FILE *
+.Fn scsi_debug_output "char *s"
+.Sh DESCRIPTION
+These functions
+use the SCIOCCOMMAND
+.Xr ioctl 2
+of the FreeBSD SCSI subsystem
+to provide user level access to SCSI commands.
+The programmer must know the SCSI CDB (Command Descriptor
+Block) to perform the desired command. These functions assist in
+building up the CDB, submitting it to the SCSI subsystem, and decoding
+the result.
+.Pp
+Look at the
+.Xr scsi 8
+command before using the library directly - simple programs are
+best implemented as scripts using that facility.
+.Pp
+To provide for security,
+not all devices accept the SCIOCCOMAND ioctl. It is accepted by the
+control device for tape drives, partition D for disk drives, partition C
+for CD ROM drives, and any "unknown" device.
+The "super scsi"
+.Xr ssc 4
+device also accepts the ioctl.
+.Pp
+Most of the SCSI library functions build up and manipulate the
+.Fa scsireq
+structure found in the include file
+.Aq Pa sys/scsiio.h :
+.Bd -literal -offset indent
+#define SENSEBUFLEN 48
+.Pp
+typedef struct scsireq {
+ u_long flags; /* info about the request status and type */
+ u_long timeout;
+ u_char cmd[16]; /* 12 is actually the max */
+ u_char cmdlen;
+ caddr_t databuf; /* address in user space of buffer */
+ u_long datalen; /* size of user buffer (request) */
+ u_long datalen_used; /* size of user buffer (used)*/
+ u_char sense[SENSEBUFLEN]; /* returned sense will be in here */
+ u_char senselen; /* sensedata request size (MAX of SENSEBUFLEN)*/
+ u_char senselen_used; /* return value only */
+ u_char status; /* what the scsi status was from the adapter */
+ u_char retsts; /* the return status for the command */
+ int error; /* error bits */
+} scsireq_t;
+.Ed
+.Pp
+.Fn scsireq_new
+allocates a new
+.Fa scsireq
+structure and returns a pointer to it or NULL if it can't allocate
+memory.
+.Pp
+.Fn scsireq_reset
+resets the structure to reasonable values and returns the same pointer passed
+in to it.
+It gracefully handles the NULL pointer passed in to it so that you can
+unconditionally use
+.Fa scsireq_new .
+.Pp
+.Fn scsireq_build
+builds up a scsireq structure based on the information provided in
+the variable argument list.
+It gracefully handles a NULL pointer passed to it.
+.Pp
+.Fa len
+is the length of the data phase; the data transfer direction is
+determined by the
+.Fa flags
+argument.
+.Pp
+.Fa buf
+is the data buffer used during the SCSI data phase. If it is NULL it
+is allocated via malloc and
+.Fa scsireq->databuf
+is set to point to the newly allocated memory.
+.Pp
+.Fa flags
+are the flags defined in
+.Aq Pa sys/scsiio.h :
+.Bd -literal -offset indent
+/* bit definitions for flags */
+#define SCCMD_READ 0x00000001
+#define SCCMD_WRITE 0x00000002
+#define SCCMD_IOV 0x00000004
+#define SCCMD_ESCAPE 0x00000010
+#define SCCMD_TARGET 0x00000020
+.Ed
+Only two of these flags are supported in this release of the software:
+.Dv SCCMD_READ
+indicates a data in phase (a transfer into the user buffer at
+.Fa scsireg->databuf
+), and
+.Dv SCCMD_WRITE
+indicates a data out phase (a transfer out of the user buffer).
+.Pp
+.Fa fmt
+is a CDB format specifier used to build up the SCSI CDB.
+This text string is made up of a list of field specifiers. Field
+specifiers specify the value for each CDB field (including indicating
+that the value be taken from the next argument in the
+variable argument list), the width
+of the field in bits or bytes, and an optional name. White space is
+ignored, and the pound sign ('#') introduces a comment that ends at the
+end of the current line.
+.Pp
+The optional name is the first part of a field specifier and
+is in curly braces. The text in curly braces in this example are
+the names:
+.Bd -literal -offset indent
+.Fa "{PS} v:b1 {Reserved} 0:b1 {Page Code} v:b6 # Mode select page"
+.Ed
+.Pp
+This field specifier has two one bit fields and one six bit field.
+The second one bit field is the constant value 0 and the first
+one bit field and the six bit field are taken from the variable
+argument list.
+Multi byte fields are swapped into the SCSI byte order in the
+CDB and white space is ignored.
+.Pp
+When the field is a hex value or the letter v, (e.g.,
+.Fa "1A"
+or
+.Fa "v" )
+then a single byte value
+is copied to the next unused byte of the CDB.
+When the letter
+.Fa v
+is used the next integer argument is taken from the variable argument list
+and that value used.
+.Pp
+A constant hex value followed by a field width specifier or the letter
+.Fa v
+followed by a field width specifier (e.g.,
+.Fa 3:4 ,
+.Fa 3:b4 ,
+.Fa 3:i3 ,
+.FR v:i3 )
+specifies a field of a given bit or byte width.
+Either the constant value or (for the V specifier) the next integer value from
+the variable argument list is copied to the next unused
+bits or bytes of the CDB.
+.Pp
+A decimal number or the letter
+.Fa b
+followed by a decimal number field width indicates a bit field of that width.
+The bit fields are packed as tightly as possible beginning with the
+high bit (so that it reads the same as the SCSI spec), and a new byte of
+the CDB is started whenever a byte fills completely or when an
+.Fa i
+field is encountered.
+.Pp
+A field width specifier consisting of the letter
+.Fa i
+followed by either
+1, 2, 3 or 4 indicates a 1, 2, 3 or 4 byte integral value that must
+be swapped into SCSI byte order (MSB first).
+.Pp
+For the
+.Fa v
+field specifier the next integer argument is taken from the variable argument
+list and that value is used swapped into SCSI byte order.
+.Pp
+.Fn scsireq_decode
+is used to decode information from the data in phase of the SCSI
+transfer.
+.Pp
+The decoding is similar to
+the command specifier processing of
+.Fn scsireq_build
+except that the data is extracted from the data pointed to by
+.Fa scsireq->databuf.
+The stdarg list should be pointers to integers instead of integer
+values.
+A seek field type and a suppression modifier are added.
+The
+.Fa *
+suppression modifier (e.g.,
+.Fa *i3
+or
+.Fa *b4 )
+suppresses assignment from the field and can be used to skip
+over bytes or bits in the data, without having to copy
+them to a dummy variable in the arg list.
+.Pp
+The seek field type
+.Fa s
+permits you to skip over data.
+This seeks to an absolute position (
+.Fa s3 )
+or a relative position (
+.Fa s+3 )
+in the data, based on whether or not the presence of the '+' sign.
+The seek value can be specified as
+.Fa v
+and the next integer value from the argument list will be
+used as the seek value.
+.Pp
+.Fn scsireq_buff_decode
+decodes an arbitrary data buffer using the method
+described above in
+.Fn scsireq_decode .
+.Pp
+.Fn scsireq_encode
+encodes the data phase section of the structure. The encoding is
+handled identically as the encoding of the CDB structure by
+.Fn scsireq_build
+.Pp
+.Fn scsireq_enter
+submits the built up structure for processing using
+the SCIOCCOMMAND ioctl.
+.Pp
+.Fn SCSIREQ_ERROR
+is a macro that determines if the result of the SCIOCCOMMAND ioctl may
+have been
+in error by examining the host adapter return code, whether sense was sent
+or not, and so on.
+.Pp
+.Fn scsi_open
+checks environment variables and initializes the library for
+consistent library use and then calls the regular open system call.
+.Pp
+.Fn scsi_debug
+prints the results of a scsireq_enter function to the specified stdio
+stream.
+.Pp
+.Fn scsi_debug_output
+requests that the results of all transactions be debugged to the
+supplied file using
+.Fn scsi_debug .
+.Sh RETURN VALUES
+The function
+.Fn scsireq_new
+returns a pointer to storage allocated from malloc, and therefore
+potentially a NULL.
+.Pp
+The functions
+.Fn scsireq_build
+and
+.Fn scsireq_reset
+return the same pointer as the one passed in.
+.Pp
+The functions
+.Fn scsireq_buff_decode
+and
+.Fn scsireq_decode
+return the number of assignments performed.
+.Pp
+.Fn scsireq_encode
+returns the number of fields processed.
+.Pp
+The function
+.Fn scsireq_enter
+returns the result of the ioctl call.
+.Sh SEE ALSO
+.Xr scsi 4 ,
+.Xr scsi 8
+.Sh BUGS
+This only works completely for the 1542C. The host adapter code
+that sets up the residual amount of data transfer has to be added
+to each individual adapter. This library is usable on the other
+host adapters, however, the SCSI driver pretends that the proper
+amount of data is always transferred. If you have an Adaptec 174x
+and can hack contact dufault@hda.com and you can have the code to
+calculate residual data for the 174x series to integrate and test.
+.Sh HISTORY
+Many systems have comparable interfaces to permit a user to construct a
+SCSI command in user space.
+.Pp
+The data structure is almost identical to the SGI /dev/scsi data
+structure. If anyone knows the name of the authors it should
+go here; Peter Dufault first read about it in a 1989 Sun Expert magazine.
+.Pp
+Peter Dufault implemented a clone of SGI's interface in 386bsd that
+led to this library and the related kernel ioctl.
+If anyone needs that for compatibility contact dufault@hda.com.
diff --git a/lib/libscsi/scsi.c b/lib/libscsi/scsi.c
new file mode 100644
index 0000000..3293a72
--- /dev/null
+++ b/lib/libscsi/scsi.c
@@ -0,0 +1,1192 @@
+/* scsi: SCSI user library
+ */
+/* Copyright (c) 1994 HD Associates
+ * (contact: dufault@hda.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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by HD Associates
+ * 4. Neither the name of the HD Associaates nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/scsiio.h>
+#include <sys/errno.h>
+#include <stdarg.h>
+#include <fcntl.h>
+
+#include "scsi.h"
+
+static struct
+{
+ FILE *db_f;
+ int db_level;
+ int db_trunc;
+} behave;
+
+/* scsireq_reset: Reset a scsireq structure.
+ */
+scsireq_t *scsireq_reset(scsireq_t *scsireq)
+{
+ if (scsireq == 0)
+ return scsireq;
+
+ scsireq->flags = 0; /* info about the request status and type */
+ scsireq->timeout = 2000; /* 2 seconds */
+ bzero(scsireq->cmd, sizeof(scsireq->cmd));
+ scsireq->cmdlen = 0;
+ /* Leave scsireq->databuf alone */
+ /* Leave scsireq->datalen alone */
+ scsireq->datalen_used = 0;
+ bzero(scsireq->sense, sizeof(scsireq->sense));
+ scsireq->senselen = sizeof(scsireq->sense);
+ scsireq->senselen_used = 0;
+ scsireq->status = 0;
+ scsireq->retsts = 0;
+ scsireq->error = 0;
+
+ return scsireq;
+}
+
+/* scsireq_new: Allocate and initialize a new scsireq.
+ */
+scsireq_t *scsireq_new(void)
+{
+ scsireq_t *p = (scsireq_t *)malloc(sizeof(scsireq_t));
+
+ if (p)
+ scsireq_reset(p);
+
+ return p;
+}
+
+/*
+ * Decode: Decode the data section of a scsireq. This decodes
+ * trivial grammar:
+ *
+ * fields : field fields
+ * ;
+ *
+ * field : field_specifier
+ * | control
+ * ;
+ *
+ * control : 's' seek_value
+ * | 's' '+' seek_value
+ * ;
+ *
+ * seek_value : DECIMAL_NUMBER
+ * | 'v' // For indirect seek, i.e., value from the arg list
+ * ;
+ *
+ * field_specifier : type_specifier field_width
+ * | '{' NAME '}' type_specifier field_width
+ * ;
+ *
+ * field_width : DECIMAL_NUMBER
+ * ;
+ *
+ * type_specifier : 'i' // Integral types (i1, i2, i3, i4)
+ * | 'b' // Bits
+ * | 't' // Bits
+ * | 'c' // Character arrays
+ * | 'z' // Character arrays with zeroed trailing spaces
+ * ;
+ *
+ * Notes:
+ * 1. Integral types are swapped into host order.
+ * 2. Bit fields are allocated MSB to LSB to match the SCSI spec documentation.
+ * 3. 's' permits "seeking" in the string. "s+DECIMAL" seeks relative to
+ * DECIMAL; "sDECIMAL" seeks absolute to decimal.
+ * 4. 's' permits an indirect reference. "sv" or "s+v" will get the
+ * next integer value from the arg array.
+ * 5. Field names can be anything between the braces
+ *
+ * BUGS:
+ * i and b types are promoted to ints.
+ *
+ */
+
+static int do_buff_decode(u_char *databuf, size_t len,
+void (*arg_put)(void *, int , void *, int, char *), void *puthook,
+char *fmt, va_list ap)
+{
+ int assigned = 0;
+ int width;
+ int suppress;
+ int plus;
+ int done = 0;
+ static u_char mask[] = {0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+ int value;
+ u_char *base = databuf;
+ char letter;
+ char field_name[80];
+
+# define ARG_PUT(ARG) \
+ do \
+ { \
+ if (!suppress) \
+ { \
+ if (arg_put) \
+ (*arg_put)(puthook, (letter == 't' ? 'b' : letter), \
+ (void *)((long)(ARG)), 1, field_name); \
+ else \
+ *(va_arg(ap, int *)) = (ARG); \
+ assigned++; \
+ } \
+ field_name[0] = 0; \
+ suppress = 0; \
+ } while (0)
+
+ u_char bits = 0; /* For bit fields */
+ int shift = 0; /* Bits already shifted out */
+ suppress = 0;
+ field_name[0] = 0;
+
+ while (!done)
+ {
+ switch(letter = *fmt)
+ {
+ case ' ': /* White space */
+ case '\t':
+ case '\r':
+ case '\n':
+ case '\f':
+ fmt++;
+ break;
+
+ case '#': /* Comment */
+ while (*fmt && (*fmt != '\n'))
+ fmt++;
+ if (fmt)
+ fmt++; /* Skip '\n' */
+ break;
+
+ case '*': /* Suppress assignment */
+ fmt++;
+ suppress = 1;
+ break;
+
+ case '{': /* Field Name */
+ {
+ int i = 0;
+ fmt++; /* Skip '{' */
+ while (*fmt && (*fmt != '}'))
+ {
+ if (i < sizeof(field_name))
+ field_name[i++] = *fmt;
+
+ fmt++;
+ }
+ if (fmt)
+ fmt++; /* Skip '}' */
+ field_name[i] = 0;
+ }
+ break;
+
+ case 't': /* Bit (field) */
+ case 'b': /* Bits */
+ fmt++;
+ width = strtol(fmt, &fmt, 10);
+ if (width > 8)
+ done = 1;
+ else
+ {
+ if (shift <= 0)
+ {
+ bits = *databuf++;
+ shift = 8;
+ }
+ value = (bits >> (shift - width)) & mask[width];
+
+#if 0
+ printf("shift %2d bits %02x value %02x width %2d mask %02x\n",
+ shift, bits, value, width, mask[width]);
+#endif
+
+ ARG_PUT(value);
+
+ shift -= width;
+ }
+
+ break;
+
+ case 'i': /* Integral values */
+ shift = 0;
+ fmt++;
+ width = strtol(fmt, &fmt, 10);
+ switch(width)
+ {
+ case 1:
+ ARG_PUT(*databuf);
+ databuf++;
+ break;
+
+ case 2:
+ ARG_PUT(
+ (*databuf) << 8 |
+ *(databuf + 1));
+ databuf += 2;
+ break;
+
+ case 3:
+ ARG_PUT(
+ (*databuf) << 16 |
+ (*(databuf + 1)) << 8 |
+ *(databuf + 2));
+ databuf += 3;
+ break;
+
+ case 4:
+ ARG_PUT(
+ (*databuf) << 24 |
+ (*(databuf + 1)) << 16 |
+ (*(databuf + 2)) << 8 |
+ *(databuf + 3));
+ databuf += 4;
+ break;
+
+ default:
+ done = 1;
+ }
+
+ break;
+
+ case 'c': /* Characters (i.e., not swapped) */
+ case 'z': /* Characters with zeroed trailing spaces */
+ shift = 0;
+ fmt++;
+ width = strtol(fmt, &fmt, 10);
+ if (!suppress)
+ {
+ if (arg_put)
+ (*arg_put)(puthook, (letter == 't' ? 'b' : letter),
+ databuf, width, field_name);
+ else
+ {
+ char *dest;
+ dest = va_arg(ap, char *);
+ bcopy(databuf, dest, width);
+ if (letter == 'z')
+ {
+ char *p;
+ for (p = dest + width - 1;
+ (p >= (char *)dest) && (*p == ' '); p--)
+ *p = 0;
+ }
+ }
+ assigned++;
+ }
+ databuf += width;
+ field_name[0] = 0;
+ suppress = 0;
+ break;
+
+ case 's': /* Seek */
+ shift = 0;
+ fmt++;
+ if (*fmt == '+')
+ {
+ plus = 1;
+ fmt++;
+ }
+ else
+ plus = 0;
+
+ if (tolower(*fmt) == 'v')
+ {
+ /* You can't suppress a seek value. You also
+ * can't have a variable seek when you are using
+ * "arg_put".
+ */
+ width = (arg_put) ? 0 : va_arg(ap, int);
+ fmt++;
+ }
+ else
+ width = strtol(fmt, &fmt, 10);
+
+ if (plus)
+ databuf += width; /* Relative seek */
+ else
+ databuf = base + width; /* Absolute seek */
+
+ break;
+
+ case 0:
+ done = 1;
+ break;
+
+ default:
+ fprintf(stderr, "Unknown letter in format: %c\n", letter);
+ fmt++;
+ }
+ }
+
+ return assigned;
+}
+
+int scsireq_decode(scsireq_t *scsireq, char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ return do_buff_decode(scsireq->databuf, (size_t)scsireq->datalen,
+ 0, 0, fmt, ap);
+}
+
+int scsireq_decode_visit(scsireq_t *scsireq, char *fmt,
+void (*arg_put)(void *, int , void *, int, char *), void *puthook)
+{
+ va_list ap = (va_list)0;
+ return do_buff_decode(scsireq->databuf, (size_t)scsireq->datalen,
+ arg_put, puthook, fmt, ap);
+}
+
+int scsireq_buff_decode(u_char *buff, size_t len, char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ return do_buff_decode(buff, len, 0, 0, fmt, ap);
+}
+
+int scsireq_buff_decode_visit(u_char *buff, size_t len, char *fmt,
+void (*arg_put)(void *, int, void *, int, char *), void *puthook)
+{
+ va_list ap = (va_list)0;
+ return do_buff_decode(buff, len, arg_put, puthook, fmt, ap);
+}
+
+/* next_field: Return the next field in a command specifier. This
+ * builds up a SCSI command using this trivial grammar:
+ *
+ * fields : field fields
+ * ;
+ *
+ * field : value
+ * | value ':' field_width
+ * ;
+ *
+ * field_width : digit
+ * | 'i' digit // i2 = 2 byte integer, i3 = 3 byte integer etc.
+ * ;
+ *
+ * value : HEX_NUMBER
+ * | 'v' // For indirection.
+ * ;
+ *
+ * Notes:
+ * Bit fields are specified MSB first to match the SCSI spec.
+ *
+ * Examples:
+ * TUR: "0 0 0 0 0 0"
+ * WRITE BUFFER: "38 v:3 0:2 0:3 v v:i3 v:i3 0", mode, buffer_id, list_length
+ *
+ * The function returns the value:
+ * 0: For reached end, with error_p set if an error was found
+ * 1: For valid stuff setup
+ * 2: For "v" was entered as the value (implies use varargs)
+ *
+ */
+
+static int next_field(char **pp,
+char *fmt, int *width_p, int *value_p, char *name, int n_name, int *error_p,
+int *suppress_p)
+{
+ char *p = *pp;
+
+ int something = 0;
+
+ enum
+ {
+ BETWEEN_FIELDS,
+ START_FIELD,
+ GET_FIELD,
+ DONE,
+ } state;
+
+ int value = 0;
+ int field_size; /* Default to byte field type... */
+ int field_width; /* 1 byte wide */
+ int is_error = 0;
+ int suppress = 0;
+
+ field_size = 8; /* Default to byte field type... */
+ *fmt = 'i';
+ field_width = 1; /* 1 byte wide */
+ if (name)
+ *name = 0;
+
+ state = BETWEEN_FIELDS;
+
+ while (state != DONE)
+ {
+ switch(state)
+ {
+ case BETWEEN_FIELDS:
+ if (*p == 0)
+ state = DONE;
+ else if (isspace(*p))
+ p++;
+ else if (*p == '#')
+ {
+ while (*p && *p != '\n')
+ p++;
+ if (p)
+ p++;
+ }
+ else if (*p == '{')
+ {
+ int i = 0;
+
+ p++;
+
+ while (*p && *p != '}')
+ {
+ if(name && i < n_name)
+ {
+ name[i] = *p;
+ i++;
+ }
+ p++;
+ }
+
+ if(name && i < n_name)
+ name[i] = 0;
+
+ if (*p == '}')
+ p++;
+ }
+ else if (*p == '*')
+ {
+ p++;
+ suppress = 1;
+ }
+ else if (isxdigit(*p))
+ {
+ something = 1;
+ value = strtol(p, &p, 16);
+ state = START_FIELD;
+ }
+ else if (tolower(*p) == 'v')
+ {
+ p++;
+ something = 2;
+ value = *value_p;
+ state = START_FIELD;
+ }
+/* Try to work without the "v".
+ */
+ else if (tolower(*p) == 'i')
+ {
+ something = 2;
+ value = *value_p;
+ p++;
+
+ *fmt = 'i';
+ field_size = 8;
+ field_width = strtol(p, &p, 10);
+ state = DONE;
+ }
+
+/* XXX: B can't work: Sees the 'b' as a hex digit in "isxdigit".
+ * try "t" for bit field.
+ */
+ else if (tolower(*p) == 't')
+ {
+ something = 2;
+ value = *value_p;
+ p++;
+
+ *fmt = 'b';
+ field_size = 1;
+ field_width = strtol(p, &p, 10);
+ state = DONE;
+ }
+ else if (tolower(*p) == 's') /* Seek */
+ {
+ *fmt = 's';
+ p++;
+ if (tolower(*p) == 'v')
+ {
+ p++;
+ something = 2;
+ value = *value_p;
+ }
+ else
+ {
+ something = 1;
+ value = strtol(p, &p, 0);
+ }
+ state = DONE;
+ }
+ else
+ {
+ fprintf(stderr, "Invalid starting character: %c\n", *p);
+ is_error = 1;
+ state = DONE;
+ }
+ break;
+
+ case START_FIELD:
+ if (*p == ':')
+ {
+ p++;
+ field_size = 1; /* Default to bits when specified */
+ state = GET_FIELD;
+ }
+ else
+ state = DONE;
+ break;
+
+ case GET_FIELD:
+ if (isdigit(*p))
+ {
+ *fmt = 'b';
+ field_size = 1;
+ field_width = strtol(p, &p, 10);
+ state = DONE;
+ }
+ else if (*p == 'i') /* Integral (bytes) */
+ {
+ p++;
+
+ *fmt = 'i';
+ field_size = 8;
+ field_width = strtol(p, &p, 10);
+ state = DONE;
+ }
+ else if (*p == 'b') /* Bits */
+ {
+ p++;
+
+ *fmt = 'b';
+ field_size = 1;
+ field_width = strtol(p, &p, 10);
+ state = DONE;
+ }
+ else
+ {
+ fprintf(stderr, "Invalid startfield %c (%02x)\n",
+ *p, *p);
+ is_error = 1;
+ state = DONE;
+ }
+ break;
+
+ case DONE:
+ break;
+ }
+ }
+
+ if (is_error)
+ {
+ *error_p = 1;
+ return 0;
+ }
+
+ *error_p = 0;
+ *pp = p;
+ *width_p = field_width * field_size;
+ *value_p = value;
+ *suppress_p = suppress;
+
+ return something;
+}
+
+static int do_encode(u_char *buff, size_t vec_max, size_t *used,
+int (*arg_get)(void *, char *), void *gethook,
+char *fmt, va_list ap)
+{
+ int ind;
+ int shift;
+ u_char val;
+ int ret;
+ int width, value, error, suppress;
+ char c;
+ int encoded = 0;
+ char field_name[80];
+
+ ind = 0;
+ shift = 0;
+ val = 0;
+
+ while ((ret = next_field(&fmt,
+ &c, &width, &value, field_name, sizeof(field_name), &error, &suppress)))
+ {
+ encoded++;
+
+ if (ret == 2) {
+ if (suppress)
+ value = 0;
+ else
+ value = arg_get ? (*arg_get)(gethook, field_name) : va_arg(ap, int);
+ }
+
+#if 0
+ printf(
+"do_encode: ret %d fmt %c width %d value %d name \"%s\" error %d suppress %d\n",
+ ret, c, width, value, field_name, error, suppress);
+#endif
+
+ if (c == 's') /* Absolute seek */
+ {
+ ind = value;
+ continue;
+ }
+
+ if (width < 8) /* A width of < 8 is a bit field. */
+ {
+
+ /* This is a bit field. We start with the high bits
+ * so it reads the same as the SCSI spec.
+ */
+
+ shift += width;
+
+ val |= (value << (8 - shift));
+
+ if (shift == 8)
+ {
+ if (ind < vec_max)
+ {
+ buff[ind++] = val;
+ val = 0;
+ }
+ shift = 0;
+ }
+ }
+ else
+ {
+ if (shift)
+ {
+ if (ind < vec_max)
+ {
+ buff[ind++] = val;
+ val = 0;
+ }
+ shift = 0;
+ }
+ switch(width)
+ {
+ case 8: /* 1 byte integer */
+ if (ind < vec_max)
+ buff[ind++] = value;
+ break;
+
+ case 16: /* 2 byte integer */
+ if (ind < vec_max - 2 + 1)
+ {
+ buff[ind++] = value >> 8;
+ buff[ind++] = value;
+ }
+ break;
+
+ case 24: /* 3 byte integer */
+ if (ind < vec_max - 3 + 1)
+ {
+ buff[ind++] = value >> 16;
+ buff[ind++] = value >> 8;
+ buff[ind++] = value;
+ }
+ break;
+
+ case 32: /* 4 byte integer */
+ if (ind < vec_max - 4 + 1)
+ {
+ buff[ind++] = value >> 24;
+ buff[ind++] = value >> 16;
+ buff[ind++] = value >> 8;
+ buff[ind++] = value;
+ }
+ break;
+
+ default:
+ fprintf(stderr, "do_encode: Illegal width\n");
+ break;
+ }
+ }
+ }
+
+ /* Flush out any remaining bits
+ */
+ if (shift && ind < vec_max)
+ {
+ buff[ind++] = val;
+ val = 0;
+ }
+
+
+ if (used)
+ *used = ind;
+
+ if (error)
+ return -1;
+
+ return encoded;
+}
+
+/* XXX: Should be a constant in scsiio.h
+ */
+#define CMD_BUFLEN 16
+
+scsireq_t *scsireq_build(scsireq_t *scsireq,
+ u_long datalen, caddr_t databuf, u_long flags,
+ char *cmd_spec, ...)
+{
+ int cmdlen;
+ va_list ap;
+
+ if (scsireq == 0)
+ return 0;
+
+ scsireq_reset(scsireq);
+
+ if (databuf)
+ {
+ scsireq->databuf = databuf;
+ scsireq->datalen = datalen;
+ scsireq->flags = flags;
+ }
+ else if (datalen)
+ {
+ /* XXX: Good way to get a memory leak. Perhaps this should be
+ * removed.
+ */
+ if ( (scsireq->databuf = malloc(datalen)) == 0)
+ return 0;
+
+ scsireq->datalen = datalen;
+ scsireq->flags = flags;
+ }
+
+ va_start(ap, cmd_spec);
+
+ if (do_encode(scsireq->cmd, CMD_BUFLEN, &cmdlen, 0, 0, cmd_spec, ap) == -1)
+ return 0;
+
+ scsireq->cmdlen = cmdlen;
+ return scsireq;
+}
+
+scsireq_t
+*scsireq_build_visit(scsireq_t *scsireq,
+ u_long datalen, caddr_t databuf, u_long flags, char *cmd_spec,
+ int (*arg_get)(void *hook, char *field_name), void *gethook)
+{
+ int cmdlen;
+ va_list ap = (va_list) 0;
+
+ if (scsireq == 0)
+ return 0;
+
+ scsireq_reset(scsireq);
+
+ if (databuf)
+ {
+ scsireq->databuf = databuf;
+ scsireq->datalen = datalen;
+ scsireq->flags = flags;
+ }
+ else if (datalen)
+ {
+ /* XXX: Good way to get a memory leak. Perhaps this should be
+ * removed.
+ */
+ if ( (scsireq->databuf = malloc(datalen)) == 0)
+ return 0;
+
+ scsireq->datalen = datalen;
+ scsireq->flags = flags;
+ }
+
+ if (do_encode(scsireq->cmd, CMD_BUFLEN, &cmdlen, arg_get, gethook,
+ cmd_spec, ap) == -1)
+ return 0;
+
+ scsireq->cmdlen = cmdlen;
+
+ return scsireq;
+}
+
+int scsireq_encode(scsireq_t *scsireq, char *fmt, ...)
+{
+ va_list ap;
+
+ if (scsireq == 0)
+ return 0;
+
+ va_start(ap, fmt);
+
+ return do_encode(scsireq->databuf,
+ scsireq->datalen, 0, 0, 0, fmt, ap);
+}
+
+int scsireq_buff_encode_visit(u_char *buff, size_t len, char *fmt,
+ int (*arg_get)(void *hook, char *field_name), void *gethook)
+{
+ va_list ap = (va_list)0;
+ return do_encode(buff, len, 0,
+ arg_get, gethook, fmt, ap);
+}
+
+int scsireq_encode_visit(scsireq_t *scsireq, char *fmt,
+ int (*arg_get)(void *hook, char *field_name), void *gethook)
+{
+ va_list ap = (va_list)0;
+ return do_encode(scsireq->databuf, scsireq->datalen, 0,
+ arg_get, gethook, fmt, ap);
+}
+
+FILE *scsi_debug_output(char *s)
+{
+ if (s == 0)
+ behave.db_f = 0;
+ else
+ {
+ behave.db_f = fopen(s, "w");
+
+ if (behave.db_f == 0)
+ behave.db_f = stderr;
+ }
+
+ return behave.db_f;
+}
+
+#define SCSI_TRUNCATE -1
+
+typedef struct scsi_assoc
+{
+ int code;
+ char *text;
+} scsi_assoc_t;
+
+static scsi_assoc_t retsts[] =
+{
+ { SCCMD_OK, "No error" },
+ { SCCMD_TIMEOUT, "Command Timeout" },
+ { SCCMD_BUSY, "Busy" },
+ { SCCMD_SENSE, "Sense Returned" },
+ { SCCMD_UNKNOWN, "Unknown return status" },
+
+ { 0, 0 }
+};
+
+static char *scsi_assoc_text(int code, scsi_assoc_t *tab)
+{
+ while (tab->text)
+ {
+ if (tab->code == code)
+ return tab->text;
+
+ tab++;
+ }
+
+ return "Unknown code";
+}
+
+void scsi_dump(FILE *f, char *text, u_char *p, int req, int got, int dump_print)
+{
+ int i;
+ int trunc = 0;
+
+ if (f == 0 || req == 0)
+ return;
+
+ fprintf(f, "%s (%d of %d):\n", text, got, req);
+
+ if (behave.db_trunc != -1 && got > behave.db_trunc)
+ {
+ trunc = 1;
+ got = behave.db_trunc;
+ }
+
+ for (i = 0; i < got; i++)
+ {
+ fprintf(f, "%02x", p[i]);
+
+ putc(' ', f);
+
+ if ((i % 16) == 15 || i == got - 1)
+ {
+ int j;
+ if (dump_print)
+ {
+ fprintf(f, " # ");
+ for (j = i - 15; j <= i; j++)
+ putc((isprint(p[j]) ? p[j] : '.'), f);
+
+ putc('\n', f);
+ }
+ else
+ putc('\n', f);
+ }
+ }
+
+ fprintf(f, "%s", (trunc) ? "(truncated)...\n" : "\n");
+}
+
+/* XXX: sense_7x_dump and scsi_sense dump was just sort of
+ * grabbed out of the old ds
+ * library and not really merged in carefully. It should use the
+ * new buffer decoding stuff.
+ */
+
+/* Get unsigned long.
+ */
+static u_long g_u_long(u_char *s)
+{
+ return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
+}
+
+/* In the old software you could patch in a special error table:
+ */
+scsi_assoc_t *error_table = 0;
+
+static void sense_7x_dump(FILE *f, scsireq_t *scsireq)
+{
+ int code;
+ u_char *s = (u_char *)scsireq->sense;
+ int valid = (*s) & 0x80;
+ u_long val;
+
+ static scsi_assoc_t sense[] = {
+ { 0, "No sense" },
+ { 1, "Recovered error" },
+ { 2, "Not Ready" },
+ { 3, "Medium error" },
+ { 4, "Hardware error" },
+ { 5, "Illegal request" },
+ { 6, "Unit attention" },
+ { 7, "Data protect" },
+ { 8, "Blank check" },
+ { 9, "Vendor specific" },
+ { 0xa, "Copy aborted" },
+ { 0xb, "Aborted Command" },
+ { 0xc, "Equal" },
+ { 0xd, "Volume overflow" },
+ { 0xe, "Miscompare" },
+ { 0, 0 },
+ };
+
+ static scsi_assoc_t code_tab[] = {
+ {0x70, "current errors"},
+ {0x71, "deferred errors"},
+ };
+
+ fprintf(f, "Error code is \"%s\"\n", scsi_assoc_text(s[0]&0x7F, code_tab));
+ fprintf(f, "Segment number is %02x\n", s[1]);
+
+ if (s[2] & 0x20)
+ fprintf(f, "Incorrect Length Indicator is set.\n");
+
+ fprintf(f, "Sense key is \"%s\"\n", scsi_assoc_text(s[2] & 0x7, sense));
+
+ val = g_u_long(s + 3);
+ fprintf(f, "The Information field is%s %08lx (%ld).\n",
+ valid ? "" : " not valid but contains", (long)val, (long)val);
+
+ val = g_u_long(s + 8);
+ fprintf(f, "The Command Specific Information field is %08lx (%ld).\n",
+ (long)val, (long)val);
+
+ fprintf(f, "Additional sense code: %02x\n", s[12]);
+ fprintf(f, "Additional sense code qualifier: %02x\n", s[13]);
+
+ code = (s[12] << 8) | s[13];
+
+ if (error_table)
+ fprintf(f, "%s\n", scsi_assoc_text(code, error_table));
+
+ if (s[15] & 0x80)
+ {
+ if ((s[2] & 0x7) == 0x05) /* Illegal request */
+ {
+ int byte;
+ u_char value, bit;
+ int bad_par = ((s[15] & 0x40) == 0);
+ fprintf(f, "Illegal value in the %s.\n",
+ (bad_par ? "parameter list" : "command descriptor block"));
+ byte = ((s[16] << 8) | s[17]);
+ value = bad_par ? (u_char)scsireq->databuf[byte] : (u_char)scsireq->cmd[byte];
+ bit = s[15] & 0x7;
+ if (s[15] & 0x08)
+ fprintf(f, "Bit %d of byte %d (value %02x) is illegal.\n",
+ bit, byte, value);
+ else
+ fprintf(f, "Byte %d (value %02x) is illegal.\n", byte, value);
+ }
+ else
+ {
+ fprintf(f, "Sense Key Specific (valid but not illegal request):\n");
+ fprintf(f,
+ "%02x %02x %02x\n", s[15] & 0x7f, s[16], s[17]);
+ }
+ }
+}
+
+/* scsi_sense_dump: Dump the sense portion of the scsireq structure.
+ */
+void scsi_sense_dump(FILE *f, scsireq_t *scsireq)
+{
+ u_char *s = (u_char *)scsireq->sense;
+ int code = (*s) & 0x7f;
+
+ if (scsireq->senselen_used == 0)
+ {
+ fprintf(f, "No sense sent.\n");
+ return;
+ }
+
+#if 0
+ if (!valid)
+ fprintf(f, "The sense data is not valid.\n");
+#endif
+
+ switch(code)
+ {
+ case 0x70:
+ case 0x71:
+ sense_7x_dump(f, scsireq);
+ break;
+
+ default:
+ fprintf(f, "No sense dump for error code %02x.\n", code);
+ }
+ scsi_dump(f, "sense", s, scsireq->senselen, scsireq->senselen_used, 0);
+}
+
+void scsi_retsts_dump(FILE *f, scsireq_t *scsireq)
+{
+ if (scsireq->retsts == 0)
+ return;
+
+ fprintf(f, "return status %d (%s)",
+ scsireq->retsts, scsi_assoc_text(scsireq->retsts, retsts));
+
+ switch(scsireq->retsts)
+ {
+ case SCCMD_TIMEOUT:
+ fprintf(f, " after %ld ms", scsireq->timeout);
+ break;
+
+ default:
+ break;
+ }
+}
+
+int scsi_debug(FILE *f, int ret, scsireq_t *scsireq)
+{
+ char *d;
+ if (f == 0)
+ return 0;
+
+ fprintf(f, "SCIOCCOMMAND ioctl");
+
+ if (ret == 0)
+ fprintf(f, ": Command accepted.");
+ else
+ {
+ if (ret != -1)
+ fprintf(f, ", return value %d?", ret);
+
+ if (errno)
+ {
+ fprintf(f, ": %s", strerror(errno));
+ errno = 0;
+ }
+ }
+
+ fputc('\n', f);
+
+ if (ret == 0 && (scsireq->status || scsireq->retsts || behave.db_level))
+ {
+ scsi_retsts_dump(f, scsireq);
+
+ if (scsireq->status)
+ fprintf(f, " host adapter status %d\n", scsireq->status);
+
+ if (scsireq->flags & SCCMD_READ)
+ d = "Data in";
+ else if (scsireq->flags & SCCMD_WRITE)
+ d = "Data out";
+ else
+ d = "No data transfer?";
+
+ if (scsireq->cmdlen == 0)
+ fprintf(f, "Zero length command????\n");
+
+ scsi_dump(f, "Command out",
+ (u_char *)scsireq->cmd, scsireq->cmdlen, scsireq->cmdlen, 0);
+ scsi_dump(f, d,
+ (u_char *)scsireq->databuf, scsireq->datalen,
+ scsireq->datalen_used, 1);
+ scsi_sense_dump(f, scsireq);
+ }
+
+ fflush(f);
+
+ return ret;
+}
+
+static char *debug_output;
+
+int scsi_open(const char *path, int flags)
+{
+ int fd = open(path, flags);
+
+ if (fd != -1)
+ {
+ char *p;
+ debug_output = getenv("SU_DEBUG_OUTPUT");
+ (void)scsi_debug_output(debug_output);
+
+ if ((p = getenv("SU_DEBUG_LEVEL")))
+ sscanf(p, "%d", &behave.db_level);
+
+ if ((p = getenv("SU_DEBUG_TRUNCATE")))
+ sscanf(p, "%d", &behave.db_trunc);
+ else
+ behave.db_trunc = SCSI_TRUNCATE;
+ }
+
+ return fd;
+}
+
+int scsireq_enter(int fid, scsireq_t *scsireq)
+{
+ int ret;
+
+ if (scsireq == 0)
+ return EFAULT;
+
+ ret = ioctl(fid, SCIOCCOMMAND, (void *)scsireq);
+
+ if (behave.db_f) scsi_debug(behave.db_f, ret, scsireq);
+
+ return ret;
+}
diff --git a/lib/libscsi/scsi.h b/lib/libscsi/scsi.h
new file mode 100644
index 0000000..e0cd340
--- /dev/null
+++ b/lib/libscsi/scsi.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 1994 HD Associates (hd@world.std.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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by HD Associates
+ * 4. Neither the name of the HD Associaates nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 _SCSI_H_
+#define _SCSI_H_
+
+#include <sys/cdefs.h>
+
+/* libscsi: Library header file for the SCSI user library.
+ */
+
+#include <sys/scsiio.h>
+#include <stdio.h>
+
+#define SCSIREQ_ERROR(SR) (\
+0 \
+|| SR->senselen_used /* Sent sense */ \
+|| SR->status /* Host adapter status */ \
+|| SR->retsts /* SCSI transfer status */ \
+|| SR->error /* copy of errno */ \
+)
+
+__BEGIN_DECLS
+scsireq_t *scsireq_reset __P((scsireq_t *));
+scsireq_t *scsireq_new __P((void));
+
+int scsireq_buff_decode __P((u_char *, size_t, char *, ...));
+int scsireq_buff_decode_visit __P((u_char *, size_t, char *,
+void (*a)(void *, int, void *, int, char *), void *));
+
+int scsireq_decode __P((scsireq_t *, char *, ...));
+int scsireq_decode_visit __P((scsireq_t *, char *,
+void (*) (void *, int, void *, int, char *), void *));
+
+int scsireq_encode __P((scsireq_t *, char *, ...));
+int scsireq_encode_visit __P((scsireq_t *, char *,
+ int (*)(void *, char *), void *));
+int scsireq_buff_encode_visit __P((u_char *, size_t, char *,
+ int (*)(void *, char *), void *));
+
+scsireq_t *scsireq_build __P((scsireq_t *,
+ u_long, caddr_t, u_long,
+ char *, ...));
+
+scsireq_t *scsireq_build_visit __P((scsireq_t *,
+ u_long, caddr_t, u_long, char *,
+ int (*)(void *, char *), void *));
+
+int scsireq_enter __P((int, scsireq_t *));
+
+void scsi_dump __P((FILE *, char *, u_char *, int, int, int ));
+
+int scsi_debug __P((FILE *, int, scsireq_t *));
+FILE *scsi_debug_output __P((char *));
+int scsi_open __P((const char *, int ));
+__END_DECLS
+
+#endif /* _SCSI_H_ */
diff --git a/lib/libskey/Makefile b/lib/libskey/Makefile
new file mode 100644
index 0000000..6e3fe92
--- /dev/null
+++ b/lib/libskey/Makefile
@@ -0,0 +1,18 @@
+# @(#)Makefile 5.4 (Berkeley) 5/7/91
+
+LIB= skey
+SRCS= skeyaccess.c put.c skey_crypt.c skey_getpass.c skeylogin.c skeysubr.c
+MAN1= skey.1
+MAN3= skey.3
+MLINKS= skey.3 skeylookup.3 skey.3 skeyverify.3 skey.3 skeychallenge.3 \
+ skey.3 skeyinfo.3 skey.3 skeyaccess.3 skey.3 skey_getpass.3 \
+ skey.3 skey_crypt.3
+MAN5= skey.access.5
+
+CFLAGS+=-DPERMIT_CONSOLE -D_SKEY_INTERNAL -I${.CURDIR}
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/skey.h \
+ ${DESTDIR}/usr/include
+
+.include <bsd.lib.mk>
diff --git a/lib/libskey/mdx.h b/lib/libskey/mdx.h
new file mode 100644
index 0000000..567d541
--- /dev/null
+++ b/lib/libskey/mdx.h
@@ -0,0 +1,19 @@
+#ifdef MD5
+/* S/Key can use MD5 now, if defined... */
+#include <md5.h>
+
+#define MDXFinal MD5Final
+#define MDXInit MD5Init
+#define MDXUpdate MD5Update
+#define MDX_CTX MD5_CTX
+#else
+
+/* By default, use MD4 for compatibility */
+#include <md4.h>
+
+#define MDXFinal MD4Final
+#define MDXInit MD4Init
+#define MDXUpdate MD4Update
+#define MDX_CTX MD4_CTX
+
+#endif
diff --git a/lib/libskey/pathnames.h b/lib/libskey/pathnames.h
new file mode 100644
index 0000000..84f0d32
--- /dev/null
+++ b/lib/libskey/pathnames.h
@@ -0,0 +1,6 @@
+/* $Id$ (FreeBSD) */
+
+#include <paths.h>
+
+#define _PATH_SKEYACCESS "/etc/skey.access"
+#define _PATH_SKEYFILE "/etc/skeykeys"
diff --git a/lib/libskey/put.c b/lib/libskey/put.c
new file mode 100644
index 0000000..5c9eaea
--- /dev/null
+++ b/lib/libskey/put.c
@@ -0,0 +1,2292 @@
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include "skey.h"
+
+static unsigned long extract __P((char *s,int start,int length));
+static void standard __P((char *word));
+static void insert __P((char *s, int x, int start, int length));
+static int wsrch __P((char *w,int low,int high));
+
+/* Dictionary for integer-word translations */
+static char Wp[2048][4] = {
+"A",
+"ABE",
+"ACE",
+"ACT",
+"AD",
+"ADA",
+"ADD",
+"AGO",
+"AID",
+"AIM",
+"AIR",
+"ALL",
+"ALP",
+"AM",
+"AMY",
+"AN",
+"ANA",
+"AND",
+"ANN",
+"ANT",
+"ANY",
+"APE",
+"APS",
+"APT",
+"ARC",
+"ARE",
+"ARK",
+"ARM",
+"ART",
+"AS",
+"ASH",
+"ASK",
+"AT",
+"ATE",
+"AUG",
+"AUK",
+"AVE",
+"AWE",
+"AWK",
+"AWL",
+"AWN",
+"AX",
+"AYE",
+"BAD",
+"BAG",
+"BAH",
+"BAM",
+"BAN",
+"BAR",
+"BAT",
+"BAY",
+"BE",
+"BED",
+"BEE",
+"BEG",
+"BEN",
+"BET",
+"BEY",
+"BIB",
+"BID",
+"BIG",
+"BIN",
+"BIT",
+"BOB",
+"BOG",
+"BON",
+"BOO",
+"BOP",
+"BOW",
+"BOY",
+"BUB",
+"BUD",
+"BUG",
+"BUM",
+"BUN",
+"BUS",
+"BUT",
+"BUY",
+"BY",
+"BYE",
+"CAB",
+"CAL",
+"CAM",
+"CAN",
+"CAP",
+"CAR",
+"CAT",
+"CAW",
+"COD",
+"COG",
+"COL",
+"CON",
+"COO",
+"COP",
+"COT",
+"COW",
+"COY",
+"CRY",
+"CUB",
+"CUE",
+"CUP",
+"CUR",
+"CUT",
+"DAB",
+"DAD",
+"DAM",
+"DAN",
+"DAR",
+"DAY",
+"DEE",
+"DEL",
+"DEN",
+"DES",
+"DEW",
+"DID",
+"DIE",
+"DIG",
+"DIN",
+"DIP",
+"DO",
+"DOE",
+"DOG",
+"DON",
+"DOT",
+"DOW",
+"DRY",
+"DUB",
+"DUD",
+"DUE",
+"DUG",
+"DUN",
+"EAR",
+"EAT",
+"ED",
+"EEL",
+"EGG",
+"EGO",
+"ELI",
+"ELK",
+"ELM",
+"ELY",
+"EM",
+"END",
+"EST",
+"ETC",
+"EVA",
+"EVE",
+"EWE",
+"EYE",
+"FAD",
+"FAN",
+"FAR",
+"FAT",
+"FAY",
+"FED",
+"FEE",
+"FEW",
+"FIB",
+"FIG",
+"FIN",
+"FIR",
+"FIT",
+"FLO",
+"FLY",
+"FOE",
+"FOG",
+"FOR",
+"FRY",
+"FUM",
+"FUN",
+"FUR",
+"GAB",
+"GAD",
+"GAG",
+"GAL",
+"GAM",
+"GAP",
+"GAS",
+"GAY",
+"GEE",
+"GEL",
+"GEM",
+"GET",
+"GIG",
+"GIL",
+"GIN",
+"GO",
+"GOT",
+"GUM",
+"GUN",
+"GUS",
+"GUT",
+"GUY",
+"GYM",
+"GYP",
+"HA",
+"HAD",
+"HAL",
+"HAM",
+"HAN",
+"HAP",
+"HAS",
+"HAT",
+"HAW",
+"HAY",
+"HE",
+"HEM",
+"HEN",
+"HER",
+"HEW",
+"HEY",
+"HI",
+"HID",
+"HIM",
+"HIP",
+"HIS",
+"HIT",
+"HO",
+"HOB",
+"HOC",
+"HOE",
+"HOG",
+"HOP",
+"HOT",
+"HOW",
+"HUB",
+"HUE",
+"HUG",
+"HUH",
+"HUM",
+"HUT",
+"I",
+"ICY",
+"IDA",
+"IF",
+"IKE",
+"ILL",
+"INK",
+"INN",
+"IO",
+"ION",
+"IQ",
+"IRA",
+"IRE",
+"IRK",
+"IS",
+"IT",
+"ITS",
+"IVY",
+"JAB",
+"JAG",
+"JAM",
+"JAN",
+"JAR",
+"JAW",
+"JAY",
+"JET",
+"JIG",
+"JIM",
+"JO",
+"JOB",
+"JOE",
+"JOG",
+"JOT",
+"JOY",
+"JUG",
+"JUT",
+"KAY",
+"KEG",
+"KEN",
+"KEY",
+"KID",
+"KIM",
+"KIN",
+"KIT",
+"LA",
+"LAB",
+"LAC",
+"LAD",
+"LAG",
+"LAM",
+"LAP",
+"LAW",
+"LAY",
+"LEA",
+"LED",
+"LEE",
+"LEG",
+"LEN",
+"LEO",
+"LET",
+"LEW",
+"LID",
+"LIE",
+"LIN",
+"LIP",
+"LIT",
+"LO",
+"LOB",
+"LOG",
+"LOP",
+"LOS",
+"LOT",
+"LOU",
+"LOW",
+"LOY",
+"LUG",
+"LYE",
+"MA",
+"MAC",
+"MAD",
+"MAE",
+"MAN",
+"MAO",
+"MAP",
+"MAT",
+"MAW",
+"MAY",
+"ME",
+"MEG",
+"MEL",
+"MEN",
+"MET",
+"MEW",
+"MID",
+"MIN",
+"MIT",
+"MOB",
+"MOD",
+"MOE",
+"MOO",
+"MOP",
+"MOS",
+"MOT",
+"MOW",
+"MUD",
+"MUG",
+"MUM",
+"MY",
+"NAB",
+"NAG",
+"NAN",
+"NAP",
+"NAT",
+"NAY",
+"NE",
+"NED",
+"NEE",
+"NET",
+"NEW",
+"NIB",
+"NIL",
+"NIP",
+"NIT",
+"NO",
+"NOB",
+"NOD",
+"NON",
+"NOR",
+"NOT",
+"NOV",
+"NOW",
+"NU",
+"NUN",
+"NUT",
+"O",
+"OAF",
+"OAK",
+"OAR",
+"OAT",
+"ODD",
+"ODE",
+"OF",
+"OFF",
+"OFT",
+"OH",
+"OIL",
+"OK",
+"OLD",
+"ON",
+"ONE",
+"OR",
+"ORB",
+"ORE",
+"ORR",
+"OS",
+"OTT",
+"OUR",
+"OUT",
+"OVA",
+"OW",
+"OWE",
+"OWL",
+"OWN",
+"OX",
+"PA",
+"PAD",
+"PAL",
+"PAM",
+"PAN",
+"PAP",
+"PAR",
+"PAT",
+"PAW",
+"PAY",
+"PEA",
+"PEG",
+"PEN",
+"PEP",
+"PER",
+"PET",
+"PEW",
+"PHI",
+"PI",
+"PIE",
+"PIN",
+"PIT",
+"PLY",
+"PO",
+"POD",
+"POE",
+"POP",
+"POT",
+"POW",
+"PRO",
+"PRY",
+"PUB",
+"PUG",
+"PUN",
+"PUP",
+"PUT",
+"QUO",
+"RAG",
+"RAM",
+"RAN",
+"RAP",
+"RAT",
+"RAW",
+"RAY",
+"REB",
+"RED",
+"REP",
+"RET",
+"RIB",
+"RID",
+"RIG",
+"RIM",
+"RIO",
+"RIP",
+"ROB",
+"ROD",
+"ROE",
+"RON",
+"ROT",
+"ROW",
+"ROY",
+"RUB",
+"RUE",
+"RUG",
+"RUM",
+"RUN",
+"RYE",
+"SAC",
+"SAD",
+"SAG",
+"SAL",
+"SAM",
+"SAN",
+"SAP",
+"SAT",
+"SAW",
+"SAY",
+"SEA",
+"SEC",
+"SEE",
+"SEN",
+"SET",
+"SEW",
+"SHE",
+"SHY",
+"SIN",
+"SIP",
+"SIR",
+"SIS",
+"SIT",
+"SKI",
+"SKY",
+"SLY",
+"SO",
+"SOB",
+"SOD",
+"SON",
+"SOP",
+"SOW",
+"SOY",
+"SPA",
+"SPY",
+"SUB",
+"SUD",
+"SUE",
+"SUM",
+"SUN",
+"SUP",
+"TAB",
+"TAD",
+"TAG",
+"TAN",
+"TAP",
+"TAR",
+"TEA",
+"TED",
+"TEE",
+"TEN",
+"THE",
+"THY",
+"TIC",
+"TIE",
+"TIM",
+"TIN",
+"TIP",
+"TO",
+"TOE",
+"TOG",
+"TOM",
+"TON",
+"TOO",
+"TOP",
+"TOW",
+"TOY",
+"TRY",
+"TUB",
+"TUG",
+"TUM",
+"TUN",
+"TWO",
+"UN",
+"UP",
+"US",
+"USE",
+"VAN",
+"VAT",
+"VET",
+"VIE",
+"WAD",
+"WAG",
+"WAR",
+"WAS",
+"WAY",
+"WE",
+"WEB",
+"WED",
+"WEE",
+"WET",
+"WHO",
+"WHY",
+"WIN",
+"WIT",
+"WOK",
+"WON",
+"WOO",
+"WOW",
+"WRY",
+"WU",
+"YAM",
+"YAP",
+"YAW",
+"YE",
+"YEA",
+"YES",
+"YET",
+"YOU",
+"ABED",
+"ABEL",
+"ABET",
+"ABLE",
+"ABUT",
+"ACHE",
+"ACID",
+"ACME",
+"ACRE",
+"ACTA",
+"ACTS",
+"ADAM",
+"ADDS",
+"ADEN",
+"AFAR",
+"AFRO",
+"AGEE",
+"AHEM",
+"AHOY",
+"AIDA",
+"AIDE",
+"AIDS",
+"AIRY",
+"AJAR",
+"AKIN",
+"ALAN",
+"ALEC",
+"ALGA",
+"ALIA",
+"ALLY",
+"ALMA",
+"ALOE",
+"ALSO",
+"ALTO",
+"ALUM",
+"ALVA",
+"AMEN",
+"AMES",
+"AMID",
+"AMMO",
+"AMOK",
+"AMOS",
+"AMRA",
+"ANDY",
+"ANEW",
+"ANNA",
+"ANNE",
+"ANTE",
+"ANTI",
+"AQUA",
+"ARAB",
+"ARCH",
+"AREA",
+"ARGO",
+"ARID",
+"ARMY",
+"ARTS",
+"ARTY",
+"ASIA",
+"ASKS",
+"ATOM",
+"AUNT",
+"AURA",
+"AUTO",
+"AVER",
+"AVID",
+"AVIS",
+"AVON",
+"AVOW",
+"AWAY",
+"AWRY",
+"BABE",
+"BABY",
+"BACH",
+"BACK",
+"BADE",
+"BAIL",
+"BAIT",
+"BAKE",
+"BALD",
+"BALE",
+"BALI",
+"BALK",
+"BALL",
+"BALM",
+"BAND",
+"BANE",
+"BANG",
+"BANK",
+"BARB",
+"BARD",
+"BARE",
+"BARK",
+"BARN",
+"BARR",
+"BASE",
+"BASH",
+"BASK",
+"BASS",
+"BATE",
+"BATH",
+"BAWD",
+"BAWL",
+"BEAD",
+"BEAK",
+"BEAM",
+"BEAN",
+"BEAR",
+"BEAT",
+"BEAU",
+"BECK",
+"BEEF",
+"BEEN",
+"BEER",
+"BEET",
+"BELA",
+"BELL",
+"BELT",
+"BEND",
+"BENT",
+"BERG",
+"BERN",
+"BERT",
+"BESS",
+"BEST",
+"BETA",
+"BETH",
+"BHOY",
+"BIAS",
+"BIDE",
+"BIEN",
+"BILE",
+"BILK",
+"BILL",
+"BIND",
+"BING",
+"BIRD",
+"BITE",
+"BITS",
+"BLAB",
+"BLAT",
+"BLED",
+"BLEW",
+"BLOB",
+"BLOC",
+"BLOT",
+"BLOW",
+"BLUE",
+"BLUM",
+"BLUR",
+"BOAR",
+"BOAT",
+"BOCA",
+"BOCK",
+"BODE",
+"BODY",
+"BOGY",
+"BOHR",
+"BOIL",
+"BOLD",
+"BOLO",
+"BOLT",
+"BOMB",
+"BONA",
+"BOND",
+"BONE",
+"BONG",
+"BONN",
+"BONY",
+"BOOK",
+"BOOM",
+"BOON",
+"BOOT",
+"BORE",
+"BORG",
+"BORN",
+"BOSE",
+"BOSS",
+"BOTH",
+"BOUT",
+"BOWL",
+"BOYD",
+"BRAD",
+"BRAE",
+"BRAG",
+"BRAN",
+"BRAY",
+"BRED",
+"BREW",
+"BRIG",
+"BRIM",
+"BROW",
+"BUCK",
+"BUDD",
+"BUFF",
+"BULB",
+"BULK",
+"BULL",
+"BUNK",
+"BUNT",
+"BUOY",
+"BURG",
+"BURL",
+"BURN",
+"BURR",
+"BURT",
+"BURY",
+"BUSH",
+"BUSS",
+"BUST",
+"BUSY",
+"BYTE",
+"CADY",
+"CAFE",
+"CAGE",
+"CAIN",
+"CAKE",
+"CALF",
+"CALL",
+"CALM",
+"CAME",
+"CANE",
+"CANT",
+"CARD",
+"CARE",
+"CARL",
+"CARR",
+"CART",
+"CASE",
+"CASH",
+"CASK",
+"CAST",
+"CAVE",
+"CEIL",
+"CELL",
+"CENT",
+"CERN",
+"CHAD",
+"CHAR",
+"CHAT",
+"CHAW",
+"CHEF",
+"CHEN",
+"CHEW",
+"CHIC",
+"CHIN",
+"CHOU",
+"CHOW",
+"CHUB",
+"CHUG",
+"CHUM",
+"CITE",
+"CITY",
+"CLAD",
+"CLAM",
+"CLAN",
+"CLAW",
+"CLAY",
+"CLOD",
+"CLOG",
+"CLOT",
+"CLUB",
+"CLUE",
+"COAL",
+"COAT",
+"COCA",
+"COCK",
+"COCO",
+"CODA",
+"CODE",
+"CODY",
+"COED",
+"COIL",
+"COIN",
+"COKE",
+"COLA",
+"COLD",
+"COLT",
+"COMA",
+"COMB",
+"COME",
+"COOK",
+"COOL",
+"COON",
+"COOT",
+"CORD",
+"CORE",
+"CORK",
+"CORN",
+"COST",
+"COVE",
+"COWL",
+"CRAB",
+"CRAG",
+"CRAM",
+"CRAY",
+"CREW",
+"CRIB",
+"CROW",
+"CRUD",
+"CUBA",
+"CUBE",
+"CUFF",
+"CULL",
+"CULT",
+"CUNY",
+"CURB",
+"CURD",
+"CURE",
+"CURL",
+"CURT",
+"CUTS",
+"DADE",
+"DALE",
+"DAME",
+"DANA",
+"DANE",
+"DANG",
+"DANK",
+"DARE",
+"DARK",
+"DARN",
+"DART",
+"DASH",
+"DATA",
+"DATE",
+"DAVE",
+"DAVY",
+"DAWN",
+"DAYS",
+"DEAD",
+"DEAF",
+"DEAL",
+"DEAN",
+"DEAR",
+"DEBT",
+"DECK",
+"DEED",
+"DEEM",
+"DEER",
+"DEFT",
+"DEFY",
+"DELL",
+"DENT",
+"DENY",
+"DESK",
+"DIAL",
+"DICE",
+"DIED",
+"DIET",
+"DIME",
+"DINE",
+"DING",
+"DINT",
+"DIRE",
+"DIRT",
+"DISC",
+"DISH",
+"DISK",
+"DIVE",
+"DOCK",
+"DOES",
+"DOLE",
+"DOLL",
+"DOLT",
+"DOME",
+"DONE",
+"DOOM",
+"DOOR",
+"DORA",
+"DOSE",
+"DOTE",
+"DOUG",
+"DOUR",
+"DOVE",
+"DOWN",
+"DRAB",
+"DRAG",
+"DRAM",
+"DRAW",
+"DREW",
+"DRUB",
+"DRUG",
+"DRUM",
+"DUAL",
+"DUCK",
+"DUCT",
+"DUEL",
+"DUET",
+"DUKE",
+"DULL",
+"DUMB",
+"DUNE",
+"DUNK",
+"DUSK",
+"DUST",
+"DUTY",
+"EACH",
+"EARL",
+"EARN",
+"EASE",
+"EAST",
+"EASY",
+"EBEN",
+"ECHO",
+"EDDY",
+"EDEN",
+"EDGE",
+"EDGY",
+"EDIT",
+"EDNA",
+"EGAN",
+"ELAN",
+"ELBA",
+"ELLA",
+"ELSE",
+"EMIL",
+"EMIT",
+"EMMA",
+"ENDS",
+"ERIC",
+"EROS",
+"EVEN",
+"EVER",
+"EVIL",
+"EYED",
+"FACE",
+"FACT",
+"FADE",
+"FAIL",
+"FAIN",
+"FAIR",
+"FAKE",
+"FALL",
+"FAME",
+"FANG",
+"FARM",
+"FAST",
+"FATE",
+"FAWN",
+"FEAR",
+"FEAT",
+"FEED",
+"FEEL",
+"FEET",
+"FELL",
+"FELT",
+"FEND",
+"FERN",
+"FEST",
+"FEUD",
+"FIEF",
+"FIGS",
+"FILE",
+"FILL",
+"FILM",
+"FIND",
+"FINE",
+"FINK",
+"FIRE",
+"FIRM",
+"FISH",
+"FISK",
+"FIST",
+"FITS",
+"FIVE",
+"FLAG",
+"FLAK",
+"FLAM",
+"FLAT",
+"FLAW",
+"FLEA",
+"FLED",
+"FLEW",
+"FLIT",
+"FLOC",
+"FLOG",
+"FLOW",
+"FLUB",
+"FLUE",
+"FOAL",
+"FOAM",
+"FOGY",
+"FOIL",
+"FOLD",
+"FOLK",
+"FOND",
+"FONT",
+"FOOD",
+"FOOL",
+"FOOT",
+"FORD",
+"FORE",
+"FORK",
+"FORM",
+"FORT",
+"FOSS",
+"FOUL",
+"FOUR",
+"FOWL",
+"FRAU",
+"FRAY",
+"FRED",
+"FREE",
+"FRET",
+"FREY",
+"FROG",
+"FROM",
+"FUEL",
+"FULL",
+"FUME",
+"FUND",
+"FUNK",
+"FURY",
+"FUSE",
+"FUSS",
+"GAFF",
+"GAGE",
+"GAIL",
+"GAIN",
+"GAIT",
+"GALA",
+"GALE",
+"GALL",
+"GALT",
+"GAME",
+"GANG",
+"GARB",
+"GARY",
+"GASH",
+"GATE",
+"GAUL",
+"GAUR",
+"GAVE",
+"GAWK",
+"GEAR",
+"GELD",
+"GENE",
+"GENT",
+"GERM",
+"GETS",
+"GIBE",
+"GIFT",
+"GILD",
+"GILL",
+"GILT",
+"GINA",
+"GIRD",
+"GIRL",
+"GIST",
+"GIVE",
+"GLAD",
+"GLEE",
+"GLEN",
+"GLIB",
+"GLOB",
+"GLOM",
+"GLOW",
+"GLUE",
+"GLUM",
+"GLUT",
+"GOAD",
+"GOAL",
+"GOAT",
+"GOER",
+"GOES",
+"GOLD",
+"GOLF",
+"GONE",
+"GONG",
+"GOOD",
+"GOOF",
+"GORE",
+"GORY",
+"GOSH",
+"GOUT",
+"GOWN",
+"GRAB",
+"GRAD",
+"GRAY",
+"GREG",
+"GREW",
+"GREY",
+"GRID",
+"GRIM",
+"GRIN",
+"GRIT",
+"GROW",
+"GRUB",
+"GULF",
+"GULL",
+"GUNK",
+"GURU",
+"GUSH",
+"GUST",
+"GWEN",
+"GWYN",
+"HAAG",
+"HAAS",
+"HACK",
+"HAIL",
+"HAIR",
+"HALE",
+"HALF",
+"HALL",
+"HALO",
+"HALT",
+"HAND",
+"HANG",
+"HANK",
+"HANS",
+"HARD",
+"HARK",
+"HARM",
+"HART",
+"HASH",
+"HAST",
+"HATE",
+"HATH",
+"HAUL",
+"HAVE",
+"HAWK",
+"HAYS",
+"HEAD",
+"HEAL",
+"HEAR",
+"HEAT",
+"HEBE",
+"HECK",
+"HEED",
+"HEEL",
+"HEFT",
+"HELD",
+"HELL",
+"HELM",
+"HERB",
+"HERD",
+"HERE",
+"HERO",
+"HERS",
+"HESS",
+"HEWN",
+"HICK",
+"HIDE",
+"HIGH",
+"HIKE",
+"HILL",
+"HILT",
+"HIND",
+"HINT",
+"HIRE",
+"HISS",
+"HIVE",
+"HOBO",
+"HOCK",
+"HOFF",
+"HOLD",
+"HOLE",
+"HOLM",
+"HOLT",
+"HOME",
+"HONE",
+"HONK",
+"HOOD",
+"HOOF",
+"HOOK",
+"HOOT",
+"HORN",
+"HOSE",
+"HOST",
+"HOUR",
+"HOVE",
+"HOWE",
+"HOWL",
+"HOYT",
+"HUCK",
+"HUED",
+"HUFF",
+"HUGE",
+"HUGH",
+"HUGO",
+"HULK",
+"HULL",
+"HUNK",
+"HUNT",
+"HURD",
+"HURL",
+"HURT",
+"HUSH",
+"HYDE",
+"HYMN",
+"IBIS",
+"ICON",
+"IDEA",
+"IDLE",
+"IFFY",
+"INCA",
+"INCH",
+"INTO",
+"IONS",
+"IOTA",
+"IOWA",
+"IRIS",
+"IRMA",
+"IRON",
+"ISLE",
+"ITCH",
+"ITEM",
+"IVAN",
+"JACK",
+"JADE",
+"JAIL",
+"JAKE",
+"JANE",
+"JAVA",
+"JEAN",
+"JEFF",
+"JERK",
+"JESS",
+"JEST",
+"JIBE",
+"JILL",
+"JILT",
+"JIVE",
+"JOAN",
+"JOBS",
+"JOCK",
+"JOEL",
+"JOEY",
+"JOHN",
+"JOIN",
+"JOKE",
+"JOLT",
+"JOVE",
+"JUDD",
+"JUDE",
+"JUDO",
+"JUDY",
+"JUJU",
+"JUKE",
+"JULY",
+"JUNE",
+"JUNK",
+"JUNO",
+"JURY",
+"JUST",
+"JUTE",
+"KAHN",
+"KALE",
+"KANE",
+"KANT",
+"KARL",
+"KATE",
+"KEEL",
+"KEEN",
+"KENO",
+"KENT",
+"KERN",
+"KERR",
+"KEYS",
+"KICK",
+"KILL",
+"KIND",
+"KING",
+"KIRK",
+"KISS",
+"KITE",
+"KLAN",
+"KNEE",
+"KNEW",
+"KNIT",
+"KNOB",
+"KNOT",
+"KNOW",
+"KOCH",
+"KONG",
+"KUDO",
+"KURD",
+"KURT",
+"KYLE",
+"LACE",
+"LACK",
+"LACY",
+"LADY",
+"LAID",
+"LAIN",
+"LAIR",
+"LAKE",
+"LAMB",
+"LAME",
+"LAND",
+"LANE",
+"LANG",
+"LARD",
+"LARK",
+"LASS",
+"LAST",
+"LATE",
+"LAUD",
+"LAVA",
+"LAWN",
+"LAWS",
+"LAYS",
+"LEAD",
+"LEAF",
+"LEAK",
+"LEAN",
+"LEAR",
+"LEEK",
+"LEER",
+"LEFT",
+"LEND",
+"LENS",
+"LENT",
+"LEON",
+"LESK",
+"LESS",
+"LEST",
+"LETS",
+"LIAR",
+"LICE",
+"LICK",
+"LIED",
+"LIEN",
+"LIES",
+"LIEU",
+"LIFE",
+"LIFT",
+"LIKE",
+"LILA",
+"LILT",
+"LILY",
+"LIMA",
+"LIMB",
+"LIME",
+"LIND",
+"LINE",
+"LINK",
+"LINT",
+"LION",
+"LISA",
+"LIST",
+"LIVE",
+"LOAD",
+"LOAF",
+"LOAM",
+"LOAN",
+"LOCK",
+"LOFT",
+"LOGE",
+"LOIS",
+"LOLA",
+"LONE",
+"LONG",
+"LOOK",
+"LOON",
+"LOOT",
+"LORD",
+"LORE",
+"LOSE",
+"LOSS",
+"LOST",
+"LOUD",
+"LOVE",
+"LOWE",
+"LUCK",
+"LUCY",
+"LUGE",
+"LUKE",
+"LULU",
+"LUND",
+"LUNG",
+"LURA",
+"LURE",
+"LURK",
+"LUSH",
+"LUST",
+"LYLE",
+"LYNN",
+"LYON",
+"LYRA",
+"MACE",
+"MADE",
+"MAGI",
+"MAID",
+"MAIL",
+"MAIN",
+"MAKE",
+"MALE",
+"MALI",
+"MALL",
+"MALT",
+"MANA",
+"MANN",
+"MANY",
+"MARC",
+"MARE",
+"MARK",
+"MARS",
+"MART",
+"MARY",
+"MASH",
+"MASK",
+"MASS",
+"MAST",
+"MATE",
+"MATH",
+"MAUL",
+"MAYO",
+"MEAD",
+"MEAL",
+"MEAN",
+"MEAT",
+"MEEK",
+"MEET",
+"MELD",
+"MELT",
+"MEMO",
+"MEND",
+"MENU",
+"MERT",
+"MESH",
+"MESS",
+"MICE",
+"MIKE",
+"MILD",
+"MILE",
+"MILK",
+"MILL",
+"MILT",
+"MIMI",
+"MIND",
+"MINE",
+"MINI",
+"MINK",
+"MINT",
+"MIRE",
+"MISS",
+"MIST",
+"MITE",
+"MITT",
+"MOAN",
+"MOAT",
+"MOCK",
+"MODE",
+"MOLD",
+"MOLE",
+"MOLL",
+"MOLT",
+"MONA",
+"MONK",
+"MONT",
+"MOOD",
+"MOON",
+"MOOR",
+"MOOT",
+"MORE",
+"MORN",
+"MORT",
+"MOSS",
+"MOST",
+"MOTH",
+"MOVE",
+"MUCH",
+"MUCK",
+"MUDD",
+"MUFF",
+"MULE",
+"MULL",
+"MURK",
+"MUSH",
+"MUST",
+"MUTE",
+"MUTT",
+"MYRA",
+"MYTH",
+"NAGY",
+"NAIL",
+"NAIR",
+"NAME",
+"NARY",
+"NASH",
+"NAVE",
+"NAVY",
+"NEAL",
+"NEAR",
+"NEAT",
+"NECK",
+"NEED",
+"NEIL",
+"NELL",
+"NEON",
+"NERO",
+"NESS",
+"NEST",
+"NEWS",
+"NEWT",
+"NIBS",
+"NICE",
+"NICK",
+"NILE",
+"NINA",
+"NINE",
+"NOAH",
+"NODE",
+"NOEL",
+"NOLL",
+"NONE",
+"NOOK",
+"NOON",
+"NORM",
+"NOSE",
+"NOTE",
+"NOUN",
+"NOVA",
+"NUDE",
+"NULL",
+"NUMB",
+"OATH",
+"OBEY",
+"OBOE",
+"ODIN",
+"OHIO",
+"OILY",
+"OINT",
+"OKAY",
+"OLAF",
+"OLDY",
+"OLGA",
+"OLIN",
+"OMAN",
+"OMEN",
+"OMIT",
+"ONCE",
+"ONES",
+"ONLY",
+"ONTO",
+"ONUS",
+"ORAL",
+"ORGY",
+"OSLO",
+"OTIS",
+"OTTO",
+"OUCH",
+"OUST",
+"OUTS",
+"OVAL",
+"OVEN",
+"OVER",
+"OWLY",
+"OWNS",
+"QUAD",
+"QUIT",
+"QUOD",
+"RACE",
+"RACK",
+"RACY",
+"RAFT",
+"RAGE",
+"RAID",
+"RAIL",
+"RAIN",
+"RAKE",
+"RANK",
+"RANT",
+"RARE",
+"RASH",
+"RATE",
+"RAVE",
+"RAYS",
+"READ",
+"REAL",
+"REAM",
+"REAR",
+"RECK",
+"REED",
+"REEF",
+"REEK",
+"REEL",
+"REID",
+"REIN",
+"RENA",
+"REND",
+"RENT",
+"REST",
+"RICE",
+"RICH",
+"RICK",
+"RIDE",
+"RIFT",
+"RILL",
+"RIME",
+"RING",
+"RINK",
+"RISE",
+"RISK",
+"RITE",
+"ROAD",
+"ROAM",
+"ROAR",
+"ROBE",
+"ROCK",
+"RODE",
+"ROIL",
+"ROLL",
+"ROME",
+"ROOD",
+"ROOF",
+"ROOK",
+"ROOM",
+"ROOT",
+"ROSA",
+"ROSE",
+"ROSS",
+"ROSY",
+"ROTH",
+"ROUT",
+"ROVE",
+"ROWE",
+"ROWS",
+"RUBE",
+"RUBY",
+"RUDE",
+"RUDY",
+"RUIN",
+"RULE",
+"RUNG",
+"RUNS",
+"RUNT",
+"RUSE",
+"RUSH",
+"RUSK",
+"RUSS",
+"RUST",
+"RUTH",
+"SACK",
+"SAFE",
+"SAGE",
+"SAID",
+"SAIL",
+"SALE",
+"SALK",
+"SALT",
+"SAME",
+"SAND",
+"SANE",
+"SANG",
+"SANK",
+"SARA",
+"SAUL",
+"SAVE",
+"SAYS",
+"SCAN",
+"SCAR",
+"SCAT",
+"SCOT",
+"SEAL",
+"SEAM",
+"SEAR",
+"SEAT",
+"SEED",
+"SEEK",
+"SEEM",
+"SEEN",
+"SEES",
+"SELF",
+"SELL",
+"SEND",
+"SENT",
+"SETS",
+"SEWN",
+"SHAG",
+"SHAM",
+"SHAW",
+"SHAY",
+"SHED",
+"SHIM",
+"SHIN",
+"SHOD",
+"SHOE",
+"SHOT",
+"SHOW",
+"SHUN",
+"SHUT",
+"SICK",
+"SIDE",
+"SIFT",
+"SIGH",
+"SIGN",
+"SILK",
+"SILL",
+"SILO",
+"SILT",
+"SINE",
+"SING",
+"SINK",
+"SIRE",
+"SITE",
+"SITS",
+"SITU",
+"SKAT",
+"SKEW",
+"SKID",
+"SKIM",
+"SKIN",
+"SKIT",
+"SLAB",
+"SLAM",
+"SLAT",
+"SLAY",
+"SLED",
+"SLEW",
+"SLID",
+"SLIM",
+"SLIT",
+"SLOB",
+"SLOG",
+"SLOT",
+"SLOW",
+"SLUG",
+"SLUM",
+"SLUR",
+"SMOG",
+"SMUG",
+"SNAG",
+"SNOB",
+"SNOW",
+"SNUB",
+"SNUG",
+"SOAK",
+"SOAR",
+"SOCK",
+"SODA",
+"SOFA",
+"SOFT",
+"SOIL",
+"SOLD",
+"SOME",
+"SONG",
+"SOON",
+"SOOT",
+"SORE",
+"SORT",
+"SOUL",
+"SOUR",
+"SOWN",
+"STAB",
+"STAG",
+"STAN",
+"STAR",
+"STAY",
+"STEM",
+"STEW",
+"STIR",
+"STOW",
+"STUB",
+"STUN",
+"SUCH",
+"SUDS",
+"SUIT",
+"SULK",
+"SUMS",
+"SUNG",
+"SUNK",
+"SURE",
+"SURF",
+"SWAB",
+"SWAG",
+"SWAM",
+"SWAN",
+"SWAT",
+"SWAY",
+"SWIM",
+"SWUM",
+"TACK",
+"TACT",
+"TAIL",
+"TAKE",
+"TALE",
+"TALK",
+"TALL",
+"TANK",
+"TASK",
+"TATE",
+"TAUT",
+"TEAL",
+"TEAM",
+"TEAR",
+"TECH",
+"TEEM",
+"TEEN",
+"TEET",
+"TELL",
+"TEND",
+"TENT",
+"TERM",
+"TERN",
+"TESS",
+"TEST",
+"THAN",
+"THAT",
+"THEE",
+"THEM",
+"THEN",
+"THEY",
+"THIN",
+"THIS",
+"THUD",
+"THUG",
+"TICK",
+"TIDE",
+"TIDY",
+"TIED",
+"TIER",
+"TILE",
+"TILL",
+"TILT",
+"TIME",
+"TINA",
+"TINE",
+"TINT",
+"TINY",
+"TIRE",
+"TOAD",
+"TOGO",
+"TOIL",
+"TOLD",
+"TOLL",
+"TONE",
+"TONG",
+"TONY",
+"TOOK",
+"TOOL",
+"TOOT",
+"TORE",
+"TORN",
+"TOTE",
+"TOUR",
+"TOUT",
+"TOWN",
+"TRAG",
+"TRAM",
+"TRAY",
+"TREE",
+"TREK",
+"TRIG",
+"TRIM",
+"TRIO",
+"TROD",
+"TROT",
+"TROY",
+"TRUE",
+"TUBA",
+"TUBE",
+"TUCK",
+"TUFT",
+"TUNA",
+"TUNE",
+"TUNG",
+"TURF",
+"TURN",
+"TUSK",
+"TWIG",
+"TWIN",
+"TWIT",
+"ULAN",
+"UNIT",
+"URGE",
+"USED",
+"USER",
+"USES",
+"UTAH",
+"VAIL",
+"VAIN",
+"VALE",
+"VARY",
+"VASE",
+"VAST",
+"VEAL",
+"VEDA",
+"VEIL",
+"VEIN",
+"VEND",
+"VENT",
+"VERB",
+"VERY",
+"VETO",
+"VICE",
+"VIEW",
+"VINE",
+"VISE",
+"VOID",
+"VOLT",
+"VOTE",
+"WACK",
+"WADE",
+"WAGE",
+"WAIL",
+"WAIT",
+"WAKE",
+"WALE",
+"WALK",
+"WALL",
+"WALT",
+"WAND",
+"WANE",
+"WANG",
+"WANT",
+"WARD",
+"WARM",
+"WARN",
+"WART",
+"WASH",
+"WAST",
+"WATS",
+"WATT",
+"WAVE",
+"WAVY",
+"WAYS",
+"WEAK",
+"WEAL",
+"WEAN",
+"WEAR",
+"WEED",
+"WEEK",
+"WEIR",
+"WELD",
+"WELL",
+"WELT",
+"WENT",
+"WERE",
+"WERT",
+"WEST",
+"WHAM",
+"WHAT",
+"WHEE",
+"WHEN",
+"WHET",
+"WHOA",
+"WHOM",
+"WICK",
+"WIFE",
+"WILD",
+"WILL",
+"WIND",
+"WINE",
+"WING",
+"WINK",
+"WINO",
+"WIRE",
+"WISE",
+"WISH",
+"WITH",
+"WOLF",
+"WONT",
+"WOOD",
+"WOOL",
+"WORD",
+"WORE",
+"WORK",
+"WORM",
+"WORN",
+"WOVE",
+"WRIT",
+"WYNN",
+"YALE",
+"YANG",
+"YANK",
+"YARD",
+"YARN",
+"YAWL",
+"YAWN",
+"YEAH",
+"YEAR",
+"YELL",
+"YOGA",
+"YOKE"
+};
+
+/* Encode 8 bytes in 'c' as a string of English words.
+ * Returns a pointer to a static buffer
+ */
+char *
+btoe(engout,c)
+char *c, *engout;
+{
+ char cp[9]; /* add in room for the parity 2 bits*/
+ int p,i ;
+
+ engout[0] = '\0';
+ memcpy(cp, c,8);
+ /* compute parity */
+ for(p = 0,i = 0; i < 64;i += 2)
+ p += extract(cp,i,2);
+
+ cp[8] = (char)p << 6;
+ strncat(engout,&Wp[extract(cp, 0,11)][0],4);
+ strcat(engout," ");
+ strncat(engout,&Wp[extract(cp,11,11)][0],4);
+ strcat(engout," ");
+ strncat(engout,&Wp[extract(cp,22,11)][0],4);
+ strcat(engout," ");
+ strncat(engout,&Wp[extract(cp,33,11)][0],4);
+ strcat(engout," ");
+ strncat(engout,&Wp[extract(cp,44,11)][0],4);
+ strcat(engout," ");
+ strncat(engout,&Wp[extract(cp,55,11)][0],4);
+#ifdef notdef
+ printf("engout is %s\n\r",engout);
+#endif
+ return(engout);
+}
+
+/* convert English to binary
+ * returns 1 OK - all good words and parity is OK
+ * 0 word not in data base
+ * -1 badly formed in put ie > 4 char word
+ * -2 words OK but parity is wrong
+ */
+int
+etob(out, e)
+char *out;
+char *e;
+{
+ char *word, *cp;
+ int i, p, v,l, low,high;
+ char b[9];
+ char input[36];
+
+ if(e == NULL)
+ return -1;
+
+ strncpy(input,e,sizeof(input));
+ cp = input;
+ memset(b, 0, sizeof(b));
+ memset(out, 0, 8);
+ for(i=0,p=0;i<6;i++,p+=11){
+ while ((word = strsep(&cp, " ")) != NULL && *word == '\0')
+ ;
+ if (word == NULL)
+ return -1;
+ l = strlen(word);
+ if(l > 4 || l < 1){
+ return -1;
+ } else if(l < 4){
+ low = 0;
+ high = 570;
+ } else {
+ low = 571;
+ high = 2047;
+ }
+ standard(word);
+ if( (v = wsrch(word,low,high)) < 0 )
+ return 0;
+ insert(b,v,p,11);
+ }
+
+ /* now check the parity of what we got */
+ for(p = 0, i = 0; i < 64; i +=2)
+ p += extract(b, i, 2);
+
+ if( (p & 3) != extract(b, 64,2) )
+ return -2;
+
+ memcpy(out,b,8);
+
+ return 1;
+}
+/* Display 8 bytes as a series of 16-bit hex digits */
+char *
+put8(out,s)
+char *out;
+char *s;
+{
+ sprintf(out,"%02X%02X %02X%02X %02X%02X %02X%02X",
+ s[0] & 0xff,s[1] & 0xff,s[2] & 0xff,
+ s[3] & 0xff,s[4] & 0xff,s[5] & 0xff,
+ s[6] & 0xff,s[7] & 0xff);
+ return out;
+}
+#ifdef notdef
+/* Encode 8 bytes in 'cp' as stream of ascii letters.
+ * Provided as a possible alternative to btoe()
+ */
+char *
+btoc(cp)
+char *cp;
+{
+ int i;
+ static char out[31];
+
+ /* code out put by characters 6 bits each added to 0x21 (!)*/
+ for(i=0;i <= 10;i++){
+ /* last one is only 4 bits not 6*/
+ out[i] = '!'+ extract(cp,6*i,i >= 10 ? 4:6);
+ }
+ out[i] = '\0';
+ return(out);
+}
+#endif
+
+/* Internal subroutines for word encoding/decoding */
+
+/* Dictionary binary search */
+static int
+wsrch(w,low,high)
+char *w;
+int low, high;
+{
+ int i,j;
+
+ for(;;){
+ i = (low + high)/2;
+ if((j = strncmp(w,Wp[i],4)) == 0)
+ return i; /* Found it */
+ if(high == low+1){
+ /* Avoid effects of integer truncation in /2 */
+ if(strncmp(w,Wp[high],4) == 0)
+ return high;
+ else
+ return -1;
+ }
+ if(low >= high)
+ return -1; /* I don't *think* this can happen...*/
+ if(j < 0)
+ high = i; /* Search lower half */
+ else
+ low = i; /* Search upper half */
+ }
+}
+static void
+insert(s, x, start, length)
+char *s;
+int x;
+int start, length;
+{
+ unsigned char cl;
+ unsigned char cc;
+ unsigned char cr;
+ unsigned long y;
+ int shift;
+
+ assert(length <= 11);
+ assert(start >= 0);
+ assert(length >= 0);
+ assert(start +length <= 66);
+
+ shift = ((8 -(( start + length) % 8))%8);
+ y = (long) x << shift;
+ cl = (y >> 16) & 0xff;
+ cc = (y >> 8) & 0xff;
+ cr = y & 0xff;
+ if(shift + length > 16){
+ s[start /8] |= cl;
+ s[start/8 +1] |= cc;
+ s[start/8 +2] |= cr;
+ } else if(shift +length > 8){
+ s[start/8] |= cc;
+ s[start/8 + 1] |= cr;
+ } else {
+ s[start/8] |= cr;
+ }
+}
+
+static void
+standard(word)
+register char *word;
+{
+ while(*word){
+ if(!isascii(*word))
+ break;
+ if(islower(*word))
+ *word = toupper(*word);
+ if(*word == '1')
+ *word = 'L';
+ if(*word == '0')
+ *word = 'O';
+ if(*word == '5')
+ *word = 'S';
+ word++;
+ }
+}
+
+/* Extract 'length' bits from the char array 's' starting with bit 'start' */
+static unsigned long
+extract(s, start, length)
+char *s;
+int start, length;
+{
+ unsigned char cl;
+ unsigned char cc;
+ unsigned char cr;
+ unsigned long x;
+
+ assert(length <= 11);
+ assert(start >= 0);
+ assert(length >= 0);
+ assert(start +length <= 66);
+
+ cl = s[start/8];
+ cc = s[start/8 +1];
+ cr = s[start/8 +2];
+ x = ((long)(cl<<8 | cc) <<8 | cr) ;
+ x = x >> (24 - (length + (start %8)));
+ x =( x & (0xffff >> (16-length) ) );
+ return(x);
+}
+
diff --git a/lib/libskey/skey.1 b/lib/libskey/skey.1
new file mode 100644
index 0000000..b4e0455
--- /dev/null
+++ b/lib/libskey/skey.1
@@ -0,0 +1,59 @@
+.ll 6i
+.pl 10.5i
+.\" @(#)skey.1 1.1 10/28/93
+.\"
+.lt 6.0i
+.TH KEY 1 "28 October 1993"
+.AT 3
+.SH NAME
+S/key \- A procedure to use one time passwords for accessing computer systems.
+.SH DESCRIPTION
+.I S/key
+is a procedure for using one time password to authenticate access to
+computer systems. It uses 64 bits of information transformed by the
+MD4 algorithm. The user supplies the 64 bits in the form of 6 English
+words that are generated by a secure computer.
+Example use of the S/key program
+.I key
+.sp
+ Usage example:
+.sp 0
+ >key 99 th91334
+.sp 0
+ Enter password: <your secret password is entered here>
+.sp 0
+ OMEN US HORN OMIT BACK AHOY
+.sp 0
+ >
+.sp
+The programs that are part of the S/Key system are keyinit, key, and
+keyinfo. Keyinit is used to get your ID set up, key is
+used to get the one time password each time,
+keyinfo is used to extract information from the S/Key database.
+.sp
+When you run "keyinit" you inform the system of your
+secret password. Running "key" then generates the
+one-time passwords, and also requires your secret
+password. If however, you misspell your password
+while running "key", you will get a list of passwords
+that will not work, and no indication about the problem.
+.sp
+Password sequence numbers count backward from 99. If you
+don't know this, the syntax for "key" will be confusing.
+.sp
+You can enter the passwords using small letters, even
+though the "key" program gives them in caps.
+.sp
+Macintosh and a general purpose PC use
+are available.
+.sp
+Under FreeBSD, you can control, with /etc/skey.access, from which
+hosts and/or networks the use of S/Key passwords is obligated.
+.LP
+.SH SEE ALSO
+.BR keyinit(1),
+.BR key(1),
+.BR keyinfo(1)
+.BR skey.access(5)
+.SH AUTHOR
+Phil Karn, Neil M. Haller, John S. Walden, Scott Chasin
diff --git a/lib/libskey/skey.3 b/lib/libskey/skey.3
new file mode 100644
index 0000000..1b368d3
--- /dev/null
+++ b/lib/libskey/skey.3
@@ -0,0 +1,157 @@
+.\" Copyright (c) 1996
+.\" David L. Nugent. All Rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (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: skey.3,v 1.5 1997/02/22 15:07:58 peter Exp $
+.\"
+.Dd December 22, 1996
+.Dt SKEY 3
+.Os
+.Sh NAME
+.Nm skeylookup ,
+.Nm skeyverify ,
+.Nm skeychallenge ,
+.Nm skeyinfo ,
+.Nm skeyaccess ,
+.Nm skey_getpass ,
+.Nm skey_crypt
+.Nd Library routines for S/Key password control table access
+.Sh SYNOPSIS
+.Fd #include <stdio.h>
+.Fd #include <skey.h>
+.Ft int
+.Fn skeylookup "struct skey *mp" "const char *name"
+.Ft int
+.Fn skeyverify "struct skey *mp" "char *response"
+.Ft int
+.Fn skeychallenge "struct skey *mp" "const char *name" "char *challenge"
+.Ft int
+.Fn skeyinfo "struct skey *mp" "const char *name" "char *ss"
+.Ft int
+.Fn skeyaccess "char *user" "const char *port" "const char *host" "const char *addr"
+.Ft char *
+.Fn skey_getpass "const char *prompt" "struct passwd *pwd" "int pwok"
+.Ft char *
+.Fn skey_crypt "char *pp" "char *salt" "struct passwd *pwd" "int pwok"
+.Sh DESCRIPTION
+These routes support the S/Key one time password system used for
+accessing computer systems.
+See
+.Xr skey 1
+for more information about the S/Key system itself.
+.Pp
+.Pp
+.Fn skeylookup
+finds an entry in the one-time password database.
+On success (an entry is found corresponding to the given name),
+they skey structure passed by the caller is filled and 0 is
+returned, with the file read/write pointer positioned at the
+beginning of the record found.
+If no entry is found corresponding to the given name, the file
+read/write pointer is positioned at end of file and the routine
+returns 1.
+If the database cannot be opened or an access error occurs,
+.Fn skeylookup
+returns -1.
+.Pp
+The
+.Fn skeyinfo
+function looks up skey info for user 'name'.
+If successful, the caller's skey structure is filled and
+.Fn skeyinfo
+returns 0.
+If an optional challenge string buffer is given, it is updated.
+If unsuccessful (e.g. if the name is unknown, or the database
+cannot be accessed) -1 is returned.
+.Pp
+.Fn skeychallenge
+returns an skey challenge string for 'name'.
+If successful, the caller's skey structure is filled, and
+the function returns 0, with the file read/write pointer
+left at the start of the record.
+If unsuccessful (ie. the name was not found), the function
+returns -1 and the database is closed.
+.Pp
+.Fn skeyverify
+verifies a response to an s/key challenge.
+If this function returns 0, the verify was successful and
+the database was updated.
+If 1 is returned, the verify failed and the database remains
+unchanged.
+If -1 is returned, some sort of error occurred with the database,
+and the database is left unchanged.
+The s/key database is always closed by this call.
+.Pp
+The
+.Fn skey_getpass
+function may be used to read regular or s/key passwords.
+The prompt to use is passed to the function, along with the
+full (secure) struct passwd for the user to be verified.
+.Fn skey_getpass
+uses the standard library getpass on the first attempt at
+retrieving the user's password, and if that is blank, turns
+echo back on and retrieves the S/Key password.
+In either case, the entered string is returned back to the
+caller.
+.Pp
+The
+.Fn skey_crypt
+is a wrapper function for the standard library
+.Xr crypt 3 ,
+which returns the encrypted UNIX password if either the given
+s/key or regular passwords are ok.
+.Fn skey_crypt
+first attempts verification of the given password via the skey
+method, and will return the encrypted password from the
+passwd structure if it can be verified, as though the user had
+actually entered the correct UNIX password.
+If s/key password verification does not work, then the password
+is encrypted in the usual way and the result passed back to the
+caller.
+If the passwd structure pointer is NULL,
+.Fn skey_crypt
+returns a non-NULL string which could not possibly be a valid
+UNIX password (namely, a string containing ":").
+.Pp
+The
+.Fn skeyaccess
+function determines whether s/key passwords are permitted for any
+combination of user name, group member, terminal port, host name or
+network.
+See
+.Xr skey.access 5
+for more information on the layout and structure of the
+skey.access configuration file which this function uses.
+.Sh RETURN VALUES
+See above.
+.Sh SEE ALSO
+.Xr skey 1 ,
+.Xr skey.access 5
+.Sh BUGS
+No advisory locking is done on the s/key database to guard against
+simultaneous access from multiple processes.
+This is not normally a problem when keys are added to or updated
+in the file, but may be problematic when keys are removed.
+.Sh AUTHOR
+Phil Karn, Neil M. Haller, John S. Walden, Scott Chasin
+
diff --git a/lib/libskey/skey.access.5 b/lib/libskey/skey.access.5
new file mode 100644
index 0000000..2e12ad1
--- /dev/null
+++ b/lib/libskey/skey.access.5
@@ -0,0 +1,125 @@
+.TH SKEY.ACCESS 5
+.SH NAME
+skey.access \- S/Key password control table
+.SH DESCRIPTION
+The S/Key password control table (\fI/etc/skey.access\fR) is used by
+\fIlogin\fR-like programs to determine when UNIX passwords may be used
+to access the system.
+.IP \(bu
+When the table does not exist, there are no password restrictions. The
+user may enter the UNIX password or the S/Key one.
+.IP \(bu
+When the table does exist, UNIX passwords are permitted only when
+explicitly specified.
+.IP \(bu
+For the sake of sanity, UNIX passwords are always permitted on the
+systems console.
+.SH "TABLE FORMAT"
+The format of the table is one rule per line. Rules are matched in
+order. The search terminates when the first matching rule is found, or
+when the end of the table is reached.
+.PP
+Rules have the form:
+.sp
+.in +5
+permit condition condition...
+.br
+deny condition condition...
+.in
+.PP
+where
+.I permit
+and
+.I deny
+may be followed by zero or more conditions. Comments begin with a `#\'
+character, and extend through the end of the line. Empty lines or
+lines with only comments are ignored.
+.PP
+A rule is matched when all conditions are satisfied. A rule without
+conditions is always satisfied. For example, the last entry could
+be a line with just the word
+.I deny
+on it.
+.SH CONDITIONS
+.IP "hostname wzv.win.tue.nl"
+True when the login comes from host wzv.win.tue.nl.
+See the WARNINGS section below.
+.IP "internet 131.155.210.0 255.255.255.0"
+True when the remote host has an internet address in network
+131.155.210. The general form of a net/mask rule is:
+.sp
+.ti +5
+internet net mask
+.sp
+The expression is true when the host has an internet address for which
+the bitwise and of
+.I address
+and
+.I mask
+equals
+.IR net.
+See the WARNINGS section below.
+.IP "port ttya"
+True when the login terminal is equal to
+.IR /dev/ttya .
+Remember that UNIX passwords are always permitted with logins on the
+system console.
+.IP "user uucp"
+True when the user attempts to log in as
+.IR uucp .
+.IP "group wheel"
+True when the user attempts to log in as a member of the
+.I wheel
+group.
+.SH COMPATIBILITY
+For the sake of backwards compatibility, the
+.I internet
+keyword may be omitted from net/mask patterns.
+.SH WARNINGS
+Several rule types depend on host name or address information obtained
+through the network. What follows is a list of conceivable attacks to
+force the system to permit UNIX passwords.
+.IP "Host address spoofing (source routing)"
+An intruder configures a local interface to an address in a trusted
+network and connects to the victim using that source address. Given
+the wrong client address, the victim draws the wrong conclusion from
+rules based on host addresses or from rules based on host names derived
+from addresses.
+.sp
+Remedies: (1) do not permit UNIX passwords with network logins; (2)
+use network software that discards source routing information (e.g.
+a tcp wrapper).
+.PP
+Almost every network server must look up the client host name using the
+client network address. The next obvious attack therefore is:
+.IP "Host name spoofing (bad PTR record)"
+An intruder manipulates the name server system so that the client
+network address resolves to the name of a trusted host. Given the
+wrong host name, the victim draws the wrong conclusion from rules based
+on host names, or from rules based on addresses derived from host
+names.
+.sp
+Remedies: (1) do not permit UNIX passwords with network logins; (2) use
+network software that verifies that the hostname resolves to the client
+network address (e.g. a tcp wrapper).
+.PP
+Some applications, such as the UNIX login program, must look up the
+client network address using the client host name. In addition to the
+previous two attacks, this opens up yet another possibility:
+.IP "Host address spoofing (extra A record)"
+An intruder manipulates the name server system so that the client host
+name (also) resolves to a trusted address.
+.sp
+Remedies: (1) do not permit UNIX passwords with network logins; (2)
+the skeyaccess() routines ignore network addresses that appear to
+belong to someone else.
+.SH DIAGNOSTICS
+Syntax errors are reported to the syslogd. When an error is found
+the rule is skipped.
+.SH FILES
+/etc/skey.access, password control table
+.SH AUTHOR
+.nf
+Wietse Venema
+Eindhoven University of Technology
+The Netherlands
diff --git a/lib/libskey/skey.h b/lib/libskey/skey.h
new file mode 100644
index 0000000..10cbebc
--- /dev/null
+++ b/lib/libskey/skey.h
@@ -0,0 +1,60 @@
+#ifndef _SKEY_H_
+#define _SKEY_H_
+
+#include <sys/cdefs.h>
+
+/* Server-side data structure for reading keys file during login */
+struct skey {
+ FILE *keyfile;
+ char buf[256];
+ char *logname;
+ int n;
+ char *seed;
+ char *val;
+ long recstart; /*needed so reread of buffer is efficient*/
+};
+
+#ifdef _SKEY_INTERNAL
+/* Client-side structure for scanning data stream for challenge */
+struct mc {
+ char buf[256];
+ int skip;
+ int cnt;
+};
+
+#define atob8 _sk_atob8
+#define btoa8 _sk_btoa8
+#define btoe _sk_btoe
+#define etob _sk_etob
+#define f _sk_f
+#define htoi _sk_htoi
+#define keycrunch _sk_keycrunch
+#define put8 _sk_put8
+#define readpass _sk_readpass
+#define rip _sk_rip
+#define sevenbit _sk_sevenbit
+
+void f __P((char *x));
+int keycrunch __P((char *result,char *seed,char *passwd));
+char *btoe __P((char *engout,char *c));
+char *put8 __P((char *out,char *s));
+int atob8 __P((char *out, char *in));
+int btoa8 __P((char *out, char *in));
+int htoi __P((char c));
+int etob __P((char *out,char *e));
+void sevenbit __P((char *s));
+char *readpass __P((char *buf, int n));
+void rip __P((char *buf));
+#endif /* _SKEY_INTERNAL */
+
+/* Simplified application programming interface. */
+#include <pwd.h>
+int skeylookup __P((struct skey *mp, const char *name));
+int skeyverify __P((struct skey *mp, char *response));
+int skeychallenge __P((struct skey *mp, const char *name, char *challenge));
+int skeyinfo __P((struct skey *mp, const char* name, char *ss));
+int skeyaccess __P((char *user, const char *port, const char *host, const char *addr));
+char *skey_getpass __P((const char *prompt, struct passwd * pwd, int pwok));
+char *skey_crypt __P((char *pp, char *salt, struct passwd *pwd, int pwok));
+
+#endif /* _SKEY_H_ */
diff --git a/lib/libskey/skey_crypt.c b/lib/libskey/skey_crypt.c
new file mode 100644
index 0000000..6ed6bdb
--- /dev/null
+++ b/lib/libskey/skey_crypt.c
@@ -0,0 +1,38 @@
+/* Author: Wietse Venema, Eindhoven University of Technology. */
+
+#include <string.h>
+#include <stdio.h>
+#include <pwd.h>
+
+#include "skey.h"
+
+/* skey_crypt - return encrypted UNIX passwd if s/key or regular password ok */
+
+char *skey_crypt(pp, salt, pwd, pwok)
+char *pp;
+char *salt;
+struct passwd *pwd;
+int pwok;
+{
+ struct skey skey;
+ char *p;
+ char *crypt();
+
+ /* Try s/key authentication even when the UNIX password is permitted. */
+
+ if (pwd != 0 && skeyinfo(&skey, pwd->pw_name, (char *) 0) == 0
+ && skeyverify(&skey, pp) == 0) {
+ /* s/key authentication succeeded */
+ return (pwd->pw_passwd);
+ }
+
+ /* When s/key authentication does not work, always invoke crypt(). */
+
+ p = crypt(pp, salt);
+ if (pwok && pwd != 0 && strcmp(p, pwd->pw_passwd) == 0)
+ return (pwd->pw_passwd);
+
+ /* The user does not exist or entered bad input. */
+
+ return (":");
+}
diff --git a/lib/libskey/skey_getpass.c b/lib/libskey/skey_getpass.c
new file mode 100644
index 0000000..c3f5432
--- /dev/null
+++ b/lib/libskey/skey_getpass.c
@@ -0,0 +1,37 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <skey.h>
+
+/* skey_getpass - read regular or s/key password */
+
+char *skey_getpass(prompt, pwd, pwok)
+const char *prompt;
+struct passwd *pwd;
+int pwok;
+{
+ static char buf[128];
+ struct skey skey;
+ char *pass;
+ int sflag;
+
+ /* Attempt an s/key challenge. */
+ sflag = (pwd == NULL || skeyinfo(&skey, pwd->pw_name, buf));
+ if (!sflag) {
+ printf("%s\n", buf);
+ if (!pwok)
+ printf("(s/key required)\n");
+ }
+
+ pass = getpass(prompt);
+
+ /* Give S/Key users a chance to do it with echo on. */
+ if (!sflag && !feof(stdin) && *pass == '\0') {
+ fputs(" (turning echo on)\n", stdout);
+ fputs(prompt, stdout);
+ fflush(stdout);
+ fgets(buf, sizeof(buf), stdin);
+ rip(buf);
+ return (buf);
+ } else
+ return (pass);
+}
diff --git a/lib/libskey/skeyaccess.c b/lib/libskey/skeyaccess.c
new file mode 100644
index 0000000..0d52caf
--- /dev/null
+++ b/lib/libskey/skeyaccess.c
@@ -0,0 +1,485 @@
+ /*
+ * Figure out if UNIX passwords are permitted for any combination of user
+ * name, group member, terminal port, host_name or network:
+ *
+ * Programmatic interface: skeyaccess(user, port, host, addr)
+ *
+ * All arguments are null-terminated strings. Specify a null character pointer
+ * where information is not available.
+ *
+ * When no address information is given this code performs the host (internet)
+ * address lookup itself. It rejects addresses that appear to belong to
+ * someone else.
+ *
+ * When compiled with -DPERMIT_CONSOLE always permits UNIX passwords with
+ * console logins, no matter what the configuration file says.
+ *
+ * To build a stand-alone test version, compile with -DTEST and run it off an
+ * skey.access file in the current directory:
+ *
+ * Command-line interface: ./skeyaccess user port [host_or_ip_addr]
+ *
+ * Errors are reported via syslogd.
+ *
+ * Author: Wietse Venema, Eindhoven University of Technology.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <grp.h>
+#include <ctype.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+
+#include "pathnames.h"
+
+ /*
+ * Token input with one-deep pushback.
+ */
+static char *prev_token = 0; /* push-back buffer */
+static char *line_pointer = NULL;
+static char *first_token();
+static int line_number;
+static void unget_token();
+static char *get_token();
+static char *need_token();
+static char *need_internet_addr();
+
+ /*
+ * Various forms of token matching.
+ */
+#define match_host_name(l) match_token((l)->host_name)
+#define match_port(l) match_token((l)->port)
+#define match_user(l) match_token((l)->user)
+static int match_internet_addr();
+static int match_group();
+static int match_token();
+static int is_internet_addr();
+static struct in_addr *convert_internet_addr();
+static struct in_addr *lookup_internet_addr();
+
+#define MAX_ADDR 32
+#define PERMIT 1
+#define DENY 0
+
+#ifndef CONSOLE
+#define CONSOLE "console"
+#endif
+#ifndef VTY_PREFIX
+#define VTY_PREFIX "ttyv"
+#endif
+
+struct login_info {
+ char *host_name; /* host name */
+ struct in_addr *internet_addr; /* null terminated list */
+ char *user; /* user name */
+ char *port; /* login port */
+};
+
+static int _skeyaccess __P(( FILE *, struct login_info * ));
+
+/* skeyaccess - find out if UNIX passwords are permitted */
+
+int skeyaccess(user, port, host, addr)
+char *user;
+char *port;
+char *host;
+char *addr;
+{
+ FILE *fp;
+ struct login_info login_info;
+ int result;
+
+ /*
+ * Assume no restriction on the use of UNIX passwords when the s/key
+ * acces table does not exist.
+ */
+ if ((fp = fopen(_PATH_SKEYACCESS, "r")) == 0) {
+#ifdef TEST
+ fprintf(stderr, "No file %s, thus no access control\n", _PATH_SKEYACCESS);
+#endif
+ return (PERMIT);
+ }
+
+ /*
+ * Bundle up the arguments in a structure so we won't have to drag around
+ * boring long argument lists.
+ *
+ * Look up the host address when only the name is given. We try to reject
+ * addresses that belong to someone else.
+ */
+ login_info.user = user;
+ login_info.port = port;
+
+ if (host != 0 && !is_internet_addr(host)) {
+ login_info.host_name = host;
+ } else {
+ login_info.host_name = 0;
+ }
+
+ if (addr != 0 && is_internet_addr(addr)) {
+ login_info.internet_addr = convert_internet_addr(addr);
+ } else if (host != 0) {
+ if (is_internet_addr(host)) {
+ login_info.internet_addr = convert_internet_addr(host);
+ } else {
+ login_info.internet_addr = lookup_internet_addr(host);
+ }
+ } else {
+ login_info.internet_addr = 0;
+ }
+
+ /*
+ * Print what we think the user wants us to do.
+ */
+#ifdef TEST
+ printf("port: %s\n", login_info.port);
+ printf("user: %s\n", login_info.user);
+ printf("host: %s\n", login_info.host_name ? login_info.host_name : "none");
+ printf("addr: ");
+ if (login_info.internet_addr == 0) {
+ printf("none\n");
+ } else {
+ int i;
+
+ for (i = 0; login_info.internet_addr[i].s_addr; i++)
+ printf("%s%s", login_info.internet_addr[i].s_addr == -1 ?
+ "(see error log)" : inet_ntoa(login_info.internet_addr[i]),
+ login_info.internet_addr[i + 1].s_addr ? " " : "\n");
+ }
+#endif
+ result = _skeyaccess(fp, &login_info);
+ fclose(fp);
+ return (result);
+}
+
+/* _skeyaccess - find out if UNIX passwords are permitted */
+
+static int _skeyaccess(fp, login_info)
+FILE *fp;
+struct login_info *login_info;
+{
+ char buf[BUFSIZ];
+ char *tok;
+ int match;
+ int permission=DENY;
+
+#ifdef PERMIT_CONSOLE
+ if (login_info->port != 0 &&
+ (strcmp(login_info->port, CONSOLE) == 0 ||
+ strncmp(login_info->port, VTY_PREFIX, sizeof(VTY_PREFIX) - 1) == 0
+ )
+ )
+ return (1);
+#endif
+
+ /*
+ * Scan the s/key access table until we find an entry that matches. If no
+ * match is found, assume that UNIX passwords are disallowed.
+ */
+ match = 0;
+ while (match == 0 && (tok = first_token(buf, sizeof(buf), fp))) {
+ if (strncasecmp(tok, "permit", 4) == 0) {
+ permission = PERMIT;
+ } else if (strncasecmp(tok, "deny", 4) == 0) {
+ permission = DENY;
+ } else {
+ syslog(LOG_ERR, "%s: line %d: bad permission: %s",
+ _PATH_SKEYACCESS, line_number, tok);
+ continue; /* error */
+ }
+
+ /*
+ * Process all conditions in this entry until we find one that fails.
+ */
+ match = 1;
+ while (match != 0 && (tok = get_token())) {
+ if (strcasecmp(tok, "hostname") == 0) {
+ match = match_host_name(login_info);
+ } else if (strcasecmp(tok, "port") == 0) {
+ match = match_port(login_info);
+ } else if (strcasecmp(tok, "user") == 0) {
+ match = match_user(login_info);
+ } else if (strcasecmp(tok, "group") == 0) {
+ match = match_group(login_info);
+ } else if (strcasecmp(tok, "internet") == 0) {
+ match = match_internet_addr(login_info);
+ } else if (is_internet_addr(tok)) {
+ unget_token(tok);
+ match = match_internet_addr(login_info);
+ } else {
+ syslog(LOG_ERR, "%s: line %d: bad condition: %s",
+ _PATH_SKEYACCESS, line_number, tok);
+ match = 0;
+ }
+ }
+ }
+ return (match ? permission : DENY);
+}
+
+/* match_internet_addr - match internet network address */
+
+static int match_internet_addr(login_info)
+struct login_info *login_info;
+{
+ char *tok;
+ long pattern;
+ long mask;
+ struct in_addr *addrp;
+
+ if (login_info->internet_addr == 0)
+ return (0);
+ if ((tok = need_internet_addr()) == 0)
+ return (0);
+ pattern = inet_addr(tok);
+ if ((tok = need_internet_addr()) == 0)
+ return (0);
+ mask = inet_addr(tok);
+
+ /*
+ * See if any of the addresses matches a pattern in the control file. We
+ * have already tried to drop addresses that belong to someone else.
+ */
+
+ for (addrp = login_info->internet_addr; addrp->s_addr; addrp++)
+ if (addrp->s_addr != -1 && (addrp->s_addr & mask) == pattern)
+ return (1);
+ return (0);
+}
+
+/* match_group - match username against group */
+
+static int match_group(login_info)
+struct login_info *login_info;
+{
+ struct group *group;
+ char *tok;
+ char **memp;
+
+ if ((tok = need_token()) && (group = getgrnam(tok))) {
+ for (memp = group->gr_mem; *memp; memp++)
+ if (strcmp(login_info->user, *memp) == 0)
+ return (1);
+ }
+ return (0); /* XXX endgrent() */
+}
+
+/* match_token - get and match token */
+
+static int match_token(str)
+char *str;
+{
+ char *tok;
+
+ return (str && (tok = need_token()) && strcasecmp(str, tok) == 0);
+}
+
+/* first_token - read line and return first token */
+
+static char *first_token(buf, len, fp)
+char *buf;
+int len;
+FILE *fp;
+{
+ char *cp;
+
+ prev_token = 0;
+ for (;;) {
+ if (fgets(buf, len, fp) == 0)
+ return (0);
+ line_number++;
+ buf[strcspn(buf, "\r\n#")] = 0;
+#ifdef TEST
+ if (buf[0])
+ printf("rule: %s\n", buf);
+#endif
+ line_pointer = buf;
+ while ((cp = strsep(&line_pointer, " \t")) != NULL && *cp == '\0')
+ ;
+ if (cp != NULL)
+ return (cp);
+ }
+}
+
+/* unget_token - push back last token */
+
+static void unget_token(cp)
+char *cp;
+{
+ prev_token = cp;
+}
+
+/* get_token - retrieve next token from buffer */
+
+static char *get_token()
+{
+ char *cp;
+
+ if ( (cp = prev_token) ) {
+ prev_token = 0;
+ } else {
+ while ((cp = strsep(&line_pointer, " \t")) != NULL && *cp == '\0')
+ ;
+ }
+ return (cp);
+}
+
+/* need_token - complain if next token is not available */
+
+static char *need_token()
+{
+ char *cp;
+
+ if ((cp = get_token()) == 0)
+ syslog(LOG_ERR, "%s: line %d: premature end of rule",
+ _PATH_SKEYACCESS, line_number);
+ return (cp);
+}
+
+/* need_internet_addr - complain if next token is not an internet address */
+
+static char *need_internet_addr()
+{
+ char *cp;
+
+ if ((cp = get_token()) == 0) {
+ syslog(LOG_ERR, "%s: line %d: internet address expected",
+ _PATH_SKEYACCESS, line_number);
+ return (0);
+ } else if (!is_internet_addr(cp)) {
+ syslog(LOG_ERR, "%s: line %d: bad internet address: %s",
+ _PATH_SKEYACCESS, line_number, cp);
+ return (0);
+ } else {
+ return (cp);
+ }
+}
+
+/* is_internet_addr - determine if string is a dotted quad decimal address */
+
+static int is_internet_addr(str)
+char *str;
+{
+ int in_run = 0;
+ int runs = 0;
+
+ /* Count the number of runs of characters between the dots. */
+
+ while (*str) {
+ if (*str == '.') {
+ in_run = 0;
+ } else {
+ if (!isdigit(*str))
+ return (0);
+ if (in_run == 0) {
+ in_run = 1;
+ runs++;
+ }
+ }
+ str++;
+ }
+ return (runs == 4);
+}
+
+/* lookup_internet_addr - look up internet addresses with extreme prejudice */
+
+static struct in_addr *lookup_internet_addr(host)
+char *host;
+{
+ struct hostent *hp;
+ static struct in_addr list[MAX_ADDR + 1];
+ char buf[MAXHOSTNAMELEN + 1];
+ int length;
+ int i;
+
+ if ((hp = gethostbyname(host)) == 0 || hp->h_addrtype != AF_INET)
+ return (0);
+
+ /*
+ * Save a copy of the results before gethostbyaddr() clobbers them.
+ */
+
+ for (i = 0; i < MAX_ADDR && hp->h_addr_list[i]; i++)
+ memcpy((char *) &list[i],
+ hp->h_addr_list[i], hp->h_length);
+ list[i].s_addr = 0;
+
+ strncpy(buf, hp->h_name, MAXHOSTNAMELEN);
+ buf[MAXHOSTNAMELEN] = 0;
+ length = hp->h_length;
+
+ /*
+ * Wipe addresses that appear to belong to someone else. We will get
+ * false alarms when when the hostname comes from DNS, while its
+ * addresses are listed under different names in local databases.
+ */
+#define NEQ(x,y) (strcasecmp((x),(y)) != 0)
+#define NEQ3(x,y,n) (strncasecmp((x),(y), (n)) != 0)
+
+ while (--i >= 0) {
+ if ((hp = gethostbyaddr((char *) &list[i], length, AF_INET)) == 0) {
+ syslog(LOG_ERR, "address %s not registered for host %s",
+ inet_ntoa(list[i]), buf);
+ list[i].s_addr = -1;
+ }
+ if (NEQ(buf, hp->h_name) && NEQ3(buf, "localhost.", 10)) {
+ syslog(LOG_ERR, "address %s registered for host %s and %s",
+ inet_ntoa(list[i]), hp->h_name, buf);
+ list[i].s_addr = -1;
+ }
+ }
+ return (list);
+}
+
+/* convert_internet_addr - convert string to internet address */
+
+static struct in_addr *convert_internet_addr(string)
+char *string;
+{
+ static struct in_addr list[2];
+
+ list[0].s_addr = inet_addr(string);
+ list[1].s_addr = 0;
+ return (list);
+}
+
+#ifdef TEST
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ struct hostent *hp;
+ char host[MAXHOSTNAMELEN + 1];
+ int verdict;
+ char *user;
+ char *port;
+
+ if (argc != 3 && argc != 4) {
+ fprintf(stderr, "usage: %s user port [host_or_ip_address]\n", argv[0]);
+ exit(0);
+ }
+ if (_PATH_SKEYACCESS[0] != '/')
+ printf("Warning: this program uses control file: %s\n", KEYACCESS);
+ openlog("login", LOG_PID, LOG_AUTH);
+
+ user = argv[1];
+ port = argv[2];
+ if (argv[3]) {
+ strncpy(host, (hp = gethostbyname(argv[3])) ?
+ hp->h_name : argv[3], MAXHOSTNAMELEN);
+ host[MAXHOSTNAMELEN] = 0;
+ }
+ verdict = skeyaccess(user, port, argv[3] ? host : (char *) 0, (char *) 0);
+ printf("UNIX passwords %spermitted\n", verdict ? "" : "NOT ");
+ return (0);
+}
+
+#endif
diff --git a/lib/libskey/skeylogin.c b/lib/libskey/skeylogin.c
new file mode 100644
index 0000000..10af30b
--- /dev/null
+++ b/lib/libskey/skeylogin.c
@@ -0,0 +1,342 @@
+/* Login code for S/KEY Authentication. S/KEY is a trademark
+ * of Bellcore.
+ *
+ * Mink is the former name of the S/KEY authentication system.
+ * Many references for mink may still be found in this program.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <errno.h>
+
+#include "skey.h"
+#include "pathnames.h"
+
+static char *skipspace();
+
+#define setpriority(x,y,z) /* nothing */
+
+static char *month[12] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+/* Look up skey info for user 'name'. If successful, fill in the caller's
+ * skey structure and return 0. If unsuccessful (e.g., if name is unknown)
+ * return -1. If an optional challenge string buffer is given, update it.
+ *
+ * The file read/write pointer is left at the start of the
+ * record.
+ */
+int
+skeyinfo(mp,name,ss)
+struct skey *mp;
+const char *name;
+char *ss;
+{
+ int rval;
+
+ rval = skeylookup(mp,name);
+ switch(rval){
+ case -1: /* File error */
+ return -1;
+ case 0: /* Lookup succeeded */
+ if (ss != 0) {
+ sprintf(ss, "s/key %d %s",mp->n - 1,mp->seed);
+ fclose(mp->keyfile);
+ }
+ return 0;
+ case 1: /* User not found */
+ fclose(mp->keyfile);
+ return -1;
+ }
+ return -1; /* Can't happen */
+}
+
+/* Return a skey challenge string for user 'name'. If successful,
+ * fill in the caller's skey structure and return 0. If unsuccessful
+ * (e.g., if name is unknown) return -1.
+ *
+ * The file read/write pointer is left at the start of the
+ * record.
+ */
+int
+skeychallenge(mp,name, ss)
+struct skey *mp;
+const char *name;
+char *ss;
+{
+ int rval;
+
+ rval = skeylookup(mp,name);
+ switch(rval){
+ case -1: /* File error */
+ return -1;
+ case 0: /* Lookup succeeded, issue challenge */
+ sprintf(ss, "s/key %d %s",mp->n - 1,mp->seed);
+ return 0;
+ case 1: /* User not found */
+ fclose(mp->keyfile);
+ return -1;
+ }
+ return -1; /* Can't happen */
+}
+
+/* Find an entry in the One-time Password database.
+ * Return codes:
+ * -1: error in opening database
+ * 0: entry found, file R/W pointer positioned at beginning of record
+ * 1: entry not found, file R/W pointer positioned at EOF
+ */
+int
+skeylookup(mp,name)
+struct skey *mp;
+const char *name;
+{
+ int found;
+ int len;
+ long recstart;
+ char *cp, *p;
+ struct stat statbuf;
+ mode_t oldmask;
+
+ /* See if the _PATH_SKEYFILE exists, and create it if not */
+ if(stat(_PATH_SKEYFILE,&statbuf) == -1 && errno == ENOENT){
+ oldmask = umask(S_IRWXG|S_IRWXO);
+ mp->keyfile = fopen(_PATH_SKEYFILE,"w+");
+ (void)umask(oldmask);
+ } else {
+ /* Otherwise open normally for update */
+ mp->keyfile = fopen(_PATH_SKEYFILE,"r+");
+ }
+ if(mp->keyfile == NULL)
+ return -1;
+
+ /* Look up user name in database */
+ len = strlen(name);
+ if( len > 8 ) len = 8; /* Added 8/2/91 - nmh */
+ found = 0;
+ while(!feof(mp->keyfile)){
+ recstart = ftell(mp->keyfile);
+ mp->recstart = recstart;
+ if(fgets(mp->buf,sizeof(mp->buf),mp->keyfile) != mp->buf){
+ break;
+ }
+ rip(mp->buf);
+ if(mp->buf[0] == '#')
+ continue; /* Comment */
+ p = mp->buf;
+ while ((cp = strsep(&p, " \t")) != NULL && *cp == '\0')
+ ;
+ if((mp->logname = cp) == NULL)
+ continue;
+ while ((cp = strsep(&p, " \t")) != NULL && *cp == '\0')
+ ;
+ if(cp == NULL)
+ continue;
+ mp->n = atoi(cp);
+ while ((cp = strsep(&p, " \t")) != NULL && *cp == '\0')
+ ;
+ if((mp->seed = cp) == NULL)
+ continue;
+ while ((cp = strsep(&p, " \t")) != NULL && *cp == '\0')
+ ;
+ if((mp->val = cp) == NULL)
+ continue;
+ if(strlen(mp->logname) == len
+ && strncmp(mp->logname,name,len) == 0){
+ found = 1;
+ break;
+ }
+ }
+ if(found){
+ fseek(mp->keyfile,recstart,0);
+ return 0;
+ } else
+ return 1;
+}
+/* Verify response to a s/key challenge.
+ *
+ * Return codes:
+ * -1: Error of some sort; database unchanged
+ * 0: Verify successful, database updated
+ * 1: Verify failed, database unchanged
+ *
+ * The database file is always closed by this call.
+ */
+int
+skeyverify(mp,response)
+struct skey *mp;
+char *response;
+{
+ char key[8];
+ char fkey[8];
+ char filekey[8];
+ time_t now;
+ struct tm *tm;
+ char tbuf[27], fbuf[20];
+ char *cp, *p;
+
+ time(&now);
+ tm = localtime(&now);
+/* can't use %b here, because it can be in national form */
+ strftime(fbuf, sizeof(fbuf), "%d,%Y %T", tm);
+ snprintf(tbuf, sizeof(tbuf), " %s %s", month[tm->tm_mon], fbuf);
+
+ if(response == NULL){
+ fclose(mp->keyfile);
+ return -1;
+ }
+ rip(response);
+
+ /* Convert response to binary */
+ if(etob(key,response) != 1 && atob8(key,response) != 0){
+ /* Neither english words or ascii hex */
+ fclose(mp->keyfile);
+ return -1;
+ }
+
+ /* Compute fkey = f(key) */
+ memcpy(fkey,key,sizeof(key));
+ f(fkey);
+ /* in order to make the window of update as short as possible
+ we must do the comparison here and if OK write it back
+ other wise the same password can be used twice to get in
+ to the system
+ */
+
+ setpriority(PRIO_PROCESS, 0, -4);
+
+ /* reread the file record NOW*/
+
+ fseek(mp->keyfile,mp->recstart,0);
+ if(fgets(mp->buf,sizeof(mp->buf),mp->keyfile) != mp->buf){
+ setpriority(PRIO_PROCESS, 0, 0);
+ fclose(mp->keyfile);
+ return -1;
+ }
+ rip(mp->buf);
+ p = mp->buf;
+ while ((cp = strsep(&p, " \t")) != NULL && *cp == '\0')
+ ;
+ mp->logname = cp;
+ while ((cp = strsep(&p, " \t")) != NULL && *cp == '\0')
+ ;
+ while ((cp = strsep(&p, " \t")) != NULL && *cp == '\0')
+ ;
+ mp->seed = cp;
+ while ((cp = strsep(&p, " \t")) != NULL && *cp == '\0')
+ ;
+ mp->val = cp;
+ /* And convert file value to hex for comparison */
+ atob8(filekey,mp->val);
+
+ /* Do actual comparison */
+ if(memcmp(filekey,fkey,8) != 0){
+ /* Wrong response */
+ setpriority(PRIO_PROCESS, 0, 0);
+ fclose(mp->keyfile);
+ return 1;
+ }
+
+ /* Update key in database by overwriting entire record. Note
+ * that we must write exactly the same number of bytes as in
+ * the original record (note fixed width field for N)
+ */
+ btoa8(mp->val,key);
+ mp->n--;
+ fseek(mp->keyfile,mp->recstart,0);
+ fprintf(mp->keyfile,"%s %04d %-16s %s %-21s\n",mp->logname,mp->n,mp->seed,
+ mp->val, tbuf);
+
+ fclose(mp->keyfile);
+
+ setpriority(PRIO_PROCESS, 0, 0);
+ return 0;
+}
+
+
+/* Convert 8-byte hex-ascii string to binary array
+ * Returns 0 on success, -1 on error
+ */
+int
+atob8(out,in)
+register char *out,*in;
+{
+ register int i;
+ register int val;
+
+ if(in == NULL || out == NULL)
+ return -1;
+
+ for(i=0;i<8;i++){
+ if((in = skipspace(in)) == NULL)
+ return -1;
+ if((val = htoi(*in++)) == -1)
+ return -1;
+ *out = val << 4;
+
+ if((in = skipspace(in)) == NULL)
+ return -1;
+ if((val = htoi(*in++)) == -1)
+ return -1;
+ *out++ |= val;
+ }
+ return 0;
+}
+
+static
+char *
+skipspace(cp)
+register char *cp;
+{
+ while(*cp == ' ' || *cp == '\t')
+ cp++;
+
+ if(*cp == '\0')
+ return NULL;
+ else
+ return cp;
+}
+
+/* Convert 8-byte binary array to hex-ascii string */
+int
+btoa8(out,in)
+register char *out,*in;
+{
+ register int i;
+
+ if(in == NULL || out == NULL)
+ return -1;
+
+ for(i=0;i<8;i++){
+ sprintf(out,"%02x",*in++ & 0xff);
+ out += 2;
+ }
+ return 0;
+}
+
+
+/* Convert hex digit to binary integer */
+int
+htoi(c)
+register char c;
+{
+ if('0' <= c && c <= '9')
+ return c - '0';
+ if('a' <= c && c <= 'f')
+ return 10 + c - 'a';
+ if('A' <= c && c <= 'F')
+ return 10 + c - 'A';
+ return -1;
+}
diff --git a/lib/libskey/skeysubr.c b/lib/libskey/skeysubr.c
new file mode 100644
index 0000000..2bd344f
--- /dev/null
+++ b/lib/libskey/skeysubr.c
@@ -0,0 +1,130 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <signal.h>
+
+#include "skey.h"
+#include "mdx.h"
+
+/* Crunch a key:
+ * concatenate the seed and the password, run through MDX and
+ * collapse to 64 bits. This is defined as the user's starting key.
+ */
+int
+keycrunch(result,seed,passwd)
+char *result; /* 8-byte result */
+char *seed; /* Seed, any length */
+char *passwd; /* Password, any length */
+{
+ char *buf;
+ MDX_CTX md;
+ u_long results[4];
+ unsigned int buflen;
+
+ buflen = strlen(seed) + strlen(passwd);
+ if((buf = malloc(buflen+1)) == NULL)
+ return -1;
+ strcpy(buf,seed);
+ strcat(buf,passwd);
+
+ /* Crunch the key through MD[45] */
+ sevenbit(buf);
+ MDXInit(&md);
+ MDXUpdate(&md,(unsigned char *)buf,buflen);
+ MDXFinal((unsigned char *)results,&md);
+ free(buf);
+
+ results[0] ^= results[2];
+ results[1] ^= results[3];
+
+ memcpy(result,(char *)results,8);
+
+ return 0;
+}
+
+/* The one-way function f(). Takes 8 bytes and returns 8 bytes in place */
+void
+f(x)
+char *x;
+{
+ MDX_CTX md;
+ u_long results[4];
+
+ MDXInit(&md);
+ MDXUpdate(&md,(unsigned char *)x,8);
+ MDXFinal((unsigned char *)results,&md);
+ /* Fold 128 to 64 bits */
+ results[0] ^= results[2];
+ results[1] ^= results[3];
+
+ memcpy(x,(char *)results,8);
+}
+
+/* Strip trailing cr/lf from a line of text */
+void
+rip(buf)
+char *buf;
+{
+ buf[strcspn(buf, "\r\n")] = 0;
+}
+
+static struct termios saved_ttymode;
+
+static void interrupt(sig)
+int sig;
+{
+ tcsetattr(0, TCSANOW, &saved_ttymode);
+ exit(1);
+}
+
+char *
+readpass(buf,n)
+char *buf;
+int n;
+{
+ struct termios noecho_ttymode;
+ void (*oldsig)();
+
+ /* Save normal line editing modes */
+ tcgetattr(0, &saved_ttymode);
+ if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN)
+ signal(SIGINT, interrupt);
+
+ /* Turn off echoing */
+ tcgetattr(0, &noecho_ttymode);
+ noecho_ttymode.c_lflag &= ~ECHO;
+ tcsetattr(0, TCSANOW, &noecho_ttymode);
+ fgets(buf,n,stdin);
+ rip(buf);
+
+ /* Restore previous tty modes */
+ tcsetattr(0, TCSANOW, &saved_ttymode);
+ if (oldsig != SIG_IGN)
+ signal(SIGINT, oldsig);
+
+ /*
+ after the secret key is taken from the keyboard, the line feed is
+ written to standard error instead of standard output. That means that
+ anyone using the program from a terminal won't notice, but capturing
+ standard output will get the key words without a newline in front of
+ them.
+ */
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ sevenbit(buf);
+
+ return buf;
+}
+
+void
+sevenbit(s)
+char *s;
+{
+ /* make sure there are only 7 bit code in the line*/
+ while(*s){
+ *s &= 0x7f;
+ s++;
+ }
+}
diff --git a/lib/libss/Makefile b/lib/libss/Makefile
new file mode 100644
index 0000000..979238b
--- /dev/null
+++ b/lib/libss/Makefile
@@ -0,0 +1,38 @@
+# $Id$
+
+LIB= ss
+SRCS= ss_err.c data.c error.c execute_cmd.c help.c invocation.c list_rqs.c \
+ listen.c pager.c parse.c prompt.c request_tbl.c requests.c \
+ std_rqs.c
+CFLAGS+= -I. -I${.CURDIR} -DPOSIX -DIN_LIBSS
+CLEANFILES+= ss ss_err.c ss_err.h std_rqs.c
+.if exists(${.OBJDIR}/../libcom_err)
+LIBDESTDIR= ${.OBJDIR}/../libcom_err
+.else
+LIBDESTDIR= ${.CURDIR}/../libcom_err
+.endif
+DPADD= ${LIBDESTDIR}/libcom_err.a
+LDADD= -L${LIBDESTDIR} -lcom_err
+
+ss_err.h ss_err.c: ${.CURDIR}/ss_err.et
+ test -e ss_err.et || ln -s ${.CURDIR}/ss_err.et .
+ compile_et ss_err.et
+ -test -h ss_err.et && rm -f ss_err.et
+
+std_rqs.c: ${.CURDIR}/std_rqs.ct
+ test -e std_rqs.ct || ln -s ${.CURDIR}/std_rqs.ct .
+ mk_cmds std_rqs.ct
+ -test -h std_rqs.ct && rm -f std_rqs.ct
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/ss.h \
+ ${DESTDIR}/usr/include/ss
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/copyright.h \
+ ${DESTDIR}/usr/include/ss/mit-sipb-copyright.h
+.if exists(${.OBJDIR}/ss_err.h)
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ss_err.h \
+ ${DESTDIR}/usr/include/ss
+.endif
+
+.include <bsd.lib.mk>
+
diff --git a/lib/libss/copyright.h b/lib/libss/copyright.h
new file mode 100644
index 0000000..e0d1572
--- /dev/null
+++ b/lib/libss/copyright.h
@@ -0,0 +1,19 @@
+/*
+
+Copyright 1987, 1989 by the Student Information Processing Board
+ of 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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+M.I.T. and the M.I.T. S.I.P.B. make no representations about
+the suitability of this software for any purpose. It is
+provided "as is" without express or implied warranty.
+
+*/
+
diff --git a/lib/libss/data.c b/lib/libss/data.c
new file mode 100644
index 0000000..45e49d7
--- /dev/null
+++ b/lib/libss/data.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright 1987, 1988, 1989 Massachusetts Institute of Technology
+ * (Student Information Processing Board)
+ *
+ * For copyright info, see copyright.h.
+ */
+
+#include <stdio.h>
+#include "ss_internal.h"
+#include "copyright.h"
+
+static const char copyright[] =
+ "Copyright 1987, 1988, 1989 by the Massachusetts Institute of Technology";
+
+ss_data **_ss_table = (ss_data **)NULL;
+char *_ss_pager_name = (char *)NULL;
diff --git a/lib/libss/error.c b/lib/libss/error.c
new file mode 100644
index 0000000..223d72a
--- /dev/null
+++ b/lib/libss/error.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright 1987, 1988, 1989 by MIT Student Information Processing
+ * Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * Our standalone dpANS environment on the RT doesn't include any
+ * header files.
+ */
+#if defined(__STDC__) && !defined(ibm032)
+#include <stdarg.h>
+#define STDARG
+#else
+#include <varargs.h>
+#define ss_error ss_error_external
+#endif
+
+#include "copyright.h"
+#include <com_err.h>
+#include "ss_internal.h"
+
+#undef ss_error
+
+extern void com_err_va __P(( ));
+
+char * ss_name(sci_idx)
+ int sci_idx;
+{
+ register char *ret_val;
+ register ss_data *infop;
+
+ infop = ss_info(sci_idx);
+ if (infop->current_request == (char const *)NULL) {
+ ret_val = malloc((unsigned)
+ (strlen(infop->subsystem_name)+1)
+ * sizeof(char));
+ if (ret_val == (char *)NULL)
+ return((char *)NULL);
+ strcpy(ret_val, infop->subsystem_name);
+ return(ret_val);
+ }
+ else {
+ register char *cp;
+ register char const *cp1;
+ ret_val = malloc((unsigned)sizeof(char) *
+ (strlen(infop->subsystem_name)+
+ strlen(infop->current_request)+
+ 4));
+ cp = ret_val;
+ cp1 = infop->subsystem_name;
+ while (*cp1)
+ *cp++ = *cp1++;
+ *cp++ = ' ';
+ *cp++ = '(';
+ cp1 = infop->current_request;
+ while (*cp1)
+ *cp++ = *cp1++;
+ *cp++ = ')';
+ *cp = '\0';
+ return(ret_val);
+ }
+}
+
+#ifdef STDARG
+void ss_error (int sci_idx, long code, const char * fmt, ...)
+#else
+void ss_error (va_alist)
+ va_dcl
+#endif
+{
+ register char const *whoami;
+ va_list pvar;
+#ifndef STDARG
+ int sci_idx;
+ long code;
+ char * fmt;
+ va_start (pvar);
+ sci_idx = va_arg (pvar, int);
+ code = va_arg (pvar, long);
+ fmt = va_arg (pvar, char *);
+#else
+ va_start (pvar, fmt);
+#endif
+ whoami = ss_name (sci_idx);
+ com_err_va (whoami, code, fmt, pvar);
+ free (whoami);
+ va_end(pvar);
+}
+
+void ss_perror (sci_idx, code, msg) /* for compatibility */
+ int sci_idx;
+ long code;
+ char const *msg;
+{
+ ss_error (sci_idx, code, "%s", msg);
+}
diff --git a/lib/libss/execute_cmd.c b/lib/libss/execute_cmd.c
new file mode 100644
index 0000000..1bb0129
--- /dev/null
+++ b/lib/libss/execute_cmd.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright 1987, 1988, 1989 by Massachusetts Institute of Technology
+ *
+ * For copyright info, see copyright.h.
+ */
+
+#include "ss_internal.h"
+#include "copyright.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef lint
+static char const rcsid[] =
+ "Header: execute_cmd.c,v 1.7 89/01/25 08:27:43 raeburn Exp ";
+#endif
+
+/*
+ * get_request(tbl, idx)
+ *
+ * Function:
+ * Gets the idx'th request from the request table pointed to
+ * by tbl.
+ * Arguments:
+ * tbl (ss_request_table *)
+ * pointer to request table
+ * idx (int)
+ * index into table
+ * Returns:
+ * (ss_request_entry *)
+ * pointer to request table entry
+ * Notes:
+ * Has been replaced by a macro.
+ */
+
+#ifdef __SABER__
+/* sigh. saber won't deal with pointer-to-const-struct */
+static struct _ss_request_entry * get_request (tbl, idx)
+ ss_request_table * tbl;
+ int idx;
+{
+ struct _ss_request_table *tbl1 = (struct _ss_request_table *) tbl;
+ struct _ss_request_entry *e = (struct _ss_request_entry *) tbl1->requests;
+ return e + idx;
+}
+#else
+#define get_request(tbl,idx) ((tbl) -> requests + (idx))
+#endif
+
+/*
+ * check_request_table(rqtbl, argc, argv, sci_idx)
+ *
+ * Function:
+ * If the command string in argv[0] is in the request table, execute
+ * the commands and return error code 0. Otherwise, return error
+ * code ss_et_command_not_found.
+ * Arguments:
+ * rqtbl (ss_request_table *)
+ * pointer to request table
+ * argc (int)
+ * number of elements in argv[]
+ * argv (char *[])
+ * argument string array
+ * sci_idx (int)
+ * ss-internal index for subsystem control info structure
+ * Returns:
+ * (int)
+ * zero if command found, ss_et_command_not_found otherwise
+ * Notes:
+ */
+
+static int check_request_table (rqtbl, argc, argv, sci_idx)
+ register ss_request_table *rqtbl;
+ int argc;
+ char *argv[];
+ int sci_idx;
+{
+#ifdef __SABER__
+ struct _ss_request_entry *request;
+#else
+ register ss_request_entry *request;
+#endif
+ register ss_data *info;
+ register char const * const * name;
+ char *string = argv[0];
+ int i;
+
+ info = ss_info(sci_idx);
+ info->argc = argc;
+ info->argv = argv;
+ for (i = 0; (request = get_request(rqtbl, i))->command_names; i++) {
+ for (name = request->command_names; *name; name++)
+ if (!strcmp(*name, string)) {
+ info->current_request = request->command_names[0];
+ (request->function)(argc, (const char *const *) argv,
+ sci_idx,info->info_ptr);
+ info->current_request = (char *)NULL;
+ return(0);
+ }
+ }
+ return(SS_ET_COMMAND_NOT_FOUND);
+}
+
+/*
+ * really_execute_command(sci_idx, argc, argv)
+ *
+ * Function:
+ * Fills in the argc, argv values in the subsystem entry and
+ * call the appropriate routine.
+ * Arguments:
+ * sci_idx (int)
+ * ss-internal index for subsystem control info structure
+ * argc (int)
+ * number of arguments in argument list
+ * argv (char **[])
+ * pointer to parsed argument list (may be reallocated
+ * on abbrev expansion)
+ *
+ * Returns:
+ * (int)
+ * Zero if successful, ss_et_command_not_found otherwise.
+ * Notes:
+ */
+
+static int really_execute_command (sci_idx, argc, argv)
+ int sci_idx;
+ int argc;
+ char **argv[];
+{
+ register ss_request_table **rqtbl;
+ register ss_data *info;
+
+ info = ss_info(sci_idx);
+
+ for (rqtbl = info->rqt_tables; *rqtbl; rqtbl++) {
+ if (check_request_table (*rqtbl, argc, *argv, sci_idx) == 0)
+ return(0);
+ }
+ return(SS_ET_COMMAND_NOT_FOUND);
+}
+
+/*
+ * ss_execute_command(sci_idx, argv)
+ *
+ * Function:
+ * Executes a parsed command list within the subsystem.
+ * Arguments:
+ * sci_idx (int)
+ * ss-internal index for subsystem control info structure
+ * argv (char *[])
+ * parsed argument list
+ * Returns:
+ * (int)
+ * Zero if successful, ss_et_command_not_found otherwise.
+ * Notes:
+ */
+
+int
+ss_execute_command(sci_idx, argv)
+ int sci_idx;
+ register char *argv[];
+{
+ register int i, argc;
+ char **argp;
+
+ argc = 0;
+ for (argp = argv; *argp; argp++)
+ argc++;
+ argp = (char **)malloc((argc+1)*sizeof(char *));
+ for (i = 0; i <= argc; i++)
+ argp[i] = argv[i];
+ i = really_execute_command(sci_idx, argc, &argp);
+ free(argp);
+ return(i);
+}
+
+/*
+ * ss_execute_line(sci_idx, line_ptr)
+ *
+ * Function:
+ * Parses and executes a command line within a subsystem.
+ * Arguments:
+ * sci_idx (int)
+ * ss-internal index for subsystem control info structure
+ * line_ptr (char *)
+ * Pointer to command line to be parsed.
+ * Returns:
+ * (int)
+ * Error code.
+ * Notes:
+ */
+
+int ss_execute_line (sci_idx, line_ptr)
+ int sci_idx;
+ char *line_ptr;
+{
+ char **argv;
+ int argc;
+
+ /* flush leading whitespace */
+ while (line_ptr[0] == ' ' || line_ptr[0] == '\t')
+ line_ptr++;
+
+ /* check if it should be sent to operating system for execution */
+ if (*line_ptr == '!') {
+ if (ss_info(sci_idx)->flags.escape_disabled)
+ return SS_ET_ESCAPE_DISABLED;
+ else {
+ line_ptr++;
+ system(line_ptr);
+ return 0;
+ }
+ }
+
+ /* parse it */
+ argv = ss_parse(sci_idx, line_ptr, &argc);
+ if (argc == 0)
+ return 0;
+
+ /* look it up in the request tables, execute if found */
+ return really_execute_command (sci_idx, argc, &argv);
+}
diff --git a/lib/libss/help.c b/lib/libss/help.c
new file mode 100644
index 0000000..48aece43
--- /dev/null
+++ b/lib/libss/help.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright info, see copyright.h.
+ */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "ss_internal.h"
+#include "copyright.h"
+
+extern int errno;
+
+void ss_help (argc, argv, sci_idx, info_ptr)
+ int argc;
+ char const * const *argv;
+ int sci_idx;
+ pointer info_ptr;
+{
+ char buffer[MAXPATHLEN];
+ char const *request_name;
+ int code;
+ int fd, child;
+ register int idx;
+ register ss_data *info;
+
+ request_name = ss_current_request(sci_idx, &code);
+ if (code != 0) {
+ ss_perror(sci_idx, code, "");
+ return; /* no ss_abort_line, if invalid invocation */
+ }
+ if (argc == 1) {
+ ss_list_requests(argc, argv, sci_idx, info_ptr);
+ return;
+ }
+ else if (argc != 2) {
+ /* should do something better than this */
+ sprintf(buffer, "usage:\n\t%s [topic|command]\nor\t%s\n",
+ request_name, request_name);
+ ss_perror(sci_idx, 0, buffer);
+ return;
+ }
+ info = ss_info(sci_idx);
+ if (info->info_dirs == (char **)NULL) {
+ ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL);
+ return;
+ }
+ if (info->info_dirs[0] == (char *)NULL) {
+ ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL);
+ return;
+ }
+ for (idx = 0; info->info_dirs[idx] != (char *)NULL; idx++) {
+ (void) strcpy(buffer, info->info_dirs[idx]);
+ (void) strcat(buffer, "/");
+ (void) strcat(buffer, argv[1]);
+ (void) strcat(buffer, ".info");
+ if ((fd = open(&buffer[0], O_RDONLY, 0)) >= 0) goto got_it;
+ }
+ if ((fd = open(&buffer[0], O_RDONLY, 0)) < 0) {
+ char buf[MAXPATHLEN];
+ strcpy(buf, "No info found for ");
+ strcat(buf, argv[1]);
+ ss_perror(sci_idx, 0, buf);
+ return;
+ }
+got_it:
+ switch (child = fork()) {
+ case -1:
+ ss_perror(sci_idx, errno, "Can't fork for pager");
+ return;
+ case 0:
+ (void) dup2(fd, 0); /* put file on stdin */
+ ss_page_stdin();
+ default:
+ (void) close(fd); /* what can we do if it fails? */
+#ifndef POSIX
+ while (wait((union wait *)NULL) != child)
+#else
+ while (wait((int *)NULL) != child)
+#endif
+ {
+ /* do nothing if wrong pid */
+ };
+ }
+}
+
+void ss_add_info_dir(sci_idx, info_dir, code_ptr)
+ int sci_idx;
+ char *info_dir;
+ int *code_ptr;
+{
+ register ss_data *info;
+ DIR *d;
+ int n_dirs;
+ register char **dirs;
+
+ info = ss_info(sci_idx);
+ if (info_dir == NULL && *info_dir) {
+ *code_ptr = SS_ET_NO_INFO_DIR;
+ return;
+ }
+ if ((d = opendir(info_dir)) == (DIR *)NULL) {
+ *code_ptr = errno;
+ return;
+ }
+ closedir(d);
+ dirs = info->info_dirs;
+ for (n_dirs = 0; dirs[n_dirs] != (char *)NULL; n_dirs++)
+ ; /* get number of non-NULL dir entries */
+ dirs = (char **)realloc((char *)dirs,
+ (unsigned)(n_dirs + 2)*sizeof(char *));
+ if (dirs == (char **)NULL) {
+ info->info_dirs = (char **)NULL;
+ *code_ptr = errno;
+ return;
+ }
+ info->info_dirs = dirs;
+ dirs[n_dirs + 1] = (char *)NULL;
+ dirs[n_dirs] = malloc((unsigned)strlen(info_dir)+1);
+ strcpy(dirs[n_dirs], info_dir);
+ *code_ptr = 0;
+}
+
+void ss_delete_info_dir(sci_idx, info_dir, code_ptr)
+ int sci_idx;
+ char *info_dir;
+ int *code_ptr;
+{
+ register char **i_d;
+ register char **info_dirs;
+
+ info_dirs = ss_info(sci_idx)->info_dirs;
+ for (i_d = info_dirs; *i_d; i_d++) {
+ if (!strcmp(*i_d, info_dir)) {
+ while (*i_d) {
+ *i_d = *(i_d+1);
+ i_d++;
+ }
+ *code_ptr = 0;
+ return;
+ }
+ }
+ *code_ptr = SS_ET_NO_INFO_DIR;
+}
diff --git a/lib/libss/invocation.c b/lib/libss/invocation.c
new file mode 100644
index 0000000..513ec7d
--- /dev/null
+++ b/lib/libss/invocation.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include <stdlib.h>
+#include "ss_internal.h"
+#include "copyright.h"
+#define size sizeof(ss_data *)
+
+#ifndef lint
+static char const rcsid[] =
+ "Header: invocation.c,v 1.6 89/01/25 07:45:47 raeburn Exp ";
+#endif
+
+int ss_create_invocation(subsystem_name, version_string, info_ptr,
+ request_table_ptr, code_ptr)
+ char *subsystem_name, *version_string;
+ char *info_ptr;
+ ss_request_table *request_table_ptr;
+ int *code_ptr;
+{
+ register int sci_idx;
+ register ss_data *new_table;
+ register ss_data **table;
+
+ *code_ptr = 0;
+ table = _ss_table;
+ new_table = (ss_data *) malloc(sizeof(ss_data));
+
+ if (table == (ss_data **) NULL) {
+ table = (ss_data **) malloc(2 * size);
+ table[0] = table[1] = (ss_data *)NULL;
+ }
+ initialize_ss_error_table ();
+
+ for (sci_idx = 1; table[sci_idx] != (ss_data *)NULL; sci_idx++)
+ ;
+ table = (ss_data **) realloc((char *)table,
+ ((unsigned)sci_idx+2)*size);
+ table[sci_idx+1] = (ss_data *) NULL;
+ table[sci_idx] = new_table;
+
+ new_table->subsystem_name = subsystem_name;
+ new_table->subsystem_version = version_string;
+ new_table->argv = (char **)NULL;
+ new_table->current_request = (char *)NULL;
+ new_table->info_dirs = (char **)malloc(sizeof(char *));
+ *new_table->info_dirs = (char *)NULL;
+ new_table->info_ptr = info_ptr;
+ new_table->prompt = malloc((unsigned)strlen(subsystem_name)+4);
+ strcpy(new_table->prompt, subsystem_name);
+ strcat(new_table->prompt, ": ");
+#ifdef silly
+ new_table->abbrev_info = ss_abbrev_initialize("/etc/passwd", code_ptr);
+#else
+ new_table->abbrev_info = NULL;
+#endif
+ new_table->flags.escape_disabled = 0;
+ new_table->flags.abbrevs_disabled = 0;
+ new_table->rqt_tables =
+ (ss_request_table **) calloc(2, sizeof(ss_request_table *));
+ *(new_table->rqt_tables) = request_table_ptr;
+ *(new_table->rqt_tables+1) = (ss_request_table *) NULL;
+ _ss_table = table;
+ return(sci_idx);
+}
+
+void
+ss_delete_invocation(sci_idx)
+ int sci_idx;
+{
+ register ss_data *t;
+ int ignored_code;
+
+ t = ss_info(sci_idx);
+ free(t->prompt);
+ free((char *)t->rqt_tables);
+ while(t->info_dirs[0] != (char *)NULL)
+ ss_delete_info_dir(sci_idx, t->info_dirs[0], &ignored_code);
+ free((char *)t->info_dirs);
+ free((char *)t);
+}
diff --git a/lib/libss/list_rqs.c b/lib/libss/list_rqs.c
new file mode 100644
index 0000000..14e7748
--- /dev/null
+++ b/lib/libss/list_rqs.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+#include "copyright.h"
+#include "ss_internal.h"
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#ifdef lint /* "lint returns a value which is sometimes ignored" */
+#define DONT_USE(x) x=x;
+#else /* !lint */
+#define DONT_USE(x) ;
+#endif /* lint */
+
+static char const twentyfive_spaces[26] =
+ " ";
+static char const NL[2] = "\n";
+
+void
+ss_list_requests(argc, argv, sci_idx, info_ptr)
+ int argc;
+ char **argv;
+ int sci_idx;
+ pointer info_ptr;
+{
+ register ss_request_entry *entry;
+ register char const * const *name;
+ register int spacing;
+ register ss_request_table **table;
+
+ char buffer[BUFSIZ];
+ FILE *output;
+ int fd;
+ int mask;
+#ifdef POSIX
+ void (*func)();
+#else
+ int (*func)();
+#endif
+#ifdef POSIX
+ int waitb;
+#else
+ union wait waitb;
+#endif
+
+ DONT_USE(argc);
+ DONT_USE(argv);
+
+ mask = sigblock(sigmask(SIGINT));
+ func = signal(SIGINT, SIG_IGN);
+ fd = ss_pager_create();
+ output = fdopen(fd, "w");
+ sigsetmask(mask);
+
+ fprintf (output, "Available %s requests:\n\n",
+ ss_info (sci_idx) -> subsystem_name);
+
+ for (table = ss_info(sci_idx)->rqt_tables; *table; table++) {
+ entry = (*table)->requests;
+ for (; entry->command_names; entry++) {
+ spacing = -2;
+ buffer[0] = '\0';
+ if (entry->flags & SS_OPT_DONT_LIST)
+ continue;
+ for (name = entry->command_names; *name; name++) {
+ register int len = strlen(*name);
+ strncat(buffer, *name, len);
+ spacing += len + 2;
+ if (name[1]) {
+ strcat(buffer, ", ");
+ }
+ }
+ if (spacing > 23) {
+ strcat(buffer, NL);
+ fputs(buffer, output);
+ spacing = 0;
+ buffer[0] = '\0';
+ }
+ strncat(buffer, twentyfive_spaces, 25-spacing);
+ strcat(buffer, entry->info_string);
+ strcat(buffer, NL);
+ fputs(buffer, output);
+ }
+ }
+ fclose(output);
+#ifndef NO_FORK
+ wait(&waitb);
+#endif
+ (void) signal(SIGINT, func);
+}
diff --git a/lib/libss/listen.c b/lib/libss/listen.c
new file mode 100644
index 0000000..351129c
--- /dev/null
+++ b/lib/libss/listen.c
@@ -0,0 +1,164 @@
+
+
+/*
+ * Listener loop for subsystem library libss.a.
+ *
+ * Header: /afs/rel-eng.athena.mit.edu/project/release/current/source/athena/athena.lib/ss/RCS/listen.c,v 1.2 90/07/12 12:28:58 epeisach Exp
+ * $Locker: $
+ *
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include "copyright.h"
+#include "ss_internal.h"
+#include <stdio.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/param.h>
+#if defined(BSD) && !defined(POSIX)
+#include <sgtty.h>
+#endif
+#ifdef POSIX
+#include <termios.h>
+#endif
+
+#ifndef lint
+static char const rcs_id[] =
+ "Header: /afs/rel-eng.athena.mit.edu/project/release/current/source/athena/athena.lib/ss/RCS/listen.c,v 1.2 90/07/12 12:28:58 epeisach Exp ";
+#endif
+
+#ifdef POSIX
+#define sigtype void
+#else
+#define sigtype int
+#endif POSIX
+
+extern char *index();
+
+static ss_data *current_info;
+static jmp_buf listen_jmpb;
+
+static sigtype print_prompt()
+{
+ /* put input into a reasonable mode */
+#if defined(BSD) && !defined(POSIX)
+ struct sgttyb ttyb;
+ if (ioctl(fileno(stdin), TIOCGETP, &ttyb) != -1) {
+ if (ttyb.sg_flags & (CBREAK|RAW)) {
+ ttyb.sg_flags &= ~(CBREAK|RAW);
+ (void) ioctl(0, TIOCSETP, &ttyb);
+ }
+#endif
+#ifdef POSIX
+ struct termios tio;
+ if (tcgetattr(fileno(stdin), &tio) != -1) {
+ tio.c_oflag |= (OPOST|ONLCR);
+ tio.c_iflag &= ~(IGNCR|INLCR);
+ tio.c_iflag |= (ICRNL);
+ tio.c_lflag |= (ICANON);
+ (void) tcsetattr(0, TCSADRAIN, &tio);
+ }
+#endif
+ (void) fputs(current_info->prompt, stdout);
+ (void) fflush(stdout);
+}
+
+static sigtype listen_int_handler()
+{
+ putc('\n', stdout);
+ longjmp(listen_jmpb, 1);
+}
+
+int ss_listen (sci_idx)
+ int sci_idx;
+{
+ register char *cp;
+ register sigtype (*sig_cont)();
+ register ss_data *info;
+ sigtype (*sig_int)(), (*old_sig_cont)();
+ char input[BUFSIZ];
+ char buffer[BUFSIZ];
+ char *end = buffer;
+ int mask;
+ int code;
+ jmp_buf old_jmpb;
+ ss_data *old_info = current_info;
+ static sigtype print_prompt();
+
+ current_info = info = ss_info(sci_idx);
+ sig_cont = (sigtype (*)())0;
+ info->abort = 0;
+ mask = sigblock(sigmask(SIGINT));
+ bcopy(listen_jmpb, old_jmpb, sizeof(jmp_buf));
+ sig_int = signal(SIGINT, listen_int_handler);
+ setjmp(listen_jmpb);
+ (void) sigsetmask(mask);
+ while(!info->abort) {
+ print_prompt();
+ *end = '\0';
+ old_sig_cont = sig_cont;
+ sig_cont = signal(SIGCONT, print_prompt);
+#ifdef mips
+ /* The mips compiler breaks on determining the types,
+ we help */
+ if ( (sigtype *) sig_cont == (sigtype *) print_prompt)
+#else
+ if ( sig_cont == print_prompt)
+#endif
+ sig_cont = old_sig_cont;
+ if (fgets(input, BUFSIZ, stdin) != input) {
+ code = SS_ET_EOF;
+ goto egress;
+ }
+ cp = index(input, '\n');
+ if (cp) {
+ *cp = '\0';
+ if (cp == input)
+ continue;
+ }
+ (void) signal(SIGCONT, sig_cont);
+ for (end = input; *end; end++)
+ ;
+
+ code = ss_execute_line (sci_idx, input);
+ if (code == SS_ET_COMMAND_NOT_FOUND) {
+ register char *c = input;
+ while (*c == ' ' || *c == '\t')
+ c++;
+ cp = index (c, ' ');
+ if (cp)
+ *cp = '\0';
+ cp = index (c, '\t');
+ if (cp)
+ *cp = '\0';
+ ss_error (sci_idx, 0,
+ "Unknown request \"%s\". Type \"?\" for a request list.",
+ c);
+ }
+ }
+ code = 0;
+egress:
+ (void) signal(SIGINT, sig_int);
+ bcopy(old_jmpb, listen_jmpb, sizeof(jmp_buf));
+ current_info = old_info;
+ return code;
+}
+
+void ss_abort_subsystem(sci_idx, code)
+ int sci_idx, code;
+{
+ ss_info(sci_idx)->abort = 1;
+ ss_info(sci_idx)->exit_status = code;
+
+}
+
+void ss_quit(argc, argv, sci_idx, infop)
+ int argc;
+ char **argv;
+ int sci_idx;
+ pointer infop;
+{
+ ss_abort_subsystem(sci_idx, 0);
+}
diff --git a/lib/libss/pager.c b/lib/libss/pager.c
new file mode 100644
index 0000000..b419725
--- /dev/null
+++ b/lib/libss/pager.c
@@ -0,0 +1,91 @@
+/*
+ * Pager: Routines to create a "more" running out of a particular file
+ * descriptor.
+ *
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include "ss_internal.h"
+#include "copyright.h"
+#include <stdio.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <unistd.h>
+
+static char MORE[] = "more";
+extern char *_ss_pager_name;
+extern char *getenv();
+extern int errno;
+
+/*
+ * this needs a *lot* of work....
+ *
+ * run in same process
+ * handle SIGINT sensibly
+ * allow finer control -- put-page-break-here
+ */
+void ss_page_stdin();
+
+#ifndef NO_FORK
+int ss_pager_create()
+{
+ int filedes[2];
+
+ if (pipe(filedes) != 0)
+ return(-1);
+
+ switch(fork()) {
+ case -1:
+ return(-1);
+ case 0:
+ /*
+ * Child; dup read half to 0, close all but 0, 1, and 2
+ */
+ if (dup2(filedes[0], 0) == -1)
+ exit(1);
+ ss_page_stdin();
+ default:
+ /*
+ * Parent: close "read" side of pipe, return
+ * "write" side.
+ */
+ (void) close(filedes[0]);
+ return(filedes[1]);
+ }
+}
+#else /* don't fork */
+int ss_pager_create()
+{
+ int fd;
+ fd = open("/dev/tty", O_WRONLY, 0);
+ return fd;
+}
+#endif
+
+void ss_page_stdin()
+{
+ int i;
+ for (i = 3; i < 32; i++)
+ (void) close(i);
+ (void) signal(SIGINT, SIG_DFL);
+ {
+ register int mask = sigblock(0);
+ mask &= ~sigmask(SIGINT);
+ sigsetmask(mask);
+ }
+ if (_ss_pager_name == (char *)NULL) {
+ if ((_ss_pager_name = getenv("PAGER")) == (char *)NULL)
+ _ss_pager_name = MORE;
+ }
+ (void) execlp(_ss_pager_name, _ss_pager_name, (char *) NULL);
+ {
+ /* minimal recovery if pager program isn't found */
+ char buf[80];
+ register int n;
+ while ((n = read(0, buf, 80)) > 0)
+ write(1, buf, n);
+ }
+ exit(errno);
+}
diff --git a/lib/libss/parse.c b/lib/libss/parse.c
new file mode 100644
index 0000000..8a61ea8
--- /dev/null
+++ b/lib/libss/parse.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright info, see copyright.h.
+ */
+
+#include <stdlib.h>
+#include "ss_internal.h"
+#include "copyright.h"
+
+#ifndef lint
+static char const rcsid[] =
+ "Header: parse.c,v 1.1 89/01/25 07:53:13 raeburn Exp ";
+#endif
+
+enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
+
+/*
+ * parse(line_ptr, argc_ptr)
+ *
+ * Function:
+ * Parses line, dividing at whitespace, into tokens, returns
+ * the "argc" and "argv" values.
+ * Arguments:
+ * line_ptr (char *)
+ * Pointer to text string to be parsed.
+ * argc_ptr (int *)
+ * Where to put the "argc" (number of tokens) value.
+ * Returns:
+ * argv (char **)
+ * Series of pointers to parsed tokens.
+ */
+
+#define NEW_ARGV(old,n) (char **)realloc((char *)old,\
+ (unsigned)(n+2)*sizeof(char*))
+
+char **ss_parse (sci_idx, line_ptr, argc_ptr)
+ int sci_idx;
+ register char *line_ptr;
+ int *argc_ptr;
+{
+ register char **argv, *cp;
+ register int argc;
+ register enum parse_mode parse_mode;
+
+ argv = (char **) malloc (sizeof(char *));
+ if (argv == (char **)NULL) {
+ ss_error(sci_idx, errno, "Can't allocate storage");
+ return(argv);
+ }
+ *argv = (char *)NULL;
+
+ argc = 0;
+
+ parse_mode = WHITESPACE; /* flushing whitespace */
+ cp = line_ptr; /* cp is for output */
+ while (1) {
+#ifdef DEBUG
+ {
+ printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
+ }
+#endif
+ while (parse_mode == WHITESPACE) {
+ if (*line_ptr == '\0')
+ goto end_of_line;
+ if (*line_ptr == ' ' || *line_ptr == '\t') {
+ line_ptr++;
+ continue;
+ }
+ if (*line_ptr == '"') {
+ /* go to quoted-string mode */
+ parse_mode = QUOTED_STRING;
+ cp = line_ptr++;
+ argv = NEW_ARGV (argv, argc);
+ argv[argc++] = cp;
+ argv[argc] = NULL;
+ }
+ else {
+ /* random-token mode */
+ parse_mode = TOKEN;
+ cp = line_ptr;
+ argv = NEW_ARGV (argv, argc);
+ argv[argc++] = line_ptr;
+ argv[argc] = NULL;
+ }
+ }
+ while (parse_mode == TOKEN) {
+ if (*line_ptr == '\0') {
+ *cp++ = '\0';
+ goto end_of_line;
+ }
+ else if (*line_ptr == ' ' || *line_ptr == '\t') {
+ *cp++ = '\0';
+ line_ptr++;
+ parse_mode = WHITESPACE;
+ }
+ else if (*line_ptr == '"') {
+ line_ptr++;
+ parse_mode = QUOTED_STRING;
+ }
+ else {
+ *cp++ = *line_ptr++;
+ }
+ }
+ while (parse_mode == QUOTED_STRING) {
+ if (*line_ptr == '\0') {
+ ss_error (sci_idx, 0,
+ "Unbalanced quotes in command line");
+ free (argv);
+ return NULL;
+ }
+ else if (*line_ptr == '"') {
+ if (*++line_ptr == '"') {
+ *cp++ = '"';
+ line_ptr++;
+ }
+ else {
+ parse_mode = TOKEN;
+ }
+ }
+ else {
+ *cp++ = *line_ptr++;
+ }
+ }
+ }
+end_of_line:
+ *argc_ptr = argc;
+#ifdef DEBUG
+ {
+ int i;
+ printf ("argc = %d\n", argc);
+ for (i = 0; i <= argc; i++)
+ printf ("\targv[%2d] = `%s'\n", i,
+ argv[i] ? argv[i] : "<NULL>");
+ }
+#endif
+ return(argv);
+}
diff --git a/lib/libss/prompt.c b/lib/libss/prompt.c
new file mode 100644
index 0000000..d6f5ff8
--- /dev/null
+++ b/lib/libss/prompt.c
@@ -0,0 +1,32 @@
+/*
+ * prompt.c: Routines for retrieving and setting a prompt.
+ *
+ * Header: prompt.c,v 1.2 89/01/18 18:27:02 raeburn Exp
+ * $Locker: $
+ *
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include "copyright.h"
+#include <stdio.h>
+#include "ss_internal.h"
+
+static const char rcsid[] =
+ "Header: prompt.c,v 1.2 89/01/18 18:27:02 raeburn Exp ";
+
+void
+ss_set_prompt(sci_idx, new_prompt)
+ int sci_idx;
+ char *new_prompt;
+{
+ ss_info(sci_idx)->prompt = new_prompt;
+}
+
+char *
+ss_get_prompt(sci_idx)
+ int sci_idx;
+{
+ return(ss_info(sci_idx)->prompt);
+}
diff --git a/lib/libss/request_tbl.c b/lib/libss/request_tbl.c
new file mode 100644
index 0000000..b860064
--- /dev/null
+++ b/lib/libss/request_tbl.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include <stdlib.h>
+#include "copyright.h"
+#include "ss_internal.h"
+
+#define ssrt ss_request_table /* for some readable code... */
+
+void
+ss_add_request_table(sci_idx, rqtbl_ptr, position, code_ptr)
+ int sci_idx;
+ ssrt *rqtbl_ptr;
+ int position; /* 1 -> becomes second... */
+ int *code_ptr;
+{
+ register ss_data *info;
+ register int i, size;
+
+ info = ss_info(sci_idx);
+ for (size=0; info->rqt_tables[size] != (ssrt *)NULL; size++)
+ ;
+ /* size == C subscript of NULL == #elements */
+ size += 2; /* new element, and NULL */
+ info->rqt_tables = (ssrt **)realloc((char *)info->rqt_tables,
+ (unsigned)size*sizeof(ssrt));
+ if (info->rqt_tables == (ssrt **)NULL) {
+ *code_ptr = errno;
+ return;
+ }
+ if (position > size - 2)
+ position = size - 2;
+
+ if (size > 1)
+ for (i = size - 2; i >= position; i--)
+ info->rqt_tables[i+1] = info->rqt_tables[i];
+
+ info->rqt_tables[position] = rqtbl_ptr;
+ info->rqt_tables[size-1] = (ssrt *)NULL;
+ *code_ptr = 0;
+}
+
+void
+ss_delete_request_table(sci_idx, rqtbl_ptr, code_ptr)
+ int sci_idx;
+ ssrt *rqtbl_ptr;
+ int *code_ptr;
+{
+ register ss_data *info;
+ register ssrt **rt1, **rt2;
+
+ *code_ptr = SS_ET_TABLE_NOT_FOUND;
+ info = ss_info(sci_idx);
+ rt1 = info->rqt_tables;
+ for (rt2 = rt1; *rt1; rt1++) {
+ if (*rt1 != rqtbl_ptr) {
+ *rt2++ = *rt1;
+ *code_ptr = 0;
+ }
+ }
+ *rt2 = (ssrt *)NULL;
+ return;
+}
diff --git a/lib/libss/requests.c b/lib/libss/requests.c
new file mode 100644
index 0000000..7aaf4f5
--- /dev/null
+++ b/lib/libss/requests.c
@@ -0,0 +1,52 @@
+/*
+ * Various minor routines...
+ *
+ * Copyright 1987, 1988, 1989 by MIT
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include "copyright.h"
+#include <stdio.h>
+#include "ss_internal.h"
+
+#define DECLARE(name) name(argc,argv,sci_idx)int argc,sci_idx;char **argv;
+
+/*
+ * ss_self_identify -- assigned by default to the "." request
+ */
+void
+DECLARE(ss_self_identify)
+{
+ register ss_data *info = ss_info(sci_idx);
+ printf("%s version %s\n", info->subsystem_name,
+ info->subsystem_version);
+}
+
+/*
+ * ss_subsystem_name -- print name of subsystem
+ */
+void
+DECLARE(ss_subsystem_name)
+{
+ printf("%s\n", ss_info(sci_idx)->subsystem_name);
+}
+
+/*
+ * ss_subsystem_version -- print version of subsystem
+ */
+void
+DECLARE(ss_subsystem_version)
+{
+ printf("%s\n", ss_info(sci_idx)->subsystem_version);
+}
+
+/*
+ * ss_unimplemented -- routine not implemented (should be
+ * set up as (dont_list,dont_summarize))
+ */
+void
+DECLARE(ss_unimplemented)
+{
+ ss_perror(sci_idx, SS_ET_UNIMPLEMENTED, "");
+}
diff --git a/lib/libss/ss.h b/lib/libss/ss.h
new file mode 100644
index 0000000..a727d8e
--- /dev/null
+++ b/lib/libss/ss.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see mit-sipb-copyright.h.
+ */
+
+#ifndef _ss_h
+#define _ss_h __FILE__
+
+#if 0
+#include <ss/mit-sipb-copyright.h>
+#endif
+#ifndef IN_MK_CMDS
+# ifdef IN_LIBSS
+# include "ss_err.h"
+# else
+# include <ss/ss_err.h>
+# endif
+#endif
+
+extern int errno;
+
+#ifdef __STDC__
+#define __SS_CONST const
+#define __SS_PROTO (int, const char * const *, int, void *)
+#else
+#define __SS_CONST
+#define __SS_PROTO ()
+#endif
+
+typedef __SS_CONST struct _ss_request_entry {
+ __SS_CONST char * __SS_CONST *command_names; /* whatever */
+ void (* __SS_CONST function) __SS_PROTO; /* foo */
+ __SS_CONST char * __SS_CONST info_string; /* NULL */
+ int flags; /* 0 */
+} ss_request_entry;
+
+typedef __SS_CONST struct _ss_request_table {
+ int version;
+ ss_request_entry *requests;
+} ss_request_table;
+
+#define SS_RQT_TBL_V2 2
+
+typedef struct _ss_rp_options { /* DEFAULT VALUES */
+ int version; /* SS_RP_V1 */
+ void (*unknown) __SS_PROTO; /* call for unknown command */
+ int allow_suspend;
+ int catch_int;
+} ss_rp_options;
+
+#define SS_RP_V1 1
+
+#define SS_OPT_DONT_LIST 0x0001
+#define SS_OPT_DONT_SUMMARIZE 0x0002
+
+void ss_help __SS_PROTO;
+char *ss_current_request();
+char *ss_name();
+#ifdef __STDC__
+void ss_error (int, long, char const *, ...);
+void ss_perror (int, long, char const *);
+#else
+void ss_error ();
+void ss_perror ();
+#endif
+void ss_abort_subsystem();
+extern ss_request_table ss_std_requests;
+#endif /* _ss_h */
diff --git a/lib/libss/ss_err.et b/lib/libss/ss_err.et
new file mode 100644
index 0000000..80e9dfa
--- /dev/null
+++ b/lib/libss/ss_err.et
@@ -0,0 +1,39 @@
+ error_table ss
+
+ec SS_ET_SUBSYSTEM_ABORTED,
+ "Subsystem aborted"
+
+ec SS_ET_VERSION_MISMATCH,
+ "Version mismatch"
+
+ec SS_ET_NULL_INV,
+ "No current invocation"
+
+ec SS_ET_NO_INFO_DIR,
+ "No info directory"
+
+ec SS_ET_COMMAND_NOT_FOUND,
+ "Command not found"
+
+ec SS_ET_LINE_ABORTED,
+ "Command line aborted"
+
+ec SS_ET_EOF,
+ "End-of-file reached"
+
+ec SS_ET_PERMISSION_DENIED,
+ "Permission denied"
+
+ec SS_ET_TABLE_NOT_FOUND,
+ "Request table not found"
+
+ec SS_ET_NO_HELP_FILE,
+ "No info available"
+
+ec SS_ET_ESCAPE_DISABLED,
+ "Shell escapes are disabled"
+
+ec SS_ET_UNIMPLEMENTED,
+ "Sorry, this request is not yet implemented"
+
+ end
diff --git a/lib/libss/ss_internal.h b/lib/libss/ss_internal.h
new file mode 100644
index 0000000..e613488
--- /dev/null
+++ b/lib/libss/ss_internal.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#ifndef _ss_ss_internal_h
+#define _ss_ss_internal_h __FILE__
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __STDC__
+
+#define PROTOTYPE(p) p
+typedef void * pointer;
+
+#else
+
+#define const
+#define volatile
+#define PROTOTYPE(p) ()
+typedef char * pointer;
+
+#endif /* not __STDC__ */
+
+#include "ss.h"
+
+#if defined(__GNUC__)
+#define LOCAL_ALLOC(x) __builtin_alloca(x)
+#define LOCAL_FREE(x)
+#else
+#if defined(vax)
+#define LOCAL_ALLOC(x) alloca(x)
+#define LOCAL_FREE(x)
+extern pointer alloca PROTOTYPE((unsigned));
+#else
+#if defined(__HIGHC__) /* Barf! */
+pragma on(alloca);
+#define LOCAL_ALLOC(x) alloca(x)
+#define LOCAL_FREE(x)
+extern pointer alloca PROTOTYPE((unsigned));
+#else
+/* no alloca? */
+#define LOCAL_ALLOC(x) malloc(x)
+#define LOCAL_FREE(x) free(x)
+#endif
+#endif
+#endif /* LOCAL_ALLOC stuff */
+
+typedef char BOOL;
+
+typedef struct _ss_abbrev_entry {
+ char *name; /* abbrev name */
+ char **abbrev; /* new tokens to insert */
+ char beginning_of_line : 1;
+} ss_abbrev_entry;
+
+typedef struct _ss_abbrev_list {
+ int n_abbrevs;
+ ss_abbrev_entry *first_abbrev;
+} ss_abbrev_list;
+
+typedef struct {
+/* char *path; */
+ ss_abbrev_list abbrevs[127];
+} ss_abbrev_info;
+
+typedef struct _ss_data { /* init values */
+ /* this subsystem */
+ char *subsystem_name;
+ char *subsystem_version;
+ /* current request info */
+ int argc;
+ char **argv; /* arg list */
+ char const *current_request; /* primary name */
+ /* info directory for 'help' */
+ char **info_dirs;
+ /* to be extracted by subroutines */
+ pointer info_ptr; /* (void *) NULL */
+ /* for ss_listen processing */
+ char *prompt;
+ ss_request_table **rqt_tables;
+ ss_abbrev_info *abbrev_info;
+ struct {
+ unsigned char escape_disabled : 1,
+ abbrevs_disabled : 1;
+ } flags;
+ /* to get out */
+ int abort; /* exit subsystem */
+ int exit_status;
+} ss_data;
+
+#define CURRENT_SS_VERSION 1
+
+#define ss_info(sci_idx) (_ss_table[sci_idx])
+#define ss_current_request(sci_idx,code_ptr) \
+ (*code_ptr=0,ss_info(sci_idx)->current_request)
+void ss_unknown_function();
+void ss_delete_info_dir();
+int ss_execute_line();
+char **ss_parse();
+ss_abbrev_info *ss_abbrev_initialize PROTOTYPE((char *, int *));
+void ss_page_stdin();
+
+extern ss_data **_ss_table;
+extern char *ss_et_msgs[];
+
+#ifndef __FreeBSD__
+extern pointer malloc PROTOTYPE((unsigned));
+extern pointer realloc PROTOTYPE((pointer, unsigned));
+extern pointer calloc PROTOTYPE((unsigned, unsigned));
+extern int exit PROTOTYPE((int));
+#endif
+
+#endif /* _ss_internal_h */
diff --git a/lib/libss/std_rqs.ct b/lib/libss/std_rqs.ct
new file mode 100644
index 0000000..500288a
--- /dev/null
+++ b/lib/libss/std_rqs.ct
@@ -0,0 +1,46 @@
+ command_table ss_std_requests;
+
+ request ss_self_identify, "Identify the subsystem.",
+ ".",
+ (dont_list, dont_summarize);
+
+ request ss_help, "Display info on command or topic.",
+ help;
+
+ unimplemented
+ ss_list_help,
+ "List topics for which help is available.",
+ list_help, lh;
+
+ request ss_list_requests, "List available commands.",
+ list_requests, lr, "?";
+
+ request ss_quit, "Leave the subsystem.",
+ quit, q;
+
+ unimplemented
+ ss_abbrev,
+ "Enable/disable abbreviation processing of request lines.",
+ abbrev, ab;
+
+ unimplemented
+ ss_execute,
+ "Execute a UNIX command line.",
+ execute, e;
+
+ unimplemented
+ ss_summarize_requests,
+ "Produce a list of the most commonly used requests.",
+ "?";
+
+ request ss_subsystem_name,
+ "Return the name of this subsystem.",
+ subsystem_name,
+ (dont_list);
+
+ request ss_subsystem_version,
+ "Return the version of this subsystem.",
+ subsystem_version,
+ (dont_list);
+
+ end;
diff --git a/lib/libtcl/Makefile b/lib/libtcl/Makefile
new file mode 100644
index 0000000..6388cce
--- /dev/null
+++ b/lib/libtcl/Makefile
@@ -0,0 +1,295 @@
+# $Id$
+#
+# This file is generated automatically, do not edit it here!
+#
+# Please change src/tools/tools/tcl_bmake/mkMakefile.sh instead
+#
+# Generated by src/tools/tools/tcl_bmake/mkMakefile.sh version:
+# Id: mkMakefile.sh,v 1.18 1996/12/17 13:08:08 peter Exp
+#
+
+TCLDIST=${.CURDIR}/../../contrib/tcl
+
+.PATH: ${TCLDIST}/generic
+.PATH: ${TCLDIST}/unix
+.PATH: ${TCLDIST}/doc
+
+CFLAGS+= -I${TCLDIST}/generic
+CFLAGS+= -I${TCLDIST}/unix
+
+TCL_LIBRARY= /usr/libdata/tcl
+SHLIB_MAJOR= 75
+SHLIB_MINOR= 1
+
+LIB= tcl
+
+.if !defined(NOPIC)
+LINKS+= ${SHLIBDIR}/lib${LIB}.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \
+ ${SHLIBDIR}/lib${LIB}${SHLIB_MAJOR}.so.1.${SHLIB_MINOR}
+.endif
+LINKS+= ${LIBDIR}/lib${LIB}.a ${LIBDIR}/lib${LIB}${SHLIB_MAJOR}.a
+
+CFLAGS+= -DHAVE_UNISTD_H=1 -DHAVE_SYS_TIME_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_TM_ZONE=1 -DHAVE_TM_GMTOFF=1 -DSTDC_HEADERS=1 -DNEED_MATHERR=1 -DTCL_SHLIB_EXT=\".so\"
+CFLAGS+= -DTCL_LIBRARY=\"${TCL_LIBRARY}\"
+
+LDADD+= -lm
+DPADD+= ${LIBM}
+
+SRCS= panic.c regexp.c tclAsync.c tclBasic.c tclCkalloc.c tclClock.c \
+ tclCmdAH.c tclCmdIL.c tclCmdMZ.c tclDate.c tclEnv.c tclEvent.c \
+ tclExpr.c tclFHandle.c tclFileName.c tclGet.c tclHash.c \
+ tclHistory.c tclInterp.c tclIO.c tclIOCmd.c tclIOSock.c \
+ tclIOUtil.c tclLink.c tclLoad.c tclMain.c tclNotify.c tclParse.c \
+ tclPkg.c tclPosixStr.c tclPreserve.c tclProc.c tclUtil.c \
+ tclVar.c tclMtherr.c tclUnixChan.c tclUnixFile.c tclUnixNotfy.c \
+ tclUnixPipe.c tclUnixSock.c tclUnixTime.c tclUnixInit.c \
+ tclLoadDl2.c
+
+HEADERS=generic/patchlevel.h generic/tclInt.h generic/tclPort.h \
+ generic/tclRegexp.h unix/tclUnixPort.h
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \
+ ${TCLDIST}/generic/tcl.h ${DESTDIR}/usr/include
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 \
+ ${TCLDIST}/library/[a-z]* ${DESTDIR}${TCL_LIBRARY}
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 \
+ ${TCLDIST}/unix/tclAppInit.c ${DESTDIR}${TCL_LIBRARY}
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 \
+ ${TCLDIST}/doc/man.macros ${DESTDIR}/usr/share/tmac/tcl.macros
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 \
+ ${.CURDIR}/tclConfig.sh ${DESTDIR}${TCL_LIBRARY}
+.for m in ${HEADERS}
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${TCLDIST}/$m \
+ ${DESTDIR}/usr/include/tcl/$m
+.endfor
+
+
+MANFILTER=sed "/\.so *man.macros/s;.*;.so /usr/share/tmac/tcl.macros;"
+
+MANn+= Tcl.n after.n append.n array.n bgerror.n break.n case.n catch.n \
+ cd.n clock.n close.n concat.n continue.n eof.n error.n eval.n \
+ exec.n exit.n expr.n fblocked.n fconfigure.n file.n fileevent.n \
+ filename.n flush.n for.n foreach.n format.n gets.n glob.n \
+ global.n history.n if.n incr.n info.n interp.n join.n lappend.n \
+ library.n lindex.n linsert.n list.n llength.n load.n lrange.n \
+ lreplace.n lsearch.n lsort.n open.n package.n pid.n pkgMkIndex.n \
+ proc.n puts.n pwd.n read.n regexp.n regsub.n rename.n return.n \
+ scan.n seek.n set.n socket.n source.n split.n string.n subst.n \
+ switch.n tclvars.n tell.n time.n trace.n unknown.n unset.n \
+ update.n uplevel.n upvar.n vwait.n while.n
+
+MAN3+= Tcl_AddErrorInfo.3 Tcl_Alloc.3 Tcl_AllowExceptions.3 \
+ Tcl_AppInit.3 Tcl_GetAssocData.3 Tcl_AsyncCreate.3 \
+ Tcl_BackgroundError.3 Tcl_Backslash.3 Tcl_CallWhenDeleted.3 \
+ Tcl_CommandComplete.3 Tcl_Concat.3 Tcl_CreateChannel.3 \
+ Tcl_CreateChannelHandler.3 Tcl_CreateCloseHandler.3 \
+ Tcl_CreateCommand.3 Tcl_CreateFileHandler.3 Tcl_CreateInterp.3 \
+ Tcl_CreateMathFunc.3 Tcl_CreateModalTimeout.3 Tcl_IsSafe.3 \
+ Tcl_CreateTimerHandler.3 Tcl_CreateTrace.3 Tcl_DStringInit.3 \
+ Tcl_DetachPids.3 Tcl_DoOneEvent.3 Tcl_DoWhenIdle.3 Tcl_Eval.3 \
+ Tcl_Exit.3 Tcl_ExprLong.3 Tcl_FindExecutable.3 Tcl_GetFile.3 \
+ Tcl_GetInt.3 Tcl_GetOpenFile.3 Tcl_GetStdChannel.3 \
+ Tcl_InitHashTable.3 Tcl_Interp.3 Tcl_LinkVar.3 \
+ Tcl_CreateEventSource.3 Tcl_OpenFileChannel.3 Tcl_OpenTcpClient.3 \
+ Tcl_PkgRequire.3 Tcl_Preserve.3 Tcl_PrintDouble.3 \
+ Tcl_RecordAndEval.3 Tcl_RegExpMatch.3 Tcl_SetErrno.3 \
+ Tcl_SetRecursionLimit.3 Tcl_SetResult.3 Tcl_SetVar.3 Tcl_Sleep.3 \
+ Tcl_SplitList.3 Tcl_SplitPath.3 Tcl_StaticPackage.3 \
+ Tcl_StringMatch.3 Tcl_Main.3 Tcl_TraceVar.3 \
+ Tcl_TranslateFileName.3 Tcl_UpVar.3
+
+MLINKS+= Tcl_AddErrorInfo.3 Tcl_SetErrorCode.3
+MLINKS+= Tcl_AddErrorInfo.3 Tcl_PosixError.3
+MLINKS+= Tcl_Alloc.3 Tcl_Free.3
+MLINKS+= Tcl_Alloc.3 Tcl_Realloc.3
+MLINKS+= Tcl_GetAssocData.3 Tcl_SetAssocData.3
+MLINKS+= Tcl_GetAssocData.3 Tcl_DeleteAssocData.3
+MLINKS+= Tcl_AsyncCreate.3 Tcl_AsyncMark.3
+MLINKS+= Tcl_AsyncCreate.3 Tcl_AsyncInvoke.3
+MLINKS+= Tcl_AsyncCreate.3 Tcl_AsyncDelete.3
+MLINKS+= Tcl_CallWhenDeleted.3 Tcl_DontCallWhenDeleted.3
+MLINKS+= Tcl_CreateChannel.3 Tcl_GetChannelInstanceData.3
+MLINKS+= Tcl_CreateChannel.3 Tcl_GetChannelType.3
+MLINKS+= Tcl_CreateChannel.3 Tcl_GetChannelName.3
+MLINKS+= Tcl_CreateChannel.3 Tcl_GetChannelFile.3
+MLINKS+= Tcl_CreateChannel.3 Tcl_GetChannelBufferSize.3
+MLINKS+= Tcl_CreateChannel.3 Tcl_SetDefaultTranslation.3
+MLINKS+= Tcl_CreateChannel.3 Tcl_SetChannelBufferSize.3
+MLINKS+= Tcl_CreateChannelHandler.3 Tcl_DeleteChannelHandler.3
+MLINKS+= Tcl_CreateCloseHandler.3 Tcl_DeleteCloseHandler.3
+MLINKS+= Tcl_CreateCommand.3 Tcl_DeleteCommand.3
+MLINKS+= Tcl_CreateCommand.3 Tcl_GetCommandInfo.3
+MLINKS+= Tcl_CreateCommand.3 Tcl_SetCommandInfo.3
+MLINKS+= Tcl_CreateFileHandler.3 Tcl_DeleteFileHandler.3
+MLINKS+= Tcl_CreateInterp.3 Tcl_DeleteInterp.3
+MLINKS+= Tcl_CreateInterp.3 Tcl_InterpDeleted.3
+MLINKS+= Tcl_CreateModalTimeout.3 Tcl_DeleteModalTimeout.3
+MLINKS+= Tcl_IsSafe.3 Tcl_MakeSafe.3
+MLINKS+= Tcl_IsSafe.3 Tcl_CreateSlave.3
+MLINKS+= Tcl_IsSafe.3 Tcl_GetSlave.3
+MLINKS+= Tcl_IsSafe.3 Tcl_GetSlaves.3
+MLINKS+= Tcl_IsSafe.3 Tcl_GetMaster.3
+MLINKS+= Tcl_IsSafe.3 Tcl_CreateAlias.3
+MLINKS+= Tcl_IsSafe.3 Tcl_GetAlias.3
+MLINKS+= Tcl_IsSafe.3 Tcl_GetAliases.3
+MLINKS+= Tcl_CreateTimerHandler.3 Tcl_DeleteTimerHandler.3
+MLINKS+= Tcl_CreateTrace.3 Tcl_DeleteTrace.3
+MLINKS+= Tcl_DStringInit.3 Tcl_DStringAppend.3
+MLINKS+= Tcl_DStringInit.3 Tcl_DStringAppendElement.3
+MLINKS+= Tcl_DStringInit.3 Tcl_DStringStartSublist.3
+MLINKS+= Tcl_DStringInit.3 Tcl_DStringEndSublist.3
+MLINKS+= Tcl_DStringInit.3 Tcl_DStringLength.3
+MLINKS+= Tcl_DStringInit.3 Tcl_DStringValue.3
+MLINKS+= Tcl_DStringInit.3 Tcl_DStringSetLength.3
+MLINKS+= Tcl_DStringInit.3 Tcl_DStringFree.3
+MLINKS+= Tcl_DStringInit.3 Tcl_DStringResult.3
+MLINKS+= Tcl_DStringInit.3 Tcl_DStringGetResult.3
+MLINKS+= Tcl_DetachPids.3 Tcl_ReapDetachedProcs.3
+MLINKS+= Tcl_DoWhenIdle.3 Tcl_CancelIdleCall.3
+MLINKS+= Tcl_Eval.3 Tcl_VarEval.3
+MLINKS+= Tcl_Eval.3 Tcl_EvalFile.3
+MLINKS+= Tcl_Eval.3 Tcl_GlobalEval.3
+MLINKS+= Tcl_Exit.3 Tcl_CreateExitHandler.3
+MLINKS+= Tcl_Exit.3 Tcl_DeleteExitHandler.3
+MLINKS+= Tcl_ExprLong.3 Tcl_ExprDouble.3
+MLINKS+= Tcl_ExprLong.3 Tcl_ExprBoolean.3
+MLINKS+= Tcl_ExprLong.3 Tcl_ExprString.3
+MLINKS+= Tcl_GetFile.3 Tcl_FreeFile.3
+MLINKS+= Tcl_GetFile.3 Tcl_GetFileInfo.3
+MLINKS+= Tcl_GetInt.3 Tcl_GetDouble.3
+MLINKS+= Tcl_GetInt.3 Tcl_GetBoolean.3
+MLINKS+= Tcl_GetStdChannel.3 Tcl_SetStdChannel.3
+MLINKS+= Tcl_InitHashTable.3 Tcl_DeleteHashTable.3
+MLINKS+= Tcl_InitHashTable.3 Tcl_CreateHashEntry.3
+MLINKS+= Tcl_InitHashTable.3 Tcl_DeleteHashEntry.3
+MLINKS+= Tcl_InitHashTable.3 Tcl_FindHashEntry.3
+MLINKS+= Tcl_InitHashTable.3 Tcl_GetHashValue.3
+MLINKS+= Tcl_InitHashTable.3 Tcl_SetHashValue.3
+MLINKS+= Tcl_InitHashTable.3 Tcl_GetHashKey.3
+MLINKS+= Tcl_InitHashTable.3 Tcl_FirstHashEntry.3
+MLINKS+= Tcl_InitHashTable.3 Tcl_NextHashEntry.3
+MLINKS+= Tcl_InitHashTable.3 Tcl_HashStats.3
+MLINKS+= Tcl_LinkVar.3 Tcl_UnlinkVar.3
+MLINKS+= Tcl_LinkVar.3 Tcl_UpdateLinkedVar.3
+MLINKS+= Tcl_CreateEventSource.3 Tcl_DeleteEventSource.3
+MLINKS+= Tcl_CreateEventSource.3 Tcl_WatchFile.3
+MLINKS+= Tcl_CreateEventSource.3 Tcl_FileReady.3
+MLINKS+= Tcl_CreateEventSource.3 Tcl_SetMaxBlockTime.3
+MLINKS+= Tcl_CreateEventSource.3 Tcl_QueueEvent.3
+MLINKS+= Tcl_CreateEventSource.3 Tcl_WaitForEvent.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_OpenCommandChannel.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_Close.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_Read.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_Gets.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_Write.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_Flush.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_Seek.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_Tell.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_Eof.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_InputBlocked.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_GetChannelOption.3
+MLINKS+= Tcl_OpenFileChannel.3 Tcl_SetChannelOption.3
+MLINKS+= Tcl_OpenTcpClient.3 Tcl_OpenTcpServer.3
+MLINKS+= Tcl_PkgRequire.3 Tcl_PkgProvide.3
+MLINKS+= Tcl_Preserve.3 Tcl_Release.3
+MLINKS+= Tcl_Preserve.3 Tcl_EventuallyFree.3
+MLINKS+= Tcl_RegExpMatch.3 Tcl_RegExpCompile.3
+MLINKS+= Tcl_RegExpMatch.3 Tcl_RegExpExec.3
+MLINKS+= Tcl_RegExpMatch.3 Tcl_RegExpRange.3
+MLINKS+= Tcl_SetErrno.3 Tcl_GetErrno.3
+MLINKS+= Tcl_SetResult.3 Tcl_AppendResult.3
+MLINKS+= Tcl_SetResult.3 Tcl_AppendElement.3
+MLINKS+= Tcl_SetResult.3 Tcl_ResetResult.3
+MLINKS+= Tcl_SetVar.3 Tcl_SetVar2.3
+MLINKS+= Tcl_SetVar.3 Tcl_GetVar.3
+MLINKS+= Tcl_SetVar.3 Tcl_GetVar2.3
+MLINKS+= Tcl_SetVar.3 Tcl_UnsetVar.3
+MLINKS+= Tcl_SetVar.3 Tcl_UnsetVar2.3
+MLINKS+= Tcl_SplitList.3 Tcl_Merge.3
+MLINKS+= Tcl_SplitList.3 Tcl_ScanElement.3
+MLINKS+= Tcl_SplitList.3 Tcl_ConvertElement.3
+MLINKS+= Tcl_SplitPath.3 Tcl_JoinPath.3
+MLINKS+= Tcl_SplitPath.3 Tcl_GetPathType.3
+MLINKS+= Tcl_TraceVar.3 Tcl_TraceVar2.3
+MLINKS+= Tcl_TraceVar.3 Tcl_UntraceVar.3
+MLINKS+= Tcl_TraceVar.3 Tcl_UntraceVar2.3
+MLINKS+= Tcl_TraceVar.3 Tcl_VarTraceInfo.3
+MLINKS+= Tcl_TraceVar.3 Tcl_VarTraceInfo2.3
+MLINKS+= Tcl_UpVar.3 Tcl_UpVar2.3
+
+# Ugly, I know, but what else can I do?!?
+TCLMAN+= Tcl_AddErrorInfo.3 AddErrInfo.3
+TCLMAN+= Tcl_Alloc.3 Alloc.3
+TCLMAN+= Tcl_AllowExceptions.3 AllowExc.3
+TCLMAN+= Tcl_AppInit.3 AppInit.3
+TCLMAN+= Tcl_GetAssocData.3 AssocData.3
+TCLMAN+= Tcl_AsyncCreate.3 Async.3
+TCLMAN+= Tcl_BackgroundError.3 BackgdErr.3
+TCLMAN+= Tcl_Backslash.3 Backslash.3
+TCLMAN+= Tcl_CallWhenDeleted.3 CallDel.3
+TCLMAN+= Tcl_CommandComplete.3 CmdCmplt.3
+TCLMAN+= Tcl_Concat.3 Concat.3
+TCLMAN+= Tcl_CreateChannel.3 CrtChannel.3
+TCLMAN+= Tcl_CreateChannelHandler.3 CrtChnlHdlr.3
+TCLMAN+= Tcl_CreateCloseHandler.3 CrtCloseHdlr.3
+TCLMAN+= Tcl_CreateCommand.3 CrtCommand.3
+TCLMAN+= Tcl_CreateFileHandler.3 CrtFileHdlr.3
+TCLMAN+= Tcl_CreateInterp.3 CrtInterp.3
+TCLMAN+= Tcl_CreateMathFunc.3 CrtMathFnc.3
+TCLMAN+= Tcl_CreateModalTimeout.3 CrtModalTmt.3
+TCLMAN+= Tcl_IsSafe.3 CrtSlave.3
+TCLMAN+= Tcl_CreateTimerHandler.3 CrtTimerHdlr.3
+TCLMAN+= Tcl_CreateTrace.3 CrtTrace.3
+TCLMAN+= Tcl_DStringInit.3 DString.3
+TCLMAN+= Tcl_DetachPids.3 DetachPids.3
+TCLMAN+= Tcl_DoOneEvent.3 DoOneEvent.3
+TCLMAN+= Tcl_DoWhenIdle.3 DoWhenIdle.3
+TCLMAN+= Tcl_Eval.3 Eval.3
+TCLMAN+= Tcl_Exit.3 Exit.3
+TCLMAN+= Tcl_ExprLong.3 ExprLong.3
+TCLMAN+= Tcl_FindExecutable.3 FindExec.3
+TCLMAN+= Tcl_GetFile.3 GetFile.3
+TCLMAN+= Tcl_GetInt.3 GetInt.3
+TCLMAN+= Tcl_GetOpenFile.3 GetOpnFl.3
+TCLMAN+= Tcl_GetStdChannel.3 GetStdChan.3
+TCLMAN+= Tcl_InitHashTable.3 Hash.3
+TCLMAN+= Tcl_Interp.3 Interp.3
+TCLMAN+= Tcl_LinkVar.3 LinkVar.3
+TCLMAN+= Tcl_CreateEventSource.3 Notifier.3
+TCLMAN+= Tcl_OpenFileChannel.3 OpenFileChnl.3
+TCLMAN+= Tcl_OpenTcpClient.3 OpenTcp.3
+TCLMAN+= Tcl_PkgRequire.3 PkgRequire.3
+TCLMAN+= Tcl_Preserve.3 Preserve.3
+TCLMAN+= Tcl_PrintDouble.3 PrintDbl.3
+TCLMAN+= Tcl_RecordAndEval.3 RecordEval.3
+TCLMAN+= Tcl_RegExpMatch.3 RegExp.3
+TCLMAN+= Tcl_SetErrno.3 SetErrno.3
+TCLMAN+= Tcl_SetRecursionLimit.3 SetRecLmt.3
+TCLMAN+= Tcl_SetResult.3 SetResult.3
+TCLMAN+= Tcl_SetVar.3 SetVar.3
+TCLMAN+= Tcl_Sleep.3 Sleep.3
+TCLMAN+= Tcl_SplitList.3 SplitList.3
+TCLMAN+= Tcl_SplitPath.3 SplitPath.3
+TCLMAN+= Tcl_StaticPackage.3 StaticPkg.3
+TCLMAN+= Tcl_StringMatch.3 StrMatch.3
+TCLMAN+= Tcl_Main.3 Tcl_Main.3
+TCLMAN+= Tcl_TraceVar.3 TraceVar.3
+TCLMAN+= Tcl_TranslateFileName.3 Translate.3
+TCLMAN+= Tcl_UpVar.3 UpVar.3
+
+_tcltmp=
+_tclprev=
+.for _tclpage in ${TCLMAN}
+.if !empty(_tclprev)
+_tcltmp:= ${_tcltmp} ${_tclprev} # assign with expansion
+${_tclprev}: ${TCLDIST}/doc/${_tclpage}
+ cp -f ${.ALLSRC} ${.TARGET}
+_tclprev=
+.else
+_tclprev=${_tclpage}
+.endif
+.endfor
+CLEANFILES+= ${_tcltmp}
+
+.include <bsd.lib.mk>
diff --git a/lib/libtcl/tclConfig.sh b/lib/libtcl/tclConfig.sh
new file mode 100644
index 0000000..863e3d9
--- /dev/null
+++ b/lib/libtcl/tclConfig.sh
@@ -0,0 +1,99 @@
+# tclConfig.sh --
+#
+# This shell script (for sh) is generated automatically by Tcl's
+# configure script. It will create shell variables for most of
+# the configuration options discovered by the configure script.
+# This script is intended to be included by the configure scripts
+# for Tcl extensions so that they don't have to figure this all
+# out for themselves.
+#
+# The information in this file is specific to a single platform.
+#
+# SCCS: @(#) tclConfig.sh.in 1.15 96/04/17 10:46:27
+
+# Tcl's version number.
+TCL_VERSION='7.5'
+TCL_MAJOR_VERSION='7'
+TCL_MINOR_VERSION='5'
+
+# C compiler to use for compilation.
+TCL_CC='cc'
+
+# -D flags for use with the C compiler.
+TCL_DEFS=' -DHAVE_UNISTD_H=1 -DHAVE_SYS_TIME_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_TM_ZONE=1 -DHAVE_TM_GMTOFF=1 -DSTDC_HEADERS=1 -DNEED_MATHERR=1 '
+
+# The name of the Tcl library (may be either a .a file or a shared library):
+TCL_LIB_FILE=libtcl75.so.1.1
+
+# Additional libraries to use when linking Tcl.
+TCL_LIBS=' -lm'
+
+# Top-level directory in which Tcl's platform-independent files are
+# installed.
+TCL_PREFIX='/usr'
+
+# Top-level directory in which Tcl's platform-specific files (e.g.
+# executables) are installed.
+TCL_EXEC_PREFIX='/usr'
+
+# Flags to pass to cc when compiling the components of a shared library:
+TCL_SHLIB_CFLAGS='-fPIC'
+
+# Base command to use for combining object files into a shared library:
+TCL_SHLIB_LD='ld -Bshareable -x'
+
+# Either '$LIBS' (if dependent libraries should be included when linking
+# shared libraries) or an empty string. See Tcl's configure.in for more
+# explanation.
+TCL_SHLIB_LD_LIBS=''
+
+# Suffix to use for the name of a shared library.
+TCL_SHLIB_SUFFIX='.so'
+
+# Library file(s) to include in tclsh and other base applications
+# in order to provide facilities needed by DLOBJ above.
+TCL_DL_LIBS=''
+
+# Flags to pass to the compiler when linking object files into
+# an executable tclsh or tcltest binary.
+TCL_LD_FLAGS=''
+
+# Flags to pass to ld, such as "-R /usr/local/tcl/lib", that tell the
+# run-time dynamic linker where to look for shared libraries such as
+# libtcl.so. Used when linking applications. Only works if there
+# is a variable "LIB_INSTALL_DIR" defined in the Makefile.
+TCL_LD_SEARCH_FLAGS=''
+
+# Additional object files linked with Tcl to provide compatibility
+# with standard facilities from ANSI C or POSIX.
+TCL_COMPAT_OBJS=''
+
+# Name of the ranlib program to use.
+TCL_RANLIB='ranlib'
+
+# String to pass to linker to pick up the Tcl library from its
+# build directory.
+TCL_BUILD_LIB_SPEC='-ltcl75'
+
+# String to pass to linker to pick up the Tcl library from its
+# installed directory.
+TCL_LIB_SPEC='-ltcl75'
+
+# Indicates whether a version numbers should be used in -l switches
+# ("ok" means it's safe to use switches like -ltcl7.5; "nodots" means
+# use switches like -ltcl75). SunOS and FreeBSD require "nodots", for
+# example.
+TCL_LIB_VERSIONS_OK='nodots'
+
+# String that can be evaluated to generate the part of a shared library
+# name that comes after the "libxxx" (includes version number, if any,
+# extension, and anything else needed). May depend on the variables
+# VERSION and SHLIB_SUFFIX. On most UNIX systems this is
+# ${VERSION}${SHLIB_SUFFIX}.
+TCL_SHARED_LIB_SUFFIX='`echo ${VERSION} | tr -d .`.so.1.0'
+
+# String that can be evaluated to generate the part of an unshared library
+# name that comes after the "libxxx" (includes version number, if any,
+# extension, and anything else needed). May depend on the variable
+# VERSION. On most UNIX systems this is ${VERSION}.a.
+TCL_UNSHARED_LIB_SUFFIX='`echo ${VERSION} | tr -d .`.a'
diff --git a/lib/libtelnet/Makefile b/lib/libtelnet/Makefile
index 495dd73..eff83a8 100644
--- a/lib/libtelnet/Makefile
+++ b/lib/libtelnet/Makefile
@@ -1,33 +1,12 @@
-# @(#)Makefile 8.2 (Berkeley) 12/15/93
+# From: @(#)Makefile 8.2 (Berkeley) 12/15/93
+# $Id$
LIB= telnet
-SRCS= auth.c encrypt.c genget.c getent.c misc.c
-SRCS+= kerberos.c enc_des.c
+SRCS= genget.c getent.c misc.c
+#SRCS+= auth.c encrypt.c
+#SRCS+= kerberos.c enc_des.c
#SRCS+= kerberos5.c
-CFLAGS+= -DENCRYPTION -DAUTHENTICATION -DHAS_CGETENT
-CFLAGS+= -DKRB4 -DDES_ENCRYPTION -I/usr/include/kerberosIV
-
-# These are the sources that have encryption stuff in them.
-CRYPT_SRC= auth.c enc-proto.h enc_des.c encrypt.c
-CRYPT_SRC+= encrypt.h kerberos.c kerberos5.c krb4encpwd.c
-CRYPT_SRC+= misc.c spx.c Makefile
-NOCRYPT_DIR=${.CURDIR}/Nocrypt
+CFLAGS+= -DHAS_CGETENT
.include <bsd.lib.mk>
-nocrypt:
-#ifdef ENCRYPTION
- @for i in ${CRYPT_SRC}; do \
- if [ ! -d ${NOCRYPT_DIR} ]; then \
- echo Creating subdirectory ${NOCRYPT_DIR}; \
- mkdir ${NOCRYPT_DIR}; \
- fi; \
- echo ${NOCRYPT_DIR}/$$i; \
- unifdef -UENCRYPTION ${.CURDIR}/$$i | \
- sed "s/ || defined(ENCRYPTION)//" > ${NOCRYPT_DIR}/$$i; \
- done
-
-placeholder:
-#else /* ENCRYPTION */
- @echo "Encryption code already removed."
-#endif /* ENCRYPTION */
diff --git a/lib/libtelnet/genget.c b/lib/libtelnet/genget.c
index a43579f..29c7519 100644
--- a/lib/libtelnet/genget.c
+++ b/lib/libtelnet/genget.c
@@ -49,7 +49,6 @@ static char sccsid[] = "@(#)genget.c 8.1 (Berkeley) 6/4/93";
isprefix(s1, s2)
register char *s1, *s2;
{
- register int n = 0;
char *os1;
register char c1, c2;
diff --git a/lib/libtelnet/getent.c b/lib/libtelnet/getent.c
index 05626f1..e87bf66 100644
--- a/lib/libtelnet/getent.c
+++ b/lib/libtelnet/getent.c
@@ -35,9 +35,12 @@
static char sccsid[] = "@(#)getent.c 8.2 (Berkeley) 12/15/93";
#endif /* not lint */
+#include <stdlib.h>
+
static char *area;
/*ARGSUSED*/
+int
getent(cp, name)
char *cp, *name;
{
diff --git a/lib/libtelnet/misc.c b/lib/libtelnet/misc.c
index 9565900..d4242b6 100644
--- a/lib/libtelnet/misc.c
+++ b/lib/libtelnet/misc.c
@@ -35,6 +35,8 @@
static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */
+#include <stdio.h>
+#include <stdlib.h>
#include "misc.h"
char *RemoteHostName;
@@ -54,9 +56,6 @@ auth_encrypt_init(local, remote, name, server)
#if defined(AUTHENTICATION)
auth_init(name, server);
#endif
-#ifdef ENCRYPTION
- encrypt_init(name, server);
-#endif /* ENCRYPTION */
if (UserNameRequested) {
free(UserNameRequested);
UserNameRequested = 0;
diff --git a/lib/libterm/Makefile b/lib/libterm/Makefile
deleted file mode 100644
index ba4218b..0000000
--- a/lib/libterm/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 6/4/93
-
-LIB= termcap
-CFLAGS+=-DCM_N -DCM_GT -DCM_B -DCM_D
-SRCS= termcap.c tgoto.c tputs.c
-
-MAN3= termcap.0
-MLINKS= termcap.3 tgetent.3 termcap.3 tgetflag.3 termcap.3 tgetnum.3 \
- termcap.3 tgetstr.3 termcap.3 tgoto.3 termcap.3 tputs.3
-LINKS= ${LIBDIR}/libtermcap.a ${LIBDIR}/libtermlib.a \
- ${LIBDIR}/libtermcap_p.a ${LIBDIR}/libtermlib_p.a
-
-.include <bsd.lib.mk>
diff --git a/lib/libtermcap/Makefile b/lib/libtermcap/Makefile
index ba4218b..6f142e3 100644
--- a/lib/libtermcap/Makefile
+++ b/lib/libtermcap/Makefile
@@ -1,13 +1,26 @@
# @(#)Makefile 8.1 (Berkeley) 6/4/93
LIB= termcap
-CFLAGS+=-DCM_N -DCM_GT -DCM_B -DCM_D
-SRCS= termcap.c tgoto.c tputs.c
+SHLIB_MAJOR= 2
+SHLIB_MINOR= 1
+CFLAGS+=-DCM_N -DCM_GT -DCM_B -DCM_D -I${.CURDIR}
+SRCS= termcap.c tgoto.c tputs.c tparm.c tospeed.c
-MAN3= termcap.0
+MAN3= termcap.3
MLINKS= termcap.3 tgetent.3 termcap.3 tgetflag.3 termcap.3 tgetnum.3 \
- termcap.3 tgetstr.3 termcap.3 tgoto.3 termcap.3 tputs.3
-LINKS= ${LIBDIR}/libtermcap.a ${LIBDIR}/libtermlib.a \
- ${LIBDIR}/libtermcap_p.a ${LIBDIR}/libtermlib_p.a
+ termcap.3 tgetstr.3 termcap.3 tgoto.3 termcap.3 tputs.3 \
+ termcap.3 tparm.3 termcap.3 __set_ospeed.3
+LINKS= ${LIBDIR}/libtermcap.a ${LIBDIR}/libtermlib.a
+.if !defined(NOPIC)
+LINKS+= ${SHLIBDIR}/libtermcap.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \
+ ${SHLIBDIR}/libtermlib.so.${SHLIB_MAJOR}.${SHLIB_MINOR}
+.endif
+.if !defined(NOPROFILE)
+LINKS+= ${LIBDIR}/libtermcap_p.a ${LIBDIR}/libtermlib_p.a
+.endif
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/termcap.h \
+ ${DESTDIR}/usr/include
.include <bsd.lib.mk>
diff --git a/lib/libtermcap/pathnames.h b/lib/libtermcap/pathnames.h
index db3ccf7..e77bab8 100644
--- a/lib/libtermcap/pathnames.h
+++ b/lib/libtermcap/pathnames.h
@@ -34,3 +34,4 @@
*/
#define _PATH_DEF ".termcap /usr/share/misc/termcap"
+#define _PATH_DEF_SEC "/usr/share/misc/termcap"
diff --git a/lib/libtermcap/termcap.3 b/lib/libtermcap/termcap.3
index 08173cd..d6d2656 100644
--- a/lib/libtermcap/termcap.3
+++ b/lib/libtermcap/termcap.3
@@ -40,21 +40,32 @@
.Nm tgetflag ,
.Nm tgetstr ,
.Nm tgoto ,
-.Nm tputs
+.Nm tputs ,
+.Nm tparm ,
+.Nm __set_ospeed
.Nd terminal independent operation routines
.Sh SYNOPSIS
+.Fd #include <termcap.h>
.Vt char PC;
.Vt char *BC;
.Vt char *UP;
.Vt short ospeed;
-.Fn tgetent "char *bp" "char *name"
-.Fn tgetnum "char *id"
-.Fn tgetflag "char *id"
+.Ft int
+.Fn tgetent "char *bp" "const char *name"
+.Ft int
+.Fn tgetnum "const char *id"
+.Ft int
+.Fn tgetflag "const char *id"
.Ft char *
-.Fn tgetstr "char *id" "char **area"
+.Fn tgetstr "const char *id" "char **area"
.Ft char *
-.Fn tgoto "char *cm" destcol destline
-.Fn tputs "register char *cp" "int affcnt" "int (*outc)()"
+.Fn tgoto "const char *cm" "int destcol" "int destline"
+.Ft int
+.Fn tputs "const char *cp" "int affcnt" "int (*outc)(int)"
+.Ft char *
+.Fn tparm "const char *cp" "..."
+.Ft void
+.Fn __set_ospeed "long speed"
.Sh DESCRIPTION
These functions extract and use capabilities from a terminal capability data
base, usually
@@ -221,10 +232,6 @@ not applicable,
.Fa outc
is a routine which is called with each character in turn.
The external variable
-.Va ospeed
-should contain the output speed of the terminal as encoded by
-.Xr stty 3 .
-The external variable
.Va PC
should contain a pad character to be used (from the
.SY pc
@@ -232,6 +239,35 @@ capability)
if a null
.Pq Sy ^@
is inappropriate.
+The external variable
+.Va ospeed
+should contain the output speed of the terminal as encoded by
+.Xr stty 3 .
+The
+.Fn __set_ospeed
+function converts the speed in cps
+.Fa speed
+to the closest
+.Xr stty 3
+encoded speed and stores the result in
+.Va ospeed .
+.Pp
+The
+.Fn tparm
+function
+instantiates the string
+.Fa cp
+with the given parameters.
+A pointer is returned which points to
+the result of
+.Fa cp
+with the parameters applied.
+If a
+.Sy %
+sequence is given which is not understood, then
+.Fn tparm
+returns
+.Pq Dv OOPS .
.Sh FILES
.Bl -tag -width /usr/share/misc/termcap -compact
.It Pa /usr/lib/libtermcap.a
diff --git a/lib/libtermcap/termcap.c b/lib/libtermcap/termcap.c
index 708ccfa..96e07e5 100644
--- a/lib/libtermcap/termcap.c
+++ b/lib/libtermcap/termcap.c
@@ -37,11 +37,15 @@ static char sccsid[] = "@(#)termcap.c 8.1 (Berkeley) 6/4/93";
#define PBUFSIZ 512 /* max length of filename path */
#define PVECSIZ 32 /* max number of names in path */
+#define TBUFSIZ 1024 /* max length of tgetent buffer */
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+#include "termcap.h"
#include "pathnames.h"
/*
@@ -64,8 +68,7 @@ static char *tbuf; /* termcap buffer */
* Get an entry for terminal name in buffer bp from the termcap file.
*/
int
-tgetent(bp, name)
- char *bp, *name;
+tgetent(char *bp, const char *name)
{
register char *p;
register char *cp;
@@ -77,7 +80,9 @@ tgetent(bp, name)
char *pathvec[PVECSIZ]; /* to point to names in pathbuf */
char **pvec; /* holds usable tail of path vector */
char *termpath;
+ struct termios tty;
+ dummy = NULL;
fname = pathvec;
pvec = pathvec;
tbuf = bp;
@@ -94,12 +99,13 @@ tgetent(bp, name)
* becomes "$HOME/.termcap /etc/termcap" if no TERMPATH exists.
*/
if (!cp || *cp != '/') { /* no TERMCAP or it holds an entry */
- if (termpath = getenv("TERMPATH"))
+ if ( (termpath = getenv("TERMPATH")) )
strncpy(pathbuf, termpath, PBUFSIZ);
else {
- if (home = getenv("HOME")) { /* set up default */
- p += strlen(home); /* path, looking in */
- strcpy(pathbuf, home); /* $HOME first */
+ if ( (home = getenv("HOME")) ) {/* set up default */
+ strncpy(pathbuf, home, PBUFSIZ - 1); /* $HOME first */
+ pathbuf[PBUFSIZ - 2] = '\0'; /* -2 because we add a slash */
+ p += strlen(pathbuf); /* path, looking in */
*p++ = '/';
} /* if no $HOME look in current directory */
strncpy(p, _PATH_DEF, PBUFSIZ - (p - pathbuf));
@@ -107,7 +113,11 @@ tgetent(bp, name)
}
else /* user-defined name in TERMCAP */
strncpy(pathbuf, cp, PBUFSIZ); /* still can be tokenized */
+ pathbuf[PBUFSIZ - 1] = '\0';
+ /* XXX Should really be issetguid(), but we don't have that */
+ if (getuid() != geteuid() || getgid() != getegid())
+ strcpy(pathbuf, _PATH_DEF_SEC);
*fname++ = pathbuf; /* tokenize path into vector of names */
while (*++p)
if (*p == ' ' || *p == ':') {
@@ -128,11 +138,62 @@ tgetent(bp, name)
if (cgetset(cp) < 0)
return(-2);
- i = cgetent(&dummy, pathvec, name);
-
- if (i == 0)
- strcpy(bp, dummy);
-
+ i = cgetent(&dummy, pathvec, (char *)name);
+
+ if (i == 0) {
+ char *pd, *ps, *tok, *s, *tcs;
+ size_t len;
+
+ pd = bp;
+ ps = dummy;
+ if ((tok = strchr(ps, ':')) == NULL) {
+ len = strlen(ps);
+ if (len >= TBUFSIZ)
+ i = -1;
+ else
+ strcpy(pd, ps);
+ goto done;
+ }
+ len = tok - ps + 1;
+ if (pd + len + 1 - bp >= TBUFSIZ) {
+ i = -1;
+ goto done;
+ }
+ memcpy(pd, ps, len);
+ ps += len;
+ pd += len;
+ *pd = '\0';
+ tcs = pd - 1;
+ for (;;) {
+ while ((tok = strsep(&ps, ":")) != NULL &&
+ (*tok == '\0' || *tok == '\\' || !isgraph(*tok)))
+ ;
+ if (tok == NULL)
+ break;
+ for (s = tcs; s != NULL && s[1] != '\0'; s = strchr(s, ':')) {
+ s++;
+ if (s[0] == tok[0] && s[1] == tok[1])
+ goto skip_it;
+ }
+ len = strlen(tok);
+ if (pd + len + 1 - bp >= TBUFSIZ) {
+ i = -1;
+ break;
+ }
+ memcpy(pd, tok, len);
+ pd += len;
+ *pd++ = ':';
+ *pd = '\0';
+ skip_it: ;
+ }
+ }
+done:
+ if ( i == 0
+ && ( tcgetattr(STDERR_FILENO, &tty) != -1
+ || tcgetattr(STDOUT_FILENO, &tty) != -1
+ )
+ )
+ __set_ospeed(cfgetospeed(&tty));
if (dummy)
free(dummy);
/* no tc reference loop return code in libterm XXX */
@@ -150,12 +211,11 @@ tgetent(bp, name)
* Note that we handle octal numbers beginning with 0.
*/
int
-tgetnum(id)
- char *id;
+tgetnum(const char *id)
{
long num;
- if (cgetnum(tbuf, id, &num) == 0)
+ if (cgetnum(tbuf, (char *)id, &num) == 0)
return(num);
else
return(-1);
@@ -168,10 +228,9 @@ tgetnum(id)
* not given.
*/
int
-tgetflag(id)
- char *id;
+tgetflag(const char *id)
{
- return(cgetcap(tbuf, id, ':') != NULL);
+ return(cgetcap(tbuf, (char *)id, ':') != NULL);
}
/*
@@ -183,13 +242,12 @@ tgetflag(id)
* No checking on area overflow.
*/
char *
-tgetstr(id, area)
- char *id, **area;
+tgetstr(const char *id, char **area)
{
char ids[3];
char *s;
int i;
-
+
/*
* XXX
* This is for all the boneheaded programs that relied on tgetstr
@@ -201,7 +259,7 @@ tgetstr(id, area)
if ((i = cgetstr(tbuf, ids, &s)) < 0)
return NULL;
-
+
strcpy(*area, s);
*area += i + 1;
return(s);
diff --git a/lib/libtermcap/termcap.h b/lib/libtermcap/termcap.h
new file mode 100644
index 0000000..38345d6
--- /dev/null
+++ b/lib/libtermcap/termcap.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 1994,1995 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 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: termcap.h,v 1.10 1997/02/22 15:08:12 peter Exp $ */
+
+#ifndef _TERMCAP_H_
+#define _TERMCAP_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+extern char PC, *UP, *BC;
+extern short ospeed;
+
+extern int tgetent __P((char *, const char *));
+extern int tgetflag __P((const char *));
+extern int tgetnum __P((const char *));
+extern char *tgetstr __P((const char *, char **));
+
+extern int tputs __P((const char *, int, int (*)(int)));
+
+extern char *tgoto __P((const char *, int, int));
+extern char *tparm __P((const char *, ...));
+
+extern void __set_ospeed __P((long speed));
+
+__END_DECLS
+
+#endif /* _TERMCAP_H_ */
diff --git a/lib/libtermcap/tgoto.c b/lib/libtermcap/tgoto.c
index f0e4cc4..4088fa5 100644
--- a/lib/libtermcap/tgoto.c
+++ b/lib/libtermcap/tgoto.c
@@ -35,6 +35,9 @@
static char sccsid[] = "@(#)tgoto.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */
+#include <string.h>
+#include "termcap.h"
+
#define CTRL(c) ((c) & 037)
#define MAXRETURNSIZE 64
@@ -67,13 +70,11 @@ char *BC;
* all other characters are ``self-inserting''.
*/
char *
-tgoto(CM, destcol, destline)
- char *CM;
- int destcol, destline;
+tgoto(const char *CM, int destcol, int destline)
{
static char result[MAXRETURNSIZE];
static char added[10];
- char *cp = CM;
+ const char *cp = CM;
register char *dp = result;
register int c;
int oncol = 0;
@@ -87,8 +88,10 @@ toohard:
return ("OOPS");
}
added[0] = 0;
- while (c = *cp++) {
+ while ( (c = *cp++) ) {
if (c != '%') {
+ if (dp >= &result[MAXRETURNSIZE])
+ return ("OVERFLOW");
*dp++ = c;
continue;
}
@@ -109,14 +112,20 @@ toohard:
/* fall into... */
case '3':
+ if (dp >= &result[MAXRETURNSIZE])
+ return ("OVERFLOW");
*dp++ = (which / 100) | '0';
which %= 100;
/* fall into... */
case '2':
-two:
+two:
+ if (dp >= &result[MAXRETURNSIZE])
+ return ("OVERFLOW");
*dp++ = which / 10 | '0';
one:
+ if (dp >= &result[MAXRETURNSIZE])
+ return ("OVERFLOW");
*dp++ = which % 10 | '0';
swap:
oncol = 1 - oncol;
@@ -165,10 +174,17 @@ casedot:
* to be the successor of tab.
*/
do {
- strcat(added, oncol ? (BC ? BC : "\b") : UP);
+ const char *extra;
+
+ extra = oncol ? (BC ? BC : "\b") : UP;
+ if (strlen(added) + strlen(extra) >= 10)
+ return ("OVERFLOW");
+ strcat(added, extra);
which++;
} while (which == '\n');
}
+ if (dp >= &result[MAXRETURNSIZE])
+ return ("OVERFLOW");
*dp++ = which;
goto swap;
@@ -183,6 +199,8 @@ casedot:
continue;
case '%':
+ if (dp >= &result[MAXRETURNSIZE])
+ return ("OVERFLOW");
*dp++ = c;
continue;
@@ -202,6 +220,8 @@ casedot:
goto toohard;
}
}
+ if (strlen(added) >= &result[MAXRETURNSIZE] - dp)
+ return ("OVERFLOW");
strcpy(dp, added);
return (result);
}
diff --git a/lib/libtermcap/tospeed.c b/lib/libtermcap/tospeed.c
new file mode 100644
index 0000000..dd2026a
--- /dev/null
+++ b/lib/libtermcap/tospeed.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 1995 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 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 <termios.h>
+#include "termcap.h"
+
+static struct stable {
+ speed_t speed;
+ short code;
+} table[] = {
+ {B115200,17},
+ {B57600, 16},
+ {B38400, 15},
+ {B19200, 14},
+ {B9600, 13},
+ {B4800, 12},
+ {B2400, 11},
+ {B1800, 10},
+ {B1200, 9},
+ {B600, 8},
+ {B300, 7},
+ {B200, 6},
+ {B150, 5},
+ {B134, 4},
+ {B110, 3},
+ {B75, 2},
+ {B50, 1},
+ {B0, 0},
+ {-1, -1}
+};
+
+void __set_ospeed(speed_t speed)
+{
+ struct stable *stable;
+
+ if (speed == B0) {
+ ospeed = 0;
+ return;
+ }
+ for (stable = table; stable->speed > B0; stable++) {
+ /* nearest one, rounded down */
+ if (stable->speed <= speed) {
+ ospeed = stable->code;
+ return;
+ }
+ }
+ ospeed = 1; /* 50, min and not hangup */
+}
+
diff --git a/lib/libtermcap/tparm.c b/lib/libtermcap/tparm.c
new file mode 100644
index 0000000..6a537ce
--- /dev/null
+++ b/lib/libtermcap/tparm.c
@@ -0,0 +1,753 @@
+/*
+ * tparm.c
+ *
+ * By Ross Ridge
+ * Public Domain
+ * 92/02/01 07:30:36
+ *
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include "termcap.h"
+
+#ifdef USE_SCCS_IDS
+static const char SCCSid[] = "@(#) mytinfo tparm.c 3.2 92/02/01 public domain, By Ross Ridge";
+#endif
+
+#ifndef MAX_PUSHED
+#define MAX_PUSHED 32
+#endif
+
+#define ARG 1
+#define NUM 2
+
+#define INTEGER 1
+#define STRING 2
+
+#define MAX_LINE 640
+
+typedef void* anyptr;
+
+typedef struct stack_str {
+ int type;
+ int argnum;
+ int value;
+} stack;
+
+static stack S[MAX_PUSHED];
+static stack vars['z'-'a'+1];
+static int pos = 0;
+
+static struct arg_str {
+ int type;
+ int integer;
+ char *string;
+} arg_list[10];
+
+static int argcnt;
+
+static va_list tparm_args;
+
+static int
+pusharg(arg)
+int arg; {
+ if (pos == MAX_PUSHED)
+ return 1;
+ S[pos].type = ARG;
+ S[pos++].argnum = arg;
+ return 0;
+}
+
+static int
+pushnum(num)
+int num; {
+ if (pos == MAX_PUSHED)
+ return 1;
+ S[pos].type = NUM;
+ S[pos++].value = num;
+ return 0;
+}
+
+/* VARARGS2 */
+static int
+getarg(argnum, type, p)
+int argnum, type;
+anyptr p; {
+ while (argcnt < argnum) {
+ arg_list[argcnt].type = INTEGER;
+ arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
+ }
+ if (argcnt > argnum) {
+ if (arg_list[argnum].type != type)
+ return 1;
+ else if (type == STRING)
+ *(char **)p = arg_list[argnum].string;
+ else
+ *(int *)p = arg_list[argnum].integer;
+ } else {
+ arg_list[argcnt].type = type;
+ if (type == STRING)
+ *(char **)p = arg_list[argcnt++].string
+ = (char *) va_arg(tparm_args, char *);
+ else
+ *(int *)p = arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
+ }
+ return 0;
+}
+
+
+static int
+popstring(str)
+char **str; {
+ if (pos-- == 0)
+ return 1;
+ if (S[pos].type != ARG)
+ return 1;
+ return(getarg(S[pos].argnum, STRING, (anyptr) str));
+}
+
+static int
+popnum(num)
+int *num; {
+ if (pos-- == 0)
+ return 1;
+ switch (S[pos].type) {
+ case ARG:
+ return (getarg(S[pos].argnum, INTEGER, (anyptr) num));
+ case NUM:
+ *num = S[pos].value;
+ return 0;
+ }
+ return 1;
+}
+
+static int
+cvtchar(sp, c)
+register char *sp, *c; {
+ switch(*sp) {
+ case '\\':
+ switch(*++sp) {
+ case '\'':
+ case '$':
+ case '\\':
+ case '%':
+ *c = *sp;
+ return 2;
+ case '\0':
+ *c = '\\';
+ return 1;
+ case '0':
+ if (sp[1] == '0' && sp[2] == '0') {
+ *c = '\0';
+ return 4;
+ }
+ *c = '\200'; /* '\0' ???? */
+ return 2;
+ default:
+ *c = *sp;
+ return 2;
+ }
+ default:
+ *c = *sp;
+ return 1;
+ }
+}
+
+static int termcap;
+
+/* sigh... this has got to be the ugliest code I've ever written.
+ Trying to handle everything has its cost, I guess.
+
+ It actually isn't to hard to figure out if a given % code is supposed
+ to be interpeted with its termcap or terminfo meaning since almost
+ all terminfo codes are invalid unless something has been pushed on
+ the stack and termcap strings will never push things on the stack
+ (%p isn't used by termcap). So where we have a choice we make the
+ decision by wether or not somthing has been pushed on the stack.
+ The static variable termcap keeps track of this; it starts out set
+ to 1 and is incremented as each argument processed by a termcap % code,
+ however if something is pushed on the stack it's set to 0 and the
+ rest of the % codes are interpeted as terminfo % codes. Another way
+ of putting it is that if termcap equals one we haven't decided either
+ way yet, if it equals zero we're looking for terminfo codes, and if
+ its greater than 1 we're looking for termcap codes.
+
+ Terminfo % codes:
+
+ %% output a '%'
+ %[[:][-+# ][width][.precision]][doxXs]
+ output pop according to the printf format
+ %c output pop as a char
+ %'c' push character constant c.
+ %{n} push decimal constant n.
+ %p[1-9] push paramter [1-9]
+ %g[a-z] push variable [a-z]
+ %P[a-z] put pop in variable [a-z]
+ %l push the length of pop (a string)
+ %+ add pop to pop and push the result
+ %- subtract pop from pop and push the result
+ %* multiply pop and pop and push the result
+ %& bitwise and pop and pop and push the result
+ %| bitwise or pop and pop and push the result
+ %^ bitwise xor pop and pop and push the result
+ %~ push the bitwise not of pop
+ %= compare if pop and pop are equal and push the result
+ %> compare if pop is less than pop and push the result
+ %< compare if pop is greater than pop and push the result
+ %A logical and pop and pop and push the result
+ %O logical or pop and pop and push the result
+ %! push the logical not of pop
+ %? condition %t if_true [%e if_false] %;
+ if condtion evaulates as true then evaluate if_true,
+ else evaluate if_false. elseif's can be done:
+%? cond %t true [%e cond2 %t true2] ... [%e condN %t trueN] [%e false] %;
+ %i add one to parameters 1 and 2. (ANSI)
+
+ Termcap Codes:
+
+ %% output a %
+ %. output parameter as a character
+ %d output parameter as a decimal number
+ %2 output parameter in printf format %02d
+ %3 output parameter in printf format %03d
+ %+x add the character x to parameter and output it as a character
+(UW) %-x subtract parameter FROM the character x and output it as a char
+(UW) %ax add the character x to parameter
+(GNU) %a[+*-/=][cp]x
+ GNU arithmetic.
+(UW) %sx subtract parameter FROM the character x
+ %>xy if parameter > character x then add character y to parameter
+ %B convert to BCD (parameter = (parameter/10)*16 + parameter%16)
+ %D Delta Data encode (parameter = parameter - 2*(paramter%16))
+ %i increment the first two parameters by one
+ %n xor the first two parameters by 0140
+(GNU) %m xor the first two parameters by 0177
+ %r swap the first two parameters
+(GNU) %b backup to previous parameter
+(GNU) %f skip this parameter
+
+ Note the two definitions of %a, the GNU defintion is used if the characters
+ after the 'a' are valid, otherwise the UW definition is used.
+
+ (GNU) used by GNU Emacs termcap libraries
+ (UW) used by the University of Waterloo (MFCF) termcap libraries
+
+*/
+
+char *tparm(const char *str, ...) {
+ static char OOPS[] = "OOPS";
+ static char buf[MAX_LINE];
+ register const char *sp;
+ register char *dp;
+ register char *fmt;
+ char conv_char;
+ char scan_for;
+ int scan_depth = 0, if_depth;
+ static int i, j;
+ static char *s, c;
+ char fmt_buf[MAX_LINE];
+ char sbuf[MAX_LINE];
+
+ va_start(tparm_args, str);
+
+ sp = str;
+ dp = buf;
+ scan_for = 0;
+ if_depth = 0;
+ argcnt = 0;
+ pos = 0;
+ termcap = 1;
+ while(*sp != '\0') {
+ switch(*sp) {
+ case '\\':
+ if (scan_for) {
+ if (*++sp != '\0')
+ sp++;
+ break;
+ }
+ *dp++ = *sp++;
+ if (*sp != '\0')
+ *dp++ = *sp++;
+ break;
+ case '%':
+ sp++;
+ if (scan_for) {
+ if (*sp == scan_for && if_depth == scan_depth) {
+ if (scan_for == ';')
+ if_depth--;
+ scan_for = 0;
+ } else if (*sp == '?')
+ if_depth++;
+ else if (*sp == ';') {
+ if (if_depth == 0)
+ return OOPS;
+ else
+ if_depth--;
+ }
+ sp++;
+ break;
+ }
+ fmt = NULL;
+ switch(*sp) {
+ case '%':
+ *dp++ = *sp++;
+ break;
+ case '+':
+ if (!termcap) {
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i += j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ }
+ ;/* FALLTHROUGH */
+ case 'C':
+ if (*sp == 'C') {
+ if (getarg(termcap - 1, INTEGER, &i))
+ return OOPS;
+ if (i >= 96) {
+ i /= 96;
+ if (i == '$')
+ *dp++ = '\\';
+ *dp++ = i;
+ }
+ }
+ fmt = "%c";
+ /* FALLTHROUGH */
+ case 'a':
+ if (!termcap)
+ return OOPS;
+ if (getarg(termcap - 1, INTEGER, (anyptr) &i))
+ return OOPS;
+ if (*++sp == '\0')
+ return OOPS;
+ if ((sp[1] == 'p' || sp[1] == 'c')
+ && sp[2] != '\0' && fmt == NULL) {
+ /* GNU aritmitic parameter, what they
+ realy need is terminfo. */
+ int val, lc;
+ if (sp[1] == 'p'
+ && getarg(termcap - 1 + sp[2] - '@',
+ INTEGER, (anyptr) &val))
+ return OOPS;
+ if (sp[1] == 'c') {
+ lc = cvtchar(sp + 2, &c) + 2;
+ /* Mask out 8th bit so \200 can be
+ used for \0 as per GNU doc's */
+ val = c & 0177;
+ } else
+ lc = 2;
+ switch(sp[0]) {
+ case '=':
+ break;
+ case '+':
+ val = i + val;
+ break;
+ case '-':
+ val = i - val;
+ break;
+ case '*':
+ val = i * val;
+ break;
+ case '/':
+ val = i / val;
+ break;
+ default:
+ /* Not really GNU's %a after all... */
+ lc = cvtchar(sp, &c);
+ val = c + i;
+ break;
+ }
+ arg_list[termcap - 1].integer = val;
+ sp += lc;
+ break;
+ }
+ sp += cvtchar(sp, &c);
+ arg_list[termcap - 1].integer = c + i;
+ if (fmt == NULL)
+ break;
+ sp--;
+ /* FALLTHROUGH */
+ case '-':
+ if (!termcap) {
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i -= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ }
+ fmt = "%c";
+ /* FALLTHROUGH */
+ case 's':
+ if (termcap && (fmt == NULL || *sp == '-')) {
+ if (getarg(termcap - 1, INTEGER, &i))
+ return OOPS;
+ if (*++sp == '\0')
+ return OOPS;
+ sp += cvtchar(sp, &c);
+ arg_list[termcap - 1].integer = c - i;
+ if (fmt == NULL)
+ break;
+ sp--;
+ }
+ if (!termcap)
+ return OOPS;
+ ;/* FALLTHROUGH */
+ case '.':
+ if (termcap && fmt == NULL)
+ fmt = "%c";
+ ;/* FALLTHROUGH */
+ case 'd':
+ if (termcap && fmt == NULL)
+ fmt = "%d";
+ ;/* FALLTHROUGH */
+ case '2':
+ if (termcap && fmt == NULL)
+ fmt = "%02d";
+ ;/* FALLTHROUGH */
+ case '3':
+ if (termcap && fmt == NULL)
+ fmt = "%03d";
+ ;/* FALLTHROUGH */
+ case ':': case ' ': case '#': case 'u':
+ case 'x': case 'X': case 'o': case 'c':
+ case '0': case '1': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ if (fmt == NULL) {
+ if (termcap)
+ return OOPS;
+ if (*sp == ':')
+ sp++;
+ fmt = fmt_buf;
+ *fmt++ = '%';
+ while(*sp != 's' && *sp != 'x' && *sp != 'X' && *sp != 'd' && *sp != 'o' && *sp != 'c' && *sp != 'u') {
+ if (*sp == '\0')
+ return OOPS;
+ *fmt++ = *sp++;
+ }
+ *fmt++ = *sp;
+ *fmt = '\0';
+ fmt = fmt_buf;
+ }
+ conv_char = fmt[strlen(fmt) - 1];
+ if (conv_char == 's') {
+ if (popstring(&s))
+ return OOPS;
+ sprintf(sbuf, fmt, s);
+ } else {
+ if (termcap) {
+ if (getarg(termcap++ - 1,
+ INTEGER, &i))
+ return OOPS;
+ } else
+ if (popnum(&i))
+ return OOPS;
+ if (i == 0 && conv_char == 'c')
+ strcpy(sbuf, "\000");
+ else
+ sprintf(sbuf, fmt, i);
+ }
+ sp++;
+ fmt = sbuf;
+ while(*fmt != '\0') {
+ if (*fmt == '$')
+ *dp++ = '\\';
+ *dp++ = *fmt++;
+ }
+ break;
+ case 'r':
+ if (!termcap || getarg(1, INTEGER, &i))
+ return OOPS;
+ arg_list[1].integer = arg_list[0].integer;
+ arg_list[0].integer = i;
+ sp++;
+ break;
+ case 'i':
+ if (getarg(1, INTEGER, &i)
+ || arg_list[0].type != INTEGER)
+ return OOPS;
+ arg_list[1].integer++;
+ arg_list[0].integer++;
+ sp++;
+ break;
+ case 'n':
+ if (!termcap || getarg(1, INTEGER, &i))
+ return OOPS;
+ arg_list[0].integer ^= 0140;
+ arg_list[1].integer ^= 0140;
+ sp++;
+ break;
+ case '>':
+ if (!termcap) {
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i = (i > j);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ }
+ if (getarg(termcap-1, INTEGER, &i))
+ return OOPS;
+ sp += cvtchar(sp, &c);
+ if (i > c) {
+ sp += cvtchar(sp, &c);
+ arg_list[termcap-1].integer += c;
+ } else
+ sp += cvtchar(sp, &c);
+ sp++;
+ break;
+ case 'B':
+ if (!termcap || getarg(termcap-1, INTEGER, &i))
+ return OOPS;
+ arg_list[termcap-1].integer = 16*(i/10)+i%10;
+ sp++;
+ break;
+ case 'D':
+ if (!termcap || getarg(termcap-1, INTEGER, &i))
+ return OOPS;
+ arg_list[termcap-1].integer = i - 2 * (i % 16);
+ sp++;
+ break;
+ case 'p':
+ if (termcap > 1)
+ return OOPS;
+ if (*++sp == '\0')
+ return OOPS;
+ if (*sp == '0')
+ i = 9;
+ else
+ i = *sp - '1';
+ if (i < 0 || i > 9)
+ return OOPS;
+ if (pusharg(i))
+ return OOPS;
+ termcap = 0;
+ sp++;
+ break;
+ case 'P':
+ if (termcap || *++sp == '\0')
+ return OOPS;
+ i = *sp++ - 'a';
+ if (i < 0 || i > 25)
+ return OOPS;
+ if (pos-- == 0)
+ return OOPS;
+ switch(vars[i].type = S[pos].type) {
+ case ARG:
+ vars[i].argnum = S[pos].argnum;
+ break;
+ case NUM:
+ vars[i].value = S[pos].value;
+ break;
+ }
+ break;
+ case 'g':
+ if (termcap || *++sp == '\0')
+ return OOPS;
+ i = *sp++ - 'a';
+ if (i < 0 || i > 25)
+ return OOPS;
+ switch(vars[i].type) {
+ case ARG:
+ if (pusharg(vars[i].argnum))
+ return OOPS;
+ break;
+ case NUM:
+ if (pushnum(vars[i].value))
+ return OOPS;
+ break;
+ }
+ break;
+ case '\'':
+ if (termcap > 1)
+ return OOPS;
+ if (*++sp == '\0')
+ return OOPS;
+ sp += cvtchar(sp, &c);
+ if (pushnum(c) || *sp++ != '\'')
+ return OOPS;
+ termcap = 0;
+ break;
+ case '{':
+ if (termcap > 1)
+ return OOPS;
+ i = 0;
+ sp++;
+ while(isdigit(*sp))
+ i = 10 * i + *sp++ - '0';
+ if (*sp++ != '}' || pushnum(i))
+ return OOPS;
+ termcap = 0;
+ break;
+ case 'l':
+ if (termcap || popstring(&s))
+ return OOPS;
+ i = strlen(s);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '*':
+ if (termcap || popnum(&j) || popnum(&i))
+ return OOPS;
+ i *= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '/':
+ if (termcap || popnum(&j) || popnum(&i))
+ return OOPS;
+ i /= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case 'm':
+ if (termcap) {
+ if (getarg(1, INTEGER, &i))
+ return OOPS;
+ arg_list[0].integer ^= 0177;
+ arg_list[1].integer ^= 0177;
+ sp++;
+ break;
+ }
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i %= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '&':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i &= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '|':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i |= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '^':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i ^= j;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '=':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i = (i == j);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '<':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i = (i < j);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case 'A':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i = (i && j);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case 'O':
+ if (popnum(&j) || popnum(&i))
+ return OOPS;
+ i = (i || j);
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '!':
+ if (popnum(&i))
+ return OOPS;
+ i = !i;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '~':
+ if (popnum(&i))
+ return OOPS;
+ i = ~i;
+ if (pushnum(i))
+ return OOPS;
+ sp++;
+ break;
+ case '?':
+ if (termcap > 1)
+ return OOPS;
+ termcap = 0;
+ if_depth++;
+ sp++;
+ break;
+ case 't':
+ if (popnum(&i) || if_depth == 0)
+ return OOPS;
+ if (!i) {
+ scan_for = 'e';
+ scan_depth = if_depth;
+ }
+ sp++;
+ break;
+ case 'e':
+ if (if_depth == 0)
+ return OOPS;
+ scan_for = ';';
+ scan_depth = if_depth;
+ sp++;
+ break;
+ case ';':
+ if (if_depth-- == 0)
+ return OOPS;
+ sp++;
+ break;
+ case 'b':
+ if (--termcap < 1)
+ return OOPS;
+ sp++;
+ break;
+ case 'f':
+ if (!termcap++)
+ return OOPS;
+ sp++;
+ break;
+ }
+ break;
+ default:
+ if (scan_for)
+ sp++;
+ else
+ *dp++ = *sp++;
+ break;
+ }
+ }
+ va_end(tparm_args);
+ *dp = '\0';
+ return buf;
+}
diff --git a/lib/libtermcap/tputs.c b/lib/libtermcap/tputs.c
index 857147d..0e8b147 100644
--- a/lib/libtermcap/tputs.c
+++ b/lib/libtermcap/tputs.c
@@ -35,8 +35,8 @@
static char sccsid[] = "@(#)tputs.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */
-#include <sgtty.h>
#include <ctype.h>
+#include "termcap.h"
/*
* The following array gives the number of tens of milliseconds per
@@ -45,7 +45,8 @@ static char sccsid[] = "@(#)tputs.c 8.1 (Berkeley) 6/4/93";
*/
static
short tmspc10[] = {
- 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
+ 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5,
+ 3, 2, 1
};
short ospeed;
@@ -56,16 +57,14 @@ char PC;
* The number of affected lines is affcnt, and the routine
* used to output one character is outc.
*/
-tputs(cp, affcnt, outc)
- register char *cp;
- int affcnt;
- int (*outc)();
+int
+tputs(const char *cp, int affcnt, int (*outc)(int))
{
register int i = 0;
register int mspc10;
if (cp == 0)
- return;
+ return 0;
/*
* Convert the number representing the delay.
@@ -105,9 +104,9 @@ tputs(cp, affcnt, outc)
* not comprehensible, then don't try to delay.
*/
if (i == 0)
- return;
+ return 0;
if (ospeed <= 0 || ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
- return;
+ return 0;
/*
* Round up by a half a character frame,
@@ -120,4 +119,5 @@ tputs(cp, affcnt, outc)
i += mspc10 / 2;
for (i /= mspc10; i > 0; i--)
(*outc)(PC);
+ return 0;
}
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile
index bbc7aab..8ac63d2 100644
--- a/lib/libutil/Makefile
+++ b/lib/libutil/Makefile
@@ -1,7 +1,37 @@
# @(#)Makefile 8.1 (Berkeley) 6/4/93
LIB= util
-CFLAGS+=-DLIBC_SCCS -I/sys
-SRCS= login.c login_tty.c logout.c logwtmp.c pty.c
+SHLIB_MAJOR= 2
+SHLIB_MINOR= 2
+CFLAGS+=-Wall -DLIBC_SCCS -I${.CURDIR} -I/sys
+#CFLAGS+=LOGIN_CAP_AUTH
+SRCS= login.c login_tty.c logout.c logwtmp.c pty.c setproctitle.c \
+ login_cap.c login_class.c login_auth.c login_times.c login_ok.c \
+ _secure_path.c uucplock.c
+MAN3+= login.3 login_tty.3 logout.3 logwtmp.3 pty.3 setproctitle.3 \
+ login_cap.3 login_class.3 login_times.3 login_ok.3 \
+ _secure_path.3 uucplock.3
+MAN5+= login.conf.5
+MLINKS+= pty.3 openpty.3 pty.3 forkpty.3
+MLINKS+=login_cap.3 login_getclassbyname.3 login_cap.3 login_close.3 \
+ login_cap.3 login_getclass.3 login_cap.3 login_getuserclass.3 \
+ login_cap.3 login_getcapstr.3 login_cap.3 login_getcaplist.3 \
+ login_cap.3 login_getstyle.3 login_cap.3 login_getcaptime.3 \
+ login_cap.3 login_getcapnum.3 login_cap.3 login_getcapsize.3 \
+ login_cap.3 login_getcapbool.3 login_cap.3 login_getpath.3
+MLINKS+=login_class.3 setusercontext.3 login_class.3 setclasscontext.3 \
+ login_class.3 setclassenvironment.3 login_class.3 setclassresources.3
+MLINKS+=login_times.3 parse_lt.3 login_times.3 in_ltm.3 \
+ login_times.3 in_lt.3 login_times.3 in_ltms.3 \
+ login_times.3 in_lts.3
+MLINKS+=login_ok.3 auth_ttyok.3 login_ok.3 auth_hostok.3 \
+ login_ok.3 auth_timeok.3
+MLINKS+=uucplock.3 uu_lock.3 uucplock.3 uu_unlock.3 uucplock.3 uu_lockerr.3
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/libutil.h \
+ ${DESTDIR}/usr/include
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/login_cap.h \
+ ${DESTDIR}/usr/include
.include <bsd.lib.mk>
diff --git a/lib/libutil/_secure_path.3 b/lib/libutil/_secure_path.3
new file mode 100644
index 0000000..66fbb2c
--- /dev/null
+++ b/lib/libutil/_secure_path.3
@@ -0,0 +1,70 @@
+.\" Copyright (c) 1997 David Nugent <davidn@blaze.net.au>
+.\" 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
+.\" David Nugent.
+.\" 5. Modifications may be freely made to this file providing the above
+.\" conditions are met.
+.\"
+.\" $Id: _secure_path.3,v 1.1 1997/05/10 18:55:37 davidn Exp $
+.\"
+.Dd May 2, 1997
+.Os FreeBSD
+.Dt _SECURE_PATH 3
+.Sh NAME
+.Nm _secure_path
+.Nd determine if a file appears to be secure
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <libutil.h>
+.Ft int
+.Fn _secure_path "const char *path" "uid_t uid" "gid_t gid"
+.Pp
+.Sh DESCRIPTION
+This function does some basic security checking on a given path.
+It is intended to be used by processes running with root privileges
+in order to decide whether or not to trust the contents of a given
+file.
+It uses a method often used to detect system compromise.
+.Pp
+A file is considered 'secure' if it meets the following conditions:
+.Bl -enum
+.It
+The file exists, and is a regular file (not a symlink, device
+special or named pipe, etc.),
+.It
+Is not world writable.
+.It
+Is owned by the given uid or uid 0, if uid is not -1,
+.It
+Is not group wriable or it has group ownership by the given
+gid, if gid is not -1.
+.El
+.Sh RETURN VALUES
+This function returns zero if the file exists and may be
+considered secure, -2 if the file does not exist, and
+-1 otherwise to indicate a security failure.
+.Xr syslog 3 ,
+is used to log any failure of this function, including the
+reason, at LOG_ERR priority.
+.Sh BUGS
+The checks carried out are rudamentary and no attempt is made
+to eliminate race conditions between use of this function and
+access to the file referenced.
+.Sh SEE ALSO
+.Xr lstat 3 ,
+.Xr syslog 3 .
+.Sh HISTORY
+Code from which this function was derived was contributed to the
+FreeBSD project by Berkeley Software Design, Inc.
diff --git a/lib/libutil/_secure_path.c b/lib/libutil/_secure_path.c
new file mode 100644
index 0000000..01c29bf
--- /dev/null
+++ b/lib/libutil/_secure_path.c
@@ -0,0 +1,72 @@
+/*-
+ * Based on code copyright (c) 1995,1997 by
+ * Berkeley Software Design, Inc.
+ * 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 authors.
+ * 5. Modifications may be freely made to this file providing the above
+ * conditions are met.
+ *
+ * $Id: _secure_path.c,v 1.1 1997/05/10 18:55:37 davidn Exp $
+ */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#include <errno.h>
+#include <libutil.h>
+
+/*
+ * Check for common security problems on a given path
+ * It must be:
+ * 1. A regular file, and exists
+ * 2. Owned and writaable only by root (or given owner)
+ * 3. Group ownership is given group or is non-group writable
+ *
+ * Returns: -2 if file does not exist,
+ * -1 if security test failure
+ * 0 otherwise
+ */
+
+int
+_secure_path(const char *path, uid_t uid, gid_t gid)
+{
+ int r = -1;
+ struct stat sb;
+ const char *msg = NULL;
+
+ if (lstat(path, &sb) < 0) {
+ if (errno == ENOENT) /* special case */
+ r = -2; /* if it is just missing, skip the log entry */
+ else
+ msg = "%s: cannot stat %s: %m";
+ }
+ else if (!S_ISREG(sb.st_mode))
+ msg = "%s: %s is not a regular file";
+ else if (sb.st_mode & S_IWOTH)
+ msg = "%s: %s is world writable";
+ else if (uid != -1 && sb.st_uid != uid && sb.st_uid != 0) {
+ if (uid == 0)
+ msg = "%s: %s is not owned by root";
+ else
+ msg = "%s: %s is not owned by uid %d";
+ } else if (gid != -1 && sb.st_gid != gid && (sb.st_mode & S_IWGRP))
+ msg = "%s: %s is group writeable by non-authorised groups";
+ else
+ r = 0;
+ if (msg != NULL)
+ syslog(LOG_ERR, msg, "_secure_path", path, uid);
+ return r;
+}
diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h
new file mode 100644
index 0000000..5404a1f
--- /dev/null
+++ b/lib/libutil/libutil.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ * $Id: libutil.h,v 1.8 1997/05/12 10:36:13 brian Exp $
+ */
+
+#ifndef _LIBUTIL_H_
+#define _LIBUTIL_H_
+
+#include <sys/cdefs.h>
+
+/* Avoid pulling in all the include files for no need */
+struct termios;
+struct winsize;
+struct utmp;
+
+__BEGIN_DECLS
+void setproctitle __P((const char *_fmt, ...));
+void login __P((struct utmp *_ut));
+int login_tty __P((int _fd));
+int logout __P((char *_line));
+void logwtmp __P((char *_line, char *_name, char *_host));
+int openpty __P((int *_amaster, int *_aslave, char *_name,
+ struct termios *_termp, struct winsize *_winp));
+int forkpty __P((int *_amaster, char *_name,
+ struct termios *_termp, struct winsize *_winp));
+const char *uu_lockerr __P((int _uu_lockresult));
+int uu_lock __P((const char *_ttyname));
+int uu_unlock __P((const char *_ttyname));
+int _secure_path __P((const char *_path, uid_t _uid, gid_t _gid));
+__END_DECLS
+
+#define UU_LOCK_INUSE (1)
+#define UU_LOCK_OK (0)
+#define UU_LOCK_OPEN_ERR (-1)
+#define UU_LOCK_READ_ERR (-2)
+#define UU_LOCK_SEEK_ERR (-3)
+#define UU_LOCK_WRITE_ERR (-4)
+
+#endif /* !_LIBUTIL_H_ */
diff --git a/lib/libutil/login.3 b/lib/libutil/login.3
new file mode 100644
index 0000000..faec5bb
--- /dev/null
+++ b/lib/libutil/login.3
@@ -0,0 +1,69 @@
+.\"
+.\" Copyright (c) 1996 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.
+.\"
+.\" $Id$
+.\" "
+.Dd December 29, 1996
+.Os
+.Dt LOGIN 3
+.Sh NAME
+.Nm login
+.Nd "log a new login record to the utmp and wtmp files"
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <utmp.h>
+.Fd #include <libutil.h>
+.Ft void
+.Fn login "struct utmp *ut"
+.Pp
+Link with
+.Va -lutil
+on the
+.Xr cc 1
+command line.
+.Sh DESCRIPTION
+The function
+.Fn login
+records the
+.Ar ut
+entry being passed into the appropriate slot of the
+.Xr utmp 5
+file (according to the controlling terminal of the calling process),
+and appends it to the
+.Xr wtmp 5
+file. The calling process must have permission to write to both files.
+.Sh RETURN VALUES
+None.
+.Sh SEE ALSO
+.Xr logout 3 ,
+.Xr ttyslot 3 ,
+.Xr utmp 5 ,
+.Xr wtmp 5
+.Sh BUGS
+The interface provided by
+.Fn login
+is rather crude. The caller must know about the details of a
+.Va struct utmp .
+Some better abstraction needs to be worked out.
diff --git a/lib/libutil/login.c b/lib/libutil/login.c
index 911c289..3e68563 100644
--- a/lib/libutil/login.c
+++ b/lib/libutil/login.c
@@ -42,6 +42,7 @@ static char sccsid[] = "@(#)login.c 8.1 (Berkeley) 6/4/93";
#include <stdlib.h>
#include <utmp.h>
#include <stdio.h>
+#include <libutil.h>
void
login(ut)
diff --git a/lib/libutil/login.conf.5 b/lib/libutil/login.conf.5
new file mode 100644
index 0000000..319cea3
--- /dev/null
+++ b/lib/libutil/login.conf.5
@@ -0,0 +1,364 @@
+.\" Copyright (c) 1996 David Nugent <davidn@blaze.net.au>
+.\" 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
+.\" David Nugent.
+.\" 5. Modifications may be freely made to this file providing the above
+.\" conditions are met.
+.\"
+.\" $Id: login.conf.5,v 1.8 1997/02/22 15:08:16 peter Exp $
+.\"
+.Dd November 22, 1996
+.Dt LOGIN.CONF 5
+.Os FreeBSD
+.Sh NAME
+.Nm login.conf
+.Nd login class capability database
+.Sh SYNOPSIS
+.Pa /etc/login.conf ,
+.Pa ~/.login_conf
+.Sh DESCRIPTION
+login.conf contains various attributes and capabilities of login classes.
+A login class (an optional annotation against each record in the user
+account database,
+.Pa /etc/master.passwd )
+determines session accounting, resource limits and user environment settings.
+It is used by various programs in the system to set up a user's login
+environment and to enforce policy, accounting and administrative restrictions.
+It also provides the means by which users are able to be
+authenticated to the system and the types of authentication available.
+.Pp
+A special record "default" in the system user class capability database
+.Pa /etc/login.conf
+is used automatically for any
+non-root user without a valid login class in
+.Pa /etc/master.passwd .
+A user with a uid of 0 without a valid login class will use the record
+"root" if it exists, or "default" if not.
+.Pp
+In FreeBSD, users may individually create a file called
+.Pa .login_conf
+in their home directory using the same format, consisting of a single
+entry with a record id of "me".
+If present, this file is used by
+.Xr login 1
+to set user-defined environment settings which override those specified
+in the system login capabilities database.
+Only a subset of login capabilities may be overridden, typically those
+which do not involve authentication, resource limits and accounting.
+.Pp
+Records in a class capabilities database consist of a number of
+colon-separated fields.
+The first entry for each record gives one or more names that a record is
+to be known by, each separated by a '|' character.
+The first name is the most common abbreviation.
+The last name given should be a long name that is more descriptive
+of the capability entry, and all others are synonyms.
+All names but the last should be in lower case and contain no blanks;
+the last name may contain upper case characters and blanks for
+readability.
+.Pp
+See
+.Xr getcap 3
+for a more in-depth description of the format of a capability database.
+.Sh CAPABILITIES
+Fields within each record in the database follow the
+.Xr getcap 3
+conventions for boolean, type string
+.Ql \&=
+and type numeric
+.Ql \&# ,
+although type numeric is depreciated in favour of the string format and
+either form is accepted for a numeric datum.
+Values fall into the following categories:
+.Bl -tag -width "program"
+.It file
+Path name to a data file
+.It program
+Path name to an executable file
+.It list
+A list of values (or pairs of values) separated by commas or spaces
+.It path
+A space or comma separated list of path names, following the usual csh
+conventions (leading tilde with and without username being expanded to
+home directories etc.)
+.It number
+A numeric value, either decimal (default), hexadecimal (with leading 0x),
+or octal (with a leading 0).
+With a numeric type, only one numeric value is allowed.
+Numeric types may also be specified in string format (ie. the capability
+tag being delimited from the value by '=' instead of '#').
+Whichever method is used, then all records in the database must use the
+same method to allow values to be correctly overridden in interpolated
+records.
+.It size
+A number which expresses a size.
+The default interpretation of a value is the number of bytes, but a
+suffix may specify alternate units:
+.Bl -tag -offset indent -compact -width xxxx
+.It b
+explicitly selects 512-byte blocks
+.It k
+selects kilobytes (1024 bytes)
+.It m
+specifies a multiplier of 1 megabyte (1048576 bytes),
+.It g
+specifies units of gigabytes, and
+.It t
+represents terabytes.
+.El
+A size value is a numeric quantity and case of the suffix is not significant.
+Concatenated values are added together.
+.It time
+A period of time, by default in seconds.
+A prefix may specify a different unit;
+.Bl -tag -offset indent -compact -width xxxx
+.It y
+indicates the number of 365 day years,
+.It w
+indicates the number of weeks,
+.It d
+the number of days,
+.It h
+the number of minutes, and
+.It s
+the number of seconds.
+.El
+Concatenated values are added together.
+For example, 2 hours and 40 minutes may be written either as
+9600s, 160m or 2h40m.
+.El
+.Pp
+The usual convention to interpolate capability entries using the special
+.Em tc=value
+notation may be used.
+.Pp
+.Sh RESOURCE LIMITS
+.Bl -column coredumpsize indent indent
+.Sy Name Type Notes Description
+.It cputime time CPU usage limit.
+.It filesize size Maximum file size limit.
+.It datasize size Maximum data size limit.
+.It stacksize size Maximum stack size limit.
+.It coredumpsize size Maximum coredump size limit.
+.It memoryuse size Maximum of core memory use size limit.
+.It memorylocked size Maximum locked in core memory size limit.
+.It maxproc number Maximum number of processes.
+.It openfiles number Maximum number of open files per process.
+.El
+.Pp
+These resource limit entries actually specify both the maximum
+and current limits (see
+.Xr getrlimit 2 ).
+The current (soft) limit is the one normally used, although the user is permitted
+to increase the current limit to the maximum (hard) limit.
+The maximum and current limits may be specified individually by appending a
+-max or -cur to the capability name.
+.Pp
+.Sh ENVIRONMENT
+.Bl -column ignorenologin indent xbinxxusrxbin
+.Sy Name Type Notes Description
+.It charset string Set $MM_CHARSET environment variable to the specified
+value.
+.It hushlogin bool false Same as having a ~/.hushlogin file.
+.It ignorenologin bool false Login not prevented by nologin.
+.It lang string Set $LANG environment variable to the specified value.
+.It manpath path Default search path for manpages.
+.It nologin file If the file exists it will be displayed and
+the login session will be terminated.
+.It path path /bin /usr/bin Default search path.
+.It priority number Initial priority (nice) level.
+.It requirehome bool false Require a valid home directory to login.
+.It setenv list A comma-separated list of environment variables and
+values to which they are to be set.
+.It shell prog Session shell to execute rather than the
+shell specified in the passwd file. The SHELL environment variable will
+contain the shell specified in the password file.
+.It term string su Default terminal type if not able to determine from
+other means.
+.It timezone string Default value of $TZ environment variable.
+.It umask number 022 Initial umask. Should always have a leading 0 to
+ensure octal interpretation.
+.It welcome file /etc/motd File containing welcome message.
+.El
+.Pp
+.Sh AUTHENTICATION
+.Bl -column minpasswordlen indent indent
+.Sy Name Type Notes Description
+.It minpasswordlen number 6 The minimum length a local password may be.
+.\" .It approve program Program to approve login.
+.It auth list passwd Allowed authentication styles. The first value is the
+default style.
+.It auth-<type> list Allowed authentication styles for the
+authentication type 'type'.
+.It copyright file File containing additional copyright information
+.\".It widepasswords bool false Use the wide password format. The wide password
+.\" format allows up to 128 significant characters in the password.
+.It host.allow list List of remote host wildcards from which users in
+the class may access.
+.It host.deny list List of remote host wildcards from which users in
+the class may not access.
+.It times.allow list List of time periods during which
+logins are allowed.
+.It times.deny list List of time periods during which logins are
+disallowed.
+.It tty.allow list List of ttys and ttygroups which users
+in the class may use for access.
+.It tty.deny list List of ttys and ttygroups which users
+in the class may not use for access.
+.El
+.Pp
+These fields are intended to be used by
+.Xr passwd 1
+and other programs in the login authentication system.
+.Pp
+Capabilities that set environment variables are scanned for both
+.Ql \&~
+and
+.Ql \&$
+characters, which are substituted for a user's home directory and name
+respectively.
+To pass these characters literally into the environment variable, escape
+the character by preceding it with a backslash '\\'.
+.Pp
+The
+.Em host.allow
+and
+.Em host.deny
+entries are comma separated lists used for checking remote access to the system,
+and consist of a list of hostnames and/or IP addresses against which remote
+network logins are checked.
+Items in these lists may contain wildcards in the form used by shell programs
+for wildcard matching (See
+.Xr fnmatch 3
+for details on the implementation).
+The check on hosts is made against both the remote system's Internet address
+and hostname (if available).
+If both lists are empty or not specified, then logins from any remote host
+are allowed.
+If host.allow contains one or more hosts, then only remote systems matching
+any of the items in that list are allowed to log in.
+If host.deny contains one or more hosts, then a login from any matching hosts
+will be disallowed.
+.Pp
+The
+.Em times.allow
+and
+.Em times.deny
+entries consist of a comma-separated list of time periods during which the users
+in a class are allowed to be logged in.
+These are expressed as one or more day codes followed by a start and end times
+expressed in 24 hour format, separated by a hyphen or dash.
+For example, MoThSa0200-1300 translates to Monday, Thursday and Saturday between
+the hours of 2 am and 1 p.m..
+If both of these time lists are empty, users in the class are allowed access at
+any time.
+If
+.Em times.allow
+is specified, then logins are only allowed during the periods given.
+If
+.Em times.deny
+is specified, then logins are denied during the periods given, regardless of whether
+one of the periods specified in
+.Em times.allow
+applies.
+.Pp
+Note that
+.Xr login 1
+enforces only that the actual login falls within periods allowed by these entries.
+Further enforcement over the life of a session requires a separate daemon to
+monitor transitions from an allowed period to a non-allowed one.
+.Pp
+The
+.Em tty.allow
+and
+.Em tty.deny
+entries contain a comma-separated list of tty devices (without the /dev/ prefix)
+that a user in a class may use to access the system, and/or a list of ttygroups
+(See
+.Xr getttyent 3
+and
+.Xr ttys 5
+for information on ttygroups).
+If neither entry exists, then the choice of login device used by the user is
+unrestricted.
+If only
+.Em tty.allow
+is specified, then the user is restricted only to ttys in the given
+group or device list.
+If only
+.Em tty.deny
+is specified, then the user is prevented from using the specified devices or
+devices in the group.
+If both lists are given and are non-empty, the user is restricted to those
+devices allowed by tty.allow that are not available by tty.deny.
+.Sh ACCOUNTING LIMITS
+.Bl -column passwordperiod indent indent
+.Sy Name Type Notes Description
+.It accounted bool false Enable session time accounting for all users
+in this class.
+.It autodelete time Time after expiry when account is auto-deleted.
+.It bootfull bool false Enable 'boot only if ttygroup is full' strategy
+when terminating sessions.
+.It daytime time Maximum login time per day.
+.It expireperiod time Time for expiry allocation.
+.It graceexpire time Grace days for expired account.
+.It gracetime time Additional grace login time allowed.
+.It host.accounted list List of remote host wildcards from which
+login sessions will be accounted.
+.It host.exempt list List of remote host wildcards from which
+login session accounting is exempted.
+.It idletime time Maximum idle time before logout.
+.It monthtime time Maximum login time per month.
+.It passwordtime time Time for password expiry.
+.It refreshtime time New time allowed on account refresh.
+.It refreshperiod str How often account time is refreshed.
+.It sessiontime time Maximum login time per session.
+.It sessionlimit number Maximum number of concurrent
+login sessions on ttys in any group.
+.It tty.accounted list List of ttys and ttygroups for which
+login accounting is active.
+.It tty.exempt list List of ttys and ttygroups for which login accounting
+is exempt.
+.It warnexpire time Advance notice for pending account expiry.
+.It warnpassword time Advance notice for pending password expiry.
+.It warntime time Advance notice for pending out-of-time.
+.It weektime time Maximum login time per week.
+.El
+.Pp
+These fields are used by the time accounting system, which regulates,
+controls and records user login access.
+.Pp
+The
+.Em ttys.accounted
+and
+.Em ttys.exempt
+fields operate in a similar manner to
+.Em ttys.allow
+and
+.Em ttys.deny
+as explained
+above.
+Similarly with the
+.Em host.accounted
+and
+.Em host.exempt
+lists.
+.Sh SEE ALSO
+.Xr login 1 ,
+.Xr getcap 3 ,
+.Xr getttyent 3 ,
+.Xr login_cap 3 ,
+.Xr login_class 3 ,
+.Xr ttys 5
diff --git a/lib/libutil/login_auth.3 b/lib/libutil/login_auth.3
new file mode 100644
index 0000000..14a2a63
--- /dev/null
+++ b/lib/libutil/login_auth.3
@@ -0,0 +1,71 @@
+.\" Copyright (c) 1995 David Nugent <davidn@blaze.net.au>
+.\" 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
+.\" David Nugent.
+.\" 5. Modifications may be freely made to this file providing the above
+.\" conditions are met.
+.\"
+.\" $Id$
+.\"
+.Dd December 29, 1996
+.Os FreeBSD
+.Dt LOGIN_AUTH 3
+.Sh NAME
+.Nm authenticate
+.Nm auth_script
+.Nm auth_env
+.Nm auth_scan
+.Nm auth_rmfiles
+.Nm auth_checknologin
+.Nm auth_cat
+.Nm auth_ttyok
+.Nm auth_hostok
+.Nm auth_timesok
+.Nd Authentication style support library for login class capabilities database.
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <login_cap.h>
+.Ft int
+.Fn authenticate "const char *name" "const char *classname" "const char *style" "const char *service"
+.Ft int
+.Fn auth_script "const char * path" ...
+.Ft int
+.Fn auth_env "void"
+.Ft int
+.Fn auth_scan "int ok"
+.Ft int
+.Fn auth_rmfiles "void"
+.Ft int
+.Fn auth_checknologin "login_cap_t *lc"
+.Ft int
+.Fn auth_cat "const char *file"
+.Ft int
+.Fn auth_ttyok "login_cap_t *lc" "const char *tty"
+.Ft int
+.Fn auth_hostok "login_cap_t *lc" "const char *hostname" "char const *ip"
+.Ft int
+.Fn auth_timesok "login_cap_t *lc" "time_t now"
+.Sh DESCRIPTION
+This set of functions support the login class authorisation style interface provided
+by
+.Xr login.conf 5 .
+
+.Sh RETURN VALUES
+.Sh SEE ALSO
+.Xr getcap 3 ,
+.Xr login_cap 3 ,
+.Xr login_class 3 ,
+.Xr login.conf 5 ,
+.Xr termcap 5
diff --git a/lib/libutil/login_auth.c b/lib/libutil/login_auth.c
new file mode 100644
index 0000000..695b006
--- /dev/null
+++ b/lib/libutil/login_auth.c
@@ -0,0 +1,670 @@
+/*-
+ * Copyright (c) 1996 by
+ * Sean Eric Fagan <sef@kithrup.com>
+ * David Nugent <davidn@blaze.net.au>
+ * All rights reserved.
+ *
+ * Portions copyright (c) 1995,1997 by
+ * Berkeley Software Design, Inc.
+ * 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 authors.
+ * 5. Modifications may be freely made to this file providing the above
+ * conditions are met.
+ *
+ * Low-level routines relating to the user capabilities database
+ *
+ * $Id: login_auth.c,v 1.6 1997/02/22 15:08:18 peter Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <login_cap.h>
+#include <stdarg.h>
+#include <paths.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <err.h>
+#include <libutil.h>
+
+#ifdef LOGIN_CAP_AUTH
+/*
+ * Comment from BSDI's authenticate.c module:
+ * NOTE: THIS MODULE IS TO BE DEPRECATED. FUTURE VERSIONS OF BSD/OS WILL
+ * HAVE AN UPDATED API, THOUGH THESE FUNCTIONS WILL CONTINUE TO BE AVAILABLE
+ * FOR BACKWARDS COMPATABILITY
+ */
+
+
+#define AUTHMAXSPOOL (8 * 1024) /* Max size of authentication data */
+#define AUTHCOMM_FD 3 /* Handle used to read/write auth data */
+
+struct rmfiles {
+ struct rmfiles *next;
+ char file[1];
+};
+
+struct authopts {
+ struct authopts *next;
+ char opt[1];
+};
+
+static char *spoolbuf = NULL;
+static int spoolidx = 0;
+static struct rmfiles *rmfirst = NULL;
+static struct authopts *optfirst = NULL;
+
+
+/*
+ * Setup a known environment for all authentication scripts.
+ */
+
+static char *auth_environ[] = {
+ "PATH=" _PATH_DEFPATH,
+ "SHELL=" _PATH_BSHELL,
+ NULL,
+};
+
+
+
+/*
+ * nextline()
+ * Get the next line from the data buffer collected from
+ * the authentication program. This function relies on the
+ * fact that lines are nul terminated.
+ */
+
+static char *
+nextline(int *idx)
+{
+ char *ptr = NULL;
+
+ if (spoolbuf != NULL && *idx < spoolidx) {
+ ptr = spoolbuf + *idx;
+ *idx += strlen(ptr) + 1;
+ }
+ return ptr;
+}
+
+
+/*
+ * spooldata()
+ * Read data returned on authentication backchannel and
+ * stuff it into our spool buffer. We also replace \n with nul
+ * to make parsing easier later.
+ */
+
+static int
+spooldata(int fd)
+{
+
+ if (spoolbuf)
+ free(spoolbuf);
+ spoolidx = 0;
+
+ if (spoolbuf == NULL && (spoolbuf = malloc(AUTHMAXSPOOL)) == NULL)
+ syslog(LOG_ERR, "authbuffer malloc: %m");
+
+ else while (spoolidx < sizeof(spoolbuf) - 1) {
+ int r = read(fd, spoolbuf + spoolidx, sizeof(spoolbuf)-spoolidx);
+ char *b;
+
+ if (r <= 0) {
+ spoolbuf[spoolidx] = '\0';
+ return 0;
+ }
+ /*
+ * Convert newlines into NULs to allow
+ * easier scanning of the file.
+ */
+ while ((b = memchr(spoolbuf + spoolidx, '\n', r)) != NULL)
+ *b = '\0';
+ spoolidx += r;
+ }
+ return -1;
+}
+
+
+/*
+ * auth_check()
+ * Starts an auth_script() for the given <user>, with a class <class>,
+ * style <style>, and service <service>. <style> is necessary,
+ * as are <user> and <class>, but <service> is optional -- it defaults
+ * to "login".
+ * Since auth_script() expects an execl'able program name, authenticate()
+ * also concatenates <style> to _PATH_AUTHPROG.
+ * Lastly, calls auth_scan(0) to see if there are any "reject" statements,
+ * or lack of "auth" statements.
+ * Returns -1 on error, 0 on rejection, and >0 on success.
+ * (See AUTH_* for the return values.)
+ *
+ */
+
+int
+auth_check(const char *name, const char *clss, const char *style,
+ const char *service, int *status)
+{
+ int _status;
+
+ if (status == NULL)
+ status = &_status;
+ *status = 0;
+
+ if (style != NULL) {
+ char path[MAXPATHLEN];
+
+ if (service == NULL)
+ service = LOGIN_DEFSERVICE;
+
+ snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", style);
+ if (auth_script(path, style, "-s", service, name, clss, 0))
+ status = 0;
+ else
+ *status = auth_scan(0);
+
+ return *status & AUTH_ALLOW;
+ }
+ return -1;
+}
+
+
+int
+auth_response(const char *name, const char *class, const char *style,
+ const char *service, int *status,
+ const char *challenge, const char *response)
+{
+ int _status;
+
+ if (status == NULL)
+ status = &_status;
+ *status = 0;
+
+ if (style != NULL) {
+ int datalen;
+ char *data;
+
+ if (service == NULL)
+ service = LOGIN_DEFSERVICE;
+
+ datalen = strlen(challenge) + strlen(response) + 2;
+
+ if ((data = malloc(datalen)) == NULL) {
+ syslog(LOG_ERR, "auth_response: %m");
+ warnx("internal resource failure");
+ } else {
+ char path[MAXPATHLEN];
+
+ snprintf(data, datalen, "%s%c%s", challenge, 0, response);
+ snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", style);
+ if (auth_script_data(data, datalen, path, style, "-s", service,
+ name, class, 0))
+ *status = 0;
+ else
+ *status = auth_scan(0);
+ free(data);
+ return (*status & AUTH_ALLOW);
+ }
+ }
+ return -1;
+}
+
+
+int
+auth_approve(login_cap_t *lc, const char *name, const char *service)
+{
+ int r = -1;
+ char path[MAXPATHLEN];
+
+ if (lc == NULL) {
+ if (strlen(name) > MAXPATHLEN) {
+ syslog(LOG_ERR, "%s: username too long", name);
+ warnx("username too long");
+ } else {
+ struct passwd *pwd;
+ char *p;
+
+ pwd = getpwnam(name);
+ if (pwd == NULL && (p = strchr(name, '.')) != NULL) {
+ int i = p - name;
+
+ if (i >= MAXPATHLEN)
+ i = MAXPATHLEN - 1;
+ strncpy(path, name, i);
+ path[i] = '\0';
+ pwd = getpwnam(path); /* Fixed bug in BSDI code... */
+ }
+ if ((lc = login_getpwclass(pwd ? pwd->pw_class : NULL)) == NULL)
+ warnx("unable to classify user '%s'", name);
+ }
+ }
+
+ if (lc != NULL) {
+ char *approve;
+ char *s;
+
+ if (service != NULL)
+ service = LOGIN_DEFSERVICE;
+
+ snprintf(path, sizeof(path), "approve-%s", service);
+
+ if ((approve = login_getcapstr(lc, s = path, NULL, NULL)) == NULL &&
+ (approve = login_getcapstr(lc, s = "approve", NULL, NULL)) == NULL)
+ r = AUTH_OKAY;
+ else {
+
+ if (approve[0] != '/') {
+ syslog(LOG_ERR, "Invalid %s script: %s", s, approve);
+ warnx("invalid path to approval script");
+ } else {
+ char *s;
+
+ s = strrchr(approve, '/') + 1;
+ if (auth_script(approve, s, name,
+ lc->lc_class, service, 0) == 0 &&
+ (r = auth_scan(AUTH_OKAY) & AUTH_ALLOW) != 0)
+ auth_env();
+ }
+ }
+ }
+ return r;
+}
+
+
+void
+auth_env(void)
+{
+ int idx = 0;
+ char *line;
+
+ while ((line = nextline(&idx)) != NULL) {
+ if (!strncasecmp(line, BI_SETENV, sizeof(BI_SETENV)-1)) {
+ line += sizeof(BI_SETENV) - 1;
+ if (*line && isspace(*line)) {
+ char *name;
+ char ch, *p;
+
+ while (*line && isspace(*line))
+ ++line;
+ name = line;
+ while (*line && !isspace(*line))
+ ++line;
+ ch = *(p = line);
+ if (*line)
+ ++line;
+ if (setenv(name, line, 1))
+ warn("setenv(%s, %s)", name, line);
+ *p = ch;
+ }
+ }
+ }
+}
+
+
+char *
+auth_value(const char *what)
+{
+ int idx = 0;
+ char *line;
+
+ while ((line = nextline(&idx)) != NULL) {
+ if (!strncasecmp(line, BI_VALUE, sizeof(BI_VALUE)-1)) {
+ char *name;
+
+ line += sizeof(BI_VALUE) - 1;
+ while (*line && isspace(*line))
+ ++line;
+ name = line;
+ if (*line) {
+ int i;
+ char ch, *p;
+
+ ch = *(p = line);
+ *line++ = '\0';
+ i = strcmp(name, what);
+ *p = ch;
+ if (i == 0)
+ return auth_mkvalue(line);
+ }
+ }
+ }
+ return NULL;
+}
+
+char *
+auth_mkvalue(const char *value)
+{
+ char *big, *p;
+
+ big = malloc(strlen(value) * 4 + 1);
+ if (big != NULL) {
+ for (p = big; *value; ++value) {
+ switch (*value) {
+ case '\r':
+ *p++ = '\\';
+ *p++ = 'r';
+ break;
+ case '\n':
+ *p++ = '\\';
+ *p++ = 'n';
+ break;
+ case '\\':
+ *p++ = '\\';
+ *p++ = *value;
+ break;
+ case '\t':
+ case ' ':
+ if (p == big)
+ *p++ = '\\';
+ *p++ = *value;
+ break;
+ default:
+ if (!isprint(*value)) {
+ *p++ = '\\';
+ *p++ = ((*value >> 6) & 0x3) + '0';
+ *p++ = ((*value >> 3) & 0x7) + '0';
+ *p++ = ((*value ) & 0x7) + '0';
+ } else
+ *p++ = *value;
+ break;
+ }
+ }
+ *p = '\0';
+ big = realloc(big, strlen(big) + 1);
+ }
+ return big;
+}
+
+
+#define NARGC 63
+static int
+_auth_script(const char *data, int nbytes, const char *path, va_list ap)
+{
+ int r, argc, status;
+ int pfd[2];
+ pid_t pid;
+ struct authopts *e;
+ char *argv[NARGC+1];
+
+ r = -1;
+ argc = 0;
+ for (e = optfirst; argc < (NARGC - 1) && e != NULL; e = e->next) {
+ argv[argc++] = "-v";
+ argv[argc++] = e->opt;
+ }
+ while (argc < NARGC && (argv[argc] = va_arg(ap, char *)) != NULL)
+ ++argc;
+ argv[argc] = NULL;
+
+ if (argc >= NARGC && va_arg(ap, char *))
+ syslog(LOG_ERR, "too many arguments");
+ else if (_secure_path(path, 0, 0) < 0) {
+ syslog(LOG_ERR, "%s: path not secure", path);
+ warnx("invalid script: %s", path);
+ } else if (socketpair(PF_LOCAL, SOCK_STREAM, 0, pfd) < 0) {
+ syslog(LOG_ERR, "unable to create backchannel %m");
+ warnx("internal resource failure");
+ } else switch (pid = fork()) {
+ case -1: /* fork() failure */
+ close(pfd[0]);
+ close(pfd[1]);
+ syslog(LOG_ERR, "fork %s: %m", path);
+ warnx("internal resource failure");
+ break;
+ case 0: /* child process */
+ close(pfd[0]);
+ if (pfd[1] != AUTHCOMM_FD) {
+ if (dup2(pfd[1], AUTHCOMM_FD) < 0)
+ err(1, "dup backchannel");
+ close(pfd[1]);
+ }
+ for (r = getdtablesize(); --r > AUTHCOMM_FD; )
+ close(r);
+ execve(path, argv, auth_environ);
+ syslog(LOG_ERR, "exec %s: %m", path);
+ err(1, path);
+ default: /* parent */
+ close(pfd[1]);
+ if (data && nbytes)
+ write(pfd[0], data, nbytes);
+ r = spooldata(pfd[0]);
+ close(pfd[0]);
+ if (waitpid(pid, &status, 0) < 0) {
+ syslog(LOG_ERR, "%s: waitpid: %m", path);
+ warnx("internal failure");
+ r = -1;
+ } else {
+ if (r != 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ r = -1;
+ }
+ /* kill the buffer if it is of no use */
+ if (r != 0) {
+ free(spoolbuf);
+ spoolbuf = NULL;
+ spoolidx = 0;
+ }
+ break;
+ }
+ return r;
+}
+
+
+
+/*
+ * auth_script()
+ * Runs an authentication program with specified arguments.
+ * It sets up file descriptor 3 for the program to write to;
+ * it stashes the output somewhere. The output of the program
+ * consists of statements:
+ * reject [challenge|silent]
+ * authorize [root|secure]
+ * setenv <name> [<value>]
+ * remove <file>
+ *
+ * Terribly exciting, isn't it?
+ * Output cannot exceed AUTHMAXSPOOL characters.
+ */
+
+int
+auth_script(const char *path, ...)
+{
+ int r;
+ va_list ap;
+
+ va_start(ap, path);
+ r = _auth_script(NULL, 0, path, ap);
+ va_end(ap);
+ return r;
+}
+
+
+int
+auth_script_data(const char *data, int nbytes, const char *path, ...)
+{
+ int r;
+ va_list ap;
+
+ va_start(ap, path);
+ r = _auth_script(data, nbytes, path, ap);
+ va_end(ap);
+ return r;
+}
+
+
+static void
+add_rmlist(const char *file)
+{
+ struct rmfiles *rm;
+
+ if ((rm = malloc(sizeof(struct rmfiles) + strlen(file) + 1)) == NULL)
+ syslog(LOG_ERR, "add_rmfile malloc: %m");
+ else {
+ strcpy(rm->file, file);
+ rm->next = rmfirst;
+ rmfirst = rm;
+ }
+}
+
+
+int
+auth_scan(int okay)
+{
+ int idx = 0;
+ char *line;
+
+ while ((line = nextline(&idx)) != NULL) {
+ if (!strncasecmp(line, BI_REJECT, sizeof(BI_REJECT)-1)) {
+ line += sizeof(BI_REJECT) - 1;
+ while (*line && isspace(*line))
+ ++line;
+ if (*line) {
+ if (!strcasecmp(line, "silent"))
+ return AUTH_SILENT;
+ if (!strcasecmp(line, "challenge"))
+ return AUTH_CHALLENGE;
+ }
+ return 0;
+ } else if (!strncasecmp(line, BI_AUTH, sizeof(BI_AUTH)-1)) {
+ line += sizeof(BI_AUTH) - 1;
+ while (*line && isspace(*line))
+ ++line;
+ if (*line == '\0')
+ okay |= AUTH_OKAY;
+ else if (!strcasecmp(line, "root"))
+ okay |= AUTH_ROOTOKAY;
+ else if (!strcasecmp(line, "secure"))
+ okay |= AUTH_SECURE;
+ }
+ else if (!strncasecmp(line, BI_REMOVE, sizeof(BI_REMOVE)-1)) {
+ line += sizeof(BI_REMOVE) - 1;
+ while (*line && isspace(*line))
+ ++line;
+ if (*line)
+ add_rmlist(line);
+ }
+ }
+
+ return okay;
+}
+
+
+int
+auth_setopt(const char *n, const char *v)
+{
+ int r;
+ struct authopts *e;
+
+ if ((e = malloc(sizeof(*e) + strlen(n) + strlen(v) + 1)) == NULL)
+ r = -1;
+ else {
+ sprintf(e->opt, "%s=%s", n, v);
+ e->next = optfirst;
+ optfirst = e;
+ r = 0;
+ }
+ return r;
+}
+
+
+void
+auth_clropts(void)
+{
+ struct authopts *e;
+
+ while ((e = optfirst) != NULL) {
+ optfirst = e->next;
+ free(e);
+ }
+}
+
+
+void
+auth_rmfiles(void)
+{
+ struct rmfiles *rm;
+
+ while ((rm = rmfirst) != NULL) {
+ unlink(rm->file);
+ rmfirst = rm->next;
+ free(rm);
+ }
+}
+
+#endif
+
+
+/*
+ * auth_checknologin()
+ * Checks for the existance of a nologin file in the login_cap
+ * capability <lc>. If there isn't one specified, then it checks
+ * to see if this class should just ignore nologin files. Lastly,
+ * it tries to print out the default nologin file, and, if such
+ * exists, it exits.
+ */
+
+void
+auth_checknologin(login_cap_t *lc)
+{
+ char *file;
+
+ /* Do we ignore a nologin file? */
+ if (login_getcapbool(lc, "ignorenologin", 0))
+ return;
+
+ /* Note that <file> will be "" if there is no nologin capability */
+ if ((file = login_getcapstr(lc, "nologin", "", NULL)) == NULL)
+ exit(1);
+
+ /*
+ * *file is true IFF there was a "nologin" capability
+ * Note that auth_cat() returns 1 only if the specified
+ * file exists, and is readable. E.g., /.nologin exists.
+ */
+ if ((*file && auth_cat(file)) || auth_cat(_PATH_NOLOGIN))
+ exit(1);
+}
+
+
+/*
+ * auth_cat()
+ * Checks for the readability of <file>; if it can be opened for
+ * reading, it prints it out to stdout, and then exits. Otherwise,
+ * it returns 0 (meaning no nologin file).
+ */
+
+int
+auth_cat(const char *file)
+{
+ int fd, count;
+ char buf[BUFSIZ];
+
+ if ((fd = open(file, O_RDONLY)) < 0)
+ return 0;
+ while ((count = read(fd, buf, sizeof(buf))) > 0)
+ (void)write(fileno(stdout), buf, count);
+ close(fd);
+ return 1;
+}
diff --git a/lib/libutil/login_cap.3 b/lib/libutil/login_cap.3
new file mode 100644
index 0000000..9017b77
--- /dev/null
+++ b/lib/libutil/login_cap.3
@@ -0,0 +1,392 @@
+.\" Copyright (c) 1995 David Nugent <davidn@blaze.net.au>
+.\" 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
+.\" David Nugent.
+.\" 5. Modifications may be freely made to this file providing the above
+.\" conditions are met.
+.\"
+.\" $Id: login_cap.3,v 1.6 1997/03/19 02:01:27 bde Exp $
+.\"
+.Dd December 27, 1996
+.Os FreeBSD
+.Dt LOGIN_CAP 3
+.Sh NAME
+.Nm login_getclassbyname ,
+.Nm login_close ,
+.Nm login_getclass ,
+.Nm login_getpwclass ,
+.Nm login_getuserclass ,
+.Nm login_getcapstr ,
+.Nm login_getcaplist ,
+.Nm login_getcaptime ,
+.Nm login_getcapnum ,
+.Nm login_getcapsize ,
+.Nm login_getcapbool ,
+.Nm login_getstyle
+.Nd functions for accessing the login class capabilities database.
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <login_cap.h>
+.Ft void
+.Fn login_close "login_cap_t * lc"
+.Ft login_cap_t *
+.Fn login_getclassbyname "const char *nam" "const char *dir"
+.Ft login_cap_t *
+.Fn login_getclass "const char *nam"
+.Ft login_cap_t *
+.Fn login_getpwclass "const struct passwd *pwd"
+.Ft login_cap_t *
+.Fn login_getuserclass "const struct passwd *pwd"
+.Ft char *
+.Fn login_getcapstr "login_cap_t *lc" "const char *cap" "char *def" "char *error"
+.Ft char **
+.Fn login_getcaplist "login_cap_t *lc" "const char *cap" "const char *chars"
+.Ft char *
+.Fn login_getpath "login_cap_t *lc" "const char *cap" "char *error"
+.Ft rlim_t
+.Fn login_getcaptime "login_cap_t *lc" "const char *cap" "rlim_t def" "rlim_t error"
+.Ft rlim_t
+.Fn login_getcapnum "login_cap_t *lc" "const char *cap" "rlim_t def" "rlim_t error"
+.Ft rlim_t
+.Fn login_getcapsize "login_cap_t *lc" "const char *cap" "rlim_t def" "rlim_t error"
+.Ft int
+.Fn login_getcapbool "login_cap_t *lc" "const char *cap" "int def"
+.Ft char *
+.Fn login_getstyle "login_cap_t *lc" "char *style" "const char *auth"
+.Pp
+.Sh DESCRIPTION
+These functions represent a programming interface to the login
+classes database provided in
+.Xr login.conf 5 .
+This database contains capabilities, attributes and default environment
+and accounting settings for users and programs running as specific users,
+as determined by the login class field within entries in
+.Pa /etc/master.passwd .
+.Pp
+Entries in
+.Xr login.conf 5
+consist of colon
+.Ql \&:
+separated fields, the first field in each record being one or more
+identifiers for the record which must be unique for the entire database
+each separated by a '|' and may optionally include a description as
+the last 'name'.
+Remaining fields in the record consist of keyword/data pairs.
+Long lines may be continued with a backslash within empty entries
+with the second and subsequent lines optionally indented for readability.
+This is similar to the format used in
+.Xr termcap 5
+except that keywords are not limited to two significant characters,
+and are usually longer for improved readability.
+As with termcap entries, multiple records can be linked together
+(one record including another) using a field containing tc=<recordid>,
+the result is that the entire record referenced by <recordid> replaces
+the tc= field at the point at which it occurs.
+See
+.Xr getcap 3
+for further details on the format and use of a capabilities database.
+.Pp
+The
+.Nm login_cap
+interface provides a convenient means of retrieving login class
+records with all tc= references expanded.
+A program will typically call one of
+.Fn login_getclass ,
+.Fn login_getpwclass ,
+.Fn login_getuserclass
+or
+.Fn login_getclassbyname
+according to its requirements.
+Each of these functions returns a login capabilities structure,
+.Ft login_cap_t
+which may subsequently be used to interrogate the database for
+specific values using the rest of the API.
+Once the login_cap_t is of no further use, the
+.Fn login_close
+function should be called to free all resources used.
+.Pp
+The structure of login_cap_t is defined in login_cap.h, as:
+.Bd -literal -offset indent
+typedef struct {
+ char *lc_class;
+ char *lc_cap;
+ char *lc_style;
+} login_cap_t;
+.Ed
+.Pp
+The
+.Ar lc_class
+member contains a pointer to the name of the login class
+retrieved.
+This may not necessarily be the same as the one requested,
+either directly via
+.Fn login_getclassbyname ,
+indirectly via a user's login record using
+.Fn login_getpwclass ,
+by class name using
+.Fn login_getclass
+or
+.Fn login_getuserclass .
+If the referenced user has no login class specified in
+.Pa /etc/master.passwd ,
+the class name is NULL or an empty string, or if the class
+specified does not exist in the database, each of these
+functions will search for a record with an id of "default",
+with that name returned in the
+.Ar lc_class
+field.
+.Pp
+The
+.Ar lc_cap
+field is used internally by the library to contain the
+expanded login capabilities record.
+Programs with unusual requirements may wish to use this
+with the lower-level
+.Fn getcap
+style functions to access the record directly.
+.Pp
+The
+.Ar lc_style
+field is set by the
+.Fn login_getstyle
+function to the authorisation style according to the requirements
+of the program handling a login itself.
+.Pp
+As noted above, the
+.Fn get*class
+functions return a login_cap_t object which is used to access
+the matching or default record in the capabilities database.
+.Fn getclassbyname
+accepts two arguments: the first one is the record identifier of the
+record to be retrieved, the second being an optional directory name.
+If the first
+.Ar name
+argument is NULL, an empty string, or a class that does not exist
+in the supplimental or system login class database, then the system
+.Em default
+record is returned instead.
+If the second
+.Ar dir
+parameter is NULL, then only the system login class database is
+used, but when not NULL, the named directory is searched for
+a login database file called ".login_conf", and capability records
+contained within it may override the system defaults.
+This scheme allows users to override some login settings from
+those in the system login class database by creating class records
+for their own private class with a record id of `me'.
+In the context of a
+.Em login ,
+it should be noted that some options cannot by overridden by
+users for two reasons; many options, such as resource settings
+and deafult process priorities, require root privileges
+in order to take effect, and other fields in the user's file are
+not be consulted at all during the early phases of login for
+security or administrative reasons.
+See
+.Xr login.conf 5
+for more information on which settings a user is able to override.
+Typically, these are limited purely to the user's default login
+environment which might otherwise have been overridden in shell
+startup scripts in any case.
+The user's
+.Pa .login_conf
+merely provides a convenient way for a user to set up their preferred
+login environment before the shell is invoked on login.
+.Pp
+If the specified record is NULL, empty or does not exist, and the
+system has no "default" record available to fallback, there is a
+memory allocation error or for some reason
+.Xr cgetent 3
+is unable to access the login capabilities database, this function
+returns NULL.
+.Pp
+The functions
+.Fn login_getpwclass ,
+.Fn login_getclass
+and
+.Fn login_getuserclass
+retrieve the applicable login class record for the user's passwd
+entry or class name by calling
+.Fn login_getclassbyname .
+On failure, NULL is returned.
+The difference between these functions is that
+.Fn login_getuserclass
+includes the user's overriding
+.Pa .login_conf
+that exists in the user's home directory,
+.Fn login_getpwclass,
+and
+.Fn login_getclass
+restricts loookup only to the system login class database in
+.Pa /etc/login.conf .
+.Fn login_getpwclass
+only differs from
+.Fn login_getclass
+in that it allows the default class for user 'root' as "root"
+if none has been specified in the password database.
+Otherwise, if the passwd pointer is NULL, or the user record
+has no login class, then the system "default" entry is retrieved.
+.Pp
+Once a program no longer wishes to use a login_cap_t object,
+.Fn login_close
+may be called to free all resources used by the login class.
+.Fn login_close
+may be passed a NULL pointer with no harmful side-effects.
+.Pp
+The remaining functions may be used to retrieve individual
+capability records.
+Each function takes a login_cap_t object as its first parameter,
+a capability tag as the second, and remaining parameters being
+default and error values that are returned if the capability is
+not found.
+The type of the additional parameters passed and returned depend
+on the
+.Em type
+of capability each deals with, be it a simple string, a list,
+a time value, a file or memory size value, a path (consisting of
+a colon-separated list of directories) or a boolean flag.
+The manpage for
+.Xr login.conf 5
+deals in specific tags and their type.
+.Pp
+Note that with all functions in this group, you should not call
+.Xr free 3
+on any pointers returned.
+Memory allocated during retrieval or processing of capability
+tags is automatically reused by subsequent calls to functions
+in this group, or deallocated on calling
+.Fn login_close .
+.Bl -tag -width "login_getcaplist()"
+.It Fn login_getcapstr
+This function returns a simple string capability.
+If the string is not found, then the value in
+.Ar def
+is returned as the default value, or if an error
+occurs, the value in the
+.Ar error
+parameter is returned.
+.It Fn login_getcaplist
+This function returns the value corresponding to the named
+capability tag as a list of values in a NULL terminated
+array.
+Within the login class database, some tags are of type
+.Em list ,
+which consist of one or more comma- or space separated
+values.
+Usually, this function is not called directly from an
+application, but is used indirectly via
+.Fn login_getstyle .
+.It Fn login_getpath
+This function returns a list of directories separated by colons
+.Ql &: .
+Capability tags for which this function is called consist of a list of
+directories separated by spaces.
+.It Fn login_getcaptime
+This function returns a
+.Em time value
+associated with a particular capability tag with the value expressed
+in seconds (the default), minutes, hours, days, weeks or (365 day)
+years or any combination of these.
+A suffix determines the units used: S for seconds, M for minutes,
+H for hours, D for days, W for weeks and Y for 365 day years.
+Case of the units suffix is ignored.
+.Pp
+Time values are normally used for setting resource, accounting and
+session limits.
+If supported by the operating system and compiler (which is true of
+FreeBSD), the value returned is a quad (long long), of type
+.Em rlim_t .
+A value "inf" or "infinity" may be used to express an infinite
+value, in which case RLIM_INFINITY is returned.
+.It Fn login_getcapnum
+This function returns a numeric value for a tag, expressed either as
+tag=<value> or the standard
+.Fn cgetnum
+format tag#<value>.
+The first format should be used in preference to the second, the
+second format is provided for compatibility and consistency with the
+.Xr getcap 3
+database format where numeric types use the
+.Ql \&#
+as the delimiter for numeric values.
+If in the first format, then the value given may be "inf" or
+"infinity" which results in a return value of RLIM_INFINITY.
+If the given capability tag cannot be found, the
+.Ar def
+parameter is returned, and if an error occurs, the
+.Ar error
+parameter is returned.
+.It Fn login_getcapsize
+.Fn login_getcapsize
+returns a value representing a size (typicially, file or memory)
+which may be expressed as bytes (the default), 512 byte blocks,
+kilobytes, megabytes, gigabytes, and on systems that support the
+.Ar long long
+type, terrabytes.
+The suffix used determines the units, and multiple values and
+units may be used in combination (e.g. 1m500k = 1.5 megabytes).
+A value with no suffix is interpreted as bytes, B as 512-byte
+blocks, K as kilobytes, M as megabytes, G as gigabytes and T as
+terrabytes.
+Case is ignored.
+The error value is returned if there is a login capabilities database
+error, if an invalid suffix is used, or if a numeric value cannot be
+interpreted.
+.It Fn login_getcapbool
+This function returns a boolean value tied to a particular flag.
+It returns 0 if the given capability tag is not present or is
+negated by the presence of a "tag@" (See
+.Xr getcap 3
+for more information on boolean flags), and returns 1 if the tag
+is found.
+.It Fn login_getstyle
+This function is used by the login authorisation system to determine
+the style of login available in a particular case.
+The function accepts three parameters, the login_cap entry itself and
+two optional parameters, and authorisation type 'auth' and 'style', and
+applies these to determine the authorisation style that best suites
+these rules.
+.Bl -bullet -indent offset
+.It
+If 'auth' is neither NULL nor an empty string, look for a tag of type
+"auth-<auth>" in the capability record.
+If not present, then look for the default default tag "auth=".
+.It
+If no valid authorisation list was found from the previous step, then
+default to "passwd" as the authorisation list.
+.It
+If 'style' is not NULL or empty, look for it in the list of authorisation
+methods found from the pprevious step.
+If 'style' is NULL or an empty string, then default to "passwd"
+authorisation.
+.It
+If 'style' is found in the chosen list of authorisation methods, then
+return that, otherwise return NULL.
+.El
+.Pp
+This scheme allows the administrator to determine the types of
+authorisation methods accepted by the system, depending on the
+means by which the access occurs.
+For example, the administrator may require skey or kerberos as
+the authentication method used for access to the system via the
+network, and standard methods via direct dialup or console
+logins, significantly reducing the risk of password discovery
+by "snooping" network packets.
+.El
+.Sh SEE ALSO
+.Xr getcap 3 ,
+.Xr login_class 3 ,
+.Xr login.conf 5 ,
+.Xr termcap 5
diff --git a/lib/libutil/login_cap.c b/lib/libutil/login_cap.c
new file mode 100644
index 0000000..0369907
--- /dev/null
+++ b/lib/libutil/login_cap.c
@@ -0,0 +1,780 @@
+/*-
+ * Copyright (c) 1996 by
+ * Sean Eric Fagan <sef@kithrup.com>
+ * David Nugent <davidn@blaze.net.au>
+ * All rights reserved.
+ *
+ * Portions copyright (c) 1995,1997
+ * Berkeley Software Design, Inc.
+ * 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 authors.
+ * 5. Modifications may be freely made to this file providing the above
+ * conditions are met.
+ *
+ * Low-level routines relating to the user capabilities database
+ *
+ * $Id: login_cap.c,v 1.13 1997/05/11 08:07:29 davidn Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/param.h>
+#include <pwd.h>
+#include <libutil.h>
+#include <syslog.h>
+#include <login_cap.h>
+
+/*
+ * allocstr()
+ * Manage a single static pointer for handling a local char* buffer,
+ * resizing as necessary to contain the string.
+ *
+ * allocarray()
+ * Manage a static array for handling a group of strings, resizing
+ * when necessary.
+ */
+
+static int lc_object_count = 0;
+
+static size_t internal_stringsz = 0;
+static char * internal_string = NULL;
+static size_t internal_arraysz = 0;
+static char ** internal_array = NULL;
+
+static char *
+allocstr(char *str)
+{
+ char *p;
+
+ size_t sz = strlen(str) + 1; /* realloc() only if necessary */
+ if (sz <= internal_stringsz)
+ p = strcpy(internal_string, str);
+ else if ((p = realloc(internal_string, sz)) != NULL) {
+ internal_stringsz = sz;
+ internal_string = strcpy(p, str);
+ }
+ return p;
+}
+
+
+static char **
+allocarray(size_t sz)
+{
+ char **p;
+
+ if (sz <= internal_arraysz)
+ p = internal_array;
+ else if ((p = realloc(internal_array, sz * sizeof(char*))) != NULL) {
+ internal_arraysz = sz;
+ internal_array = p;
+ }
+ return p;
+}
+
+
+/*
+ * arrayize()
+ * Turn a simple string <str> seperated by any of
+ * the set of <chars> into an array. The last element
+ * of the array will be NULL, as is proper.
+ * Free using freearraystr()
+ */
+
+static char **
+arrayize(char *str, const char *chars, int *size)
+{
+ int i;
+ char *ptr;
+ char **res = NULL;
+
+ /* count the sub-strings */
+ for (i = 0, ptr = str; *ptr; i++) {
+ int count = strcspn(ptr, chars);
+ ptr += count;
+ if (*ptr)
+ ++ptr;
+ }
+
+ /* alloc the array */
+ if ((ptr = allocstr(str)) != NULL) {
+ if ((res = allocarray(++i)) == NULL)
+ free(str);
+ else {
+ /* now split the string */
+ i = 0;
+ while (*ptr) {
+ int count = strcspn(ptr, chars);
+ res[i++] = ptr;
+ ptr += count;
+ if (*ptr)
+ *ptr++ = '\0';
+ }
+ res[i] = NULL;
+ }
+ }
+
+ if (size)
+ *size = i;
+
+ return res;
+}
+
+
+/*
+ * login_close()
+ * Frees up all resources relating to a login class
+ *
+ */
+
+void
+login_close(login_cap_t * lc)
+{
+ if (lc) {
+ free(lc->lc_style);
+ free(lc->lc_class);
+ free(lc);
+ if (--lc_object_count == 0) {
+ free(internal_string);
+ free(internal_array);
+ internal_array = NULL;
+ internal_arraysz = 0;
+ internal_string = NULL;
+ internal_stringsz = 0;
+ cgetclose();
+ }
+ }
+}
+
+
+/*
+ * login_getclassbyname() get the login class by its name.
+ * If the name given is NULL or empty, the default class
+ * LOGIN_DEFCLASS (ie. "default") is fetched. If the
+ * 'dir' argument contains a non-NULL non-empty string,
+ * then the file _FILE_LOGIN_CONF is picked up from that
+ * directory instead of the system login database.
+ * Return a filled-out login_cap_t structure, including
+ * class name, and the capability record buffer.
+ */
+
+login_cap_t *
+login_getclassbyname(char const *name, const struct passwd *pwd)
+{
+ login_cap_t *lc;
+
+ if ((lc = malloc(sizeof(login_cap_t))) != NULL) {
+ int r, i = 0;
+ const char *msg = NULL;
+ const char *dir = (pwd == NULL) ? NULL : pwd->pw_dir;
+ char userpath[MAXPATHLEN];
+
+ static char *login_dbarray[] = { NULL, NULL, NULL };
+
+ if (dir && snprintf(userpath, MAXPATHLEN, "%s/%s", dir,
+ _FILE_LOGIN_CONF) < MAXPATHLEN) {
+ login_dbarray[i] = userpath;
+ if (_secure_path(userpath, pwd->pw_uid, pwd->pw_gid) != -1)
+ i++; /* only use 'secure' data */
+ }
+ if (_secure_path(_PATH_LOGIN_CONF, 0, 0) != -1)
+ login_dbarray[i++] = _PATH_LOGIN_CONF;
+ login_dbarray[i] = NULL;
+
+ memset(lc, 0, sizeof(login_cap_t));
+ lc->lc_cap = lc->lc_class = lc->lc_style = NULL;
+
+ if (name == NULL || *name == '\0')
+ name = LOGIN_DEFCLASS;
+
+ switch (cgetent(&lc->lc_cap, login_dbarray, (char*)name)) {
+ case -1: /* Failed, entry does not exist */
+ if (strcmp(name, LOGIN_MECLASS) == 0)
+ break; /* Don't retry default on 'me' */
+ if (i == 0)
+ r = -1;
+ else if ((r = open(login_dbarray[0], O_RDONLY)) >= 0)
+ close(r);
+ /*
+ * If there's at least one login class database,
+ * and we aren't searching for a default class
+ * then complain about a non-existent class.
+ */
+ if (r >= 0 || strcmp(name, LOGIN_DEFCLASS) != 0)
+ syslog(LOG_ERR, "login_getclass: unknown class '%s'", name);
+ /* fall-back to default class */
+ name = LOGIN_DEFCLASS;
+ msg = "%s: no default/fallback class '%s'";
+ if (cgetent(&lc->lc_cap, login_dbarray, (char*)name) != 0 && r >= 0)
+ break;
+ /* Fallthru - just return system defaults */
+ case 0: /* success! */
+ if ((lc->lc_class = strdup(name)) != NULL) {
+ ++lc_object_count;
+ return lc;
+ }
+ msg = "%s: strdup: %m";
+ break;
+ case -2:
+ msg = "%s: retrieving class information: %m";
+ break;
+ case -3:
+ msg = "%s: 'tc=' reference loop '%s'";
+ break;
+ case 1:
+ msg = "couldn't resolve 'tc=' reference in '%s'";
+ break;
+ default:
+ msg = "%s: unexpected cgetent() error '%s': %m";
+ break;
+ }
+ if (msg != NULL)
+ syslog(LOG_ERR, msg, "login_getclass", name);
+ free(lc);
+ }
+
+ return NULL;
+}
+
+
+
+/*
+ * login_getclass()
+ * Get the login class for the system (only) login class database.
+ * Return a filled-out login_cap_t structure, including
+ * class name, and the capability record buffer.
+ */
+
+login_cap_t *
+login_getclass(const char *cls)
+{
+ return login_getclassbyname(cls, NULL);
+}
+
+
+/*
+ * login_getclass()
+ * Get the login class for a given password entry from
+ * the system (only) login class database.
+ * If the password entry's class field is not set, or
+ * the class specified does not exist, then use the
+ * default of LOGIN_DEFCLASS (ie. "default").
+ * Return a filled-out login_cap_t structure, including
+ * class name, and the capability record buffer.
+ */
+
+login_cap_t *
+login_getpwclass(const struct passwd *pwd)
+{
+ const char *cls = NULL;
+
+ if (pwd != NULL) {
+ cls = pwd->pw_class;
+ if (cls == NULL || *cls == '\0')
+ cls = (pwd->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
+ }
+ return login_getclassbyname(cls, pwd);
+}
+
+
+/*
+ * login_getuserclass()
+ * Get the login class for a given password entry, allowing user
+ * overrides via ~/.login_conf.
+ */
+
+login_cap_t *
+login_getuserclass(const struct passwd *pwd)
+{
+ return login_getclassbyname(LOGIN_MECLASS, pwd);
+}
+
+
+
+/*
+ * login_getcapstr()
+ * Given a login_cap entry, and a capability name, return the
+ * value defined for that capability, a defualt if not found, or
+ * an error string on error.
+ */
+
+char *
+login_getcapstr(login_cap_t *lc, const char *cap, char *def, char *error)
+{
+ char *res;
+ int ret;
+
+ if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0')
+ return def;
+
+ if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+ return def;
+ return (ret >= 0) ? res : error;
+}
+
+
+/*
+ * login_getcaplist()
+ * Given a login_cap entry, and a capability name, return the
+ * value defined for that capability split into an array of
+ * strings.
+ */
+
+char **
+login_getcaplist(login_cap_t *lc, const char *cap, const char *chars)
+{
+ char *lstring;
+
+ if (chars == NULL)
+ chars = ", \t";
+ if ((lstring = login_getcapstr(lc, (char*)cap, NULL, NULL)) != NULL)
+ return arrayize(lstring, chars, NULL);
+ return NULL;
+}
+
+
+/*
+ * login_getpath()
+ * From the login_cap_t <lc>, get the capability <cap> which is
+ * formatted as either a space or comma delimited list of paths
+ * and append them all into a string and separate by semicolons.
+ * If there is an error of any kind, return <error>.
+ */
+
+char *
+login_getpath(login_cap_t *lc, const char *cap, char * error)
+{
+ char *str;
+
+ if ((str = login_getcapstr(lc, (char*)cap, NULL, NULL)) == NULL)
+ str = error;
+ else {
+ char *ptr = str;
+
+ while (*ptr) {
+ int count = strcspn(ptr, ", \t");
+ ptr += count;
+ if (*ptr)
+ *ptr++ = ':';
+ }
+ }
+ return str;
+}
+
+
+static int
+isinfinite(const char *s)
+{
+ static const char *infs[] = {
+ "infinity",
+ "inf",
+ "unlimited",
+ "unlimit",
+ "-1",
+ NULL
+ };
+ const char **i = &infs[0];
+
+ while (*i != NULL) {
+ if (strcasecmp(s, *i) == 0)
+ return 1;
+ ++i;
+ }
+ return 0;
+}
+
+
+static u_quad_t
+rmultiply(u_quad_t n1, u_quad_t n2)
+{
+ u_quad_t m, r;
+ int b1, b2;
+
+ static int bpw = 0;
+
+ /* Handle simple cases */
+ if (n1 == 0 || n2 == 0)
+ return 0;
+ if (n1 == 1)
+ return n2;
+ if (n2 == 1)
+ return n1;
+
+ /*
+ * sizeof() returns number of bytes needed for storage.
+ * This may be different from the actual number of useful bits.
+ */
+ if (!bpw) {
+ bpw = sizeof(u_quad_t) * 8;
+ while (((u_quad_t)1 << (bpw-1)) == 0)
+ --bpw;
+ }
+
+ /*
+ * First check the magnitude of each number. If the sum of the
+ * magnatude is way to high, reject the number. (If this test
+ * is not done then the first multiply below may overflow.)
+ */
+ for (b1 = bpw; (((u_quad_t)1 << (b1-1)) & n1) == 0; --b1)
+ ;
+ for (b2 = bpw; (((u_quad_t)1 << (b2-1)) & n2) == 0; --b2)
+ ;
+ if (b1 + b2 - 2 > bpw) {
+ errno = ERANGE;
+ return (UQUAD_MAX);
+ }
+
+ /*
+ * Decompose the multiplication to be:
+ * h1 = n1 & ~1
+ * h2 = n2 & ~1
+ * l1 = n1 & 1
+ * l2 = n2 & 1
+ * (h1 + l1) * (h2 + l2)
+ * (h1 * h2) + (h1 * l2) + (l1 * h2) + (l1 * l2)
+ *
+ * Since h1 && h2 do not have the low bit set, we can then say:
+ *
+ * (h1>>1 * h2>>1 * 4) + ...
+ *
+ * So if (h1>>1 * h2>>1) > (1<<(bpw - 2)) then the result will
+ * overflow.
+ *
+ * Finally, if MAX - ((h1 * l2) + (l1 * h2) + (l1 * l2)) < (h1*h2)
+ * then adding in residual amout will cause an overflow.
+ */
+
+ m = (n1 >> 1) * (n2 >> 1);
+ if (m >= ((u_quad_t)1 << (bpw-2))) {
+ errno = ERANGE;
+ return (UQUAD_MAX);
+ }
+ m *= 4;
+
+ r = (n1 & n2 & 1)
+ + (n2 & 1) * (n1 & ~(u_quad_t)1)
+ + (n1 & 1) * (n2 & ~(u_quad_t)1);
+
+ if ((u_quad_t)(m + r) < m) {
+ errno = ERANGE;
+ return (UQUAD_MAX);
+ }
+ m += r;
+
+ return (m);
+}
+
+
+/*
+ * login_getcaptime()
+ * From the login_cap_t <lc>, get the capability <cap>, which is
+ * formatted as a time (e.g., "<cap>=10h3m2s"). If <cap> is not
+ * present in <lc>, return <def>; if there is an error of some kind,
+ * return <error>.
+ */
+
+rlim_t
+login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
+{
+ char *res, *ep, *oval;
+ int r;
+ rlim_t tot;
+
+ errno = 0;
+ if (lc == NULL || lc->lc_cap == NULL)
+ return def;
+
+ /*
+ * Look for <cap> in lc_cap.
+ * If it's not there (-1), return <def>.
+ * If there's an error, return <error>.
+ */
+
+ if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+ return def;
+ else if (r < 0) {
+ errno = ERANGE;
+ return error;
+ }
+
+ /* "inf" and "infinity" are special cases */
+ if (isinfinite(res))
+ return RLIM_INFINITY;
+
+ /*
+ * Now go through the string, turning something like 1h2m3s into
+ * an integral value. Whee.
+ */
+
+ errno = 0;
+ tot = 0;
+ oval = res;
+ while (*res) {
+ rlim_t tim = strtoq(res, &ep, 0);
+ rlim_t mult = 1;
+
+ if (ep == NULL || ep == res || errno != 0) {
+ invalid:
+ syslog(LOG_WARNING, "login_getcaptime: class '%s' bad value %s=%s",
+ lc->lc_class, cap, oval);
+ errno = ERANGE;
+ return error;
+ }
+ /* Look for suffixes */
+ switch (*ep++) {
+ case 0:
+ ep--;
+ break; /* end of string */
+ case 's': case 'S': /* seconds */
+ break;
+ case 'm': case 'M': /* minutes */
+ mult = 60;
+ break;
+ case 'h': case 'H': /* hours */
+ mult = 60L * 60L;
+ break;
+ case 'd': case 'D': /* days */
+ mult = 60L * 60L * 24L;
+ break;
+ case 'w': case 'W': /* weeks */
+ mult = 60L * 60L * 24L * 7L;
+ break;
+ case 'y': case 'Y': /* 365-day years */
+ mult = 60L * 60L * 24L * 365L;
+ break;
+ default:
+ goto invalid;
+ }
+ res = ep;
+ tot += rmultiply(tim, mult);
+ if (errno)
+ goto invalid;
+ }
+
+ return tot;
+}
+
+
+/*
+ * login_getcapnum()
+ * From the login_cap_t <lc>, extract the numerical value <cap>.
+ * If it is not present, return <def> for a default, and return
+ * <error> if there is an error.
+ * Like login_getcaptime(), only it only converts to a number, not
+ * to a time; "infinity" and "inf" are 'special.'
+ */
+
+rlim_t
+login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
+{
+ char *ep, *res;
+ int r;
+ rlim_t val;
+
+ if (lc == NULL || lc->lc_cap == NULL)
+ return def;
+
+ /*
+ * For BSDI compatibility, try for the tag=<val> first
+ */
+ if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) {
+ long lval;
+ /* string capability not present, so try for tag#<val> as numeric */
+ if ((r = cgetnum(lc->lc_cap, (char *)cap, &lval)) == -1)
+ return def; /* Not there, so return default */
+ else if (r >= 0)
+ return (rlim_t)lval;
+ }
+
+ if (r < 0) {
+ errno = ERANGE;
+ return error;
+ }
+
+ if (isinfinite(res))
+ return RLIM_INFINITY;
+
+ errno = 0;
+ val = strtoq(res, &ep, 0);
+ if (ep == NULL || ep == res || errno != 0) {
+ syslog(LOG_WARNING, "login_getcapnum: class '%s' bad value %s=%s",
+ lc->lc_class, cap, res);
+ errno = ERANGE;
+ return error;
+ }
+
+ return val;
+}
+
+
+
+/*
+ * login_getcapsize()
+ * From the login_cap_t <lc>, extract the capability <cap>, which is
+ * formatted as a size (e.g., "<cap>=10M"); it can also be "infinity".
+ * If not present, return <def>, or <error> if there is an error of
+ * some sort.
+ */
+
+rlim_t
+login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
+{
+ char *ep, *res, *oval;
+ int r;
+ rlim_t tot;
+
+ if (lc == NULL || lc->lc_cap == NULL)
+ return def;
+
+ if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+ return def;
+ else if (r < 0) {
+ errno = ERANGE;
+ return error;
+ }
+
+ if (isinfinite(res))
+ return RLIM_INFINITY;
+
+ errno = 0;
+ tot = 0;
+ oval = res;
+ while (*res) {
+ rlim_t siz = strtoq(res, &ep, 0);
+ rlim_t mult = 1;
+
+ if (ep == NULL || ep == res || errno != 0) {
+ invalid:
+ syslog(LOG_WARNING, "login_getcapsize: class '%s' bad value %s=%s",
+ lc->lc_class, cap, oval);
+ errno = ERANGE;
+ return error;
+ }
+ switch (*ep++) {
+ case 0: /* end of string */
+ ep--;
+ break;
+ case 'b': case 'B': /* 512-byte blocks */
+ mult = 512;
+ break;
+ case 'k': case 'K': /* 1024-byte Kilobytes */
+ mult = 1024;
+ break;
+ case 'm': case 'M': /* 1024-k kbytes */
+ mult = 1024 * 1024;
+ break;
+ case 'g': case 'G': /* 1Gbyte */
+ mult = 1024 * 1024 * 1024;
+ break;
+ case 't': case 'T': /* 1TBte */
+ mult = 1024LL * 1024LL * 1024LL * 1024LL;
+ break;
+ default:
+ goto invalid;
+ }
+ res = ep;
+ tot += rmultiply(siz, mult);
+ if (errno)
+ goto invalid;
+ }
+
+ return tot;
+}
+
+
+/*
+ * login_getcapbool()
+ * From the login_cap_t <lc>, check for the existance of the capability
+ * of <cap>. Return <def> if <lc>->lc_cap is NULL, otherwise return
+ * the whether or not <cap> exists there.
+ */
+
+int
+login_getcapbool(login_cap_t *lc, const char *cap, int def)
+{
+ if (lc == NULL || lc->lc_cap == NULL)
+ return def;
+ return (cgetcap(lc->lc_cap, (char *)cap, ':') != NULL);
+}
+
+
+/*
+ * login_getstyle()
+ * Given a login_cap entry <lc>, and optionally a type of auth <auth>,
+ * and optionally a style <style>, find the style that best suits these
+ * rules:
+ * 1. If <auth> is non-null, look for an "auth-<auth>=" string
+ * in the capability; if not present, default to "auth=".
+ * 2. If there is no auth list found from (1), default to
+ * "passwd" as an authorization list.
+ * 3. If <style> is non-null, look for <style> in the list of
+ * authorization methods found from (2); if <style> is NULL, default
+ * to LOGIN_DEFSTYLE ("passwd").
+ * 4. If the chosen style is found in the chosen list of authorization
+ * methods, return that; otherwise, return NULL.
+ * E.g.:
+ * login_getstyle(lc, NULL, "ftp");
+ * login_getstyle(lc, "login", NULL);
+ * login_getstyle(lc, "skey", "network");
+ */
+
+char *
+login_getstyle(login_cap_t *lc, char *style, const char *auth)
+{
+ int i;
+ char **authtypes = NULL;
+ char *auths= NULL;
+ char realauth[64];
+
+ static char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL };
+
+ if (auth != NULL && *auth != '\0') {
+ if (snprintf(realauth, sizeof realauth, "auth-%s", auth) < sizeof realauth)
+ authtypes = login_getcaplist(lc, realauth, NULL);
+ }
+
+ if (authtypes == NULL)
+ authtypes = login_getcaplist(lc, "auth", NULL);
+
+ if (authtypes == NULL)
+ authtypes = defauthtypes;
+
+ /*
+ * We have at least one authtype now; auths is a comma-seperated
+ * (or space-separated) list of authentication types. We have to
+ * convert from this to an array of char*'s; authtypes then gets this.
+ */
+ i = 0;
+ if (style != NULL && *style != '\0') {
+ while (authtypes[i] != NULL && strcmp(style, authtypes[i]) != 0)
+ i++;
+ }
+
+ lc->lc_style = NULL;
+ if (authtypes[i] != NULL && (auths = strdup(authtypes[i])) != NULL)
+ lc->lc_style = auths;
+
+ if (lc->lc_style != NULL)
+ lc->lc_style = strdup(lc->lc_style);
+
+ return lc->lc_style;
+}
diff --git a/lib/libutil/login_cap.h b/lib/libutil/login_cap.h
new file mode 100644
index 0000000..f380936
--- /dev/null
+++ b/lib/libutil/login_cap.h
@@ -0,0 +1,156 @@
+/*-
+ * Copyright (c) 1996 by
+ * Sean Eric Fagan <sef@kithrup.com>
+ * David Nugent <davidn@blaze.net.au>
+ * 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 authors.
+ * 5. Modifications may be freely made to this file providing the above
+ * conditions are met.
+ *
+ * Low-level routines relating to the user capabilities database
+ *
+ * Was login_cap.h,v 1.9 1997/05/07 20:00:01 eivind Exp
+ * $Id: login_cap.h,v 1.1 1997/05/10 12:49:30 davidn Exp $
+ */
+
+#ifndef _LOGIN_CAP_H_
+#define _LOGIN_CAP_H_
+
+#define LOGIN_DEFCLASS "default"
+#define LOGIN_DEFROOTCLASS "root"
+#define LOGIN_MECLASS "me"
+#define LOGIN_DEFSTYLE "passwd"
+#define LOGIN_DEFSERVICE "login"
+#define LOGIN_DEFUMASK 022
+#define LOGIN_DEFPRI 0
+#define _PATH_LOGIN_CONF "/etc/login.conf"
+#define _FILE_LOGIN_CONF ".login_conf"
+#define _PATH_AUTHPROG "/usr/libexec/login_"
+
+#define LOGIN_SETGROUP 0x0001 /* set group */
+#define LOGIN_SETLOGIN 0x0002 /* set login (via setlogin) */
+#define LOGIN_SETPATH 0x0004 /* set path */
+#define LOGIN_SETPRIORITY 0x0008 /* set priority */
+#define LOGIN_SETRESOURCES 0x0010 /* set resources (cputime, etc.) */
+#define LOGIN_SETUMASK 0x0020 /* set umask, obviously */
+#define LOGIN_SETUSER 0x0040 /* set user (via setuid) */
+#define LOGIN_SETENV 0x0080 /* set user environment */
+#define LOGIN_SETALL 0x00ff /* set everything */
+
+#define BI_AUTH "authorize" /* accepted authentication */
+#define BI_REJECT "reject" /* rejected authentication */
+#define BI_CHALLENG "reject challenge" /* reject with a challenge */
+#define BI_SILENT "reject silent" /* reject silently */
+#define BI_REMOVE "remove" /* remove file on error */
+#define BI_ROOTOKAY "authorize root" /* root authenticated */
+#define BI_SECURE "authorize secure" /* okay on non-secure line */
+#define BI_SETENV "setenv" /* set environment variable */
+#define BI_VALUE "value" /* set local variable */
+
+#define AUTH_OKAY 0x01 /* user authenticated */
+#define AUTH_ROOTOKAY 0x02 /* root login okay */
+#define AUTH_SECURE 0x04 /* secure login */
+#define AUTH_SILENT 0x08 /* silent rejection */
+#define AUTH_CHALLENGE 0x10 /* a chellenge was given */
+
+#define AUTH_ALLOW (AUTH_OKAY | AUTH_ROOTOKAY | AUTH_SECURE)
+
+typedef struct login_cap {
+ char *lc_class;
+ char *lc_cap;
+ char *lc_style;
+} login_cap_t;
+
+typedef struct login_time {
+ u_short lt_start; /* Start time */
+ u_short lt_end; /* End time */
+#define LTM_NONE 0x00
+#define LTM_SUN 0x01
+#define LTM_MON 0x02
+#define LTM_TUE 0x04
+#define LTM_WED 0x08
+#define LTM_THU 0x10
+#define LTM_FRI 0x20
+#define LTM_SAT 0x40
+#define LTM_ANY 0x7F
+#define LTM_WK 0x3E
+#define LTM_WD 0x41
+ u_char lt_dow; /* Days of week */
+} login_time_t;
+
+#define LC_MAXTIMES 64
+
+#include <sys/cdefs.h>
+__BEGIN_DECLS
+struct passwd;
+
+void login_close __P((login_cap_t *));
+login_cap_t *login_getclassbyname __P((const char *, const struct passwd *));
+login_cap_t *login_getclass __P((const char *));
+login_cap_t *login_getpwclass __P((const struct passwd *));
+login_cap_t *login_getuserclass __P((const struct passwd *));
+
+char *login_getcapstr __P((login_cap_t*, const char *, char *, char *));
+char **login_getcaplist __P((login_cap_t *, const char *, const char *));
+char *login_getstyle __P((login_cap_t *, char *, const char *));
+rlim_t login_getcaptime __P((login_cap_t *, const char *, rlim_t, rlim_t));
+rlim_t login_getcapnum __P((login_cap_t *, const char *, rlim_t, rlim_t));
+rlim_t login_getcapsize __P((login_cap_t *, const char *, rlim_t, rlim_t));
+char *login_getpath __P((login_cap_t *, const char *, char *));
+int login_getcapbool __P((login_cap_t *, const char *, int));
+
+int setclasscontext __P((const char*, unsigned int));
+int setusercontext __P((login_cap_t*, const struct passwd*, uid_t, unsigned int));
+void setclassresources __P((login_cap_t *));
+void setclassenvironment __P((login_cap_t *, const struct passwd *, int));
+
+/* Most of these functions are deprecated */
+int auth_approve __P((login_cap_t*, const char*, const char*));
+int auth_check __P((const char *, const char *, const char *, const char *, int *));
+void auth_env __P((void));
+char *auth_mkvalue __P((const char *n));
+int auth_response __P((const char *, const char *, const char *, const char *, int *, const char *, const char *));
+void auth_rmfiles __P((void));
+int auth_scan __P((int));
+int auth_script __P((const char*, ...));
+int auth_script_data __P((const char *, int, const char *, ...));
+char *auth_valud __P((const char *));
+int auth_setopt __P((const char *, const char *));
+void auth_clropts __P((void));
+
+void auth_checknologin __P((login_cap_t*));
+int auth_cat __P((const char*));
+
+int auth_ttyok __P((login_cap_t*, const char *));
+int auth_hostok __P((login_cap_t*, const char *, char const *));
+int auth_timeok __P((login_cap_t*, time_t));
+
+struct tm;
+
+login_time_t parse_lt __P((const char *));
+int in_ltm __P((const login_time_t *, struct tm *, time_t *));
+int in_ltms __P((const login_time_t *, struct tm *, time_t *));
+
+/* helper functions */
+
+int login_strinlist __P((char **, char const *, int));
+int login_str2inlist __P((char **, const char *, const char *, int));
+login_time_t * login_timelist __P((login_cap_t *, char const *, int *, login_time_t **));
+int login_ttyok __P((login_cap_t *, const char *, const char *, const char *));
+int login_hostok __P((login_cap_t *, const char *, const char *, const char *, const char *));
+
+__END_DECLS
+
+#endif /* _LOGIN_CAP_H_ */
diff --git a/lib/libutil/login_class.3 b/lib/libutil/login_class.3
new file mode 100644
index 0000000..f74803c
--- /dev/null
+++ b/lib/libutil/login_class.3
@@ -0,0 +1,187 @@
+.\" Copyright (c) 1995 David Nugent <davidn@blaze.net.au>
+.\" 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
+.\" David Nugent.
+.\" 5. Modifications may be freely made to this file providing the above
+.\" conditions are met.
+.\"
+.\" $Id: login_class.3,v 1.4 1997/02/22 15:08:20 peter Exp $
+.\"
+.Dd December 28, 1996
+.Os FreeBSD
+.Dt LOGIN_CLASS 3
+.Sh NAME
+.Nm setclasscontext ,
+.Nm setusercontext ,
+.Nm setclassresources ,
+.Nm setclassenvironment
+.Nd functions for using the login class capabilities database.
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <login_cap.h>
+.Ft int
+.Fn setclasscontext "const char *classname" "unsigned int flags"
+.Ft int
+.Fn setusercontext "login_cap_t *lc" "const struct passwd *pwd" "uid_t uid" "unsigned int flags"
+.Ft void
+.Fn setclassresources "login_cap_t *lc"
+.Ft void
+.Fn setclassenvironment "login_cap_t *lc" "const struct passwd *pwd" "int paths"
+.Pp
+.Sh DESCRIPTION
+These functions provide a higher level interface to the login class
+database than those documented in
+.Xr login_cap 3 .
+These functions are used to set resource limits, environment and
+accounting settings for users on logging into the system and when
+selecting an appropriate set of environment and resource settings
+for system daemons based on login classes.
+These functions may only be called if the current process is
+running with root priviledges.
+If the LOGIN_SETLOGIN flag is used this function calls
+.Xr setlogin 2 ,
+and due care must be taken as detailed in the manpage for that
+function and this affects all processes running in the same session
+and not just the current process.
+.Pp
+.Fn setclasscontext
+sets various class context values (resource limits, umask and
+process priorities) based on values for a specific named class.
+.Pp
+The function
+.Fn setusercontext
+sets class context values based on a given login_cap_t
+object, a specific passwd record (if login_cap_t is NULL),
+sets the current session's login and the current process
+user and group ownership.
+Each of these functions is selectable via bit-flags passed
+in the
+.Ar flags
+parameter, which is comprised of one or more of the following:
+.Bl -tag -width LOGIN_SETRESOURCES
+.It LOGIN_SETLOGIN
+Set the login associated with the current session to the user
+specified in the passwd structure.
+.Xr setlogin 2 .
+The
+.Ar pwd
+parameter must not be NULL if this option is used.
+.It LOGIN_SETUSER
+Set ownship of the current process to the uid specified in the
+.Ar uid
+parameter using
+.Xr setuid 2 .
+.It LOGIN_SETGROUP
+Set group ownership of the current process to the group id
+specified in the passwd structure using
+.Xr setgid 2 ,
+and calls
+.Xr initgroups 3
+to set up the group access list for the current process.
+The
+.Ar pwd
+parameter must not be NULL if this option is used.
+.It LOGIN_SETRESOURCES
+Set resource limits for the current process based on values
+specified in the system login class database.
+Class capability tags used, with and without -cur (soft limit)
+or -max (hard limit) suffixes and the corresponding resource
+setting:
+.Bd -literal
+cputime RLIMIT_CPU
+filesize RLIMIT_FSIZE
+datasize RLIMIT_DATA
+stacksize RLIMIT_STACK
+coredumpsize RLIMIT_CORE
+memoryuse RLIMIT_RSS
+memorylocked RLIMIT_MEMLOCK
+maxproc RLIMIT_NPROC
+openfiles RLIMIT_NOFILE
+.Ed
+.It LOGIN_SETPRIORITY
+Set the scheduling priority for the current process based on the
+value specified in the system login class database.
+Class capability tags used:
+.Bd -literal
+priority
+.Ed
+.It LOGIN_SETUMASK
+Set the umask for the current process to a value in the user or
+system login class database.
+Class capability tags used:
+.Bd -literal
+umask
+.Ed
+.It LOGIN_SETPATH
+Set the "path" and "manpath" environment variables based on values
+in the user or system login class database.
+Class capability tags used with the corresponding environment
+variables set:
+.Bd -literal
+path PATH
+manpath MANPATH
+.Ed
+.It LOGIN_SETENV
+Set various environment variables based on values in the user or
+system login class database.
+Class capability tags used with the corresponding environment
+variables set:
+.Bd -literal
+lang LANG
+charset MM_CHARSET
+timezone TZ
+term TERM
+.Ed
+.Pp
+Additional environment variables may be set using the list type
+capability "setenv=var1 val1,var2 val2..,varN valN".
+.It LOGIN_SETALL
+Enables all of the above settings.
+.El
+.Pp
+Note that when setting environment variables and a valid passwd
+pointer is provided in the
+.Ar pwd
+parameter, the characters
+.Ql \&~
+and
+.Ql \&$
+are substituted for the user's home directory and login name
+respectively.
+.Pp
+The
+.Fn setclassresources
+and
+.Fn setclassenvironment
+functions are subsets of the setcontext functions above, but may
+be useful in isolation.
+.Sh RETURN VALUES
+.Fn setclasscontext
+and
+.Fn setusercontext
+return -1 if an error occured, or 0 on success.
+If an error occurs when attempting to set the user, login, group
+or resources, a message is reported to
+.Xr syslog 3 ,
+with LOG_ERR priority and directed to the currently active facility.
+.Sh SEE ALSO
+.Xr setgid 2 ,
+.Xr setlogin 2 ,
+.Xr setuid 2 ,
+.Xr getcap 3 ,
+.Xr initgroups 3 ,
+.Xr login_cap 3 ,
+.Xr login.conf 5 ,
+.Xr termcap 5
diff --git a/lib/libutil/login_class.c b/lib/libutil/login_class.c
new file mode 100644
index 0000000..73190e9
--- /dev/null
+++ b/lib/libutil/login_class.c
@@ -0,0 +1,387 @@
+/*-
+ * Copyright (c) 1996 by
+ * Sean Eric Fagan <sef@kithrup.com>
+ * David Nugent <davidn@blaze.net.au>
+ * 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 authors.
+ * 5. Modifications may be freely made to this file providing the above
+ * conditions are met.
+ *
+ * High-level routines relating to use of the user capabilities database
+ *
+ * $Id: login_class.c,v 1.5 1997/02/22 15:08:22 peter Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <syslog.h>
+#include <login_cap.h>
+#include <paths.h>
+
+
+#undef UNKNOWN
+#define UNKNOWN "su"
+
+
+static struct login_res {
+ const char *what;
+ rlim_t (*who)(login_cap_t *, const char *, rlim_t, rlim_t);
+ int why;
+} resources[] = {
+ { "cputime", login_getcaptime, RLIMIT_CPU },
+ { "filesize", login_getcapsize, RLIMIT_FSIZE },
+ { "datasize", login_getcapsize, RLIMIT_DATA },
+ { "stacksize", login_getcapsize, RLIMIT_STACK },
+ { "memoryuse", login_getcapsize, RLIMIT_RSS },
+ { "memorylocked", login_getcapsize, RLIMIT_MEMLOCK },
+ { "maxproc", login_getcapnum, RLIMIT_NPROC },
+ { "openfiles", login_getcapnum, RLIMIT_NOFILE },
+ { "coredumpsize", login_getcapsize, RLIMIT_CORE },
+ { NULL, 0, 0 }
+};
+
+
+void
+setclassresources(login_cap_t *lc)
+{
+ struct login_res *lr;
+
+ if (lc == NULL)
+ return;
+
+ for (lr = resources; lr->what != NULL; ++lr) {
+ struct rlimit rlim;
+
+ /*
+ * The login.conf file can have <limit>, <limit>-max, and
+ * <limit>-cur entries.
+ * What we do is get the current current- and maximum- limits.
+ * Then, we try to get an entry for <limit> from the capability,
+ * using the current and max limits we just got as the
+ * default/error values.
+ * *Then*, we try looking for <limit>-cur and <limit>-max,
+ * again using the appropriate values as the default/error
+ * conditions.
+ */
+
+ if (getrlimit(lr->why, &rlim) != 0)
+ syslog(LOG_ERR, "getting %s resource limit: %m", lr->what);
+ else {
+ char name_cur[40];
+ char name_max[40];
+ rlim_t rcur = rlim.rlim_cur;
+ rlim_t rmax = rlim.rlim_max;
+
+ sprintf(name_cur, "%s-cur", lr->what);
+ sprintf(name_max, "%s-max", lr->what);
+
+ rcur = (*lr->who)(lc, lr->what, rcur, rcur);
+ rmax = (*lr->who)(lc, lr->what, rmax, rmax);
+ rlim.rlim_cur = (*lr->who)(lc, name_cur, rcur, rcur);
+ rlim.rlim_max = (*lr->who)(lc, name_max, rmax, rmax);
+
+ if (setrlimit(lr->why, &rlim) == -1)
+ syslog(LOG_WARNING, "set class '%s' resource limit %s: %m", lc->lc_class, lr->what);
+ }
+ }
+}
+
+
+
+static struct login_vars {
+ const char *tag;
+ const char *var;
+ const char *def;
+} pathvars[] = {
+ { "path", "PATH", NULL },
+ { "cdpath", "CDPATH", NULL },
+ { "manpath", "MANPATH", NULL },
+ { NULL, NULL, NULL }
+}, envars[] = {
+ { "lang", "LANG", NULL },
+ { "charset", "MM_CHARSET", NULL },
+ { "timezone", "TZ", NULL },
+ { "term", "TERM", UNKNOWN },
+ { NULL, NULL, NULL }
+};
+
+static char *
+substvar(char * var, const struct passwd * pwd, int hlen, int pch, int nlen)
+{
+ char *np = NULL;
+
+ if (var != NULL) {
+ int tildes = 0;
+ int dollas = 0;
+ char *p;
+
+ if (pwd != NULL) {
+ /* Count the number of ~'s in var to substitute */
+ p = var;
+ for (p = var; (p = strchr(p, '~')) != NULL; p++)
+ ++tildes;
+ /* Count the number of $'s in var to substitute */
+ p = var;
+ for (p = var; (p = strchr(p, '$')) != NULL; p++)
+ ++dollas;
+ }
+
+ np = malloc(strlen(var) + (dollas * nlen)
+ - dollas + (tildes * (pch+hlen))
+ - tildes + 1);
+
+ if (np != NULL) {
+ p = strcpy(np, var);
+
+ if (pwd != NULL) {
+ /*
+ * This loop does user username and homedir substitutions
+ * for unescaped $ (username) and ~ (homedir)
+ */
+ while (*(p += strcspn(p, "~$")) != '\0') {
+ int l = strlen(p);
+
+ if (p > var && *(p-1) == '\\') /* Escaped: */
+ memmove(p - 1, p, l + 1); /* Slide-out the backslash */
+ else if (*p == '~') {
+ int v = pch && *(p+1) != '/'; /* Avoid double // */
+ memmove(p + hlen + v, p + 1, l); /* Subst homedir */
+ memmove(p, pwd->pw_dir, hlen);
+ if (v)
+ p[hlen] = '/';
+ p += hlen + v;
+ }
+ else /* if (*p == '$') */ {
+ memmove(p + nlen, p + 1, l); /* Subst username */
+ memmove(p, pwd->pw_name, nlen);
+ p += nlen;
+ }
+ }
+ }
+ }
+ }
+
+ return np;
+}
+
+
+void
+setclassenvironment(login_cap_t *lc, const struct passwd * pwd, int paths)
+{
+ struct login_vars *vars = paths ? pathvars : envars;
+ int hlen = pwd ? strlen(pwd->pw_dir) : 0;
+ int nlen = pwd ? strlen(pwd->pw_name) : 0;
+ char pch = 0;
+
+ if (hlen && pwd->pw_dir[hlen-1] != '/')
+ ++pch;
+
+ while (vars->tag != NULL) {
+ char * var = paths ? login_getpath(lc, vars->tag, NULL)
+ : login_getcapstr(lc, vars->tag, NULL, NULL);
+
+ char * np = substvar(var, pwd, hlen, pch, nlen);
+
+ if (np != NULL) {
+ setenv(vars->var, np, 1);
+ free(np);
+ } else if (vars->def != NULL) {
+ setenv(vars->var, vars->def, 0);
+ }
+ ++vars;
+ }
+
+ /*
+ * If we're not processing paths, then see if there is a setenv list by
+ * which the admin and/or user may set an arbitrary set of env vars.
+ */
+ if (!paths) {
+ char **set_env = login_getcaplist(lc, "setenv", ",");
+
+ if (set_env != NULL) {
+ while (*set_env != NULL) {
+ char *p = strchr(*set_env, '=');
+
+ if (p != NULL) { /* Discard invalid entries */
+ char *np;
+
+ *p++ = '\0';
+ if ((np = substvar(p, pwd, hlen, pch, nlen)) != NULL) {
+ setenv(*set_env, np, 1);
+ free(np);
+ }
+ }
+ ++set_env;
+ }
+ }
+ }
+}
+
+
+/*
+ * setclasscontext()
+ *
+ * For the login class <class>, set various class context values
+ * (limits, mainly) to the values for that class. Which values are
+ * set are controlled by <flags> -- see <login_class.h> for the
+ * possible values.
+ *
+ * setclasscontext() can only set resources, priority, and umask.
+ */
+
+int
+setclasscontext(const char *classname, unsigned int flags)
+{
+ int rc;
+ login_cap_t *lc;
+
+ lc = login_getclassbyname(classname, NULL);
+
+ flags &= LOGIN_SETRESOURCES | LOGIN_SETPRIORITY |
+ LOGIN_SETUMASK | LOGIN_SETPATH;
+
+ rc = lc ? setusercontext(lc, NULL, 0, flags) : -1;
+ login_close(lc);
+ return rc;
+}
+
+
+
+/*
+ * Private functionw which takes care of processing
+ */
+
+static mode_t
+setlogincontext(login_cap_t *lc, const struct passwd *pwd,
+ mode_t mymask, unsigned long flags)
+{
+ if (lc) {
+ /* Set resources */
+ if (flags & LOGIN_SETRESOURCES)
+ setclassresources(lc);
+ /* See if there's a umask override */
+ if (flags & LOGIN_SETUMASK)
+ mymask = (mode_t)login_getcapnum(lc, "umask", mymask, mymask);
+ /* Set paths */
+ if (flags & LOGIN_SETPATH)
+ setclassenvironment(lc, pwd, 1);
+ /* Set environment */
+ if (flags & LOGIN_SETENV)
+ setclassenvironment(lc, pwd, 0);
+ }
+ return mymask;
+}
+
+
+
+/*
+ * setusercontext()
+ *
+ * Given a login class <lc> and a user in <pwd>, with a uid <uid>,
+ * set the context as in setclasscontext(). <flags> controls which
+ * values are set.
+ *
+ * The difference between setclasscontext() and setusercontext() is
+ * that the former sets things up for an already-existing process,
+ * while the latter sets things up from a root context. Such as might
+ * be called from login(1).
+ *
+ */
+
+int
+setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned int flags)
+{
+ quad_t p;
+ mode_t mymask;
+ login_cap_t *llc = NULL;
+
+ if (lc == NULL) {
+ if (pwd != NULL && (lc = login_getpwclass(pwd)) != NULL)
+ llc = lc; /* free this when we're done */
+ }
+
+ if (flags & LOGIN_SETPATH)
+ pathvars[0].def = uid ? _PATH_DEFPATH : _PATH_STDPATH;
+
+ /* we need a passwd entry to set these */
+ if (pwd == NULL)
+ flags &= ~(LOGIN_SETGROUP | LOGIN_SETLOGIN);
+
+ /* Set the process priority */
+ if (flags & LOGIN_SETPRIORITY) {
+ p = login_getcapnum(lc, "priority", LOGIN_DEFPRI, LOGIN_DEFPRI);
+
+ p = (p < PRIO_MIN || p > PRIO_MAX) ? LOGIN_DEFPRI : p;
+ if (setpriority(PRIO_PROCESS, 0, (int)p) != 0)
+ syslog(LOG_WARNING, "setpriority '%s' (%s): %m",
+ pwd->pw_name, lc ? lc->lc_class : LOGIN_DEFCLASS);
+ }
+
+ /* Setup the user's group permissions */
+ if (flags & LOGIN_SETGROUP) {
+ if (setgid(pwd->pw_gid) != 0) {
+ syslog(LOG_ERR, "setgid(%ld): %m", (long)pwd->pw_gid);
+ login_close(llc);
+ return -1;
+ }
+ if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
+ syslog(LOG_ERR, "initgroups(%s,%ld): %m", pwd->pw_name,
+ pwd->pw_gid);
+ login_close(llc);
+ return -1;
+ }
+ }
+
+ /* Set the sessions login */
+ if ((flags & LOGIN_SETLOGIN) && setlogin(pwd->pw_name) != 0) {
+ syslog(LOG_ERR, "setlogin(%s): %m", pwd->pw_name);
+ login_close(llc);
+ return -1;
+ }
+
+ mymask = (flags & LOGIN_SETUMASK) ? umask(LOGIN_DEFUMASK) : 0;
+ mymask = setlogincontext(lc, pwd, mymask, flags);
+ login_close(llc);
+
+ /* This needs to be done after anything that needs root privs */
+ if ((flags & LOGIN_SETUSER) && setuid(uid) != 0) {
+ syslog(LOG_ERR, "setuid(%ld): %m", uid);
+ return -1; /* Paranoia again */
+ }
+
+ /*
+ * Now, we repeat some of the above for the user's private entries
+ */
+ if ((lc = login_getuserclass(pwd)) != NULL) {
+ mymask = setlogincontext(lc, pwd, mymask, flags);
+ login_close(lc);
+ }
+
+ /* Finally, set any umask we've found */
+ if (flags & LOGIN_SETUMASK)
+ umask(mymask);
+
+ return 0;
+}
+
diff --git a/lib/libutil/login_ok.3 b/lib/libutil/login_ok.3
new file mode 100644
index 0000000..f90710f
--- /dev/null
+++ b/lib/libutil/login_ok.3
@@ -0,0 +1,138 @@
+.\" Copyright (c) 1995 David Nugent <davidn@blaze.net.au>
+.\" 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
+.\" David Nugent.
+.\" 5. Modifications may be freely made to this file providing the above
+.\" conditions are met.
+.\"
+.\" $Id$
+.\"
+.Dd January 2, 1997
+.Os FreeBSD
+.Dt LOGIN_OK 3
+.Sh NAME
+.Nm auth_ttyok
+.Nm auth_hostok
+.Nm auth_timeok
+.Nd Functions for checking login class based login restrictions
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <time.h>
+.Fd #include <login_cap.h>
+.Ft int
+.Fn auth_ttyok "login_cap_t *lc" "const char *tty"
+.Ft int
+.Fn auth_hostok "login_cap_t *lc" "const char *host" "char const *ip"
+.Ft int
+.Fn auth_timeok "login_cap_t *lc" "time_t t"
+.Sh DESCRIPTION
+This set of functions checks to see if login is allowed based on login
+class capability entries in the login database,
+.Xr login.conf 5 .
+.Pp
+.Fn auth_ttyok
+checks to see if the named tty is available to users of a specific
+class, and is either in the
+.Em ttys.allow
+access list, and not in
+the
+.Em ttys.deny
+access list.
+An empty
+.Em ttys.allow
+list (or if no such capability exists for
+the give login class) logins via any tty device are allowed unless
+the
+.Em ttys.deny
+list exists and is non-empty, and the device or its
+tty group (see
+.Xr ttys 5 )
+is not in the list.
+Access to ttys may be allowed or restricted specifically by tty device
+name, a device name which includes a wildcard (e.g. ttyD* or cuaD*),
+or may name a ttygroup, when group=<name> tags have been assigned in
+.Pa /etc/ttys .
+Matching of ttys and ttygroups is case sensitive.
+Passing a
+.Dv NULL
+or empty string as the
+.Ar tty
+parameter causes the function to return a non-zero value.
+.Pp
+.Fn auth_hostok
+checks for any host restrictions for remote logins.
+The function checks on both a host name and IP address (given in its
+text form, typically n.n.n.n) against the
+.Em host.allow
+and
+.Em host.deny
+login class capabilities.
+As with ttys and their groups, wildcards and character classes may be
+used in the host allow and deny capability records.
+The
+.Xr fnmatch 3
+function is used for matching, and the matching on hostnames is case
+insensitive.
+Note that this function expects that the hostname is fully expanded
+(i.e. the local domain name added if necessary) and the IP address
+is in its canonical form.
+No hostname or address lookups are attempted.
+.Pp
+It is possible to call this function with either the hostname or
+the IP address missing (i.e.
+.Dv NULL )
+and matching will be performed
+only on the basis of the parameter given.
+Passing
+.Dv NULL
+or empty strings in both parameters will result in
+a non-zero return value.
+.Pp
+The
+.Fn auth_timeok
+function checks to see that a given time value is within the
+.Em times.allow
+login class capability and not within the
+.Em times.deny
+access lists.
+An empty or non-existent
+.Em times.allow
+list allows access at any
+time, except if a given time is falls within a period in the
+.Em times.deny
+list.
+The format of time period records contained in both
+.Em times.allow
+and
+.Em times.deny
+capability fields is explained in detail in the
+.Xr login_times 3
+manual page.
+.Sh RETURN VALUES
+A non-zero return value from any of these functions indicates that
+login access is granted.
+A zero return value means either that the item being tested is not
+in the
+.Em allow
+access list, or is within the
+.Em deny
+access list.
+.Sh SEE ALSO
+.Xr getcap 3 ,
+.Xr login_cap 3 ,
+.Xr login_class 3 ,
+.Xr login_times 3 ,
+.Xr login.conf 5 ,
+.Xr termcap 5
diff --git a/lib/libutil/login_ok.c b/lib/libutil/login_ok.c
new file mode 100644
index 0000000..1bfcd2f
--- /dev/null
+++ b/lib/libutil/login_ok.c
@@ -0,0 +1,251 @@
+/*-
+ * Copyright (c) 1996 by
+ * David Nugent <davidn@blaze.net.au>
+ * 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 authors.
+ * 5. Modifications may be freely made to this file providing the above
+ * conditions are met.
+ *
+ * Support allow/deny lists in login class capabilities
+ *
+ * $Id: login_ok.c,v 1.4 1997/05/10 18:55:38 davidn Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ttyent.h>
+#include <fnmatch.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/param.h>
+#include <login_cap.h>
+
+
+/* -- support functions -- */
+
+/*
+ * login_strinlist()
+ * This function is intentionally public - reused by TAS.
+ * Returns TRUE (non-zero) if a string matches a pattern
+ * in a given array of patterns. 'flags' is passed directly
+ * to fnmatch(3).
+ */
+
+int
+login_strinlist(char **list, char const *str, int flags)
+{
+ int rc = 0;
+
+ if (str != NULL && *str != '\0') {
+ int i = 0;
+
+ while (rc == 0 && list[i] != NULL)
+ rc = fnmatch(list[i++], str, flags) == 0;
+ }
+ return rc;
+}
+
+
+/*
+ * login_str2inlist()
+ * Locate either or two strings in a given list
+ */
+
+int
+login_str2inlist(char **ttlst, const char *str1, const char *str2, int flags)
+{
+ int rc = 0;
+
+ if (login_strinlist(ttlst, str1, flags))
+ rc = 1;
+ else if (login_strinlist(ttlst, str2, flags))
+ rc = 1;
+ return rc;
+}
+
+
+/*
+ * login_timelist()
+ * This function is intentinoally public - reused by TAS.
+ * Returns an allocated list of time periods given an array
+ * of time periods in ascii form.
+ */
+
+login_time_t *
+login_timelist(login_cap_t *lc, char const *cap, int *ltno,
+ login_time_t **ltptr)
+{
+ int j = 0;
+ struct login_time *lt = NULL;
+ char **tl;
+
+ if ((tl = login_getcaplist(lc, cap, NULL)) != NULL) {
+
+ while (tl[j++] != NULL)
+ ;
+ if (*ltno >= j)
+ lt = *ltptr;
+ else if ((lt = realloc(*ltptr, j)) != NULL) {
+ *ltno = j;
+ *ltptr = lt;
+ }
+ if (lt != NULL) {
+ int i = 0;
+
+ for (--j; i < j; i++)
+ lt[i] = parse_lt(tl[i]);
+ lt[i].lt_dow = LTM_NONE;
+ }
+ }
+ return lt;
+}
+
+
+/*
+ * login_ttyok()
+ * This function is a variation of auth_ttyok(), but it checks two
+ * arbitrary capability lists not necessarily related to access.
+ * This hook is provided for the accounted/exclude accounting lists.
+ */
+
+int
+login_ttyok(login_cap_t *lc, const char *tty, const char *allowcap,
+ const char *denycap)
+{
+ int rc = 1;
+
+ if (lc != NULL && tty != NULL && *tty != '\0') {
+ struct ttyent *te;
+ char *grp;
+ char **ttl;
+
+ te = getttynam(tty); /* Need group name */
+ grp = te ? te->ty_group : NULL;
+ ttl = login_getcaplist(lc, allowcap, NULL);
+
+ if (ttl != NULL && !login_str2inlist(ttl, tty, grp, 0))
+ rc = 0; /* tty or ttygroup not in allow list */
+ else {
+
+ ttl = login_getcaplist(lc, denycap, NULL);
+ if (ttl != NULL && login_str2inlist(ttl, tty, grp, 0))
+ rc = 0; /* tty or ttygroup in deny list */
+ }
+ }
+
+ return rc;
+}
+
+
+/*
+ * auth_ttyok()
+ * Determine whether or not login on a tty is accessible for
+ * a login class
+ */
+
+int
+auth_ttyok(login_cap_t *lc, const char * tty)
+{
+ return login_ttyok(lc, tty, "ttys.allow", "ttys.deny");
+}
+
+
+/*
+ * login_hostok()
+ * This function is a variation of auth_hostok(), but it checks two
+ * arbitrary capability lists not necessarily related to access.
+ * This hook is provided for the accounted/exclude accounting lists.
+ */
+
+int
+login_hostok(login_cap_t *lc, const char *host, const char *ip,
+ const char *allowcap, const char *denycap)
+{
+ int rc = 1; /* Default is ok */
+
+ if (lc != NULL &&
+ ((host != NULL && *host != '\0') || (ip != NULL && *ip != '\0'))) {
+ char **hl;
+
+ hl = login_getcaplist(lc, allowcap, NULL);
+ if (hl != NULL && !login_str2inlist(hl, host, ip, FNM_CASEFOLD))
+ rc = 0; /* host or IP not in allow list */
+ else {
+
+ hl = login_getcaplist(lc, "host.deny", NULL);
+ if (hl != NULL && login_str2inlist(hl, host, ip, FNM_CASEFOLD))
+ rc = 0; /* host or IP in deny list */
+ }
+ }
+
+ return rc;
+}
+
+
+/*
+ * auth_hostok()
+ * Determine whether or not login from a host is ok
+ */
+
+int
+auth_hostok(login_cap_t *lc, const char *host, const char *ip)
+{
+ return login_hostok(lc, host, ip, "host.allow", "host.deny");
+}
+
+
+/*
+ * auth_timeok()
+ * Determine whether or not login is ok at a given time
+ */
+
+int
+auth_timeok(login_cap_t *lc, time_t t)
+{
+ int rc = 1; /* Default is ok */
+
+ if (lc != NULL && t != (time_t)0 && t != (time_t)-1) {
+ struct tm *tptr;
+
+ static int ltimesno = 0;
+ static struct login_time *ltimes = NULL;
+
+ if ((tptr = localtime(&t)) != NULL) {
+ struct login_time *lt;
+
+ lt = login_timelist(lc, "times.allow", &ltimesno, &ltimes);
+ if (lt != NULL && in_ltms(lt, tptr, NULL) == -1)
+ rc = 0; /* not in allowed times list */
+ else {
+
+ lt = login_timelist(lc, "times.deny", &ltimesno, &ltimes);
+ if (lt != NULL && in_ltms(lt, tptr, NULL) != -1)
+ rc = 0; /* in deny times list */
+ }
+ if (ltimes) {
+ free(ltimes);
+ ltimes = NULL;
+ ltimesno = 0;
+ }
+ }
+ }
+
+ return rc;
+}
diff --git a/lib/libutil/login_times.3 b/lib/libutil/login_times.3
new file mode 100644
index 0000000..e2e7a3f
--- /dev/null
+++ b/lib/libutil/login_times.3
@@ -0,0 +1,155 @@
+.\" Copyright (c) 1995 David Nugent <davidn@blaze.net.au>
+.\" 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
+.\" David Nugent.
+.\" 5. Modifications may be freely made to this file providing the above
+.\" conditions are met.
+.\"
+.\" $Id$
+.\"
+.Dd January 2, 1997
+.Os FreeBSD
+.Dt LOGIN_TIMES 3
+.Sh NAME
+.Nm parse_lt
+.Nm in_ltm
+.Nm in_ltms
+.Nd Functions for parsing and checking login time periods
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <time.h>
+.Fd #include <login_cap.h>
+.Ft login_time_t
+.Fn parse_lt "const char *str"
+.Ft int
+.Fn in_ltm "const login_time_t *lt" "struct tm *t" "time_t *ends"
+.Ft int
+.Fn in_ltms "const login_time_t *lt" "struct tm *t" "time_t *ends"
+.Sh DESCRIPTION
+This set of functions may be used for parsing and checking login and
+session times against a predefined list of allowed login times as
+used in
+.Xr login.conf 5 .
+.Pp
+The format of allowed and disallowed session times specified in the
+.Ar times.allow
+and
+.Ar times.deny
+capability fields in a login class are comprised of a prefix which
+specifies one or more 2- or 3-character day codes, followed by
+a start and end time in 24 hour format separated by a hyphen.
+Day codes may be concatenated together to select specific days, or
+the special mnemonics "Any" and "All" (for any/all days of the week),
+"Wk" for any day of the week (excluding Saturdays and Sundays) and
+"Wd" for any weekend day may be used.
+.Pp
+For example, the following time period:
+.Dl MoThFrSa1400-2200
+is interpreted as Monday, Thursday through Saturday between the hours
+of 2pm and 10pm.
+.Dl Wd0600-1800
+means Saturday and Sunday, between the hours of 6am through 6pm, and
+.Dl Any0400-1600
+means any day of the week, between 4am and 4pm.
+.Pp
+Note that all time periods reference system local time.
+.Pp
+The
+.Fn parse_lt
+function converts the ascii representation of a time period into
+a structure of type
+.Ft login_time_t .
+This is defined as:
+.Bd -literal
+typedef struct login_time
+{
+ u_short lt_start; /* Start time */
+ u_short lt_end; /* End time */
+ u_char lt_dow; /* Days of week */
+} login_time_t;
+.Ed
+.Pp
+The
+.Ar lt_start
+and
+.Ar lt_end
+fields contain the number of minutes past midnight at which the
+described period begins and ends.
+The
+.Ar lt_dow
+field is a bit field, containing one bit for each day of the week
+and one bit unused.
+A series
+.Em LTM_*
+macros may be used for testing bits individually and in combination.
+If no bits are set in this field - ie. it contains the value
+.Em LTM_NONE -
+then the entire period is assumed invalid.
+This is used as a convention to mark the termination of an array
+of login_time_t values.
+If
+.Fn parse_lt
+returns a
+.Ar login_time_t
+with
+.Ar lt_dow
+equal to
+.Em LTM_NONE
+then a parsing error was encountered.
+.Pp
+The remaining functions provide the ability to test a given time_t or
+struct tm value against a specific time period or array of time
+periods.
+.Fn in_ltm
+determines whether the given time described by the struct tm
+passed as the second parameter falls within the period described
+by the first parameter.
+A boolean value is returned, indicating whether or not the time
+specified falls within the period.
+If the time does fall within the time period, and the third
+parameter to the function is not NULL, the time at which the
+period ends relative to the time passed is returned.
+.Pp
+The
+.Fn in_ltms
+function is similar to
+.Fn in_ltm
+except that the first parameter must be a pointer to an array
+of login_time_t objects, which is up to LC_MAXTIMES (64)
+elements in length, and terminated by an element with its
+.Ar lt_dow
+field set to
+.Em LTM_NONE.
+.Sh RETURN VALUES
+.Fn parse_lt
+returns a filled in structure of type login_time_t containing the
+parsed time period.
+If a parsing error occurs, the lt_dow field is set to
+.Em LTM_NONE
+(i.e. 0).
+.Pp
+.Fn in_ltm
+returns non-zero if the given time falls within the period described
+by the login_time_t passed as the first parameter.
+.Pp
+.Fn in_ltms
+returns the index of the first time period found in which the given
+time falls, or -1 if none of them apply.
+.Sh SEE ALSO
+.Xr getcap 3 ,
+.Xr login_cap 3 ,
+.Xr login_class 3 ,
+.Xr login.conf 5 ,
+.Xr termcap 5
diff --git a/lib/libutil/login_times.c b/lib/libutil/login_times.c
new file mode 100644
index 0000000..598592b
--- /dev/null
+++ b/lib/libutil/login_times.c
@@ -0,0 +1,162 @@
+/*-
+ * Copyright (c) 1996 by
+ * David Nugent <davidn@blaze.net.au>
+ * 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 authors.
+ * 5. Modifications may be freely made to this file providing the above
+ * conditions are met.
+ *
+ * Login period parsing and comparison functions.
+ *
+ * $Id: login_times.c,v 1.4 1997/02/22 15:08:27 peter Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+#include <sys/types.h>
+#include <login_cap.h>
+
+static struct
+{
+ const char *dw;
+ u_char cn;
+ u_char fl;
+} dws[] =
+{
+ { "su", 2, LTM_SUN }, { "mo", 2, LTM_MON }, { "tu", 2, LTM_TUE },
+ { "we", 2, LTM_WED }, { "th", 2, LTM_THU }, { "fr", 2, LTM_FRI },
+ { "sa", 2, LTM_SAT }, { "any",3, LTM_ANY }, { "all",3, LTM_ANY },
+ { "wk", 2, LTM_WK }, { "wd", 2, LTM_WD }, { NULL, 0, 0 }
+};
+
+static char *
+parse_time(char * ptr, u_short * t)
+{
+ u_short val;
+
+ for (val = 0; *ptr && isdigit(*ptr); ptr++)
+ val = (u_short)(val * 10 + (*ptr - '0'));
+
+ *t = (u_short)((val / 100) * 60 + (val % 100));
+
+ return ptr;
+}
+
+
+login_time_t
+parse_lt(const char * str)
+{
+ login_time_t t;
+
+ memset(&t, 0, sizeof t);
+ t.lt_dow = LTM_NONE;
+ if (str && *str && strcmp(str, "Never") != 0 && strcmp(str, "None") != 0) {
+ int i;
+ login_time_t m = t;
+ char *p;
+ char buf[64];
+
+ /* Make local copy and force lowercase to simplify parsing */
+ p = strncpy(buf, str, sizeof buf);
+ buf[sizeof buf - 1] = '\0';
+ for (i = 0; buf[i]; i++)
+ buf[i] = (char)tolower(buf[i]);
+
+ while (isalpha(*p)) {
+
+ i = 0;
+ while (dws[i].dw && strncmp(p, dws[i].dw, dws[i].cn) != 0)
+ i++;
+ if (dws[i].dw == NULL)
+ break;
+ m.lt_dow |= dws[i].fl;
+ p += dws[i].cn;
+ }
+
+ if (m.lt_dow == LTM_NONE) /* No (valid) prefix, assume any */
+ m.lt_dow |= LTM_ANY;
+
+ if (isdigit(*p))
+ p = parse_time(p, &m.lt_start);
+ else
+ m.lt_start = 0;
+ if (*p == '-')
+ p = parse_time(++p, &m.lt_end);
+ else
+ m.lt_end = 1440;
+
+ t = m;
+ }
+ return t;
+}
+
+
+int
+in_ltm(const login_time_t * ltm, struct tm * tt, time_t * ends)
+{
+ int rc = 0;
+
+ if (tt != NULL) {
+ /* First, examine the day of the week */
+ if ((u_char)(0x01 << tt->tm_wday) & ltm->lt_dow) {
+ /* Convert `current' time to minute of the day */
+ u_short now = (u_short)((tt->tm_hour * 60) + tt->tm_min);
+
+ if (tt->tm_sec > 30)
+ ++now;
+ if (now >= ltm->lt_start && now < ltm->lt_end) {
+ rc = 2;
+ if (ends != NULL) {
+ /* If requested, return ending time for this period */
+ tt->tm_hour = (int)(ltm->lt_end / 60);
+ tt->tm_min = (int)(ltm->lt_end % 60);
+ *ends = mktime(tt);
+ }
+ }
+ }
+ }
+ return rc;
+}
+
+
+int
+in_lt(const login_time_t * ltm, time_t * t)
+{
+ return in_ltm(ltm, localtime(t), t);
+}
+
+int
+in_ltms(const login_time_t * ltm, struct tm * tm, time_t * t)
+{
+ int i = 0;
+
+ while (i < LC_MAXTIMES && ltm[i].lt_dow != LTM_NONE) {
+ if (in_ltm(ltm + i, tm, t))
+ return i;
+ i++;
+ }
+ return -1;
+}
+
+int
+in_lts(const login_time_t * ltm, time_t * t)
+{
+ return in_ltms(ltm, localtime(t), t);
+}
+
diff --git a/lib/libutil/login_tty.3 b/lib/libutil/login_tty.3
new file mode 100644
index 0000000..8a4c8fe
--- /dev/null
+++ b/lib/libutil/login_tty.3
@@ -0,0 +1,66 @@
+.\"
+.\" Copyright (c) 1996 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.
+.\"
+.\" $Id$
+.\" "
+.Dd December 29, 1996
+.Os
+.Dt LOGIN_TTY 3
+.Sh NAME
+.Nm login_tty
+.Nd prepare a tty for a new login session
+.Sh SYNOPSIS
+.Fd #include <libutil.h>
+.Ft int
+.Fn login_tty "int fd"
+.Pp
+Link with
+.Va -lutil
+on the
+.Xr cc 1
+command line.
+.Sh DESCRIPTION
+The function
+.Fn login_tty
+prepares a terminal for a new login session. The file descriptor
+.Ar fd
+passed to
+.Fn login_tty
+must be opened for reading and writing on a terminal device. It will be
+made the controlling terminal for the calling process, after allocating
+a new session with
+.Xr setsid 2 .
+This terminal device will also be made the standard input, standard output,
+and standard error output of the calling process.
+.Sh RETURN VALUES
+.Fn Login_tty
+returns -1 if it could not make the device referenced by
+.Ar fd
+the controlling terminal of the calling process, and 0 otherwise.
+.Sh SEE ALSO
+.Xr dup2 2 ,
+.Xr ioctl 2 ,
+.Xr setsid 2 ,
+.Xr tty 4
diff --git a/lib/libutil/login_tty.c b/lib/libutil/login_tty.c
index 5692637..a5b19ba 100644
--- a/lib/libutil/login_tty.c
+++ b/lib/libutil/login_tty.c
@@ -38,6 +38,11 @@ static char sccsid[] = "@(#)login_tty.c 8.1 (Berkeley) 6/4/93";
#include <sys/param.h>
#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <libutil.h>
+
+int
login_tty(fd)
int fd;
{
diff --git a/lib/libutil/logout.3 b/lib/libutil/logout.3
new file mode 100644
index 0000000..7127e8a
--- /dev/null
+++ b/lib/libutil/logout.3
@@ -0,0 +1,71 @@
+.\"
+.\" Copyright (c) 1996 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.
+.\"
+.\" $Id: logout.3,v 1.4 1997/02/22 15:08:28 peter Exp $
+.\" "
+.Dd December 29, 1996
+.Os
+.Dt LOGOUT 3
+.Sh NAME
+.Nm logout
+.Nd remove an entry from the utmp file
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <libutil.h>
+.Ft int
+.Fn logout "char *line"
+.Pp
+Link with
+.Va -lutil
+on the
+.Xr cc 1
+command line.
+.Sh DESCRIPTION
+The function
+.Fn logout
+searches the
+.Xr utmp 5
+file for the slot described by
+.Ar line
+(usually a tty name). If such a slot could be found, it will be updated
+with a record where the
+.Em name
+and
+.Em host
+fields are empty, and the time stamp field is updated to the current time.
+.Sh RETURN VALUES
+.Fn Logout
+returns 1 if the slot described by
+.Ar line
+has been found and updated, 0 otherwise.
+.Sh SEE ALSO
+.Xr login 3 ,
+.Xr utmp 5 ,
+.Xr wtmp 5
+.Sh BUGS
+The calling interface of
+.Fn logout
+is inconsistent with that of
+.Xr login 3 .
diff --git a/lib/libutil/logout.c b/lib/libutil/logout.c
index 11da24f..d8cf3c8 100644
--- a/lib/libutil/logout.c
+++ b/lib/libutil/logout.c
@@ -43,6 +43,7 @@ static char sccsid[] = "@(#)logout.c 8.1 (Berkeley) 6/4/93";
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
+#include <libutil.h>
typedef struct utmp UTMP;
diff --git a/lib/libutil/logwtmp.3 b/lib/libutil/logwtmp.3
new file mode 100644
index 0000000..765fdde
--- /dev/null
+++ b/lib/libutil/logwtmp.3
@@ -0,0 +1,73 @@
+.\"
+.\" Copyright (c) 1996 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.
+.\"
+.\" $Id: logwtmp.3,v 1.4 1997/02/22 15:08:30 peter Exp $
+.\" "
+.Dd December 29, 1996
+.Os
+.Dt LOGWTMP 3
+.Sh NAME
+.Nm logwtmp
+.Nd append a new record to the wtmp file
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <libutil.h>
+.Ft void
+.Fn logwtmp "char *line" "char *name" "char *host"
+.Pp
+Link with
+.Va -lutil
+on the
+.Xr cc 1
+command line.
+.Sh DESCRIPTION
+The function
+.Fn logwtmp
+tries to append a new record to the
+.Xr wtmp 5
+file, using the provided arguments
+.Ar line ,
+.Ar name ,
+and
+.Ar host ,
+and the current time.
+.Pp
+If the length of the hostname string
+.Ar host
+is longer than what would fit into the hostname field of the
+.Xr wtmp 5
+file, it will first be attempted to convert it into a numerical IP
+address using
+.Xr gethostbyname 3 .
+Failing this, the hostname will be recorded as
+.Qq invalid hostname .
+.Pp
+The calling process must have permission to write to both files.
+.Sh RETURN VALUES
+None.
+.Sh SEE ALSO
+.Xr gethostbyname 3 ,
+.Xr login 3 ,
+.Xr wtmp 5
diff --git a/lib/libutil/logwtmp.c b/lib/libutil/logwtmp.c
index d55ac9e..a19e651 100644
--- a/lib/libutil/logwtmp.c
+++ b/lib/libutil/logwtmp.c
@@ -37,20 +37,36 @@ static char sccsid[] = "@(#)logwtmp.c 8.1 (Berkeley) 6/4/93";
#include <sys/types.h>
#include <sys/file.h>
-#include <sys/time.h>
#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <string.h>
+#include <time.h>
#include <unistd.h>
#include <utmp.h>
+void
logwtmp(line, name, host)
char *line, *name, *host;
{
struct utmp ut;
struct stat buf;
int fd;
- time_t time();
- char *strncpy();
+
+ if (strlen(host) > UT_HOSTSIZE) {
+ struct hostent *hp = gethostbyname(host);
+
+ if (hp != NULL) {
+ struct in_addr in;
+
+ memmove(&in, hp->h_addr, sizeof(in));
+ host = inet_ntoa(in);
+ } else
+ host = "invalid hostname";
+ }
if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0)
return;
diff --git a/lib/libutil/pty.3 b/lib/libutil/pty.3
new file mode 100644
index 0000000..74c8f97
--- /dev/null
+++ b/lib/libutil/pty.3
@@ -0,0 +1,144 @@
+.\"
+.\" Copyright (c) 1996 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.
+.\"
+.\" $Id$
+.\" "
+.Dd December 29, 1996
+.Os
+.Dt PTY 3
+.Sh NAME
+.Nm openpty ,
+.Nm forkpty
+.Nd auxiliary functions to obtain a pseudo-terminal
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/ioctl.h>
+.Fd #include <termios.h>
+.Fd #include <libutil.h>
+.Ft int
+.Fn openpty "int *amaster" "int *aslave" "char *name" "struct termios *termp" "struct winsize *winp"
+.Ft int
+.Fn forkpty "int *amaster" "char *name" "struct termios *termp" "struct winsize *winp"
+.Pp
+Link with
+.Va -lutil
+on the
+.Xr cc 1
+command line.
+.Sh DESCRIPTION
+The function
+.Fn openpty
+attempts to obtain the next available pseudo-terminal from the system (see
+.Xr pty 4 ) .
+If it successfully finds one, it subsequently tries to change the
+ownership of the slave device to the real UID of the current process,
+the group membership to the group
+.Dq tty
+(if such a group exists in the system), the access permissions for
+reading and writing by the owner, and for writing by the group, and to
+invalidate any current use of the line by calling
+.Xr revoke 2 .
+.Pp
+If the argument
+.Fa name
+is not
+.Dv NULL ,
+.Fn openpty
+copies the pathname of the slave pty to this area. The caller is
+responsible for allocating the required space in this array.
+.Pp
+If the arguments
+.Fa termp
+or
+.Fa winp
+are not
+.Dv NULL ,
+.Fn openpty
+initializes the termios and window size settings from the structures
+these arguments point to, respectively.
+.Pp
+Upon return, the open file descriptors for the master and slave side
+of the pty are returned in the locations pointed to by
+.Fa amaster
+and
+.Fa aslave ,
+respectively.
+.Pp
+.Fn Forkpty
+first calls
+.Fn openpty
+to obtain the next available pseudo-terminal from the system. Upon success,
+it forks off a new process. In the child process, it closes the descriptor
+for the master side of the pty, and calls
+.Xr login_tty 3
+for the slave pty. In the parent process, it closes the descriptor for the
+slave side of the pty. The arguments
+.Fa amaster ,
+.Fa name ,
+.Fa termp ,
+and
+.Fa winp
+have the same meaning as described for
+.Fn openpty .
+.Sh RETURN VALUES
+.Fn Openpty
+returns 0 on success, or -1 on failure.
+.Pp
+.Fn Forkpty
+returns -1 on failure, 0 in the slave process, and the process ID of the
+slave process in the parent process.
+.Sh ERRORS
+On failure,
+.Fn openpty
+will set the global variable
+.Dv errno
+to
+.Er ENOENT .
+.Pp
+In addition to this,
+.Fn forkpty
+may set it to any value as described for
+.Xr fork 2 .
+.Sh SEE ALSO
+.Xr chmod 2 ,
+.Xr chown 2 ,
+.Xr fork 2 ,
+.Xr getuid 2 ,
+.Xr open 2 ,
+.Xr revoke 2 ,
+.Xr login_tty 3 ,
+.Xr termios 3 ,
+.Xr pty 4 ,
+.Xr group 5
+.Sh BUGS
+The calling process must have an effective UID of super-user in order
+to perform all the intended actions. No notification will occur if
+.Fn openpty
+or
+.Fn forkpty
+failed to proceed with one of the described steps, as long as they could
+at least allocate the pty at all (and create the new process in the case
+of
+.Fn forkpty ) .
diff --git a/lib/libutil/pty.c b/lib/libutil/pty.c
index 6104461..b00d687 100644
--- a/lib/libutil/pty.c
+++ b/lib/libutil/pty.c
@@ -47,7 +47,9 @@ static char sccsid[] = "@(#)pty.c 8.3 (Berkeley) 5/16/94";
#include <string.h>
#include <termios.h>
#include <unistd.h>
+#include <libutil.h>
+int
openpty(amaster, aslave, name, termp, winp)
int *amaster, *aslave;
char *name;
@@ -64,9 +66,9 @@ openpty(amaster, aslave, name, termp, winp)
else
ttygid = -1;
- for (cp1 = "pqrs"; *cp1; cp1++) {
+ for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
line[8] = *cp1;
- for (cp2 = "0123456789abcdef"; *cp2; cp2++) {
+ for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
line[5] = 'p';
line[9] = *cp2;
if ((master = open(line, O_RDWR, 0)) == -1) {
@@ -83,10 +85,10 @@ openpty(amaster, aslave, name, termp, winp)
if (name)
strcpy(name, line);
if (termp)
- (void) tcsetattr(slave,
+ (void) tcsetattr(slave,
TCSAFLUSH, termp);
if (winp)
- (void) ioctl(slave, TIOCSWINSZ,
+ (void) ioctl(slave, TIOCSWINSZ,
(char *)winp);
return (0);
}
@@ -98,6 +100,7 @@ openpty(amaster, aslave, name, termp, winp)
return (-1);
}
+int
forkpty(amaster, name, termp, winp)
int *amaster;
char *name;
@@ -112,7 +115,7 @@ forkpty(amaster, name, termp, winp)
case -1:
return (-1);
case 0:
- /*
+ /*
* child
*/
(void) close(master);
diff --git a/lib/libutil/pw_util.c b/lib/libutil/pw_util.c
new file mode 100644
index 0000000..7ebe86e
--- /dev/null
+++ b/lib/libutil/pw_util.c
@@ -0,0 +1,233 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+
+/*
+ * This file is used by all the "password" programs; vipw(8), chpass(1),
+ * and passwd(1).
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pw_util.h"
+
+extern char *tempname;
+static pid_t editpid = -1;
+static int lockfd;
+
+void
+pw_cont(sig)
+ int sig;
+{
+
+ if (editpid != -1)
+ kill(editpid, sig);
+}
+
+void
+pw_init()
+{
+ struct rlimit rlim;
+
+ /* Unlimited resource limits. */
+ rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
+ (void)setrlimit(RLIMIT_CPU, &rlim);
+ (void)setrlimit(RLIMIT_FSIZE, &rlim);
+ (void)setrlimit(RLIMIT_STACK, &rlim);
+ (void)setrlimit(RLIMIT_DATA, &rlim);
+ (void)setrlimit(RLIMIT_RSS, &rlim);
+
+ /* Don't drop core (not really necessary, but GP's). */
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ (void)setrlimit(RLIMIT_CORE, &rlim);
+
+ /* Turn off signals. */
+ (void)signal(SIGALRM, SIG_IGN);
+ (void)signal(SIGHUP, SIG_IGN);
+ (void)signal(SIGINT, SIG_IGN);
+ (void)signal(SIGPIPE, SIG_IGN);
+ (void)signal(SIGQUIT, SIG_IGN);
+ (void)signal(SIGTERM, SIG_IGN);
+ (void)signal(SIGCONT, pw_cont);
+
+ /* Create with exact permissions. */
+ (void)umask(0);
+}
+
+int
+pw_lock()
+{
+ /*
+ * If the master password file doesn't exist, the system is hosed.
+ * Might as well try to build one. Set the close-on-exec bit so
+ * that users can't get at the encrypted passwords while editing.
+ * Open should allow flock'ing the file; see 4.4BSD. XXX
+ */
+ lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
+ if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
+ err(1, "%s", _PATH_MASTERPASSWD);
+ if (flock(lockfd, LOCK_EX|LOCK_NB))
+ errx(1, "the password db file is busy");
+ return (lockfd);
+}
+
+int
+pw_tmp()
+{
+ static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
+ int fd;
+ char *p;
+
+ if (p = strrchr(path, '/'))
+ ++p;
+ else
+ p = path;
+ strcpy(p, "pw.XXXXXX");
+ if ((fd = mkstemp(path)) == -1)
+ err(1, "%s", path);
+ tempname = path;
+ return (fd);
+}
+
+int
+pw_mkdb(username)
+char *username;
+{
+ int pstat;
+ pid_t pid;
+
+ warnx("rebuilding the database...");
+ (void)fflush(stderr);
+ if (!(pid = vfork())) {
+ if(!username) {
+ execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
+ } else {
+ execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-u",
+ username, tempname, NULL);
+ }
+ pw_error(_PATH_PWD_MKDB, 1, 1);
+ }
+ pid = waitpid(pid, &pstat, 0);
+ if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
+ return (0);
+ warnx("done");
+ return (1);
+}
+
+void
+pw_edit(notsetuid)
+ int notsetuid;
+{
+ int pstat;
+ char *p, *editor;
+
+ if (!(editor = getenv("EDITOR")))
+ editor = _PATH_VI;
+ if (p = strrchr(editor, '/'))
+ ++p;
+ else
+ p = editor;
+
+ if (!(editpid = vfork())) {
+ if (notsetuid) {
+ (void)setgid(getgid());
+ (void)setuid(getuid());
+ }
+ execlp(editor, p, tempname, NULL);
+ _exit(1);
+ }
+ for (;;) {
+ editpid = waitpid(editpid, (int *)&pstat, WUNTRACED);
+ if (editpid == -1)
+ pw_error(editor, 1, 1);
+ else if (WIFSTOPPED(pstat))
+ raise(WSTOPSIG(pstat));
+ else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0)
+ break;
+ else
+ pw_error(editor, 1, 1);
+ }
+ editpid = -1;
+}
+
+void
+pw_prompt()
+{
+ int c;
+
+ (void)printf("re-edit the password file? [y]: ");
+ (void)fflush(stdout);
+ c = getchar();
+ if (c != EOF && c != '\n')
+ while (getchar() != '\n');
+ if (c == 'n')
+ pw_error(NULL, 0, 0);
+}
+
+void
+pw_error(name, err, eval)
+ char *name;
+ int err, eval;
+{
+#ifdef YP
+ extern int _use_yp;
+#endif /* YP */
+ if (err)
+ warn(name);
+#ifdef YP
+ if (_use_yp)
+ warnx("NIS information unchanged");
+ else
+#endif /* YP */
+ warnx("%s: unchanged", _PATH_MASTERPASSWD);
+ (void)unlink(tempname);
+ exit(eval);
+}
diff --git a/lib/libutil/setproctitle.3 b/lib/libutil/setproctitle.3
new file mode 100644
index 0000000..c3f2031
--- /dev/null
+++ b/lib/libutil/setproctitle.3
@@ -0,0 +1,113 @@
+.\" 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.
+.\"
+.\" $Id: setproctitle.3,v 1.8 1997/04/17 23:31:47 danny Exp $
+.\"
+.\" The following requests are required for all man pages.
+.Dd December 16, 1995
+.Os FreeBSD
+.Dt SETPROCTITLE 3
+.Sh NAME
+.Nm setproctitle
+.Nd set the process title for
+.Xr ps 1
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <libutil.h>
+.Ft void
+.Fn setproctitle "const char *fmt" "..."
+.Pp
+Link with
+.Va -lutil
+on the
+.Xr cc 1
+command line.
+.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.
+.Pp
+If
+.Va fmt
+is NULL, the process title is reset to simply the name of the executable.
+.\" The following requests should be uncommented and used where appropriate.
+.\" This next request is for sections 2 and 3 function return values only.
+.\" .Sh RETURN VALUES
+.\" This next request is for sections 1, 6, 7 & 8 only
+.\" .Sh ENVIRONMENT
+.\" .Sh FILES
+.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
+.\" This next request is for sections 1, 6, 7 & 8 only
+.\" (command return values (to shell) and fprintf/stderr type diagnostics)
+.\" .Sh DIAGNOSTICS
+.\" The next request is for sections 2 and 3 error and signal handling only.
+.\" .Sh ERRORS
+.Sh SEE ALSO
+.Xr ps 1 ,
+.Xr w 1 ,
+.Xr kvm 3 ,
+.Xr kvm_getargv 3 ,
+.Xr printf 3
+.Sh STANDARDS
+.Fn setproctitle
+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
+.Tn NetBSD
+and
+.Tn BSD/OS .
+.Sh HISTORY
+.Fn setproctitle
+first appeared in
+.Fx 2.2 .
+Other operating systems have
+similar functions.
+.Sh AUTHORS
+.Sy "Peter Wemm <peter@FreeBSD.org>"
+stole the idea from the
+.Sy "Sendmail 8.7.3"
+source code by
+.Sy "Eric Allman <eric@sendmail.org>" .
+.\" .Sh BUGS
diff --git a/lib/libutil/setproctitle.c b/lib/libutil/setproctitle.c
new file mode 100644
index 0000000..ba21d1c
--- /dev/null
+++ b/lib/libutil/setproctitle.c
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#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>
+
+/*
+ * 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)))
+
+#if defined(__STDC__) /* from other parts of sendmail */
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+
+#define SPT_BUFSIZE 2048 /* from other parts of sendmail */
+extern char * __progname; /* is this defined in a .h anywhere? */
+
+void
+#if defined(__STDC__)
+setproctitle(const char *fmt, ...)
+#else
+setproctitle(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ static char buf[SPT_BUFSIZE];
+ static char *ps_argv[2];
+ va_list ap;
+ int mib[2];
+ struct ps_strings *ps_strings;
+ size_t len;
+
+#if defined(__STDC__)
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+
+ buf[sizeof(buf) - 1] = '\0';
+ if (fmt) {
+
+ /* print program name heading for grep */
+ (void) snprintf(buf, sizeof(buf) - 1, "%s: ", __progname);
+
+ /*
+ * can't use return from sprintf, as that is the count of how
+ * much it wanted to write, not how much it actually did.
+ */
+
+ len = strlen(buf);
+
+ /* print the argument string */
+ (void) vsnprintf(buf + len, sizeof(buf) - 1 - len, fmt, ap);
+ } else {
+ /* Idea from NetBSD - reset the title on fmt == NULL */
+ strncpy(buf, __progname, sizeof(buf) - 1);
+ }
+
+ va_end(ap);
+
+ ps_strings = NULL;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PS_STRINGS;
+ len = sizeof(ps_strings);
+ if (sysctl(mib, 2, &ps_strings, &len, NULL, 0) < 0 ||
+ ps_strings == NULL)
+ ps_strings = PS_STRINGS;
+
+ /* PS_STRINGS points to zeroed memory on a style #2 kernel */
+ if (ps_strings->ps_argvstr) {
+ /* style #3 */
+ ps_argv[0] = buf;
+ ps_argv[1] = NULL;
+ ps_strings->ps_nargvstr = 1;
+ ps_strings->ps_argvstr = ps_argv;
+ } else {
+ /* style #2 */
+ OLD_PS_STRINGS->old_ps_nargvstr = 1;
+ OLD_PS_STRINGS->old_ps_argvstr = buf;
+ }
+}
diff --git a/lib/libutil/stat_flags.c b/lib/libutil/stat_flags.c
new file mode 100644
index 0000000..b1e7062
--- /dev/null
+++ b/lib/libutil/stat_flags.c
@@ -0,0 +1,163 @@
+/*-
+ * 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.
+ * 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.
+ *
+ * $Id: stat_flags.c,v 1.5 1997/02/22 14:04:02 peter Exp $
+ */
+
+#ifndef lint
+static char const sccsid[] = "@(#)stat_flags.c 8.1 (Berkeley) 5/31/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stddef.h>
+#include <string.h>
+
+#define SAPPEND(s) { \
+ if (prefix != NULL) \
+ (void)strcat(string, prefix); \
+ (void)strcat(string, s); \
+ prefix = ","; \
+}
+
+/*
+ * flags_to_string --
+ * Convert stat flags to a comma-separated string. If no flags
+ * are set, return the default string.
+ */
+char *
+flags_to_string(flags, def)
+ u_long flags;
+ char *def;
+{
+ static char string[128];
+ char *prefix;
+
+ string[0] = '\0';
+ prefix = NULL;
+ if (flags & UF_APPEND)
+ SAPPEND("uappnd");
+ if (flags & UF_IMMUTABLE)
+ SAPPEND("uchg");
+ if (flags & UF_NOUNLINK)
+ SAPPEND("uunlnk");
+ if (flags & UF_NODUMP)
+ SAPPEND("nodump");
+ if (flags & UF_OPAQUE)
+ SAPPEND("opaque");
+ if (flags & SF_APPEND)
+ SAPPEND("sappnd");
+ if (flags & SF_ARCHIVED)
+ SAPPEND("arch");
+ if (flags & SF_IMMUTABLE)
+ SAPPEND("schg");
+ if (flags & SF_NOUNLINK)
+ SAPPEND("sunlnk");
+ return (prefix == NULL && def != NULL ? def : string);
+}
+
+#define TEST(a, b, f) { \
+ if (!memcmp(a, b, sizeof(b))) { \
+ if (clear) { \
+ if (clrp) \
+ *clrp |= (f); \
+ } else if (setp) \
+ *setp |= (f); \
+ break; \
+ } \
+}
+
+/*
+ * string_to_flags --
+ * Take string of arguments and return stat flags. Return 0 on
+ * success, 1 on failure. On failure, stringp is set to point
+ * to the offending token.
+ */
+int
+string_to_flags(stringp, setp, clrp)
+ char **stringp;
+ u_long *setp, *clrp;
+{
+ int clear;
+ char *string, *p;
+
+ clear = 0;
+ if (setp)
+ *setp = 0;
+ if (clrp)
+ *clrp = 0;
+ string = *stringp;
+ while ((p = strsep(&string, "\t ,")) != NULL) {
+ *stringp = p;
+ if (*p == '\0')
+ continue;
+ if (p[0] == 'n' && p[1] == 'o') {
+ clear = 1;
+ p += 2;
+ }
+ switch (p[0]) {
+ case 'a':
+ TEST(p, "arch", SF_ARCHIVED);
+ TEST(p, "archived", SF_ARCHIVED);
+ return (1);
+ case 'd':
+ clear = !clear;
+ TEST(p, "dump", UF_NODUMP);
+ return (1);
+ case 'o':
+ TEST(p, "opaque", UF_OPAQUE);
+ return (1);
+ case 's':
+ TEST(p, "sappnd", SF_APPEND);
+ TEST(p, "sappend", SF_APPEND);
+ TEST(p, "schg", SF_IMMUTABLE);
+ TEST(p, "schange", SF_IMMUTABLE);
+ TEST(p, "simmutable", SF_IMMUTABLE);
+ TEST(p, "sunlnk", SF_NOUNLINK);
+ TEST(p, "sunlink", SF_NOUNLINK);
+ return (1);
+ case 'u':
+ TEST(p, "uappnd", UF_APPEND);
+ TEST(p, "uappend", UF_APPEND);
+ TEST(p, "uchg", UF_IMMUTABLE);
+ TEST(p, "uchange", UF_IMMUTABLE);
+ TEST(p, "uimmutable", UF_IMMUTABLE);
+ TEST(p, "uunlnk", UF_NOUNLINK);
+ TEST(p, "uunlink", UF_NOUNLINK);
+ /* FALLTHROUGH */
+ default:
+ return (1);
+ }
+ }
+ return (0);
+}
diff --git a/lib/libutil/uucplock.3 b/lib/libutil/uucplock.3
new file mode 100644
index 0000000..7f93aa0
--- /dev/null
+++ b/lib/libutil/uucplock.3
@@ -0,0 +1,170 @@
+.\"
+.\" Copyright (c) 1996 Brian Somers <brian@awfulhak.demon.co.uk>
+.\"
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this 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.
+.\"
+.\" $Id: uucplock.3,v 1.6 1997/05/11 08:50:33 davidn Exp $
+.\" "
+.Dd March 30, 1997
+.Os
+.Dt uucplock 3
+.Sh NAME
+.Nm uu_lock ,
+.Nm uu_unlock ,
+.Nm uu_lockerr
+.Nd acquire and release control of a serial device
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <libutil.h>
+.Ft int
+.Fn uu_lock "const char *ttyname"
+.Ft int
+.Fn uu_unlock "const char *ttyname"
+.Ft const char *
+.Fn uu_lockerr "int uu_lockresult"
+.Pp
+Link with
+.Va -lutil
+on the
+.Xr cc 1
+command line.
+.Sh DESCRIPTION
+The
+.Fn uu_lock
+function attempts to create a lock file called
+.Pa /var/spool/lock/LCK..
+with a suffix given by the passed
+.Fa ttyname .
+If the file already exists, it is expected to contain the process
+id of the locking program.
+.Pp
+If the file does not already exist, or the owning process given by
+the process id found in the lock file is no longer running,
+.Fn uu_lock
+will write its own process id into the file and return success.
+.Pp
+.Fn uu_unlock
+removes the lockfile created by
+.Fn uu_lock
+for the given
+.Fa ttyname .
+Care should be taken that
+.Fn uu_lock
+was successful before calling
+.Fn uu_unlock .
+.Pp
+.Fn uu_lockerr
+returns an error string representing the error
+.Fa uu_lockresult ,
+as returned from
+.Fn uu_lock .
+.Sh RETURN VALUES
+.Fn uu_unlock
+returns 0 on success and -1 on failure.
+.Pp
+.Fn uu_lock
+may return any of the following values:
+.Pp
+.Dv UU_LOCK_INUSE:
+The lock is in use by another process.
+.Pp
+.Dv UU_LOCK_OK:
+The lock was successfully created.
+.Pp
+.Dv UU_LOCK_OPEN_ERR:
+The lock file could not be opened via
+.Xr open 2 .
+.Pp
+.Dv UU_LOCK_READ_ERR:
+The lock file could not be read via
+.Xr read 2 .
+.Pp
+.Dv UU_LOCK_SEEK_ERR:
+The lock file was
+.Dq stale ,
+but the call to
+.Xr lseek 2
+necessary to write the current process id failed.
+.Pp
+.Dv UU_LOCK_WRITE_ERR:
+The current process id could not be written to the lock file via a call to
+.Xr write 2 .
+.Pp
+If a value of
+.Dv UU_LOCK_OK
+is passed to
+.Fn uu_lockerr ,
+an empty string is returned.
+Otherwise, a string specifying
+the reason for failure is returned.
+.Fn uu_lockerr
+uses the current value of
+.Va errno
+to determine the exact error. Care should be made not to allow
+.Va errno
+to be changed between calls to
+.Fn uu_lock
+and
+.Fn uu_lockerr .
+.Sh ERRORS
+If
+.Fn uu_lock
+returns one of the four error values above, the global value
+.Va errno
+can be used to determine the cause. Refer to the respective manual pages
+for further details.
+.Pp
+.Fn uu_unlock
+will set the global variable
+.Va errno
+to reflect the reason that the lock file could not be removed.
+Refer to the description of
+.Xr unlink 2
+for further details.
+.Sh SEE ALSO
+.Xr open 2 ,
+.Xr read 2 ,
+.Xr lseek 2 ,
+.Xr write 2
+.Sh BUGS
+Locking is not atomic. Should a race condition occur, it's
+possible that the
+.Dq losing
+process fails to identify the
+.Dq winning
+process. If this happens,
+.Fn uu_lock
+returns
+.Dv UU_LOCK_READ_ERR
+and errno is set to
+.Er EINVAL .
+.Pp
+It is possible that a stale lock is not recognised as such if a new
+processes is assigned the same processes id as the program that left
+the stale lock.
+.Pp
+The calling process must have write permissions to the
+.Pa /var/spool/lock
+directory. There is no mechanism in place to ensure that the
+permissions of this directory are the same as those of the
+serial devices that might be locked.
diff --git a/lib/libutil/uucplock.c b/lib/libutil/uucplock.c
new file mode 100644
index 0000000..5559990
--- /dev/null
+++ b/lib/libutil/uucplock.c
@@ -0,0 +1,182 @@
+/*
+ * 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. 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.
+ *
+ * $Id: uucplock.c,v 1.5 1997/04/02 04:24:39 ache Exp $
+ *
+ */
+
+#ifndef lint
+static const char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <paths.h>
+#include <string.h>
+#include "libutil.h"
+
+#define LOCKFMT "LCK..%s"
+
+/* Forward declarations */
+static int put_pid (int fd, pid_t pid);
+static pid_t get_pid (int fd,int *err);
+
+/*
+ * uucp style locking routines
+ * return: 0 - success
+ * -1 - failure
+ */
+
+int uu_lock (const char *ttyname)
+{
+ int fd;
+ pid_t pid;
+ char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
+ int err;
+
+ (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, ttyname);
+ fd = open(tbuf, O_RDWR|O_CREAT|O_EXCL, 0660);
+ if (fd < 0) {
+ /*
+ * file is already locked
+ * check to see if the process holding the lock still exists
+ */
+ fd = open(tbuf, O_RDWR, 0);
+ if (fd < 0)
+ return UU_LOCK_OPEN_ERR;
+
+ if ((pid = get_pid (fd, &err)) == -1) {
+ (void)close(fd);
+ errno = err;
+ return UU_LOCK_READ_ERR;
+ }
+
+ if (kill(pid, 0) == 0 || errno != ESRCH) {
+ (void)close(fd); /* process is still running */
+ return UU_LOCK_INUSE;
+ }
+ /*
+ * The process that locked the file isn't running, so
+ * we'll lock it ourselves
+ */
+ if (lseek(fd, (off_t) 0, L_SET) < 0) {
+ err = errno;
+ (void)close(fd);
+ errno = err;
+ return UU_LOCK_SEEK_ERR;
+ }
+ /* fall out and finish the locking process */
+ }
+ pid = getpid();
+ if (!put_pid (fd, pid)) {
+ err = errno;
+ (void)close(fd);
+ (void)unlink(tbuf);
+ errno = err;
+ return UU_LOCK_WRITE_ERR;
+ }
+ (void)close(fd);
+ return UU_LOCK_OK;
+}
+
+int uu_unlock (const char *ttyname)
+{
+ char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
+
+ (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, ttyname);
+ return unlink(tbuf);
+}
+
+const char *uu_lockerr (int uu_lockresult)
+{
+ static char errbuf[128];
+ char *fmt;
+
+ switch (uu_lockresult) {
+ case UU_LOCK_INUSE:
+ return "device in use";
+ case UU_LOCK_OK:
+ return "";
+ case UU_LOCK_OPEN_ERR:
+ fmt = "open error: %s";
+ break;
+ case UU_LOCK_READ_ERR:
+ fmt = "read error: %s";
+ break;
+ case UU_LOCK_SEEK_ERR:
+ fmt = "seek error: %s";
+ break;
+ case UU_LOCK_WRITE_ERR:
+ fmt = "write error: %s";
+ break;
+ default:
+ fmt = "undefined error: %s";
+ break;
+ }
+
+ (void)snprintf(errbuf, sizeof(errbuf), fmt, strerror(errno));
+ return errbuf;
+}
+
+static int put_pid (int fd, pid_t pid)
+{
+ char buf[32];
+ int len;
+
+ len = sprintf (buf, "%10d\n", pid);
+ return write (fd, buf, len) == len;
+}
+
+static pid_t get_pid (int fd,int *err)
+{
+ int bytes_read;
+ char buf[32];
+ pid_t pid;
+
+ bytes_read = read (fd, buf, sizeof (buf) - 1);
+ if (bytes_read > 0) {
+ buf[bytes_read] = '\0';
+ pid = strtol (buf, (char **) NULL, 10);
+ } else {
+ pid = -1;
+ *err = bytes_read ? errno : EINVAL;
+ }
+ return pid;
+}
+
+/* end of uucplock.c */
diff --git a/lib/libxpg4/Makefile b/lib/libxpg4/Makefile
new file mode 100644
index 0000000..1fe1e9a
--- /dev/null
+++ b/lib/libxpg4/Makefile
@@ -0,0 +1,9 @@
+LIB= xpg4
+SRCS= setlocale.c setrunelocale.c euc.c utf2.c runetype.c \
+ tolower.c toupper.c
+CFLAGS+= -Wall -DXPG4 -I${.CURDIR}/../libc/locale
+.PATH: ${.CURDIR}/../libc/locale
+
+NOMAN= YES
+
+.include <bsd.lib.mk>
diff --git a/lib/liby/Makefile b/lib/liby/Makefile
index 545ff04..eebde5e 100644
--- a/lib/liby/Makefile
+++ b/lib/liby/Makefile
@@ -1,6 +1,27 @@
-# @(#)Makefile 8.1 (Berkeley) 6/4/93
+# $Id$
+
+LIB= y
+SHLIB_MAJOR= 2
+SHLIB_MINOR= 0
-LIB= y
SRCS= main.c yyerror.c
+#
+# Before complaining about this, please *double-check* that you have
+# updated the ldconfig path in /etc/rc to include /usr/lib/compat that
+# was added in src/etc/rc rev 1.98.
+# This is so that `ld' will not continue to generatebinaries linked
+# shared against liby, so that in a future release we can move this
+# off to a compat dist (like compat22).
+#
+beforeinstall:
+ rm -f ${DESTDIR}${ORIG_SHLIBDIR}/lib${LIB}.so.${SHLIB_MAJOR}.${SHLIB_MINOR}
+
.include <bsd.lib.mk>
+
+# This must follow the .include in case SHLIBDIR is defined there.
+ORIG_SHLIBDIR:= ${SHLIBDIR}
+
+# The ldconfig line in/etc/rc doesn't depend on ${LIBDIR} or ${SHLIBDIR},
+# so neither does this.
+SHLIBDIR= /usr/lib/compat
diff --git a/lib/liby/main.c b/lib/liby/main.c
index cd288e0..4b4e67a 100644
--- a/lib/liby/main.c
+++ b/lib/liby/main.c
@@ -35,7 +35,8 @@
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */
-main()
+int
+main(void)
{
exit(yyparse());
}
diff --git a/lib/liby/yyerror.c b/lib/liby/yyerror.c
index 6465e23..b21a7a8 100644
--- a/lib/liby/yyerror.c
+++ b/lib/liby/yyerror.c
@@ -37,6 +37,7 @@ static char sccsid[] = "@(#)yyerror.c 8.1 (Berkeley) 6/4/93";
#include <stdio.h>
+int
yyerror(msg)
char *msg;
{
diff --git a/lib/libz/ChangeLog b/lib/libz/ChangeLog
new file mode 100644
index 0000000..218cfb0
--- /dev/null
+++ b/lib/libz/ChangeLog
@@ -0,0 +1,239 @@
+
+ ChangeLog file for zlib
+
+Changes in 1.0.4 (24 Jul 96)
+- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
+ bit, so the decompressor could decompress all the correct data but went
+ on to attempt decompressing extra garbage data. This affected minigzip too.
+- zlibVersion and gzerror return const char* (needed for DLL)
+- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
+- use z_error only for DEBUG (avoid problem with DLLs)
+
+Changes in 1.0.3 (2 Jul 96)
+- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
+ small and medium models; this makes the library incompatible with previous
+ versions for these models. (No effect in large model or on other systems.)
+- return OK instead of BUF_ERROR if previous deflate call returned with
+ avail_out as zero but there is nothing to do
+- added memcmp for non STDC compilers
+- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
+- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
+- better check for 16-bit mode MSC (avoids problem with Symantec)
+
+Changes in 1.0.2 (23 May 96)
+- added Windows DLL support
+- added a function zlibVersion (for the DLL support)
+- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
+- Bytef is define's instead of typedef'd only for Borland C
+- avoid reading uninitialized memory in example.c
+- mention in README that the zlib format is now RFC1950
+- updated Makefile.dj2
+- added algorithm.doc
+
+Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
+- fix array overlay in deflate.c which sometimes caused bad compressed data
+- fix inflate bug with empty stored block
+- fix MSDOS medium model which was broken in 0.99
+- fix deflateParams() which could generated bad compressed data.
+- Bytef is define'd instead of typedef'ed (work around Borland bug)
+- added an INDEX file
+- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
+ Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
+- speed up adler32 for modern machines without auto-increment
+- added -ansi for IRIX in configure
+- static_init_done in trees.c is an int
+- define unlink as delete for VMS
+- fix configure for QNX
+- add configure branch for SCO and HPUX
+- avoid many warnings (unused variables, dead assignments, etc...)
+- no fdopen for BeOS
+- fix the Watcom fix for 32 bit mode (define FAR as empty)
+- removed redefinition of Byte for MKWERKS
+- work around an MWKERKS bug (incorrect merge of all .h files)
+
+Changes in 0.99 (27 Jan 96)
+- allow preset dictionary shared between compressor and decompressor
+- allow compression level 0 (no compression)
+- add deflateParams in zlib.h: allow dynamic change of compression level
+ and compression strategy.
+- test large buffers and deflateParams in example.c
+- add optional "configure" to build zlib as a shared library
+- suppress Makefile.qnx, use configure instead
+- fixed deflate for 64-bit systems (detected on Cray)
+- fixed inflate_blocks for 64-bit systems (detected on Alpha)
+- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
+- always return Z_BUF_ERROR when deflate() has nothing to do
+- deflateInit and inflateInit are now macros to allow version checking
+- prefix all global functions and types with z_ with -DZ_PREFIX
+- make falloc completely reentrant (inftrees.c)
+- fixed very unlikely race condition in ct_static_init
+- free in reverse order of allocation to help memory manager
+- use zlib-1.0/* instead of zlib/* inside the tar.gz
+- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
+ -Wconversion -Wstrict-prototypes -Wmissing-prototypes"
+- allow gzread on concatenated .gz files
+- deflateEnd now returns Z_DATA_ERROR if it was premature
+- deflate is finally (?) fully deterministic (no matches beyond end of input)
+- Document Z_SYNC_FLUSH
+- add uninstall in Makefile
+- Check for __cpluplus in zlib.h
+- Better test in ct_align for partial flush
+- avoid harmless warnings for Borland C++
+- initialize hash_head in deflate.c
+- avoid warning on fdopen (gzio.c) for HP cc -Aa
+- include stdlib.h for STDC compilers
+- include errno.h for Cray
+- ignore error if ranlib doesn't exist
+- call ranlib twice for NeXTSTEP
+- use exec_prefix instead of prefix for libz.a
+- renamed ct_* as _tr_* to avoid conflict with applications
+- clear z->msg in inflateInit2 before any error return
+- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
+- fixed typo in zconf.h (_GNUC__ => __GNUC__)
+- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
+- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
+- in fcalloc, normalize pointer if size > 65520 bytes
+- don't use special fcalloc for 32 bit Borland C++
+- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
+- use Z_BINARY instead of BINARY
+- document that gzclose after gzdopen will close the file
+- allow "a" as mode in gzopen.
+- fix error checking in gzread
+- allow skipping .gz extra-field on pipes
+- added reference to Perl interface in README
+- put the crc table in FAR data (I dislike more and more the medium model :)
+- added get_crc_table
+- added a dimension to all arrays (Borland C can't count).
+- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
+- guard against multiple inclusion of *.h (for precompiled header on Mac)
+- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
+- don't use unsized arrays to avoid silly warnings by Visual C++:
+ warning C4746: 'inflate_mask' : unsized array treated as '__far'
+ (what's wrong with far data in far model?).
+- define enum out of inflate_blocks_state to allow compilation with C++
+
+Changes in 0.95 (16 Aug 95)
+- fix MSDOS small and medium model (now easier to adapt to any compiler)
+- inlined send_bits
+- fix the final (:-) bug for deflate with flush (output was correct but
+ not completely flushed in rare occasions).
+- default window size is same for compression and decompression
+ (it's now sufficient to set MAX_WBITS in zconf.h).
+- voidp -> voidpf and voidnp -> voidp (for consistency with other
+ typedefs and because voidnp was not near in large model).
+
+Changes in 0.94 (13 Aug 95)
+- support MSDOS medium model
+- fix deflate with flush (could sometimes generate bad output)
+- fix deflateReset (zlib header was incorrectly suppressed)
+- added support for VMS
+- allow a compression level in gzopen()
+- gzflush now calls fflush
+- For deflate with flush, flush even if no more input is provided.
+- rename libgz.a as libz.a
+- avoid complex expression in infcodes.c triggering Turbo C bug
+- work around a problem with gcc on Alpha (in INSERT_STRING)
+- don't use inline functions (problem with some gcc versions)
+- allow renaming of Byte, uInt, etc... with #define.
+- avoid warning about (unused) pointer before start of array in deflate.c
+- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
+- avoid reserved word 'new' in trees.c
+
+Changes in 0.93 (25 June 95)
+- temporarily disable inline functions
+- make deflate deterministic
+- give enough lookahead for PARTIAL_FLUSH
+- Set binary mode for stdin/stdout in minigzip.c for OS/2
+- don't even use signed char in inflate (not portable enough)
+- fix inflate memory leak for segmented architectures
+
+Changes in 0.92 (3 May 95)
+- don't assume that char is signed (problem on SGI)
+- Clear bit buffer when starting a stored block
+- no memcpy on Pyramid
+- suppressed inftest.c
+- optimized fill_window, put longest_match inline for gcc
+- optimized inflate on stored blocks.
+- untabify all sources to simplify patches
+
+Changes in 0.91 (2 May 95)
+- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
+- Document the memory requirements in zconf.h
+- added "make install"
+- fix sync search logic in inflateSync
+- deflate(Z_FULL_FLUSH) now works even if output buffer too short
+- after inflateSync, don't scare people with just "lo world"
+- added support for DJGPP
+
+Changes in 0.9 (1 May 95)
+- don't assume that zalloc clears the allocated memory (the TurboC bug
+ was Mark's bug after all :)
+- let again gzread copy uncompressed data unchanged (was working in 0.71)
+- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
+- added a test of inflateSync in example.c
+- moved MAX_WBITS to zconf.h because users might want to change that.
+- document explicitly that zalloc(64K) on MSDOS must return a normalized
+ pointer (zero offset)
+- added Makefiles for Microsoft C, Turbo C, Borland C++
+- faster crc32()
+
+Changes in 0.8 (29 April 95)
+- added fast inflate (inffast.c)
+- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
+ is incompatible with previous versions of zlib which returned Z_OK.
+- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
+ (actually that was not a compiler bug, see 0.81 above)
+- gzread no longer reads one extra byte in certain cases
+- In gzio destroy(), don't reference a freed structure
+- avoid many warnings for MSDOS
+- avoid the ERROR symbol which is used by MS Windows
+
+Changes in 0.71 (14 April 95)
+- Fixed more MSDOS compilation problems :( There is still a bug with
+ TurboC large model.
+
+Changes in 0.7 (14 April 95)
+- Added full inflate support.
+- Simplified the crc32() interface. The pre- and post-conditioning
+ (one's complement) is now done inside crc32(). WARNING: this is
+ incompatible with previous versions; see zlib.h for the new usage.
+
+Changes in 0.61 (12 April 95)
+- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
+
+Changes in 0.6 (11 April 95)
+- added minigzip.c
+- added gzdopen to reopen a file descriptor as gzFile
+- added transparent reading of non-gziped files in gzread.
+- fixed bug in gzread (don't read crc as data)
+- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
+- don't allocate big arrays in the stack (for MSDOS)
+- fix some MSDOS compilation problems
+
+Changes in 0.5:
+- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
+ not yet Z_FULL_FLUSH.
+- support decompression but only in a single step (forced Z_FINISH)
+- added opaque object for zalloc and zfree.
+- added deflateReset and inflateReset
+- added a variable zlib_version for consistency checking.
+- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
+ Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
+
+Changes in 0.4:
+- avoid "zip" everywhere, use zlib instead of ziplib.
+- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
+ if compression method == 8.
+- added adler32 and crc32
+- renamed deflateOptions as deflateInit2, call one or the other but not both
+- added the method parameter for deflateInit2.
+- added inflateInit2
+- simplied considerably deflateInit and inflateInit by not supporting
+ user-provided history buffer. This is supported only in deflateInit2
+ and inflateInit2.
+
+Changes in 0.3:
+- prefix all macro names with Z_
+- use Z_FINISH instead of deflateEnd to finish compression.
+- added Z_HUFFMAN_ONLY
+- added gzerror()
diff --git a/lib/libz/Makefile b/lib/libz/Makefile
new file mode 100644
index 0000000..7cce380
--- /dev/null
+++ b/lib/libz/Makefile
@@ -0,0 +1,36 @@
+#
+# $Id$
+#
+
+MAINTAINER=peter@FreeBSD.org
+
+LIB= z
+
+#CFLAGS+= -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS+= -g -DDEBUG
+#CFLAGS+= -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+# -Wstrict-prototypes -Wmissing-prototypes
+
+CLEANFILES+= example.o example minigzip.o minigzip
+
+SRCS = adler32.c compress.c crc32.c gzio.c uncompr.c deflate.c trees.c \
+ zutil.c inflate.c infblock.c inftrees.c infcodes.c infutil.c inffast.c
+
+beforeinstall:
+.for hdr in zconf.h zlib.h
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/${hdr} \
+ ${DESTDIR}/usr/include
+.endfor
+
+minigzip: all minigzip.o
+ $(CC) -o minigzip minigzip.o -L. -lz
+
+example: all example.o
+ $(CC) -o example example.o -L. -lz
+
+test: example minigzip
+ (export LD_LIBRARY_PATH=. ; ./example )
+ (export LD_LIBRARY_PATH=. ; \
+ echo hello world | ./minigzip | ./minigzip -d )
+
+.include <bsd.lib.mk>
diff --git a/lib/libz/README b/lib/libz/README
new file mode 100644
index 0000000..28adc90
--- /dev/null
+++ b/lib/libz/README
@@ -0,0 +1,99 @@
+zlib 1.0.4 is a general purpose data compression library. All the code
+is reentrant (thread safe). The data format used by the zlib library
+is described by RFCs (Request for Comments) 1950 to 1952 in the files
+ftp://ds.internic.net/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
+format) and rfc1952.txt (gzip format). These documents are also available in
+other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+
+All functions of the compression library are documented in the file
+zlib.h. A usage example of the library is given in the file example.c
+which also tests that the library is working correctly. Another
+example is given in the file minigzip.c. The compression library itself
+is composed of all source files except example.c and minigzip.c.
+
+To compile all files and run the test program, follow the instructions
+given at the top of Makefile. In short "make test; make install"
+should work for most machines. For MSDOS, use one of the special
+makefiles such as Makefile.msc; for VMS, use Make_vms.com or descrip.mms.
+
+Questions about zlib should be sent to <zlib@quest.jpl.nasa.gov> or,
+if this fails, to the addresses given below in the Copyright section.
+The zlib home page is http://quest.jpl.nasa.gov/zlib/
+
+The changes made in version 1.0.4 are documented in the file ChangeLog.
+The main changes since 1.0.3 are:
+
+- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
+ bit, so the decompressor could decompress all the correct data but went
+ on to attempt decompressing extra garbage data. This affected minigzip too.
+- zlibVersion and gzerror return const char* (needed for DLL)
+- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
+
+
+A Perl interface to zlib written by Paul Marquess <pmarquess@bfsec.bt.co.uk>
+is in the CPAN (Comprehensive Perl Archive Network) sites, such as:
+ftp://ftp.cis.ufl.edu/pub/perl/CPAN/modules/by-module/Compress/Compress-Zlib*
+
+
+Notes for some targets:
+
+- For Turbo C the small model is supported only with reduced performance to
+ avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
+
+- For 64-bit Iris, deflate.c must be compiled without any optimization.
+ With -O, one libpng test fails. The test works in 32 bit mode (with
+ the -32 compiler flag). The compiler bug has been reported to SGI.
+
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1
+ it works when compiled with cc.
+
+- zlib doesn't work on HP-UX 9.05 with one cc compiler (the one not
+ accepting the -O option). It works with the other cc compiler.
+
+- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc
+ and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL
+ For help on building a zlib DLL, contact Alessandro Iacopetti
+ <iaco@email.alessandria.alpcom.it> http://lisa.unial.it/iaco ,
+ or contact Brad Clarke <bclarke@cyberus.ca>.
+
+- gzdopen is not supported on RISCOS
+
+
+Acknowledgments:
+
+ The deflate format used by zlib was defined by Phil Katz. The deflate
+ and zlib specifications were written by Peter Deutsch. Thanks to all the
+ people who reported problems and suggested various improvements in zlib;
+ they are too numerous to cite here.
+
+Copyright notice:
+
+ (C) 1995-1996 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ gzip@prep.ai.mit.edu madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not*
+receiving lengthy legal documents to sign. The sources are provided
+for free but without warranty of any kind. The library has been
+entirely written by Jean-loup Gailly and Mark Adler; it does not
+include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include
+in the file ChangeLog history information documenting your changes.
diff --git a/lib/libz/adler32.c b/lib/libz/adler32.c
new file mode 100644
index 0000000..7c35d51
--- /dev/null
+++ b/lib/libz/adler32.c
@@ -0,0 +1,48 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $FreeBSD$ */
+
+#include "zlib.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+uLong adler32(adler, buf, len)
+ uLong adler;
+ const Bytef *buf;
+ uInt len;
+{
+ unsigned long s1 = adler & 0xffff;
+ unsigned long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ if (buf == Z_NULL) return 1L;
+
+ while (len > 0) {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16) {
+ DO16(buf);
+ buf += 16;
+ k -= 16;
+ }
+ if (k != 0) do {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k);
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+}
diff --git a/lib/libz/algorithm.doc b/lib/libz/algorithm.doc
new file mode 100644
index 0000000..01902af
--- /dev/null
+++ b/lib/libz/algorithm.doc
@@ -0,0 +1,105 @@
+1. Compression algorithm (deflate)
+
+The deflation algorithm used by zlib (also zip and gzip) is a variation of
+LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
+the input data. The second occurrence of a string is replaced by a
+pointer to the previous string, in the form of a pair (distance,
+length). Distances are limited to 32K bytes, and lengths are limited
+to 258 bytes. When a string does not occur anywhere in the previous
+32K bytes, it is emitted as a sequence of literal bytes. (In this
+description, `string' must be taken as an arbitrary sequence of bytes,
+and is not restricted to printable characters.)
+
+Literals or match lengths are compressed with one Huffman tree, and
+match distances are compressed with another tree. The trees are stored
+in a compact form at the start of each block. The blocks can have any
+size (except that the compressed data for one block must fit in
+available memory). A block is terminated when deflate() determines that
+it would be useful to start another block with fresh trees. (This is
+somewhat similar to the behavior of LZW-based _compress_.)
+
+Duplicated strings are found using a hash table. All input strings of
+length 3 are inserted in the hash table. A hash index is computed for
+the next 3 bytes. If the hash chain for this index is not empty, all
+strings in the chain are compared with the current input string, and
+the longest match is selected.
+
+The hash chains are searched starting with the most recent strings, to
+favor small distances and thus take advantage of the Huffman encoding.
+The hash chains are singly linked. There are no deletions from the
+hash chains, the algorithm simply discards matches that are too old.
+
+To avoid a worst-case situation, very long hash chains are arbitrarily
+truncated at a certain length, determined by a runtime option (level
+parameter of deflateInit). So deflate() does not always find the longest
+possible match but generally finds a match which is long enough.
+
+deflate() also defers the selection of matches with a lazy evaluation
+mechanism. After a match of length N has been found, deflate() searches for a
+longer match at the next input byte. If a longer match is found, the
+previous match is truncated to a length of one (thus producing a single
+literal byte) and the longer match is emitted afterwards. Otherwise,
+the original match is kept, and the next match search is attempted only
+N steps later.
+
+The lazy match evaluation is also subject to a runtime parameter. If
+the current match is long enough, deflate() reduces the search for a longer
+match, thus speeding up the whole process. If compression ratio is more
+important than speed, deflate() attempts a complete second search even if
+the first match is already long enough.
+
+The lazy match evaluation is not performed for the fastest compression
+modes (level parameter 1 to 3). For these fast modes, new strings
+are inserted in the hash table only when no match was found, or
+when the match is not too long. This degrades the compression ratio
+but saves time since there are both fewer insertions and fewer searches.
+
+
+2. Decompression algorithm (inflate)
+
+The real question is, given a Huffman tree, how to decode fast. The most
+important realization is that shorter codes are much more common than
+longer codes, so pay attention to decoding the short codes fast, and let
+the long codes take longer to decode.
+
+inflate() sets up a first level table that covers some number of bits of
+input less than the length of longest code. It gets that many bits from the
+stream, and looks it up in the table. The table will tell if the next
+code is that many bits or less and how many, and if it is, it will tell
+the value, else it will point to the next level table for which inflate()
+grabs more bits and tries to decode a longer code.
+
+How many bits to make the first lookup is a tradeoff between the time it
+takes to decode and the time it takes to build the table. If building the
+table took no time (and if you had infinite memory), then there would only
+be a first level table to cover all the way to the longest code. However,
+building the table ends up taking a lot longer for more bits since short
+codes are replicated many times in such a table. What inflate() does is
+simply to make the number of bits in the first table a variable, and set it
+for the maximum speed.
+
+inflate() sends new trees relatively often, so it is possibly set for a
+smaller first level table than an application that has only one tree for
+all the data. For inflate, which has 286 possible codes for the
+literal/length tree, the size of the first table is nine bits. Also the
+distance trees have 30 possible values, and the size of the first table is
+six bits. Note that for each of those cases, the table ended up one bit
+longer than the ``average'' code length, i.e. the code length of an
+approximately flat code which would be a little more than eight bits for
+286 symbols and a little less than five bits for 30 symbols. It would be
+interesting to see if optimizing the first level table for other
+applications gave values within a bit or two of the flat code size.
+
+
+Jean-loup Gailly Mark Adler
+gzip@prep.ai.mit.edu madler@alumni.caltech.edu
+
+
+References:
+
+[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
+Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
+pp. 337-343.
+
+``DEFLATE Compressed Data Format Specification'' available in
+ftp://ds.internic.net/rfc/rfc1951.txt
diff --git a/lib/libz/compress.c b/lib/libz/compress.c
new file mode 100644
index 0000000..686f365
--- /dev/null
+++ b/lib/libz/compress.c
@@ -0,0 +1,57 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $FreeBSD$ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least 0.1% larger than
+ sourceLen plus 8 bytes. Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+int compress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
+ if (err != Z_OK) return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = deflateEnd(&stream);
+ return err;
+}
diff --git a/lib/libz/crc32.c b/lib/libz/crc32.c
new file mode 100644
index 0000000..8fa0ee6
--- /dev/null
+++ b/lib/libz/crc32.c
@@ -0,0 +1,162 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $FreeBSD$ */
+
+#include "zlib.h"
+
+#define local static
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local int crc_table_empty = 1;
+local uLongf crc_table[256];
+local void make_crc_table OF((void));
+
+/*
+ Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+ x (which is shifting right by one and adding x^32 mod p if the bit shifted
+ out is a one). We start with the highest power (least significant bit) of
+ q and repeat for all eight bits of q.
+
+ The table is simply the CRC of all possible eight bit values. This is all
+ the information needed to generate CRC's on data a byte at a time for all
+ combinations of CRC register values and incoming bytes.
+*/
+local void make_crc_table()
+{
+ uLong c;
+ int n, k;
+ uLong poly; /* polynomial exclusive-or pattern */
+ /* terms of polynomial defining this crc (except x^32): */
+ static Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+ /* make exclusive-or pattern from polynomial (0xedb88320L) */
+ poly = 0L;
+ for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
+ poly |= 1L << (31 - p[n]);
+
+ for (n = 0; n < 256; n++)
+ {
+ c = (uLong)n;
+ for (k = 0; k < 8; k++)
+ c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+ crc_table[n] = c;
+ }
+ crc_table_empty = 0;
+}
+#else
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+local uLongf crc_table[256] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+#endif
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+uLongf *get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty) make_crc_table();
+#endif
+ return (uLongf *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
+#define DO2(buf) DO1(buf); DO1(buf);
+#define DO4(buf) DO2(buf); DO2(buf);
+#define DO8(buf) DO4(buf); DO4(buf);
+
+/* ========================================================================= */
+uLong crc32(crc, buf, len)
+ uLong crc;
+ const Bytef *buf;
+ uInt len;
+{
+ if (buf == Z_NULL) return 0L;
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif
+ crc = crc ^ 0xffffffffL;
+ while (len >= 8)
+ {
+ DO8(buf);
+ len -= 8;
+ }
+ if (len) do {
+ DO1(buf);
+ } while (--len);
+ return crc ^ 0xffffffffL;
+}
diff --git a/lib/libz/deflate.c b/lib/libz/deflate.c
new file mode 100644
index 0000000..81c649e
--- /dev/null
+++ b/lib/libz/deflate.c
@@ -0,0 +1,1207 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* $FreeBSD$ */
+
+#include "deflate.h"
+
+char deflate_copyright[] = " deflate 1.0.4 Copyright 1995-1996 Jean-loup Gailly ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ * Function prototypes.
+ */
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast OF((deflate_state *s, int flush));
+local block_state deflate_slow OF((deflate_state *s, int flush));
+local void lm_init OF((deflate_state *s));
+local uInt longest_match OF((deflate_state *s, IPos cur_match));
+local void putShortMSB OF((deflate_state *s, uInt b));
+local void flush_pending OF((z_streamp strm));
+local int read_buf OF((z_streamp strm, charf *buf, unsigned size));
+#ifdef ASMV
+ void match_init OF((void)); /* asm code initialization */
+#endif
+
+#ifdef DEBUG
+local void check_match OF((deflate_state *s, IPos start, IPos match,
+ int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+local config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of str are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ s->head[s->hash_size-1] = NIL; \
+ zmemzero((charf *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int deflateInit_(strm, level, version, stream_size)
+ z_streamp strm;
+ int level;
+ const char *version;
+ int stream_size;
+{
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+ version, stream_size)
+ z_streamp strm;
+ int level;
+ int method;
+ int windowBits;
+ int memLevel;
+ int strategy;
+ const char *version;
+ int stream_size;
+{
+ deflate_state *s;
+ int noheader = 0;
+
+ ushf *overlay;
+ /* We overlay pending_buf and d_buf+l_buf. This works since the average
+ * output size for (length,distance) codes is <= 24 bits.
+ */
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == Z_NULL) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == Z_NULL) strm->zfree = zcfree;
+
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+
+ if (windowBits < 0) { /* undocumented feature: suppress zlib header */
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+ return Z_STREAM_ERROR;
+ }
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+
+ s->noheader = noheader;
+ s->w_bits = windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+ s->pending_buf = (uchf *) overlay;
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int deflateSetDictionary (strm, dictionary, dictLength)
+ z_streamp strm;
+ const Bytef *dictionary;
+ uInt dictLength;
+{
+ deflate_state *s;
+ uInt length = dictLength;
+ uInt n;
+ IPos hash_head = 0;
+
+ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+ strm->state->status != INIT_STATE) return Z_STREAM_ERROR;
+
+ s = strm->state;
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+ if (length < MIN_MATCH) return Z_OK;
+ if (length > MAX_DIST(s)) {
+ length = MAX_DIST(s);
+ dictionary += dictLength - length;
+ }
+ zmemcpy((charf *)s->window, dictionary, length);
+ s->strstart = length;
+ s->block_start = (long)length;
+
+ /* Insert all strings in the hash table (except for the last two bytes).
+ * s->lookahead stays null, so s->ins_h will be recomputed at the next
+ * call of fill_window.
+ */
+ s->ins_h = s->window[0];
+ UPDATE_HASH(s, s->ins_h, s->window[1]);
+ for (n = 0; n <= length - MIN_MATCH; n++) {
+ INSERT_STRING(s, n, hash_head);
+ }
+ if (hash_head) hash_head = 0; /* to make compiler happy */
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int deflateReset (strm)
+ z_streamp strm;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->noheader < 0) {
+ s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */
+ }
+ s->status = s->noheader ? BUSY_STATE : INIT_STATE;
+ strm->adler = 1;
+ s->last_flush = Z_NO_FLUSH;
+
+ _tr_init(s);
+ lm_init(s);
+
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int deflateParams(strm, level, strategy)
+ z_streamp strm;
+ int level;
+ int strategy;
+{
+ deflate_state *s;
+ compress_func func;
+ int err = Z_OK;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+
+ if (level == Z_DEFAULT_COMPRESSION) {
+ level = 6;
+ }
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if (func != configuration_table[level].func && strm->total_in != 0) {
+ /* Flush the last buffer: */
+ err = deflate(strm, Z_PARTIAL_FLUSH);
+ }
+ if (s->level != level) {
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return err;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+ deflate_state *s;
+ uInt b;
+{
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+ z_streamp strm;
+{
+ unsigned len = strm->state->pending;
+
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, strm->state->pending_out, len);
+ strm->next_out += len;
+ strm->state->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ strm->state->pending -= len;
+ if (strm->state->pending == 0) {
+ strm->state->pending_out = strm->state->pending_buf;
+ }
+}
+
+/* ========================================================================= */
+int deflate (strm, flush)
+ z_streamp strm;
+ int flush;
+{
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ flush > Z_FINISH || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ s->strm = strm; /* just in case */
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Write the zlib header */
+ if (s->status == INIT_STATE) {
+
+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uInt level_flags = (s->level-1) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ s->status = BUSY_STATE;
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = 1L;
+ }
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && flush <= old_flush &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+ Assert(strm->avail_out > 0, "bug2");
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->noheader) return Z_STREAM_END;
+
+ /* Write the zlib trailer (adler32) */
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ s->noheader = -1; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int deflateEnd (strm)
+ z_streamp strm;
+{
+ int status;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ status = strm->state->status;
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* ========================================================================= */
+int deflateCopy (dest, source)
+ z_streamp dest;
+ z_streamp source;
+{
+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+ *dest = *source;
+ return Z_STREAM_ERROR; /* to be implemented */
+#if 0
+ dest->state = (struct internal_state FAR *)
+ (*dest->zalloc)(1, sizeof(deflate_state));
+ if (dest->state == Z_NULL) return Z_MEM_ERROR;
+
+ *(dest->state) = *(source->state);
+ return Z_OK;
+#endif
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+ z_streamp strm;
+ charf *buf;
+ unsigned size;
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ if (!strm->state->noheader) {
+ strm->adler = adler32(strm->adler, strm->next_in, len);
+ }
+ zmemcpy(buf, strm->next_in, len);
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+ deflate_state *s;
+{
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+#ifdef ASMV
+ match_init(); /* initialize the asm code */
+#endif
+}
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan+best_len-1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len-1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2:
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match+best_len-1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return best_len;
+ return s->lookahead;
+}
+#endif /* ASMV */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+ deflate_state *s;
+ IPos start, match;
+ int length;
+{
+ /* check that the match is indeed a match */
+ if (zmemcmp((charf *)s->window + match,
+ (charf *)s->window + start, length) != EQUAL) {
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window(s)
+ deflate_state *s;
+{
+ register unsigned n, m;
+ register Posf *p;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if strstart == 0
+ * and lookahead == 1 (input done one byte at time)
+ */
+ more--;
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ } else if (s->strstart >= wsize+MAX_DIST(s)) {
+
+ zmemcpy((charf *)s->window, (charf *)s->window+wsize,
+ (unsigned)wsize);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+
+ s->block_start -= (long) wsize;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ at the expense of memory usage):
+ */
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ } while (--n);
+
+ n = wsize;
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) return;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, (charf *)s->window + s->strstart + s->lookahead,
+ more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead >= MIN_MATCH) {
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (eof)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+ FLUSH_BLOCK_ONLY(s, eof); \
+ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying.
+ */
+local block_state deflate_stored(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ for (;;) {
+ /* Fill the window as much as possible: */
+ if (s->lookahead <= 1) {
+
+ Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+ s->block_start >= (long)s->w_size, "slide too late");
+
+ fill_window(s);
+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+ Assert(s->block_start >= 0L, "block gone");
+
+ s->strstart += s->lookahead;
+ s->lookahead = 0;
+
+ /* Stored blocks are limited to 0xffff bytes: */
+ if (s->strstart == 0 || s->strstart > 0xfffe) {
+ /* strstart == 0 is possible when wraparound on 16-bit machine */
+ s->lookahead = s->strstart - 0xffff;
+ s->strstart = 0xffff;
+ }
+
+ /* Emit a stored block if it is large enough: */
+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+ FLUSH_BLOCK(s, 0);
+ }
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head = NIL; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY) {
+ s->match_length = longest_match (s, hash_head);
+ }
+ /* longest_match() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ bflush = _tr_tally(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in hash table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ bflush = _tr_tally (s, 0, s->window[s->strstart]);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head = NIL; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY) {
+ s->match_length = longest_match (s, hash_head);
+ }
+ /* longest_match() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
+ (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR))) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+ bflush = _tr_tally(s, s->strstart -1 - s->prev_match,
+ s->prev_length - MIN_MATCH);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length-1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ if (_tr_tally (s, 0, s->window[s->strstart-1])) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally (s, 0, s->window[s->strstart-1]);
+ s->match_available = 0;
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
diff --git a/lib/libz/deflate.h b/lib/libz/deflate.h
new file mode 100644
index 0000000..689adea
--- /dev/null
+++ b/lib/libz/deflate.h
@@ -0,0 +1,275 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-1996 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* $FreeBSD$ */
+
+#ifndef _DEFLATE_H
+#define _DEFLATE_H
+
+#include "zutil.h"
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE 42
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ int pending; /* nb of bytes in the pending buffer */
+ int noheader; /* suppress zlib header and adler32 */
+ Byte data_type; /* UNKNOWN, BINARY or ASCII */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to supress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ ulg compressed_len; /* total bit length of compressed file */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+ ulg bits_sent; /* bit length of the compressed data */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+ /* in trees.c */
+void _tr_init OF((deflate_state *s));
+int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+ulg _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+void _tr_align OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+#endif
diff --git a/lib/libz/example.c b/lib/libz/example.c
new file mode 100644
index 0000000..3830842
--- /dev/null
+++ b/lib/libz/example.c
@@ -0,0 +1,503 @@
+/* example.c -- usage example of the zlib compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $FreeBSD$ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#else
+ extern void exit OF((int));
+#endif
+
+#define CHECK_ERR(err, msg) { \
+ if (err != Z_OK) { \
+ fprintf(stderr, "%s error: %d\n", msg, err); \
+ exit(1); \
+ } \
+}
+
+const char hello[] = "hello, hello!";
+/* "hello world" would be more standard, but the repeated "hello"
+ * stresses the compression code better, sorry...
+ */
+
+const char dictionary[] = "hello";
+uLong dictId; /* Adler32 value of the dictionary */
+
+void test_compress OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_gzio OF((const char *out, const char *in,
+ Byte *uncompr, int uncomprLen));
+void test_deflate OF((Byte *compr, uLong comprLen));
+void test_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_deflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_flush OF((Byte *compr, uLong comprLen));
+void test_sync OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_dict_deflate OF((Byte *compr, uLong comprLen));
+void test_dict_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+int main OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Test compress() and uncompress()
+ */
+void test_compress(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ uLong len = strlen(hello)+1;
+
+ err = compress(compr, &comprLen, (const Bytef*)hello, len);
+ CHECK_ERR(err, "compress");
+
+ strcpy((char*)uncompr, "garbage");
+
+ err = uncompress(uncompr, &uncomprLen, compr, comprLen);
+ CHECK_ERR(err, "uncompress");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad uncompress\n");
+ } else {
+ printf("uncompress(): %s\n", uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test read/write of .gz files
+ */
+void test_gzio(out, in, uncompr, uncomprLen)
+ const char *out; /* output file */
+ const char *in; /* input file */
+ Byte *uncompr;
+ int uncomprLen;
+{
+ int err;
+ int len = strlen(hello)+1;
+ gzFile file;
+
+ file = gzopen(out, "wb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ exit(1);
+ }
+
+ if (gzwrite(file, (const voidp)hello, (unsigned)len) != len) {
+ fprintf(stderr, "gzwrite err: %s\n", gzerror(file, &err));
+ }
+ gzclose(file);
+
+ file = gzopen(in, "rb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ }
+ strcpy((char*)uncompr, "garbage");
+
+ uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen);
+ if (uncomprLen != len) {
+ fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
+ }
+ gzclose(file);
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad gzread\n");
+ } else {
+ printf("gzread(): %s\n", uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with small buffers
+ */
+void test_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ int len = strlen(hello)+1;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+
+ while (c_stream.total_in != (uLong)len && c_stream.total_out < comprLen) {
+ c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ }
+ /* Finish the stream, still forcing small buffers: */
+ for (;;) {
+ c_stream.avail_out = 1;
+ err = deflate(&c_stream, Z_FINISH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "deflate");
+ }
+
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with small buffers
+ */
+void test_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_in = compr;
+ d_stream.next_out = uncompr;
+
+ while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
+ d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate\n");
+ } else {
+ printf("inflate(): %s\n", uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with large buffers and dynamic change of compression level
+ */
+void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_SPEED);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ /* At this point, uncompr is still mostly zeroes, so it should compress
+ * very well:
+ */
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ if (c_stream.avail_in != 0) {
+ fprintf(stderr, "deflate not greedy\n");
+ }
+
+ /* Feed in already compressed data and switch to no compression: */
+ deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+ c_stream.next_in = compr;
+ c_stream.avail_in = (uInt)comprLen/2;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ /* Switch back to compressing mode: */
+ deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with large buffers
+ */
+void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ for (;;) {
+ d_stream.next_out = uncompr; /* discard the output */
+ d_stream.avail_out = (uInt)uncomprLen;
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "large inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
+ fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
+ } else {
+ printf("large_inflate(): OK\n");
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with full flush
+ */
+void test_flush(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ int len = strlen(hello)+1;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+ c_stream.avail_in = 3;
+ c_stream.avail_out = (uInt)comprLen;
+ err = deflate(&c_stream, Z_FULL_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ compr[3]++; /* force an error in first compressed block */
+ c_stream.avail_in = len - 3;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ CHECK_ERR(err, "deflate");
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflateSync()
+ */
+void test_sync(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_in = compr;
+ d_stream.next_out = uncompr;
+ d_stream.avail_in = 2; /* just read the zlib header */
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ inflate(&d_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "inflate");
+
+ d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */
+ err = inflateSync(&d_stream); /* but skip the damaged part */
+ CHECK_ERR(err, "inflateSync");
+
+ err = inflate(&d_stream, Z_FINISH);
+ if (err != Z_DATA_ERROR) {
+ fprintf(stderr, "inflate should report DATA_ERROR\n");
+ /* Because of incorrect adler32 */
+ }
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ printf("after inflateSync(): hel%s\n", uncompr);
+}
+
+/* ===========================================================================
+ * Test deflate() with preset dictionary
+ */
+void test_dict_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ err = deflateSetDictionary(&c_stream,
+ (const Bytef*)dictionary, sizeof(dictionary));
+ CHECK_ERR(err, "deflateSetDictionary");
+
+ dictId = c_stream.adler;
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.avail_in = (uInt)strlen(hello)+1;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with a preset dictionary
+ */
+void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ for (;;) {
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ if (err == Z_NEED_DICT) {
+ if (d_stream.adler != dictId) {
+ fprintf(stderr, "unexpected dictionary");
+ exit(1);
+ }
+ err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
+ sizeof(dictionary));
+ }
+ CHECK_ERR(err, "inflate with dict");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate with dict\n");
+ } else {
+ printf("inflate with dictionary: %s\n", uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Usage: example [output.gz [input.gz]]
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ Byte *compr, *uncompr;
+ uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
+ uLong uncomprLen = comprLen;
+
+ if (zlibVersion()[0] != ZLIB_VERSION[0]) {
+ fprintf(stderr, "incompatible zlib version\n");
+ exit(1);
+
+ } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
+ fprintf(stderr, "warning: different zlib version\n");
+ }
+
+ compr = (Byte*)calloc((uInt)comprLen, 1);
+ uncompr = (Byte*)calloc((uInt)uncomprLen, 1);
+ /* compr and uncompr are cleared to avoid reading uninitialized
+ * data and to ensure that uncompr compresses well.
+ */
+ if (compr == Z_NULL || uncompr == Z_NULL) {
+ printf("out of memory\n");
+ exit(1);
+ }
+
+ test_compress(compr, comprLen, uncompr, uncomprLen);
+
+ test_gzio((argc > 1 ? argv[1] : "foo.gz"),
+ (argc > 2 ? argv[2] : "foo.gz"),
+ uncompr, (int)uncomprLen);
+
+ test_deflate(compr, comprLen);
+ test_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+ test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_flush(compr, comprLen);
+ test_sync(compr, comprLen, uncompr, uncomprLen);
+
+ test_dict_deflate(compr, comprLen);
+ test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ exit(0);
+ return 0; /* to avoid warning */
+}
diff --git a/lib/libz/gzio.c b/lib/libz/gzio.c
new file mode 100644
index 0000000..f62b125
--- /dev/null
+++ b/lib/libz/gzio.c
@@ -0,0 +1,523 @@
+/* gzio.c -- IO on .gz files
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $FreeBSD$ */
+
+#include <stdio.h>
+
+#include "zutil.h"
+
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+#define Z_BUFSIZE 4096
+
+#define ALLOC(size) malloc(size)
+#define TRYFREE(p) {if (p) free(p);}
+
+static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+typedef struct gz_stream {
+ z_stream stream;
+ int z_err; /* error code for last stream operation */
+ int z_eof; /* set if end of input file */
+ FILE *file; /* .gz file */
+ Byte *inbuf; /* input buffer */
+ Byte *outbuf; /* output buffer */
+ uLong crc; /* crc32 of uncompressed data */
+ char *msg; /* error message */
+ char *path; /* path name for debugging only */
+ int transparent; /* 1 if input file is not a .gz file */
+ char mode; /* 'w' or 'r' */
+} gz_stream;
+
+
+local gzFile gz_open OF((const char *path, const char *mode, int fd));
+local int get_byte OF((gz_stream *s));
+local void check_header OF((gz_stream *s));
+local int destroy OF((gz_stream *s));
+local void putLong OF((FILE *file, uLong x));
+local uLong getLong OF((gz_stream *s));
+
+/* ===========================================================================
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb"). The file is given either by file descriptor
+ or path name (if fd == -1).
+ gz_open return NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR).
+*/
+local gzFile gz_open (path, mode, fd)
+ const char *path;
+ const char *mode;
+ int fd;
+{
+ int err;
+ int level = Z_DEFAULT_COMPRESSION; /* compression level */
+ char *p = (char*)mode;
+ gz_stream *s;
+ char fmode[80]; /* copy of mode, without the compression level */
+ char *m = fmode;
+
+ if (!path || !mode) return Z_NULL;
+
+ s = (gz_stream *)ALLOC(sizeof(gz_stream));
+ if (!s) return Z_NULL;
+
+ s->stream.zalloc = (alloc_func)0;
+ s->stream.zfree = (free_func)0;
+ s->stream.opaque = (voidpf)0;
+ s->stream.next_in = s->inbuf = Z_NULL;
+ s->stream.next_out = s->outbuf = Z_NULL;
+ s->stream.avail_in = s->stream.avail_out = 0;
+ s->file = NULL;
+ s->z_err = Z_OK;
+ s->z_eof = 0;
+ s->crc = crc32(0L, Z_NULL, 0);
+ s->msg = NULL;
+ s->transparent = 0;
+
+ s->path = (char*)ALLOC(strlen(path)+1);
+ if (s->path == NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ strcpy(s->path, path); /* do this early for debugging */
+
+ s->mode = '\0';
+ do {
+ if (*p == 'r') s->mode = 'r';
+ if (*p == 'w' || *p == 'a') s->mode = 'w';
+ if (*p >= '0' && *p <= '9') {
+ level = *p - '0';
+ } else {
+ *m++ = *p; /* copy the mode */
+ }
+ } while (*p++ && m != fmode + sizeof(fmode));
+ if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
+
+ if (s->mode == 'w') {
+ err = deflateInit2(&(s->stream), level,
+ Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0);
+ /* windowBits is passed < 0 to suppress zlib header */
+
+ s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+
+ if (err != Z_OK || s->outbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ } else {
+ err = inflateInit2(&(s->stream), -MAX_WBITS);
+ s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
+
+ if (err != Z_OK || s->inbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+
+ errno = 0;
+ s->file = fd < 0 ? FOPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
+
+ if (s->file == NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ if (s->mode == 'w') {
+ /* Write a very simple .gz header:
+ */
+ fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
+ Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
+ } else {
+ check_header(s); /* skip the .gz header */
+ }
+ return (gzFile)s;
+}
+
+/* ===========================================================================
+ Opens a gzip (.gz) file for reading or writing.
+*/
+gzFile gzopen (path, mode)
+ const char *path;
+ const char *mode;
+{
+ return gz_open (path, mode, -1);
+}
+
+/* ===========================================================================
+ Associate a gzFile with the file descriptor fd. fd is not dup'ed here
+ to mimic the behavio(u)r of fdopen.
+*/
+gzFile gzdopen (fd, mode)
+ int fd;
+ const char *mode;
+{
+ char name[20];
+
+ if (fd < 0) return (gzFile)Z_NULL;
+ sprintf(name, "<fd:%d>", fd); /* for debugging */
+
+ return gz_open (name, mode, fd);
+}
+
+/* ===========================================================================
+ Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+ for end of file.
+ IN assertion: the stream s has been sucessfully opened for reading.
+*/
+local int get_byte(s)
+ gz_stream *s;
+{
+ if (s->z_eof) return EOF;
+ if (s->stream.avail_in == 0) {
+ errno = 0;
+ s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) s->z_err = Z_ERRNO;
+ return EOF;
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->stream.avail_in--;
+ return *(s->stream.next_in)++;
+}
+
+/* ===========================================================================
+ Check the gzip header of a gz_stream opened for reading. Set the stream
+ mode to transparent if the gzip magic header is not present; set s->err
+ to Z_DATA_ERROR if the magic header is present but the rest of the header
+ is incorrect.
+ IN assertion: the stream s has already been created sucessfully;
+ s->stream.avail_in is zero for the first time, but may be non-zero
+ for concatenated .gz files.
+*/
+local void check_header(s)
+ gz_stream *s;
+{
+ int method; /* method byte */
+ int flags; /* flags byte */
+ uInt len;
+ int c;
+
+ /* Check the gzip magic header */
+ for (len = 0; len < 2; len++) {
+ c = get_byte(s);
+ if (c != gz_magic[len]) {
+ s->transparent = 1;
+ if (c != EOF) s->stream.avail_in++, s->stream.next_in--;
+ s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
+ return;
+ }
+ }
+ method = get_byte(s);
+ flags = get_byte(s);
+ if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+ s->z_err = Z_DATA_ERROR;
+ return;
+ }
+
+ /* Discard time, xflags and OS code: */
+ for (len = 0; len < 6; len++) (void)get_byte(s);
+
+ if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+ len = (uInt)get_byte(s);
+ len += ((uInt)get_byte(s))<<8;
+ /* len is garbage if EOF but the loop below will quit anyway */
+ while (len-- != 0 && get_byte(s) != EOF) ;
+ }
+ if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
+ for (len = 0; len < 2; len++) (void)get_byte(s);
+ }
+ s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+}
+
+ /* ===========================================================================
+ * Cleanup then free the given gz_stream. Return a zlib error code.
+ Try freeing in the reverse order of allocations.
+ */
+local int destroy (s)
+ gz_stream *s;
+{
+ int err = Z_OK;
+
+ if (!s) return Z_STREAM_ERROR;
+
+ TRYFREE(s->msg);
+
+ if (s->stream.state != NULL) {
+ if (s->mode == 'w') {
+ err = deflateEnd(&(s->stream));
+ } else if (s->mode == 'r') {
+ err = inflateEnd(&(s->stream));
+ }
+ }
+ if (s->file != NULL && fclose(s->file)) {
+ err = Z_ERRNO;
+ }
+ if (s->z_err < 0) err = s->z_err;
+
+ TRYFREE(s->inbuf);
+ TRYFREE(s->outbuf);
+ TRYFREE(s->path);
+ TRYFREE(s);
+ return err;
+}
+
+/* ===========================================================================
+ Reads the given number of uncompressed bytes from the compressed file.
+ gzread returns the number of bytes actually read (0 for end of file).
+*/
+int gzread (file, buf, len)
+ gzFile file;
+ voidp buf;
+ unsigned len;
+{
+ gz_stream *s = (gz_stream*)file;
+ Bytef *start = buf; /* starting point for crc computation */
+ Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
+
+ if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
+
+ if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
+ if (s->z_err == Z_STREAM_END) return 0; /* EOF */
+
+ s->stream.next_out = next_out = buf;
+ s->stream.avail_out = len;
+
+ while (s->stream.avail_out != 0) {
+
+ if (s->transparent) {
+ /* Copy first the lookahead bytes: */
+ uInt n = s->stream.avail_in;
+ if (n > s->stream.avail_out) n = s->stream.avail_out;
+ if (n > 0) {
+ zmemcpy(s->stream.next_out, s->stream.next_in, n);
+ next_out += n;
+ s->stream.next_out = next_out;
+ s->stream.next_in += n;
+ s->stream.avail_out -= n;
+ s->stream.avail_in -= n;
+ }
+ if (s->stream.avail_out > 0) {
+ s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
+ s->file);
+ }
+ return (int)(len - s->stream.avail_out);
+ }
+ if (s->stream.avail_in == 0 && !s->z_eof) {
+
+ errno = 0;
+ s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) {
+ s->z_err = Z_ERRNO;
+ break;
+ }
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
+
+ if (s->z_err == Z_STREAM_END) {
+ /* Check CRC and original size */
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+ start = s->stream.next_out;
+
+ if (getLong(s) != s->crc || getLong(s) != s->stream.total_out) {
+ s->z_err = Z_DATA_ERROR;
+ } else {
+ /* Check for concatenated .gz files: */
+ check_header(s);
+ if (s->z_err == Z_OK) {
+ inflateReset(&(s->stream));
+ s->crc = crc32(0L, Z_NULL, 0);
+ }
+ }
+ }
+ if (s->z_err != Z_OK || s->z_eof) break;
+ }
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+
+ return (int)(len - s->stream.avail_out);
+}
+
+/* ===========================================================================
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of bytes actually written (0 in case of error).
+*/
+int gzwrite (file, buf, len)
+ gzFile file;
+ const voidp buf;
+ unsigned len;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+ s->stream.next_in = buf;
+ s->stream.avail_in = len;
+
+ while (s->stream.avail_in != 0) {
+
+ if (s->stream.avail_out == 0) {
+
+ s->stream.next_out = s->outbuf;
+ if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+ s->z_err = Z_ERRNO;
+ break;
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+ }
+ s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
+ if (s->z_err != Z_OK) break;
+ }
+ s->crc = crc32(s->crc, buf, len);
+
+ return (int)(len - s->stream.avail_in);
+}
+
+/* ===========================================================================
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+int gzflush (file, flush)
+ gzFile file;
+ int flush;
+{
+ uInt len;
+ int done = 0;
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+ s->stream.avail_in = 0; /* should be zero already anyway */
+
+ for (;;) {
+ len = Z_BUFSIZE - s->stream.avail_out;
+
+ if (len != 0) {
+ if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
+ s->z_err = Z_ERRNO;
+ return Z_ERRNO;
+ }
+ s->stream.next_out = s->outbuf;
+ s->stream.avail_out = Z_BUFSIZE;
+ }
+ if (done) break;
+ s->z_err = deflate(&(s->stream), flush);
+
+ /* deflate has finished flushing only when it hasn't used up
+ * all the available space in the output buffer:
+ */
+ done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
+
+ if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
+ }
+ fflush(s->file);
+ return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+
+/* ===========================================================================
+ Outputs a long in LSB order to the given file
+*/
+local void putLong (file, x)
+ FILE *file;
+ uLong x;
+{
+ int n;
+ for (n = 0; n < 4; n++) {
+ fputc((int)(x & 0xff), file);
+ x >>= 8;
+ }
+}
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets
+*/
+local uLong getLong (s)
+ gz_stream *s;
+{
+ uLong x = (uLong)get_byte(s);
+ int c;
+
+ x += ((uLong)get_byte(s))<<8;
+ x += ((uLong)get_byte(s))<<16;
+ c = get_byte(s);
+ if (c == EOF) s->z_err = Z_DATA_ERROR;
+ x += ((uLong)c)<<24;
+ return x;
+}
+
+/* ===========================================================================
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state.
+*/
+int gzclose (file)
+ gzFile file;
+{
+ int err;
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL) return Z_STREAM_ERROR;
+
+ if (s->mode == 'w') {
+ err = gzflush (file, Z_FINISH);
+ if (err != Z_OK) return destroy(file);
+
+ putLong (s->file, s->crc);
+ putLong (s->file, s->stream.total_in);
+
+ }
+ return destroy(file);
+}
+
+/* ===========================================================================
+ Returns the error message for the last error which occured on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occured in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+const char* gzerror (file, errnum)
+ gzFile file;
+ int *errnum;
+{
+ char *m;
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL) {
+ *errnum = Z_STREAM_ERROR;
+ return (const char*)ERR_MSG(Z_STREAM_ERROR);
+ }
+ *errnum = s->z_err;
+ if (*errnum == Z_OK) return (const char*)"";
+
+ m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
+
+ if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
+
+ TRYFREE(s->msg);
+ s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
+ strcpy(s->msg, s->path);
+ strcat(s->msg, ": ");
+ strcat(s->msg, m);
+ return (const char*)s->msg;
+}
diff --git a/lib/libz/infblock.c b/lib/libz/infblock.c
new file mode 100644
index 0000000..cc2e674
--- /dev/null
+++ b/lib/libz/infblock.c
@@ -0,0 +1,402 @@
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local uInt border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+
+void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_streamp z;
+uLongf *c;
+{
+ if (s->checkfn != Z_NULL)
+ *c = s->check;
+ if (s->mode == BTREE || s->mode == DTREE)
+ ZFREE(z, s->sub.trees.blens);
+ if (s->mode == CODES)
+ {
+ inflate_codes_free(s->sub.decode.codes, z);
+ inflate_trees_free(s->sub.decode.td, z);
+ inflate_trees_free(s->sub.decode.tl, z);
+ }
+ s->mode = TYPE;
+ s->bitk = 0;
+ s->bitb = 0;
+ s->read = s->write = s->window;
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(0L, Z_NULL, 0);
+ Trace((stderr, "inflate: blocks reset\n"));
+}
+
+
+inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_streamp z;
+check_func c;
+uInt w;
+{
+ inflate_blocks_statef *s;
+
+ if ((s = (inflate_blocks_statef *)ZALLOC
+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+ return s;
+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+ {
+ ZFREE(z, s);
+ return Z_NULL;
+ }
+ s->end = s->window + w;
+ s->checkfn = c;
+ s->mode = TYPE;
+ Trace((stderr, "inflate: blocks allocated\n"));
+ inflate_blocks_reset(s, z, &s->check);
+ return s;
+}
+
+
+#ifdef DEBUG
+ extern uInt inflate_hufts;
+#endif
+int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt t; /* temporary storage */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input based on current state */
+ while (1) switch (s->mode)
+ {
+ case TYPE:
+ NEEDBITS(3)
+ t = (uInt)b & 7;
+ s->last = t & 1;
+ switch (t >> 1)
+ {
+ case 0: /* stored */
+ Trace((stderr, "inflate: stored block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ t = k & 7; /* go to byte boundary */
+ DUMPBITS(t)
+ s->mode = LENS; /* get length of stored block */
+ break;
+ case 1: /* fixed */
+ Trace((stderr, "inflate: fixed codes block%s\n",
+ s->last ? " (last)" : ""));
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+
+ inflate_trees_fixed(&bl, &bd, &tl, &td);
+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+ if (s->sub.decode.codes == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.decode.tl = Z_NULL; /* don't try to free these */
+ s->sub.decode.td = Z_NULL;
+ }
+ DUMPBITS(3)
+ s->mode = CODES;
+ break;
+ case 2: /* dynamic */
+ Trace((stderr, "inflate: dynamic codes block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ s->mode = TABLE;
+ break;
+ case 3: /* illegal */
+ DUMPBITS(3)
+ s->mode = BAD;
+ z->msg = (char*)"invalid block type";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ break;
+ case LENS:
+ NEEDBITS(32)
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ s->mode = BAD;
+ z->msg = (char*)"invalid stored block lengths";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ s->sub.left = (uInt)b & 0xffff;
+ b = k = 0; /* dump bits */
+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
+ s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+ break;
+ case STORED:
+ if (n == 0)
+ LEAVE
+ NEEDOUT
+ t = s->sub.left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ zmemcpy(q, p, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((s->sub.left -= t) != 0)
+ break;
+ Tracev((stderr, "inflate: stored end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ s->mode = s->last ? DRY : TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14)
+ s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ s->mode = BAD;
+ z->msg = (char*)"too many length or distance symbols";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+#endif
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (t < 19)
+ t = 19;
+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ DUMPBITS(14)
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ s->mode = BTREE;
+ case BTREE:
+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+ {
+ NEEDBITS(3)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+ DUMPBITS(3)
+ }
+ while (s->sub.trees.index < 19)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+ s->sub.trees.bb = 7;
+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+ &s->sub.trees.tb, z);
+ if (t != Z_OK)
+ {
+ r = t;
+ if (r == Z_DATA_ERROR)
+ s->mode = BAD;
+ LEAVE
+ }
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: bits tree ok\n"));
+ s->mode = DTREE;
+ case DTREE:
+ while (t = s->sub.trees.table,
+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+ {
+ inflate_huft *h;
+ uInt i, j, c;
+
+ t = s->sub.trees.bb;
+ NEEDBITS(t)
+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+ t = h->word.what.Bits;
+ c = h->more.Base;
+ if (c < 16)
+ {
+ DUMPBITS(t)
+ s->sub.trees.blens[s->sub.trees.index++] = c;
+ }
+ else /* c == 16..18 */
+ {
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+ NEEDBITS(t + i)
+ DUMPBITS(t)
+ j += (uInt)b & inflate_mask[i];
+ DUMPBITS(i)
+ i = s->sub.trees.index;
+ t = s->sub.trees.table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ s->mode = BAD;
+ z->msg = (char*)"invalid bit length repeat";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+ do {
+ s->sub.trees.blens[i++] = c;
+ } while (--j);
+ s->sub.trees.index = i;
+ }
+ }
+ inflate_trees_free(s->sub.trees.tb, z);
+ s->sub.trees.tb = Z_NULL;
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+ inflate_codes_statef *c;
+
+ bl = 9; /* must be <= 9 for lookahead assumptions */
+ bd = 6; /* must be <= 9 for lookahead assumptions */
+ t = s->sub.trees.table;
+#ifdef DEBUG
+ inflate_hufts = 0;
+#endif
+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+ s->sub.trees.blens, &bl, &bd, &tl, &td, z);
+ if (t != Z_OK)
+ {
+ if (t == (uInt)Z_DATA_ERROR)
+ s->mode = BAD;
+ r = t;
+ LEAVE
+ }
+ Tracev((stderr, "inflate: trees ok, %d * %d bytes used\n",
+ inflate_hufts, sizeof(inflate_huft)));
+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+ {
+ inflate_trees_free(td, z);
+ inflate_trees_free(tl, z);
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ ZFREE(z, s->sub.trees.blens);
+ s->sub.decode.codes = c;
+ s->sub.decode.tl = tl;
+ s->sub.decode.td = td;
+ }
+ s->mode = CODES;
+ case CODES:
+ UPDATE
+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+ return inflate_flush(s, z, r);
+ r = Z_OK;
+ inflate_codes_free(s->sub.decode.codes, z);
+ inflate_trees_free(s->sub.decode.td, z);
+ inflate_trees_free(s->sub.decode.tl, z);
+ LOAD
+ Tracev((stderr, "inflate: codes end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ if (!s->last)
+ {
+ s->mode = TYPE;
+ break;
+ }
+ if (k > 7) /* return unused byte, if any */
+ {
+ Assert(k < 16, "inflate_codes grabbed too many bytes")
+ k -= 8;
+ n++;
+ p--; /* can always return one */
+ }
+ s->mode = DRY;
+ case DRY:
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ s->mode = DONE;
+ case DONE:
+ r = Z_STREAM_END;
+ LEAVE
+ case BAD:
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+}
+
+
+int inflate_blocks_free(s, z, c)
+inflate_blocks_statef *s;
+z_streamp z;
+uLongf *c;
+{
+ inflate_blocks_reset(s, z, c);
+ ZFREE(z, s->window);
+ ZFREE(z, s);
+ Trace((stderr, "inflate: blocks freed\n"));
+ return Z_OK;
+}
+
+
+void inflate_set_dictionary(s, d, n)
+inflate_blocks_statef *s;
+const Bytef *d;
+uInt n;
+{
+ zmemcpy((charf *)s->window, d, n);
+ s->read = s->write = s->window + n;
+}
diff --git a/lib/libz/infblock.h b/lib/libz/infblock.h
new file mode 100644
index 0000000..3ecd50c
--- /dev/null
+++ b/lib/libz/infblock.h
@@ -0,0 +1,37 @@
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+extern inflate_blocks_statef * inflate_blocks_new OF((
+ z_streamp z,
+ check_func c, /* check function */
+ uInt w)); /* window size */
+
+extern int inflate_blocks OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int)); /* initial return code */
+
+extern void inflate_blocks_reset OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ uLongf *)); /* check value on output */
+
+extern int inflate_blocks_free OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ uLongf *)); /* check value on output */
+
+extern void inflate_set_dictionary OF((
+ inflate_blocks_statef *s,
+ const Bytef *d, /* dictionary */
+ uInt n)); /* dictionary length */
diff --git a/lib/libz/infcodes.c b/lib/libz/infcodes.c
new file mode 100644
index 0000000..3ae3818
--- /dev/null
+++ b/lib/libz/infcodes.c
@@ -0,0 +1,247 @@
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+ /* mode */
+ enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ START, /* x: set up for LEN */
+ LEN, /* i: get length/literal/eob next */
+ LENEXT, /* i: getting length extra (have base) */
+ DIST, /* i: get distance next */
+ DISTEXT, /* i: getting distance extra */
+ COPY, /* o: copying bytes in window, waiting for space */
+ LIT, /* o: got literal, waiting for output space */
+ WASH, /* o: got eob, possibly still output waiting */
+ END, /* x: got eob and all data flushed */
+ BADCODE} /* x: got error */
+ mode; /* current inflate_codes mode */
+
+ /* mode dependent information */
+ uInt len;
+ union {
+ struct {
+ inflate_huft *tree; /* pointer into tree */
+ uInt need; /* bits needed */
+ } code; /* if LEN or DIST, where in tree */
+ uInt lit; /* if LIT, literal */
+ struct {
+ uInt get; /* bits to get for extra */
+ uInt dist; /* distance back to copy from */
+ } copy; /* if EXT or COPY, where and how much */
+ } sub; /* submode */
+
+ /* mode independent information */
+ Byte lbits; /* ltree bits decoded per branch */
+ Byte dbits; /* dtree bits decoder per branch */
+ inflate_huft *ltree; /* literal/length/eob tree */
+ inflate_huft *dtree; /* distance tree */
+
+};
+
+
+inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+z_streamp z;
+{
+ inflate_codes_statef *c;
+
+ if ((c = (inflate_codes_statef *)
+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+ {
+ c->mode = START;
+ c->lbits = (Byte)bl;
+ c->dbits = (Byte)bd;
+ c->ltree = tl;
+ c->dtree = td;
+ Tracev((stderr, "inflate: codes new\n"));
+ }
+ return c;
+}
+
+
+int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt j; /* temporary storage */
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ Bytef *f; /* pointer to copy strings from */
+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input and output based on current state */
+ while (1) switch (c->mode)
+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ case START: /* x: set up for LEN */
+#ifndef SLOW
+ if (m >= 258 && n >= 10)
+ {
+ UPDATE
+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+ LOAD
+ if (r != Z_OK)
+ {
+ c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+ break;
+ }
+ }
+#endif /* !SLOW */
+ c->sub.code.need = c->lbits;
+ c->sub.code.tree = c->ltree;
+ c->mode = LEN;
+ case LEN: /* i: get length/literal/eob next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e == 0) /* literal */
+ {
+ c->sub.lit = t->base;
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", t->base));
+ c->mode = LIT;
+ break;
+ }
+ if (e & 16) /* length */
+ {
+ c->sub.copy.get = e & 15;
+ c->len = t->base;
+ c->mode = LENEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t->next;
+ break;
+ }
+ if (e & 32) /* end of block */
+ {
+ Tracevv((stderr, "inflate: end of block\n"));
+ c->mode = WASH;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid literal/length code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case LENEXT: /* i: getting length extra (have base) */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->len += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ c->sub.code.need = c->dbits;
+ c->sub.code.tree = c->dtree;
+ Tracevv((stderr, "inflate: length %u\n", c->len));
+ c->mode = DIST;
+ case DIST: /* i: get distance next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e & 16) /* distance */
+ {
+ c->sub.copy.get = e & 15;
+ c->sub.copy.dist = t->base;
+ c->mode = DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t->next;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid distance code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case DISTEXT: /* i: getting distance extra */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->sub.copy.dist += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
+ c->mode = COPY;
+ case COPY: /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+ f = (uInt)(q - s->window) < c->sub.copy.dist ?
+ s->end - (c->sub.copy.dist - (q - s->window)) :
+ q - c->sub.copy.dist;
+#else
+ f = q - c->sub.copy.dist;
+ if ((uInt)(q - s->window) < c->sub.copy.dist)
+ f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
+#endif
+ while (c->len)
+ {
+ NEEDOUT
+ OUTBYTE(*f++)
+ if (f == s->end)
+ f = s->window;
+ c->len--;
+ }
+ c->mode = START;
+ break;
+ case LIT: /* o: got literal, waiting for output space */
+ NEEDOUT
+ OUTBYTE(c->sub.lit)
+ c->mode = START;
+ break;
+ case WASH: /* o: got eob, possibly more output */
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ c->mode = END;
+ case END:
+ r = Z_STREAM_END;
+ LEAVE
+ case BADCODE: /* x: got error */
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+}
+
+
+void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_streamp z;
+{
+ ZFREE(z, c);
+ Tracev((stderr, "inflate: codes free\n"));
+}
diff --git a/lib/libz/infcodes.h b/lib/libz/infcodes.h
new file mode 100644
index 0000000..c2c38df
--- /dev/null
+++ b/lib/libz/infcodes.h
@@ -0,0 +1,27 @@
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+extern inflate_codes_statef *inflate_codes_new OF((
+ uInt, uInt,
+ inflate_huft *, inflate_huft *,
+ z_streamp ));
+
+extern int inflate_codes OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+extern void inflate_codes_free OF((
+ inflate_codes_statef *,
+ z_streamp ));
+
diff --git a/lib/libz/inffast.c b/lib/libz/inffast.c
new file mode 100644
index 0000000..86eee4a
--- /dev/null
+++ b/lib/libz/inffast.c
@@ -0,0 +1,168 @@
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
+
+/* Called with number of bytes left to write in window at least 258
+ (the maximum string length) and number of input bytes available
+ at least ten. The ten bytes are six bytes for the longest length/
+ distance pair plus four bytes for overloading the bit buffer. */
+
+int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+inflate_blocks_statef *s;
+z_streamp z;
+{
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ uInt ml; /* mask for literal/length tree */
+ uInt md; /* mask for distance tree */
+ uInt c; /* bytes to copy */
+ uInt d; /* distance back to copy from */
+ Bytef *r; /* copy source pointer */
+
+ /* load input, output, bit values */
+ LOAD
+
+ /* initialize masks */
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ /* do until not enough input or output space for fast loop */
+ do { /* assume called with m >= 258 && n >= 10 */
+ /* get literal/length code */
+ GRABBITS(20) /* max bits for literal/length code */
+ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: * literal '%c'\n" :
+ "inflate: * literal 0x%02x\n", t->base));
+ *q++ = (Byte)t->base;
+ m--;
+ continue;
+ }
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits for length */
+ e &= 15;
+ c = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+ Tracevv((stderr, "inflate: * length %u\n", c));
+
+ /* decode distance base of block to copy */
+ GRABBITS(15); /* max bits for distance code */
+ e = (t = td + ((uInt)b & md))->exop;
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits to add to distance base */
+ e &= 15;
+ GRABBITS(e) /* get extra bits (up to 13) */
+ d = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+ Tracevv((stderr, "inflate: * distance %u\n", d));
+
+ /* do the copy */
+ m -= c;
+ if ((uInt)(q - s->window) >= d) /* offset before dest */
+ { /* just copy */
+ r = q - d;
+ *q++ = *r++; c--; /* minimum count is three, */
+ *q++ = *r++; c--; /* so unroll loop a little */
+ }
+ else /* else offset after destination */
+ {
+ e = d - (uInt)(q - s->window); /* bytes from offset to end */
+ r = s->end - e; /* pointer to offset */
+ if (c > e) /* if source crosses, */
+ {
+ c -= e; /* copy to end of window */
+ do {
+ *q++ = *r++;
+ } while (--e);
+ r = s->window; /* copy rest from start of window */
+ }
+ }
+ do { /* copy all or what's left */
+ *q++ = *r++;
+ } while (--c);
+ break;
+ }
+ else if ((e & 64) == 0)
+ e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
+ else
+ {
+ z->msg = (char*)"invalid distance code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ break;
+ }
+ if ((e & 64) == 0)
+ {
+ if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: * literal '%c'\n" :
+ "inflate: * literal 0x%02x\n", t->base));
+ *q++ = (Byte)t->base;
+ m--;
+ break;
+ }
+ }
+ else if (e & 32)
+ {
+ Tracevv((stderr, "inflate: * end of block\n"));
+ UNGRAB
+ UPDATE
+ return Z_STREAM_END;
+ }
+ else
+ {
+ z->msg = (char*)"invalid literal/length code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ } while (m >= 258 && n >= 10);
+
+ /* not enough input or output--restore pointers and return */
+ UNGRAB
+ UPDATE
+ return Z_OK;
+}
diff --git a/lib/libz/inffast.h b/lib/libz/inffast.h
new file mode 100644
index 0000000..8cc644e
--- /dev/null
+++ b/lib/libz/inffast.h
@@ -0,0 +1,17 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+extern int inflate_fast OF((
+ uInt,
+ uInt,
+ inflate_huft *,
+ inflate_huft *,
+ inflate_blocks_statef *,
+ z_streamp ));
diff --git a/lib/libz/inflate.c b/lib/libz/inflate.c
new file mode 100644
index 0000000..74cc69c
--- /dev/null
+++ b/lib/libz/inflate.c
@@ -0,0 +1,345 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+
+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
+
+/* inflate private state */
+struct internal_state {
+
+ /* mode */
+ enum {
+ METHOD, /* waiting for method byte */
+ FLAG, /* waiting for flag byte */
+ DICT4, /* four dictionary check bytes to go */
+ DICT3, /* three dictionary check bytes to go */
+ DICT2, /* two dictionary check bytes to go */
+ DICT1, /* one dictionary check byte to go */
+ DICT0, /* waiting for inflateSetDictionary */
+ BLOCKS, /* decompressing blocks */
+ CHECK4, /* four check bytes to go */
+ CHECK3, /* three check bytes to go */
+ CHECK2, /* two check bytes to go */
+ CHECK1, /* one check byte to go */
+ DONE, /* finished check, done */
+ BAD} /* got an error--stay here */
+ mode; /* current inflate mode */
+
+ /* mode dependent information */
+ union {
+ uInt method; /* if FLAGS, method byte */
+ struct {
+ uLong was; /* computed check value */
+ uLong need; /* stream check value */
+ } check; /* if CHECK, check values to compare */
+ uInt marker; /* if BAD, inflateSync's marker bytes count */
+ } sub; /* submode */
+
+ /* mode independent information */
+ int nowrap; /* flag for no wrapper */
+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */
+ inflate_blocks_statef
+ *blocks; /* current inflate_blocks state */
+
+};
+
+
+int inflateReset(z)
+z_streamp z;
+{
+ uLong c;
+
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->total_in = z->total_out = 0;
+ z->msg = Z_NULL;
+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+ inflate_blocks_reset(z->state->blocks, z, &c);
+ Trace((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+
+int inflateEnd(z)
+z_streamp z;
+{
+ uLong c;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->blocks != Z_NULL)
+ inflate_blocks_free(z->state->blocks, z, &c);
+ ZFREE(z, z->state);
+ z->state = Z_NULL;
+ Trace((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+
+int inflateInit2_(z, w, version, stream_size)
+z_streamp z;
+int w;
+const char *version;
+int stream_size;
+{
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != sizeof(z_stream))
+ return Z_VERSION_ERROR;
+
+ /* initialize state */
+ if (z == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->msg = Z_NULL;
+ if (z->zalloc == Z_NULL)
+ {
+ z->zalloc = zcalloc;
+ z->opaque = (voidpf)0;
+ }
+ if (z->zfree == Z_NULL) z->zfree = zcfree;
+ if ((z->state = (struct internal_state FAR *)
+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+ return Z_MEM_ERROR;
+ z->state->blocks = Z_NULL;
+
+ /* handle undocumented nowrap option (no zlib header or check) */
+ z->state->nowrap = 0;
+ if (w < 0)
+ {
+ w = - w;
+ z->state->nowrap = 1;
+ }
+
+ /* set window size */
+ if (w < 8 || w > 15)
+ {
+ inflateEnd(z);
+ return Z_STREAM_ERROR;
+ }
+ z->state->wbits = (uInt)w;
+
+ /* create inflate_blocks state */
+ if ((z->state->blocks =
+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+ == Z_NULL)
+ {
+ inflateEnd(z);
+ return Z_MEM_ERROR;
+ }
+ Trace((stderr, "inflate: allocated\n"));
+
+ /* reset state */
+ inflateReset(z);
+ return Z_OK;
+}
+
+
+int inflateInit_(z, version, stream_size)
+z_streamp z;
+const char *version;
+int stream_size;
+{
+ return inflateInit2_(z, DEF_WBITS, version, stream_size);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)return r;r=Z_OK;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int inflate(z, f)
+z_streamp z;
+int f;
+{
+ int r;
+ uInt b;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL || f < 0)
+ return Z_STREAM_ERROR;
+ r = Z_BUF_ERROR;
+ while (1) switch (z->state->mode)
+ {
+ case METHOD:
+ NEEDBYTE
+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"unknown compression method";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"invalid window size";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ z->state->mode = FLAG;
+ case FLAG:
+ NEEDBYTE
+ b = NEXTBYTE;
+ if (((z->state->sub.method << 8) + b) % 31)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect header check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Trace((stderr, "inflate: zlib header ok\n"));
+ if (!(b & PRESET_DICT))
+ {
+ z->state->mode = BLOCKS;
+ break;
+ }
+ z->state->mode = DICT4;
+ case DICT4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = DICT3;
+ case DICT3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = DICT2;
+ case DICT2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = DICT1;
+ case DICT1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+ z->adler = z->state->sub.check.need;
+ z->state->mode = DICT0;
+ return Z_NEED_DICT;
+ case DICT0:
+ z->state->mode = BAD;
+ z->msg = (char*)"need dictionary";
+ z->state->sub.marker = 0; /* can try inflateSync */
+ return Z_STREAM_ERROR;
+ case BLOCKS:
+ r = inflate_blocks(z->state->blocks, z, r);
+ if (r == Z_DATA_ERROR)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0; /* can try inflateSync */
+ break;
+ }
+ if (r != Z_STREAM_END)
+ return r;
+ r = Z_OK;
+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+ if (z->state->nowrap)
+ {
+ z->state->mode = DONE;
+ break;
+ }
+ z->state->mode = CHECK4;
+ case CHECK4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = CHECK3;
+ case CHECK3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = CHECK2;
+ case CHECK2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = CHECK1;
+ case CHECK1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+
+ if (z->state->sub.check.was != z->state->sub.check.need)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect data check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Trace((stderr, "inflate: zlib check ok\n"));
+ z->state->mode = DONE;
+ case DONE:
+ return Z_STREAM_END;
+ case BAD:
+ return Z_DATA_ERROR;
+ default:
+ return Z_STREAM_ERROR;
+ }
+}
+
+
+int inflateSetDictionary(z, dictionary, dictLength)
+z_streamp z;
+const Bytef *dictionary;
+uInt dictLength;
+{
+ uInt length = dictLength;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
+ return Z_STREAM_ERROR;
+
+ if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
+ z->adler = 1L;
+
+ if (length >= ((uInt)1<<z->state->wbits))
+ {
+ length = (1<<z->state->wbits)-1;
+ dictionary += dictLength - length;
+ }
+ inflate_set_dictionary(z->state->blocks, dictionary, length);
+ z->state->mode = BLOCKS;
+ return Z_OK;
+}
+
+
+int inflateSync(z)
+z_streamp z;
+{
+ uInt n; /* number of bytes to look at */
+ Bytef *p; /* pointer to bytes */
+ uInt m; /* number of marker bytes found in a row */
+ uLong r, w; /* temporaries to save total_in and total_out */
+
+ /* set up */
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->mode != BAD)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0;
+ }
+ if ((n = z->avail_in) == 0)
+ return Z_BUF_ERROR;
+ p = z->next_in;
+ m = z->state->sub.marker;
+
+ /* search */
+ while (n && m < 4)
+ {
+ if (*p == (Byte)(m < 2 ? 0 : 0xff))
+ m++;
+ else if (*p)
+ m = 0;
+ else
+ m = 4 - m;
+ p++, n--;
+ }
+
+ /* restore */
+ z->total_in += p - z->next_in;
+ z->next_in = p;
+ z->avail_in = n;
+ z->state->sub.marker = m;
+
+ /* return no joy or set up to restart on a new block */
+ if (m != 4)
+ return Z_DATA_ERROR;
+ r = z->total_in; w = z->total_out;
+ inflateReset(z);
+ z->total_in = r; z->total_out = w;
+ z->state->mode = BLOCKS;
+ return Z_OK;
+}
diff --git a/lib/libz/inftrees.c b/lib/libz/inftrees.c
new file mode 100644
index 0000000..90205bd
--- /dev/null
+++ b/lib/libz/inftrees.c
@@ -0,0 +1,470 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+char inflate_copyright[] = " inflate 1.0.4 Copyright 1995-1996 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+ uIntf *, /* code lengths in bits */
+ uInt, /* number of codes */
+ uInt, /* number of "simple" codes */
+ uIntf *, /* list of base values for non-simple codes */
+ uIntf *, /* list of extra bits for non-simple codes */
+ inflate_huft * FAR*,/* result: starting table */
+ uIntf *, /* maximum lookup bits (returns actual) */
+ z_streamp )); /* for zalloc function */
+
+local voidpf falloc OF((
+ voidpf, /* opaque pointer (not used) */
+ uInt, /* number of items */
+ uInt)); /* size of item */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* actually lengths - 2; also see note #13 above about 258 */
+local uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
+local uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+local uInt cpdext[30] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15 /* maximum bit length of any code */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+#ifdef DEBUG
+ uInt inflate_hufts;
+#endif
+
+local int huft_build(b, n, s, d, e, t, m, zs)
+uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
+uInt n; /* number of codes (assumed <= N_MAX) */
+uInt s; /* number of simple-valued codes (0..s-1) */
+uIntf *d; /* list of base values for non-simple codes */
+uIntf *e; /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t; /* result: starting table */
+uIntf *m; /* maximum lookup bits, returns actual */
+z_streamp zs; /* for zalloc function */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ if the given code set is incomplete (the tables are still built in this
+ case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
+ over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+ uInt a; /* counter for codes of length k */
+ uInt c[BMAX+1]; /* bit length count table */
+ uInt f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register uInt i; /* counter, current code */
+ register uInt j; /* counter */
+ register int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ register uIntf *p; /* pointer into c[], b[], or v[] */
+ inflate_huft *q; /* points to current table */
+ struct inflate_huft_s r; /* table entry for structure assignment */
+ inflate_huft *u[BMAX]; /* table stack */
+ uInt v[N_MAX]; /* values in order of bit length */
+ register int w; /* bits before this table == (l * h) */
+ uInt x[BMAX+1]; /* bit offsets, then code stack */
+ uIntf *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ uInt z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+ C4 /* clear c[]--assume BMAX+1 is 16 */
+ p = b; i = n;
+ do {
+ c[*p++]++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (inflate_huft *)Z_NULL;
+ *m = 0;
+ return Z_OK;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((uInt)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((uInt)l > i)
+ l = i;
+ *m = l;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return Z_DATA_ERROR;
+ if ((y -= c[i]) < 0)
+ return Z_DATA_ERROR;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
+ q = (inflate_huft *)Z_NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = g - w;
+ z = z > (uInt)l ? l : z; /* table size upper limit */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ if (j < z)
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate and link in new table */
+ if ((q = (inflate_huft *)ZALLOC
+ (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
+ {
+ if (h)
+ inflate_trees_free(u[0], zs);
+ return Z_MEM_ERROR; /* not enough memory */
+ }
+#ifdef DEBUG
+ inflate_hufts += z + 1;
+#endif
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->next)) = Z_NULL;
+ u[h] = ++q; /* table starts after link */
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.bits = (Byte)l; /* bits to dump before this table */
+ r.exop = (Byte)j; /* bits in this table */
+ r.next = q; /* pointer to this table */
+ j = i >> (w - l); /* (get around Turbo C bug) */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* set up table entry in r */
+ r.bits = (Byte)(k - w);
+ if (p >= v + n)
+ r.exop = 128 + 64; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
+ r.base = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+ r.base = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ }
+ }
+ }
+
+
+ /* Return Z_BUF_ERROR if we were given an incomplete table */
+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+int inflate_trees_bits(c, bb, tb, z)
+uIntf *c; /* 19 code lengths */
+uIntf *bb; /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+z_streamp z; /* for zfree function */
+{
+ int r;
+
+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+ else if (r == Z_BUF_ERROR)
+ {
+ inflate_trees_free(*tb, z);
+ z->msg = (char*)"incomplete dynamic bit lengths tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+}
+
+
+int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
+uInt nl; /* number of literal/length codes */
+uInt nd; /* number of distance codes */
+uIntf *c; /* that many (total) code lengths */
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+z_streamp z; /* for zfree function */
+{
+ int r;
+
+ /* build literal/length tree */
+ if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed literal/length tree";
+ else if (r == Z_BUF_ERROR)
+ {
+ inflate_trees_free(*tl, z);
+ z->msg = (char*)"incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+ }
+
+ /* build distance tree */
+ if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed literal/length tree";
+ else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+ r = Z_OK;
+ }
+#else
+ inflate_trees_free(*td, z);
+ z->msg = (char*)"incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ inflate_trees_free(*tl, z);
+ return r;
+#endif
+ }
+
+ /* done */
+ return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+local int fixed_built = 0;
+#define FIXEDH 530 /* number of hufts used by fixed tables */
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+
+
+local voidpf falloc(q, n, s)
+voidpf q; /* opaque pointer */
+uInt n; /* number of items */
+uInt s; /* size of item */
+{
+ Assert(s == sizeof(inflate_huft) && n <= *(intf *)q,
+ "inflate_trees falloc overflow");
+ *(intf *)q -= n+s-s; /* s-s to avoid warning */
+ return (voidpf)(fixed_mem + *(intf *)q);
+}
+
+
+int inflate_trees_fixed(bl, bd, tl, td)
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+{
+ /* build fixed tables if not already (multiple overlapped executions ok) */
+ if (!fixed_built)
+ {
+ int k; /* temporary variable */
+ unsigned c[288]; /* length list for huft_build */
+ z_stream z; /* for falloc function */
+ int f = FIXEDH; /* number of hufts left in fixed_mem */
+
+ /* set up fake z_stream for memory routines */
+ z.zalloc = falloc;
+ z.zfree = Z_NULL;
+ z.opaque = (voidpf)&f;
+
+ /* literal table */
+ for (k = 0; k < 144; k++)
+ c[k] = 8;
+ for (; k < 256; k++)
+ c[k] = 9;
+ for (; k < 280; k++)
+ c[k] = 7;
+ for (; k < 288; k++)
+ c[k] = 8;
+ fixed_bl = 7;
+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
+
+ /* distance table */
+ for (k = 0; k < 30; k++)
+ c[k] = 5;
+ fixed_bd = 5;
+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
+
+ /* done */
+ Assert(f == 0, "invalid build of fixed tables");
+ fixed_built = 1;
+ }
+ *bl = fixed_bl;
+ *bd = fixed_bd;
+ *tl = fixed_tl;
+ *td = fixed_td;
+ return Z_OK;
+}
+
+
+int inflate_trees_free(t, z)
+inflate_huft *t; /* table to free */
+z_streamp z; /* for zfree function */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register inflate_huft *p, *q, *r;
+
+ /* Reverse linked list */
+ p = Z_NULL;
+ q = t;
+ while (q != Z_NULL)
+ {
+ r = (q - 1)->next;
+ (q - 1)->next = p;
+ p = q;
+ q = r;
+ }
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ while (p != Z_NULL)
+ {
+ q = (--p)->next;
+ ZFREE(z,p);
+ p = q;
+ }
+ return Z_OK;
+}
diff --git a/lib/libz/inftrees.h b/lib/libz/inftrees.h
new file mode 100644
index 0000000..b06613d
--- /dev/null
+++ b/lib/libz/inftrees.h
@@ -0,0 +1,59 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+ union {
+ struct {
+ Byte Exop; /* number of extra bits or operation */
+ Byte Bits; /* number of bits in this code or subcode */
+ } what;
+ Bytef *pad; /* pad structure to a power of 2 (4 bytes for */
+ } word; /* 16-bit, 8 bytes for 32-bit machines) */
+ union {
+ uInt Base; /* literal, length base, or distance base */
+ inflate_huft *Next; /* pointer to next level of table */
+ } more;
+};
+
+#ifdef DEBUG
+ extern uInt inflate_hufts;
+#endif
+
+extern int inflate_trees_bits OF((
+ uIntf *, /* 19 code lengths */
+ uIntf *, /* bits tree desired/actual depth */
+ inflate_huft * FAR *, /* bits tree result */
+ z_streamp )); /* for zalloc, zfree functions */
+
+extern int inflate_trees_dynamic OF((
+ uInt, /* number of literal/length codes */
+ uInt, /* number of distance codes */
+ uIntf *, /* that many (total) code lengths */
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *, /* distance tree result */
+ z_streamp )); /* for zalloc, zfree functions */
+
+extern int inflate_trees_fixed OF((
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *)); /* distance tree result */
+
+extern int inflate_trees_free OF((
+ inflate_huft *, /* tables to free */
+ z_streamp )); /* for zfree function */
+
diff --git a/lib/libz/infutil.c b/lib/libz/infutil.c
new file mode 100644
index 0000000..eb21199
--- /dev/null
+++ b/lib/libz/infutil.c
@@ -0,0 +1,87 @@
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* And'ing with mask[n] masks the lower n bits */
+uInt inflate_mask[17] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* copy as much as possible from the sliding window to the output area */
+int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt n;
+ Bytef *p;
+ Bytef *q;
+
+ /* local copies of source and destination pointers */
+ p = z->next_out;
+ q = s->read;
+
+ /* compute number of bytes to copy as far as end of window */
+ n = (uInt)((q <= s->write ? s->write : s->end) - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy as far as end of window */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+
+ /* see if more to copy at beginning of window */
+ if (q == s->end)
+ {
+ /* wrap pointers */
+ q = s->window;
+ if (s->write == s->end)
+ s->write = s->window;
+
+ /* compute bytes to copy */
+ n = (uInt)(s->write - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+ }
+
+ /* update pointers */
+ z->next_out = p;
+ s->read = q;
+
+ /* done */
+ return r;
+}
diff --git a/lib/libz/infutil.h b/lib/libz/infutil.h
new file mode 100644
index 0000000..702cd29
--- /dev/null
+++ b/lib/libz/infutil.h
@@ -0,0 +1,99 @@
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+ TYPE, /* get type bits (3, including end bit) */
+ LENS, /* get lengths for stored */
+ STORED, /* processing stored block */
+ TABLE, /* get table lengths */
+ BTREE, /* get bit lengths tree for a dynamic block */
+ DTREE, /* get length, distance trees for a dynamic block */
+ CODES, /* processing fixed or dynamic block */
+ DRY, /* output remaining window bytes */
+ DONE, /* finished last block, done */
+ BAD} /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+ /* mode */
+ inflate_block_mode mode; /* current inflate_block mode */
+
+ /* mode dependent information */
+ union {
+ uInt left; /* if STORED, bytes left to copy */
+ struct {
+ uInt table; /* table lengths (14 bits) */
+ uInt index; /* index into blens (or border) */
+ uIntf *blens; /* bit lengths of codes */
+ uInt bb; /* bit length tree depth */
+ inflate_huft *tb; /* bit length decoding tree */
+ } trees; /* if DTREE, decoding info for trees */
+ struct {
+ inflate_huft *tl;
+ inflate_huft *td; /* trees to free */
+ inflate_codes_statef
+ *codes;
+ } decode; /* if CODES, current state */
+ } sub; /* submode */
+ uInt last; /* true if this block is the last block */
+
+ /* mode independent information */
+ uInt bitk; /* bits in bit buffer */
+ uLong bitb; /* bit buffer */
+ Bytef *window; /* sliding window */
+ Bytef *end; /* one byte after sliding window */
+ Bytef *read; /* window read pointer */
+ Bytef *write; /* window write pointer */
+ check_func checkfn; /* check function */
+ uLong check; /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/* update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/* get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/* output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/* load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+extern uInt inflate_mask[17];
+
+/* copy as much as possible from the sliding window to the output area */
+extern int inflate_flush OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+#endif
diff --git a/lib/libz/minigzip.c b/lib/libz/minigzip.c
new file mode 100644
index 0000000..9548ab8
--- /dev/null
+++ b/lib/libz/minigzip.c
@@ -0,0 +1,246 @@
+/* minigzip.c -- simulate gzip using the zlib compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * minigzip is a minimal implementation of the gzip utility. This is
+ * only an example of using zlib and isn't meant to replace the
+ * full-featured gzip. No attempt is made to deal with file systems
+ * limiting names to 14 or 8+3 characters, etc... Error checking is
+ * very limited. So use minigzip only for testing; use gzip for the
+ * real thing. On MSDOS, use only on file names without extension
+ * or in pipe mode.
+ */
+
+/* $FreeBSD$ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#else
+ extern void exit OF((int));
+#endif
+
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32)
+# include <fcntl.h>
+# include <io.h>
+# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+# define SET_BINARY_MODE(file)
+#endif
+
+#ifdef VMS
+# define unlink delete
+# define GZ_SUFFIX "-gz"
+#endif
+#ifdef RISCOS
+# define unlink remove
+# define GZ_SUFFIX "-gz"
+# define fileno(file) file->__file
+#endif
+
+#ifndef GZ_SUFFIX
+# define GZ_SUFFIX ".gz"
+#endif
+#define SUFFIX_LEN sizeof(GZ_SUFFIX)
+
+extern int unlink OF((const char *));
+
+#define BUFLEN 4096
+#define MAX_NAME_LEN 1024
+
+#define local static
+/* For MSDOS and other systems with limitation on stack size. For Unix,
+ #define local
+ works also.
+ */
+
+char *prog;
+
+void error OF((const char *msg));
+void gz_compress OF((FILE *in, gzFile out));
+void gz_uncompress OF((gzFile in, FILE *out));
+void file_compress OF((char *file));
+void file_uncompress OF((char *file));
+int main OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Display error message and exit
+ */
+void error(msg)
+ const char *msg;
+{
+ fprintf(stderr, "%s: %s\n", prog, msg);
+ exit(1);
+}
+
+/* ===========================================================================
+ * Compress input to output then close both files.
+ */
+void gz_compress(in, out)
+ FILE *in;
+ gzFile out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+ for (;;) {
+ len = fread(buf, 1, sizeof(buf), in);
+ if (ferror(in)) {
+ perror("fread");
+ exit(1);
+ }
+ if (len == 0) break;
+
+ if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
+ }
+ fclose(in);
+ if (gzclose(out) != Z_OK) error("failed gzclose");
+}
+
+/* ===========================================================================
+ * Uncompress input to output then close both files.
+ */
+void gz_uncompress(in, out)
+ gzFile in;
+ FILE *out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+ for (;;) {
+ len = gzread(in, buf, sizeof(buf));
+ if (len < 0) error (gzerror(in, &err));
+ if (len == 0) break;
+
+ if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
+ error("failed fwrite");
+ }
+ }
+ if (fclose(out)) error("failed fclose");
+
+ if (gzclose(in) != Z_OK) error("failed gzclose");
+}
+
+
+/* ===========================================================================
+ * Compress the given file: create a corresponding .gz file and remove the
+ * original.
+ */
+void file_compress(file)
+ char *file;
+{
+ local char outfile[MAX_NAME_LEN];
+ FILE *in;
+ gzFile out;
+
+ strcpy(outfile, file);
+ strcat(outfile, GZ_SUFFIX);
+
+ in = fopen(file, "rb");
+ if (in == NULL) {
+ perror(file);
+ exit(1);
+ }
+ out = gzopen(outfile, "wb"); /* use "wb9" for maximal compression */
+ if (out == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
+ exit(1);
+ }
+ gz_compress(in, out);
+
+ unlink(file);
+}
+
+
+/* ===========================================================================
+ * Uncompress the given file and remove the original.
+ */
+void file_uncompress(file)
+ char *file;
+{
+ local char buf[MAX_NAME_LEN];
+ char *infile, *outfile;
+ FILE *out;
+ gzFile in;
+ int len = strlen(file);
+
+ strcpy(buf, file);
+
+ if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
+ infile = file;
+ outfile = buf;
+ outfile[len-3] = '\0';
+ } else {
+ outfile = file;
+ infile = buf;
+ strcat(infile, GZ_SUFFIX);
+ }
+ in = gzopen(infile, "rb");
+ if (in == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
+ exit(1);
+ }
+ out = fopen(outfile, "wb");
+ if (out == NULL) {
+ perror(file);
+ exit(1);
+ }
+
+ gz_uncompress(in, out);
+
+ unlink(infile);
+}
+
+
+/* ===========================================================================
+ * Usage: minigzip [-d] [files...]
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int uncompr = 0;
+ gzFile file;
+
+ prog = argv[0];
+ argc--, argv++;
+
+ if (argc > 0) {
+ uncompr = (strcmp(*argv, "-d") == 0);
+ if (uncompr) {
+ argc--, argv++;
+ }
+ }
+ if (argc == 0) {
+ SET_BINARY_MODE(stdin);
+ SET_BINARY_MODE(stdout);
+ if (uncompr) {
+ file = gzdopen(fileno(stdin), "rb");
+ if (file == NULL) error("can't gzdopen stdin");
+ gz_uncompress(file, stdout);
+ } else {
+ file = gzdopen(fileno(stdout), "wb"); /* "wb9" for max compr. */
+ if (file == NULL) error("can't gzdopen stdout");
+ gz_compress(stdin, file);
+ }
+ } else {
+ do {
+ if (uncompr) {
+ file_uncompress(*argv);
+ } else {
+ file_compress(*argv);
+ }
+ } while (argv++, --argc);
+ }
+ exit(0);
+ return 0; /* to avoid warning */
+}
diff --git a/lib/libz/trees.c b/lib/libz/trees.c
new file mode 100644
index 0000000..a5a8173
--- /dev/null
+++ b/lib/libz/trees.c
@@ -0,0 +1,1141 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-1996 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* $FreeBSD$ */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+# include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+local uch dist_code[512];
+/* distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+local uch length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+struct static_tree_desc_s {
+ ct_data *static_tree; /* static tree or NULL */
+ intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+local static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local static_tree_desc static_bl_desc =
+{(ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block OF((deflate_state *s));
+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen OF((deflate_state *s, tree_desc *desc));
+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree OF((deflate_state *s, tree_desc *desc));
+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local int build_bl_tree OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+ int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+ ct_data *dtree));
+local void set_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup OF((deflate_state *s));
+local void bi_flush OF((deflate_state *s));
+local void copy_block OF((deflate_state *s, charf *buf, unsigned len,
+ int header));
+
+#ifndef DEBUG
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+# define send_code(s, c, tree) \
+ { if (verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+#define d_code(dist) \
+ ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. dist_code[256] and dist_code[257] are never
+ * used.
+ */
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+ deflate_state *s;
+ int value; /* value to send */
+ int length; /* number of bits */
+{
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (value << s->bi_valid);
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = value;\
+ s->bi_buf |= (val << s->bi_valid);\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* DEBUG */
+
+
+#define MAX(a,b) (a >= b ? a : b)
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables. In a multi-threaded environment,
+ * this function may be called by two threads concurrently, but this is
+ * harmless since both invocations do exactly the same thing.
+ */
+local void tr_static_init()
+{
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+}
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(s)
+ deflate_state *s;
+{
+ tr_static_init();
+
+ s->compressed_len = 0L;
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+ deflate_state *s;
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+ deflate_state *s;
+ ct_data *tree; /* the tree to restore */
+ int k; /* node to move down */
+{
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ ct_data *stree = desc->stat_desc->static_tree;
+ intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (bits + xbits);
+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if (tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((long)bits - (long)tree[m].Len)
+ *(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+ ct_data *tree; /* the tree to decorate */
+ int max_code; /* largest code with non zero frequency */
+ ushf *bl_count; /* number of codes at each bit length */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+ deflate_state *s;
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+ deflate_state *s;
+ int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes-1, 5);
+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void _tr_stored_block(s, buf, stored_len, eof)
+ deflate_state *s;
+ charf *buf; /* input block */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+
+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void _tr_align(s)
+ deflate_state *s;
+{
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+ bi_flush(s);
+ /* Of the 10 bits for the empty block, we have already sent
+ * (10 - bi_valid) bits. The lookahead for the last real code (before
+ * the EOB of the previous block) was thus at least one plus the length
+ * of the EOB plus what we have just sent of the empty static block.
+ */
+ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+ s->compressed_len += 10L;
+ bi_flush(s);
+ }
+ s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file. This function
+ * returns the total compressed length for the file so far.
+ */
+ulg _tr_flush_block(s, buf, stored_len, eof)
+ deflate_state *s;
+ charf *buf; /* input block, or NULL if too old */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is ascii or binary */
+ if (s->data_type == Z_UNKNOWN) set_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute first the block length in bytes*/
+ opt_lenb = (s->opt_len+3+7)>>3;
+ static_lenb = (s->static_len+3+7)>>3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->last_lit));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+ /* If compression failed and this is the first and last block,
+ * and if the .zip file can be seeked (to rewrite the local header),
+ * the whole file is transformed into a stored file:
+ */
+#ifdef STORED_FILE_OK
+# ifdef FORCE_STORED_FILE
+ if (eof && s->compressed_len == 0L) { /* force stored file */
+# else
+ if (stored_len <= opt_lenb && eof && s->compressed_len==0L && seekable()) {
+# endif
+ /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
+ if (buf == (charf*)0) error ("block vanished");
+
+ copy_block(buf, (unsigned)stored_len, 0); /* without header */
+ s->compressed_len = stored_len << 3;
+ s->method = STORED;
+ } else
+#endif /* STORED_FILE_OK */
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+ } else if (static_lenb >= 0) { /* force static trees */
+#else
+ } else if (static_lenb == opt_lenb) {
+#endif
+ send_bits(s, (STATIC_TREES<<1)+eof, 3);
+ compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+ s->compressed_len += 3 + s->static_len;
+ } else {
+ send_bits(s, (DYN_TREES<<1)+eof, 3);
+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+ max_blindex+1);
+ compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+ s->compressed_len += 3 + s->opt_len;
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ init_block(s);
+
+ if (eof) {
+ bi_windup(s);
+ s->compressed_len += 7; /* align on byte boundary */
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ s->compressed_len-7*eof));
+
+ return s->compressed_len >> 3;
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int _tr_tally (s, dist, lc)
+ deflate_state *s;
+ unsigned dist; /* distance of matched string */
+ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ s->d_buf[s->last_lit] = (ush)dist;
+ s->l_buf[s->last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[length_code[lc]+LITERALS+1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+
+ /* Try to guess if it is profitable to stop the current block here */
+ if (s->level > 2 && (s->last_lit & 0xfff) == 0) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)s->last_lit*8L;
+ ulg in_length = (ulg)((long)s->strstart - s->block_start);
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)s->dyn_dtree[dcode].Freq *
+ (5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+ s->last_lit, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+ }
+ return (s->last_lit == s->lit_bufsize-1);
+ /* We avoid equality with lit_bufsize because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+ deflate_state *s;
+ ct_data *ltree; /* literal tree */
+ ct_data *dtree; /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->last_lit != 0) do {
+ dist = s->d_buf[lx];
+ lc = s->l_buf[lx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = length_code[lc];
+ send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+ Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow");
+
+ } while (lx < s->last_lit);
+
+ send_code(s, END_BLOCK, ltree);
+ s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to ASCII or BINARY, using a crude approximation:
+ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ * IN assertion: the fields freq of dyn_ltree are set and the total of all
+ * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ */
+local void set_data_type(s)
+ deflate_state *s;
+{
+ int n = 0;
+ unsigned ascii_freq = 0;
+ unsigned bin_freq = 0;
+ while (n < 7) bin_freq += s->dyn_ltree[n++].Freq;
+ while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq;
+ while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
+ s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII);
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+ unsigned code; /* the value to invert */
+ int len; /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+ deflate_state *s;
+{
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+ deflate_state *s;
+{
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef DEBUG
+ s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+ deflate_state *s;
+ charf *buf; /* the input data */
+ unsigned len; /* its length */
+ int header; /* true if block header must be written */
+{
+ bi_windup(s); /* align on byte boundary */
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+
+ if (header) {
+ put_short(s, (ush)len);
+ put_short(s, (ush)~len);
+#ifdef DEBUG
+ s->bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG
+ s->bits_sent += (ulg)len<<3;
+#endif
+ while (len--) {
+ put_byte(s, *buf++);
+ }
+}
diff --git a/lib/libz/uncompr.c b/lib/libz/uncompr.c
new file mode 100644
index 0000000..06cd6a8
--- /dev/null
+++ b/lib/libz/uncompr.c
@@ -0,0 +1,58 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $FreeBSD$ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int uncompress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ return err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd(&stream);
+ return err;
+}
diff --git a/lib/libz/zconf.h b/lib/libz/zconf.h
new file mode 100644
index 0000000..858e0a0
--- /dev/null
+++ b/lib/libz/zconf.h
@@ -0,0 +1,184 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $FreeBSD$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateReset z_inflateReset
+# define compress z_compress
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+# define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+# ifndef __32BIT__
+# define __32BIT__
+# endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)
+# define STDC
+#endif
+#if (defined(__STDC__) || defined(__cplusplus)) && !defined(STDC)
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ 1 << (windowBits+2) + 1 << (memLevel+9)
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR __far
+# else
+# define FAR far
+# endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+# ifndef __32BIT__
+# define SMALL_MEDIUM
+# define FAR __far
+# endif
+#endif
+#ifndef FAR
+# define FAR
+#endif
+
+typedef unsigned char Byte; /* 8 bits */
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#if defined(__BORLANDC__) && defined(SMALL_MEDIUM)
+ /* Borland C/C++ ignores FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if (defined(_WINDOWS) || defined(WINDOWS)) && defined(ZLIB_DLL)
+# include <windows.h>
+# define EXPORT WINAPI
+#else
+# define EXPORT
+#endif
+
+#endif /* _ZCONF_H */
diff --git a/lib/libz/zlib.h b/lib/libz/zlib.h
new file mode 100644
index 0000000..337fe9f
--- /dev/null
+++ b/lib/libz/zlib.h
@@ -0,0 +1,780 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.0.4, Jul 24th, 1996.
+
+ Copyright (C) 1995-1996 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ gzip@prep.ai.mit.edu madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "zconf.h"
+
+#define ZLIB_VERSION "1.0.4"
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms may be added later and will have the same
+ stream interface.
+
+ For compression the application must provide the output buffer and
+ may optionally provide the input buffer for optimization. For decompression,
+ the application must provide the input buffer and may optionally provide
+ the output buffer for optimization.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The library does not install any signal handler. It is recommended to
+ add at least a handler for SIGSEGV when decompressing; the library checks
+ the consistency of the input data whenever possible but may go nuts
+ for some forms of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: ascii or binary */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+extern const char * EXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+extern int EXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+extern int EXPORT deflate OF((z_streamp strm, int flush));
+/*
+ Performs one or both of the following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression
+ block is terminated and flushed to the output buffer so that the
+ decompressor can get all input data available so far. For method 9, a future
+ variant on method 8, the current block will be flushed but not terminated.
+ Z_SYNC_FLUSH has the same effect as partial flush except that the compressed
+ output is byte aligned (the compressor can clear its internal bit buffer)
+ and the current block is always terminated; this can be useful if the
+ compressor has to be restarted from scratch after an interruption (in which
+ case the internal state of the compressor may be lost).
+ If flush is set to Z_FULL_FLUSH, the compression block is terminated, a
+ special marker is output and the compression dictionary is discarded; this
+ is useful to allow the decompressor to synchronize if one compressed block
+ has been damaged (see inflateSync below). Flushing degrades compression and
+ so should be used only when necessary. Using Z_FULL_FLUSH too often can
+ seriously degrade the compression. If deflate returns with avail_out == 0,
+ this function must be called again with the same value of the flush
+ parameter and more output space (updated avail_out), until the flush is
+ complete (deflate returns with non-zero avail_out).
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() may update data_type if it can make a good guess about
+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible.
+*/
+
+
+extern int EXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+extern int EXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller. If
+ zalloc and zfree are set to Z_NULL, inflateInit updates them to use default
+ allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_VERSION_ERROR if the zlib library version is incompatible
+ with the version assumed by the caller. msg is set to null if there is no
+ error message. inflateInit does not perform any decompression: this will be
+ done by inflate().
+*/
+
+
+extern int EXPORT inflate OF((z_streamp strm, int flush));
+/*
+ Performs one or both of the following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ If the parameter flush is set to Z_PARTIAL_FLUSH, inflate flushes as much
+ output as possible to the output buffer. The flushing behavior of inflate is
+ not specified for values of the flush parameter other than Z_PARTIAL_FLUSH
+ and Z_FINISH, but the current implementation actually flushes as much output
+ as possible anyway.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster routine
+ may be used for the single inflate() call.
+
+ inflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if the end of the
+ compressed data has been reached and all uncompressed output has been
+ produced, Z_NEED_DICT if a preset dictionary is needed at this point (see
+ inflateSetDictionary below), Z_DATA_ERROR if the input data was corrupted,
+ Z_STREAM_ERROR if the stream structure was inconsistent (for example if
+ next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in
+ the output buffer when Z_FINISH is used. In the Z_DATA_ERROR case, the
+ application may then call inflateSync to look for a good compression block.
+ In the Z_NEED_DICT case, strm->adler is set to the Adler32 value of the
+ dictionary chosen by the compressor.
+*/
+
+
+extern int EXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+extern int EXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library. (Method 9 will allow a 64K history buffer and
+ partial block flushes.)
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library (the value 16 will be allowed for method 9). Larger
+ values of this parameter result in better compression at the expense of
+ memory usage. The default value is 15 if deflateInit is used instead.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match). Filtered data consists mostly of small values with a
+ somewhat random distribution. In this case, the compression algorithm is
+ tuned to compress them better. The effect of Z_FILTERED is to force more
+ Huffman coding and less string matching; it is somewhat intermediate
+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+ the compression ratio but not the correctness of the compressed output even
+ if it is not set appropriately.
+
+ If next_in is not null, the library will use this buffer to hold also
+ some history information; the buffer must either hold the entire input
+ data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in
+ is null, the library will allocate its own history buffer (and leave next_in
+ null). next_out need not be provided here but must be provided by the
+ application for the next call of deflate().
+
+ If the history buffer is provided by the application, next_in must
+ must never be changed by the application since the compressor maintains
+ information inside this buffer from call to call; the application
+ must provide more input only by increasing avail_in. next_in is always
+ reset by the library in this case.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
+ not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
+ an invalid method). msg is set to null if there is no error message.
+ deflateInit2 does not perform any compression: this will be done by
+ deflate().
+*/
+
+extern int EXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary (history buffer) from the given
+ byte sequence without producing any compressed output. This function must
+ be called immediately after deflateInit or deflateInit2, before any call
+ of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and
+ can be predicted with good accuracy; the data can then be compressed better
+ than with the default empty dictionary. In this version of the library,
+ only the last 32K bytes of the dictionary are used.
+ Upon return of this function, strm->adler is set to the Adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.)
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state
+ is inconsistent (for example if deflate has already been called for this
+ stream). deflateSetDictionary does not perform any compression: this will
+ be done by deflate().
+*/
+
+extern int EXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream. If
+ the source stream is using an application-supplied history buffer, a new
+ buffer is allocated for the destination stream. The compressed output
+ buffer is always application-supplied. It's the responsibility of the
+ application to provide the correct values of next_out and avail_out for the
+ next call of deflate.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+extern int EXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+extern int EXPORT deflateParams OF((z_streamp strm, int level, int strategy));
+/*
+ Dynamically update the compression level and compression strategy.
+ This can be used to switch between compression and straight copy of
+ the input data, or to switch to a different kind of input data requiring
+ a different strategy. If the compression level is changed, the input
+ available so far is compressed with the old level (and may be flushed);
+ the new level will take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+/*
+extern int EXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with more compression options. The
+ fields next_out, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library (the value 16 will be allowed soon). The
+ default value is 15 if inflateInit is used instead. If a compressed stream
+ with a larger window size is given as input, inflate() will return with
+ the error code Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ If next_out is not null, the library will use this buffer for the history
+ buffer; the buffer must either be large enough to hold the entire output
+ data, or have at least 1<<windowBits bytes. If next_out is null, the
+ library will allocate its own buffer (and leave next_out null). next_in
+ need not be provided here but must be provided by the application for the
+ next call of inflate().
+
+ If the history buffer is provided by the application, next_out must
+ never be changed by the application since the decompressor maintains
+ history information inside this buffer from call to call; the application
+ can only reset next_out to the beginning of the history buffer when
+ avail_out is zero and all output has been consumed.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
+ not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
+ windowBits < 8). msg is set to null if there is no error message.
+ inflateInit2 does not perform any decompression: this will be done by
+ inflate().
+*/
+
+extern int EXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary (history buffer) from the given
+ uncompressed byte sequence. This function must be called immediately after
+ a call of inflate if this call returned Z_NEED_DICT. The dictionary chosen
+ by the compressor can be determined from the Adler32 value returned by this
+ call of inflate. The compressor and decompressor must use exactly the same
+ dictionary (see deflateSetDictionary).
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+extern int EXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until the special marker (see deflate()
+ above) can be found, or until all available input is skipped. No output
+ is provided.
+
+ inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no marker has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+extern int EXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level, window size,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+extern int EXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least 0.1% larger than
+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+extern int EXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+typedef voidp gzFile;
+
+extern gzFile EXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9"). gzopen can be used to read a file which is not in gzip format;
+ in this case gzread will directly read from the file without decompression.
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR).
+*/
+
+extern gzFile EXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+extern int EXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+extern int EXPORT gzwrite OF((gzFile file, const voidp buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+extern int EXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+extern int EXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+extern const char * EXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+extern uLong EXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+extern uLong EXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running crc with the bytes buf[0..len-1] and return the updated
+ crc. If buf is NULL, this function returns the required initial value
+ for the crc. Pre- and post-conditioning (one's complement) is performed
+ within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+extern int EXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+extern int EXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+extern int EXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel, int strategy,
+ const char *version, int stream_size));
+extern int EXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+uLongf *get_crc_table OF((void)); /* can be used by asm versions of crc32() */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/lib/libz/zutil.c b/lib/libz/zutil.c
new file mode 100644
index 0000000..5858792
--- /dev/null
+++ b/lib/libz/zutil.c
@@ -0,0 +1,211 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $FreeBSD$ */
+
+#include <stdio.h>
+
+#include "zutil.h"
+
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+#ifndef STDC
+extern void exit OF((int));
+#endif
+
+const char *z_errmsg[10] = {
+"need dictionary", /* Z_NEED_DICT 2 */
+"stream end", /* Z_STREAM_END 1 */
+"", /* Z_OK 0 */
+"file error", /* Z_ERRNO (-1) */
+"stream error", /* Z_STREAM_ERROR (-2) */
+"data error", /* Z_DATA_ERROR (-3) */
+"insufficient memory", /* Z_MEM_ERROR (-4) */
+"buffer error", /* Z_BUF_ERROR (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char *zlibVersion()
+{
+ return ZLIB_VERSION;
+}
+
+#ifdef DEBUG
+void z_error (m)
+ char *m;
+{
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+ Bytef* dest;
+ Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+ Bytef* s1;
+ Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+#ifdef __TURBOC__
+#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
+/* Small and medium model in Turbo C are for now limited to near allocation
+ * with reduced MAX_WBITS and MAX_MEM_LEVEL
+ */
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+#endif
+#endif /* __TURBOC__ */
+
+
+#if defined(M_I86) && !defined(__32BIT__)
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER < 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* MSC */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+ voidpf opaque;
+ unsigned items;
+ unsigned size;
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return (voidpf)calloc(items, size);
+}
+
+void zcfree (opaque, ptr)
+ voidpf opaque;
+ voidpf ptr;
+{
+ free(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/lib/libz/zutil.h b/lib/libz/zutil.h
new file mode 100644
index 0000000..14b6f0a
--- /dev/null
+++ b/lib/libz/zutil.h
@@ -0,0 +1,203 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* $FreeBSD$ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#if defined(MSDOS)||defined(VMS)||defined(CRAY)||defined(WIN32)||defined(RISCOS)
+# include <stddef.h>
+# include <errno.h>
+#else
+ extern int errno;
+#endif
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#ifdef MSDOS
+# define OS_CODE 0x00
+# ifdef __TURBOC__
+# include <alloc.h>
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+#endif
+
+#ifdef WIN32 /* Window 95 & Windows NT */
+# define OS_CODE 0x0b
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define FOPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#ifdef MACOS
+# define OS_CODE 0x07
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0F
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+ /* Common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef FOPEN
+# define FOPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#ifdef HAVE_STRERROR
+ extern char *strerror OF((int));
+# define zstrerror(errnum) strerror(errnum)
+#else
+# define zstrerror(errnum) ""
+#endif
+
+#if defined(pyr)
+# define NO_MEMCPY
+#endif
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(_MSC_VER)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ extern void zmemcpy OF((Bytef* dest, Bytef* source, uInt len));
+ extern int zmemcmp OF((Bytef* s1, Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# include <stdio.h>
+# ifndef verbose
+# define verbose 0
+# endif
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) fprintf x
+# define Tracev(x) {if (verbose) fprintf x ;}
+# define Tracevv(x) {if (verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+typedef uLong (*check_func) OF((uLong check, const Bytef *buf, uInt len));
+
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void zcfree OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* _Z_UTIL_H */
diff --git a/lib/msun/Makefile b/lib/msun/Makefile
new file mode 100644
index 0000000..81576f7
--- /dev/null
+++ b/lib/msun/Makefile
@@ -0,0 +1,154 @@
+# @(#)Makefile 5.1beta 93/09/24
+# $Id: Makefile,v 1.18 1997/02/22 15:08:42 peter Exp $
+#
+# ====================================================
+# 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.
+# ====================================================
+#
+#
+
+#
+# There are two options in making libm at fdlibm compile time:
+# _IEEE_LIBM --- IEEE libm; smaller, and somewhat faster
+# _MULTI_LIBM --- Support multi-standard at runtime by
+# imposing wrapper functions defined in
+# fdlibm.h:
+# _IEEE_MODE -- IEEE
+# _XOPEN_MODE -- X/OPEN
+# _POSIX_MODE -- POSIX/ANSI
+# _SVID3_MODE -- SVID
+#
+# Here is how to set up CFLAGS to create the desired libm at
+# compile time:
+#
+# CFLAGS = -D_IEEE_LIBM ... IEEE libm (recommended)
+# CFLAGS = -D_SVID3_MODE ... Multi-standard supported
+# libm with SVID as the
+# default standard
+# CFLAGS = -D_XOPEN_MODE ... Multi-standard supported
+# libm with XOPEN as the
+# default standard
+# CFLAGS = -D_POSIX_MODE ... Multi-standard supported
+# libm with POSIX as the
+# default standard
+# CFLAGS = ... Multi-standard supported
+# libm with IEEE as the
+# default standard
+#
+
+ARCH= i387
+ARCH_PREFIX= ${ARCH}_
+ARCH_SRCS = e_acos.S e_asin.S e_atan2.S e_exp.S e_fmod.S e_log.S e_log10.S \
+ e_remainder.S e_scalb.S e_sqrt.S s_atan.S s_ceil.S s_copysign.S \
+ s_cos.S s_finite.S s_floor.S s_ilogb.S s_logb.S \
+ s_rint.S s_scalbn.S s_significand.S s_sin.S s_tan.S
+
+# Broken
+# ARCH_SRCS+= s_log1p.S
+
+.PATH: ${.CURDIR}/man
+.PATH: ${.CURDIR}/src
+
+CFLAGS+= -D_IEEE_LIBM -D_ARCH_INDIRECT=${ARCH_PREFIX}
+
+LIB= m
+COMMON_SRCS = e_acos.c e_acosf.c e_acosh.c e_acoshf.c e_asin.c e_asinf.c \
+ e_atan2.c e_atan2f.c e_atanh.c e_atanhf.c e_cosh.c e_coshf.c e_exp.c \
+ e_expf.c e_fmod.c e_fmodf.c e_gamma.c e_gamma_r.c e_gammaf.c \
+ e_gammaf_r.c e_hypot.c e_hypotf.c e_j0.c e_j0f.c e_j1.c e_j1f.c \
+ e_jn.c e_jnf.c e_lgamma.c e_lgamma_r.c e_lgammaf.c e_lgammaf_r.c \
+ e_log.c e_log10.c e_log10f.c e_logf.c e_pow.c e_powf.c e_rem_pio2.c \
+ e_rem_pio2f.c e_remainder.c e_remainderf.c e_scalb.c e_scalbf.c \
+ e_sinh.c e_sinhf.c e_sqrt.c e_sqrtf.c \
+ get_hw_float.c \
+ k_cos.c k_cosf.c k_rem_pio2.c k_rem_pio2f.c k_sin.c k_sinf.c \
+ k_standard.c k_tan.c k_tanf.c \
+ s_asinh.c s_asinhf.c s_atan.c s_atanf.c s_cbrt.c s_cbrtf.c s_ceil.c \
+ s_ceilf.c s_copysign.c s_copysignf.c s_cos.c s_cosf.c s_erf.c s_erff.c \
+ s_expm1.c s_expm1f.c s_fabsf.c s_finite.c s_finitef.c \
+ s_floor.c s_floorf.c s_frexpf.c s_ilogb.c s_ilogbf.c \
+ s_isnanf.c s_ldexpf.c s_lib_version.c s_log1p.c \
+ s_log1pf.c s_logb.c s_logbf.c s_matherr.c s_modff.c \
+ s_nextafter.c s_nextafterf.c s_rint.c s_rintf.c s_scalbn.c s_scalbnf.c \
+ s_signgam.c s_significand.c s_significandf.c s_sin.c s_sinf.c s_tan.c \
+ s_tanf.c s_tanh.c s_tanhf.c \
+ w_acos.c w_acosf.c w_acosh.c w_acoshf.c w_asin.c w_asinf.c w_atan2.c \
+ w_atan2f.c w_atanh.c w_atanhf.c w_cabs.c w_cabsf.c w_cosh.c w_coshf.c \
+ w_drem.c w_dremf.c w_exp.c w_expf.c w_fmod.c w_fmodf.c w_gamma.c \
+ w_gamma_r.c w_gammaf.c w_gammaf_r.c w_hypot.c w_hypotf.c w_j0.c \
+ w_j0f.c w_j1.c w_j1f.c w_jn.c w_jnf.c w_lgamma.c w_lgamma_r.c \
+ w_lgammaf.c w_lgammaf_r.c w_log.c w_log10.c w_log10f.c w_logf.c \
+ w_pow.c w_powf.c w_remainder.c w_remainderf.c w_scalb.c w_scalbf.c \
+ w_sinh.c w_sinhf.c w_sqrt.c w_sqrtf.c \
+ w_y0.c w_y0f.c w_y1.c w_y1f.c w_yn.c w_ynf.c
+
+# FreeBSD's C library supplies these functions:
+#COMMON_SRCS+= s_fabs.c s_frexp.c s_isnan.c s_ldexp.c s_modf.c
+
+CLEANFILES+= ${RENAMED_ARCH_SRCS}
+RENAMED_ARCH_SRCS= ${ARCH_SRCS:S/^/${ARCH_PREFIX}/g}
+SRCS= ${COMMON_SRCS} ${RENAMED_ARCH_SRCS}
+
+# Generate rules to rename arch-specific sources to avoid conflicts.
+# The path to the arch-specific sources is given explicitly instead of
+# with `.PATH: ${.CURDIR}/${ARCH}' since otherwise bsd.lib.mk would
+# use .S.o rules instead of .c.o rules for the conflicting prefixes
+# (except after `make depend' it uses the correct rules!).
+.for i in ${ARCH_SRCS}
+${ARCH_PREFIX}${i}: ${.CURDIR}/${ARCH}/${i}
+ cp ${.ALLSRC} ${.TARGET}
+.endfor
+
+MANSRC= ${.CURDIR}/man
+
+MAN3+= acos.3 acosh.3 asin.3 asinh.3 atan.3 atan2.3 atanh.3 ceil.3 \
+ cos.3 cosh.3 erf.3 exp.3 fabs.3 floor.3 fmod.3 hypot.3 ieee.3 \
+ ieee_test.3 j0.3 lgamma.3 math.3 rint.3 sin.3 sinh.3 sqrt.3 \
+ tan.3 tanh.3
+
+MLINKS+=acos.3 acosf.3
+MLINKS+=acosh.3 acoshf.3
+MLINKS+=asin.3 asinf.3
+MLINKS+=asinh.3 asinhf.3
+MLINKS+=atan.3 atanf.3
+MLINKS+=atanh.3 atanhf.3
+MLINKS+=atan2.3 atan2f.3
+MLINKS+=ceil.3 ceilf.3
+MLINKS+=cos.3 cosf.3
+MLINKS+=cosh.3 coshf.3
+MLINKS+=erf.3 erfc.3 erf.3 erff.3 erf.3 erfcf.3
+MLINKS+=exp.3 expm1.3 exp.3 log.3 exp.3 log10.3 exp.3 log1p.3 exp.3 pow.3 \
+ exp.3 expf.3 exp.3 exp2.3 exp.3 exp2f.3 exp.3 exp10.3 exp.3 exp10f.3 \
+ exp.3 expm1f.3 exp.3 logf.3 exp.3 log2.3 exp.3 log2f.3 exp.3 powf.3 \
+ exp.3 log10f.3 exp.3 log1pf.3
+MLINKS+=fabs.3 fabsf.3
+MLINKS+=floor.3 floorf.3
+MLINKS+=fmod.3 fmodf.3
+MLINKS+=hypot.3 cabs.3 hypot.3 cabsf.3 hypot.3 hypotf.3
+MLINKS+=ieee.3 copysign.3 ieee.3 copysignf.3 ieee.3 finite.3 ieee.3 finitef.3 \
+ ieee.3 ilogb.3 ieee.3 ilogbf.3 ieee.3 nextafter.3 ieee.3 nextafterf.3 \
+ ieee.3 remainder.3 ieee.3 remainderf.3 ieee.3 scalbn.3 ieee.3 scalbnf.3
+MLINKS+=ieee_test.3 logb.3 ieee_test.3 logbf.3
+MLINKS+=ieee_test.3 scalb.3 ieee_test.3 scalbf.3
+MLINKS+=ieee_test.3 significand.3 ieee_test.3 significandf.3
+MLINKS+=j0.3 j1.3 j0.3 jn.3 j0.3 y0.3 j0.3 y1.3 j0.3 y1f.3 j0.3 yn.3
+MLINKS+=j0.3 j0f.3 j0.3 j1f.3 j0.3 jnf.3 j0.3 y0f.3 j0.3 ynf.3
+MLINKS+=lgamma.3 gamma.3 lgamma.3 lgammaf.3 lgamma.3 gammaf.3
+MLINKS+=rint.3 rintf.3
+MLINKS+=sin.3 sinf.3
+MLINKS+=sinh.3 sinhf.3
+MLINKS+=sqrt.3 cbrt.3 sqrt.3 cbrtf.3 sqrt.3 sqrtf.3
+MLINKS+=tan.3 tanf.3
+MLINKS+=tanh.3 tanhf.3
+
+# XXX we should have only one math.h, and a rule for installing .h's...
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/src/math.h \
+ ${DESTDIR}/usr/include
+
+.include <bsd.lib.mk>
diff --git a/lib/msun/bsdsrc/b_exp.c b/lib/msun/bsdsrc/b_exp.c
new file mode 100644
index 0000000..fa6ea75
--- /dev/null
+++ b/lib/msun/bsdsrc/b_exp.c
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)exp.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/* EXP(X)
+ * RETURN THE EXPONENTIAL OF X
+ * DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS)
+ * CODED IN C BY K.C. NG, 1/19/85;
+ * REVISED BY K.C. NG on 2/6/85, 2/15/85, 3/7/85, 3/24/85, 4/16/85, 6/14/86.
+ *
+ * Required system supported functions:
+ * scalb(x,n)
+ * copysign(x,y)
+ * finite(x)
+ *
+ * Method:
+ * 1. Argument Reduction: given the input x, find r and integer k such
+ * that
+ * x = k*ln2 + r, |r| <= 0.5*ln2 .
+ * r will be represented as r := z+c for better accuracy.
+ *
+ * 2. Compute exp(r) by
+ *
+ * exp(r) = 1 + r + r*R1/(2-R1),
+ * where
+ * R1 = x - x^2*(p1+x^2*(p2+x^2*(p3+x^2*(p4+p5*x^2)))).
+ *
+ * 3. exp(x) = 2^k * exp(r) .
+ *
+ * Special cases:
+ * exp(INF) is INF, exp(NaN) is NaN;
+ * exp(-INF)= 0;
+ * for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ * exp(x) returns the exponential of x nearly rounded. In a test run
+ * with 1,156,000 random arguments on a VAX, the maximum observed
+ * error was 0.869 ulps (units in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following constants.
+ * The decimal values may be used, provided that the compiler will convert
+ * from decimal to binary accurately enough to produce the hexadecimal values
+ * shown.
+ */
+
+#include "mathimpl.h"
+
+vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000)
+vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC)
+vc(lnhuge, 9.4961163736712506989E1 ,ec1d,43bd,9010,a73e, 7, .BDEC1DA73E9010)
+vc(lntiny,-9.5654310917272452386E1 ,4f01,c3bf,33af,d72e, 7,-.BF4F01D72E33AF)
+vc(invln2, 1.4426950408889634148E0 ,aa3b,40b8,17f1,295c, 1, .B8AA3B295C17F1)
+vc(p1, 1.6666666666666602251E-1 ,aaaa,3f2a,a9f1,aaaa, -2, .AAAAAAAAAAA9F1)
+vc(p2, -2.7777777777015591216E-3 ,0b60,bc36,ec94,b5f5, -8,-.B60B60B5F5EC94)
+vc(p3, 6.6137563214379341918E-5 ,b355,398a,f15f,792e, -13, .8AB355792EF15F)
+vc(p4, -1.6533902205465250480E-6 ,ea0e,b6dd,5f84,2e93, -19,-.DDEA0E2E935F84)
+vc(p5, 4.1381367970572387085E-8 ,bb4b,3431,2683,95f5, -24, .B1BB4B95F52683)
+
+#ifdef vccast
+#define ln2hi vccast(ln2hi)
+#define ln2lo vccast(ln2lo)
+#define lnhuge vccast(lnhuge)
+#define lntiny vccast(lntiny)
+#define invln2 vccast(invln2)
+#define p1 vccast(p1)
+#define p2 vccast(p2)
+#define p3 vccast(p3)
+#define p4 vccast(p4)
+#define p5 vccast(p5)
+#endif
+
+ic(p1, 1.6666666666666601904E-1, -3, 1.555555555553E)
+ic(p2, -2.7777777777015593384E-3, -9, -1.6C16C16BEBD93)
+ic(p3, 6.6137563214379343612E-5, -14, 1.1566AAF25DE2C)
+ic(p4, -1.6533902205465251539E-6, -20, -1.BBD41C5D26BF1)
+ic(p5, 4.1381367970572384604E-8, -25, 1.6376972BEA4D0)
+ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000)
+ic(ln2lo, 1.9082149292705877000E-10,-33, 1.A39EF35793C76)
+ic(lnhuge, 7.1602103751842355450E2, 9, 1.6602B15B7ECF2)
+ic(lntiny,-7.5137154372698068983E2, 9, -1.77AF8EBEAE354)
+ic(invln2, 1.4426950408889633870E0, 0, 1.71547652B82FE)
+
+double exp(x)
+double x;
+{
+ double z,hi,lo,c;
+ int k;
+
+#if !defined(vax)&&!defined(tahoe)
+ if(x!=x) return(x); /* x is NaN */
+#endif /* !defined(vax)&&!defined(tahoe) */
+ if( x <= lnhuge ) {
+ if( x >= lntiny ) {
+
+ /* argument reduction : x --> x - k*ln2 */
+
+ k=invln2*x+copysign(0.5,x); /* k=NINT(x/ln2) */
+
+ /* express x-k*ln2 as hi-lo and let x=hi-lo rounded */
+
+ hi=x-k*ln2hi;
+ x=hi-(lo=k*ln2lo);
+
+ /* return 2^k*[1+x+x*c/(2+c)] */
+ z=x*x;
+ c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5))));
+ return scalb(1.0+(hi-(lo-(x*c)/(2.0-c))),k);
+
+ }
+ /* end of x > lntiny */
+
+ else
+ /* exp(-big#) underflows to zero */
+ if(finite(x)) return(scalb(1.0,-5000));
+
+ /* exp(-INF) is zero */
+ else return(0.0);
+ }
+ /* end of x < lnhuge */
+
+ else
+ /* exp(INF) is INF, exp(+big#) overflows to INF */
+ return( finite(x) ? scalb(1.0,5000) : x);
+}
+
+/* returns exp(r = x + c) for |c| < |x| with no overlap. */
+
+double __exp__D(x, c)
+double x, c;
+{
+ double z,hi,lo, t;
+ int k;
+
+#if !defined(vax)&&!defined(tahoe)
+ if (x!=x) return(x); /* x is NaN */
+#endif /* !defined(vax)&&!defined(tahoe) */
+ if ( x <= lnhuge ) {
+ if ( x >= lntiny ) {
+
+ /* argument reduction : x --> x - k*ln2 */
+ z = invln2*x;
+ k = z + copysign(.5, x);
+
+ /* express (x+c)-k*ln2 as hi-lo and let x=hi-lo rounded */
+
+ hi=(x-k*ln2hi); /* Exact. */
+ x= hi - (lo = k*ln2lo-c);
+ /* return 2^k*[1+x+x*c/(2+c)] */
+ z=x*x;
+ c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5))));
+ c = (x*c)/(2.0-c);
+
+ return scalb(1.+(hi-(lo - c)), k);
+ }
+ /* end of x > lntiny */
+
+ else
+ /* exp(-big#) underflows to zero */
+ if(finite(x)) return(scalb(1.0,-5000));
+
+ /* exp(-INF) is zero */
+ else return(0.0);
+ }
+ /* end of x < lnhuge */
+
+ else
+ /* exp(INF) is INF, exp(+big#) overflows to INF */
+ return( finite(x) ? scalb(1.0,5000) : x);
+}
diff --git a/lib/msun/bsdsrc/b_log.c b/lib/msun/bsdsrc/b_log.c
new file mode 100644
index 0000000..908b8544
--- /dev/null
+++ b/lib/msun/bsdsrc/b_log.c
@@ -0,0 +1,486 @@
+/*
+ * 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.
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)log.c 8.2 (Berkeley) 11/30/93";
+#endif /* not lint */
+
+#include <math.h>
+#include <errno.h>
+
+#include "mathimpl.h"
+
+/* Table-driven natural logarithm.
+ *
+ * This code was derived, with minor modifications, from:
+ * Peter Tang, "Table-Driven Implementation of the
+ * Logarithm in IEEE Floating-Point arithmetic." ACM Trans.
+ * Math Software, vol 16. no 4, pp 378-400, Dec 1990).
+ *
+ * Calculates log(2^m*F*(1+f/F)), |f/j| <= 1/256,
+ * where F = j/128 for j an integer in [0, 128].
+ *
+ * log(2^m) = log2_hi*m + log2_tail*m
+ * since m is an integer, the dominant term is exact.
+ * m has at most 10 digits (for subnormal numbers),
+ * and log2_hi has 11 trailing zero bits.
+ *
+ * log(F) = logF_hi[j] + logF_lo[j] is in tabular form in log_table.h
+ * logF_hi[] + 512 is exact.
+ *
+ * log(1+f/F) = 2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ...
+ * the leading term is calculated to extra precision in two
+ * parts, the larger of which adds exactly to the dominant
+ * m and F terms.
+ * There are two cases:
+ * 1. when m, j are non-zero (m | j), use absolute
+ * precision for the leading term.
+ * 2. when m = j = 0, |1-x| < 1/256, and log(x) ~= (x-1).
+ * In this case, use a relative precision of 24 bits.
+ * (This is done differently in the original paper)
+ *
+ * Special cases:
+ * 0 return signalling -Inf
+ * neg return signalling NaN
+ * +Inf return +Inf
+*/
+
+#if defined(vax) || defined(tahoe)
+#define _IEEE 0
+#define TRUNC(x) x = (double) (float) (x)
+#else
+#define _IEEE 1
+#define endian (((*(int *) &one)) ? 1 : 0)
+#define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000
+#define infnan(x) 0.0
+#endif
+
+#define N 128
+
+/* Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128.
+ * Used for generation of extend precision logarithms.
+ * The constant 35184372088832 is 2^45, so the divide is exact.
+ * It ensures correct reading of logF_head, even for inaccurate
+ * decimal-to-binary conversion routines. (Everybody gets the
+ * right answer for integers less than 2^53.)
+ * Values for log(F) were generated using error < 10^-57 absolute
+ * with the bc -l package.
+*/
+static double A1 = .08333333333333178827;
+static double A2 = .01250000000377174923;
+static double A3 = .002232139987919447809;
+static double A4 = .0004348877777076145742;
+
+static double logF_head[N+1] = {
+ 0.,
+ .007782140442060381246,
+ .015504186535963526694,
+ .023167059281547608406,
+ .030771658666765233647,
+ .038318864302141264488,
+ .045809536031242714670,
+ .053244514518837604555,
+ .060624621816486978786,
+ .067950661908525944454,
+ .075223421237524235039,
+ .082443669210988446138,
+ .089612158689760690322,
+ .096729626458454731618,
+ .103796793681567578460,
+ .110814366340264314203,
+ .117783035656430001836,
+ .124703478501032805070,
+ .131576357788617315236,
+ .138402322859292326029,
+ .145182009844575077295,
+ .151916042025732167530,
+ .158605030176659056451,
+ .165249572895390883786,
+ .171850256926518341060,
+ .178407657472689606947,
+ .184922338493834104156,
+ .191394852999565046047,
+ .197825743329758552135,
+ .204215541428766300668,
+ .210564769107350002741,
+ .216873938300523150246,
+ .223143551314024080056,
+ .229374101064877322642,
+ .235566071312860003672,
+ .241719936886966024758,
+ .247836163904594286577,
+ .253915209980732470285,
+ .259957524436686071567,
+ .265963548496984003577,
+ .271933715484010463114,
+ .277868451003087102435,
+ .283768173130738432519,
+ .289633292582948342896,
+ .295464212893421063199,
+ .301261330578199704177,
+ .307025035294827830512,
+ .312755710004239517729,
+ .318453731118097493890,
+ .324119468654316733591,
+ .329753286372579168528,
+ .335355541920762334484,
+ .340926586970454081892,
+ .346466767346100823488,
+ .351976423156884266063,
+ .357455888922231679316,
+ .362905493689140712376,
+ .368325561158599157352,
+ .373716409793814818840,
+ .379078352934811846353,
+ .384411698910298582632,
+ .389716751140440464951,
+ .394993808240542421117,
+ .400243164127459749579,
+ .405465108107819105498,
+ .410659924985338875558,
+ .415827895143593195825,
+ .420969294644237379543,
+ .426084395310681429691,
+ .431173464818130014464,
+ .436236766774527495726,
+ .441274560805140936281,
+ .446287102628048160113,
+ .451274644139630254358,
+ .456237433481874177232,
+ .461175715122408291790,
+ .466089729924533457960,
+ .470979715219073113985,
+ .475845904869856894947,
+ .480688529345570714212,
+ .485507815781602403149,
+ .490303988045525329653,
+ .495077266798034543171,
+ .499827869556611403822,
+ .504556010751912253908,
+ .509261901790523552335,
+ .513945751101346104405,
+ .518607764208354637958,
+ .523248143765158602036,
+ .527867089620485785417,
+ .532464798869114019908,
+ .537041465897345915436,
+ .541597282432121573947,
+ .546132437597407260909,
+ .550647117952394182793,
+ .555141507540611200965,
+ .559615787935399566777,
+ .564070138285387656651,
+ .568504735352689749561,
+ .572919753562018740922,
+ .577315365035246941260,
+ .581691739635061821900,
+ .586049045003164792433,
+ .590387446602107957005,
+ .594707107746216934174,
+ .599008189645246602594,
+ .603290851438941899687,
+ .607555250224322662688,
+ .611801541106615331955,
+ .616029877215623855590,
+ .620240409751204424537,
+ .624433288012369303032,
+ .628608659422752680256,
+ .632766669570628437213,
+ .636907462236194987781,
+ .641031179420679109171,
+ .645137961373620782978,
+ .649227946625615004450,
+ .653301272011958644725,
+ .657358072709030238911,
+ .661398482245203922502,
+ .665422632544505177065,
+ .669430653942981734871,
+ .673422675212350441142,
+ .677398823590920073911,
+ .681359224807238206267,
+ .685304003098281100392,
+ .689233281238557538017,
+ .693147180560117703862
+};
+
+static double logF_tail[N+1] = {
+ 0.,
+ -.00000000000000543229938420049,
+ .00000000000000172745674997061,
+ -.00000000000001323017818229233,
+ -.00000000000001154527628289872,
+ -.00000000000000466529469958300,
+ .00000000000005148849572685810,
+ -.00000000000002532168943117445,
+ -.00000000000005213620639136504,
+ -.00000000000001819506003016881,
+ .00000000000006329065958724544,
+ .00000000000008614512936087814,
+ -.00000000000007355770219435028,
+ .00000000000009638067658552277,
+ .00000000000007598636597194141,
+ .00000000000002579999128306990,
+ -.00000000000004654729747598444,
+ -.00000000000007556920687451336,
+ .00000000000010195735223708472,
+ -.00000000000017319034406422306,
+ -.00000000000007718001336828098,
+ .00000000000010980754099855238,
+ -.00000000000002047235780046195,
+ -.00000000000008372091099235912,
+ .00000000000014088127937111135,
+ .00000000000012869017157588257,
+ .00000000000017788850778198106,
+ .00000000000006440856150696891,
+ .00000000000016132822667240822,
+ -.00000000000007540916511956188,
+ -.00000000000000036507188831790,
+ .00000000000009120937249914984,
+ .00000000000018567570959796010,
+ -.00000000000003149265065191483,
+ -.00000000000009309459495196889,
+ .00000000000017914338601329117,
+ -.00000000000001302979717330866,
+ .00000000000023097385217586939,
+ .00000000000023999540484211737,
+ .00000000000015393776174455408,
+ -.00000000000036870428315837678,
+ .00000000000036920375082080089,
+ -.00000000000009383417223663699,
+ .00000000000009433398189512690,
+ .00000000000041481318704258568,
+ -.00000000000003792316480209314,
+ .00000000000008403156304792424,
+ -.00000000000034262934348285429,
+ .00000000000043712191957429145,
+ -.00000000000010475750058776541,
+ -.00000000000011118671389559323,
+ .00000000000037549577257259853,
+ .00000000000013912841212197565,
+ .00000000000010775743037572640,
+ .00000000000029391859187648000,
+ -.00000000000042790509060060774,
+ .00000000000022774076114039555,
+ .00000000000010849569622967912,
+ -.00000000000023073801945705758,
+ .00000000000015761203773969435,
+ .00000000000003345710269544082,
+ -.00000000000041525158063436123,
+ .00000000000032655698896907146,
+ -.00000000000044704265010452446,
+ .00000000000034527647952039772,
+ -.00000000000007048962392109746,
+ .00000000000011776978751369214,
+ -.00000000000010774341461609578,
+ .00000000000021863343293215910,
+ .00000000000024132639491333131,
+ .00000000000039057462209830700,
+ -.00000000000026570679203560751,
+ .00000000000037135141919592021,
+ -.00000000000017166921336082431,
+ -.00000000000028658285157914353,
+ -.00000000000023812542263446809,
+ .00000000000006576659768580062,
+ -.00000000000028210143846181267,
+ .00000000000010701931762114254,
+ .00000000000018119346366441110,
+ .00000000000009840465278232627,
+ -.00000000000033149150282752542,
+ -.00000000000018302857356041668,
+ -.00000000000016207400156744949,
+ .00000000000048303314949553201,
+ -.00000000000071560553172382115,
+ .00000000000088821239518571855,
+ -.00000000000030900580513238244,
+ -.00000000000061076551972851496,
+ .00000000000035659969663347830,
+ .00000000000035782396591276383,
+ -.00000000000046226087001544578,
+ .00000000000062279762917225156,
+ .00000000000072838947272065741,
+ .00000000000026809646615211673,
+ -.00000000000010960825046059278,
+ .00000000000002311949383800537,
+ -.00000000000058469058005299247,
+ -.00000000000002103748251144494,
+ -.00000000000023323182945587408,
+ -.00000000000042333694288141916,
+ -.00000000000043933937969737844,
+ .00000000000041341647073835565,
+ .00000000000006841763641591466,
+ .00000000000047585534004430641,
+ .00000000000083679678674757695,
+ -.00000000000085763734646658640,
+ .00000000000021913281229340092,
+ -.00000000000062242842536431148,
+ -.00000000000010983594325438430,
+ .00000000000065310431377633651,
+ -.00000000000047580199021710769,
+ -.00000000000037854251265457040,
+ .00000000000040939233218678664,
+ .00000000000087424383914858291,
+ .00000000000025218188456842882,
+ -.00000000000003608131360422557,
+ -.00000000000050518555924280902,
+ .00000000000078699403323355317,
+ -.00000000000067020876961949060,
+ .00000000000016108575753932458,
+ .00000000000058527188436251509,
+ -.00000000000035246757297904791,
+ -.00000000000018372084495629058,
+ .00000000000088606689813494916,
+ .00000000000066486268071468700,
+ .00000000000063831615170646519,
+ .00000000000025144230728376072,
+ -.00000000000017239444525614834
+};
+
+double
+#ifdef _ANSI_SOURCE
+log(double x)
+#else
+log(x) double x;
+#endif
+{
+ int m, j;
+ double F, f, g, q, u, u2, v, zero = 0.0, one = 1.0;
+ volatile double u1;
+
+ /* Catch special cases */
+ if (x <= 0)
+ if (_IEEE && x == zero) /* log(0) = -Inf */
+ return (-one/zero);
+ else if (_IEEE) /* log(neg) = NaN */
+ return (zero/zero);
+ else if (x == zero) /* NOT REACHED IF _IEEE */
+ return (infnan(-ERANGE));
+ else
+ return (infnan(EDOM));
+ else if (!finite(x))
+ if (_IEEE) /* x = NaN, Inf */
+ return (x+x);
+ else
+ return (infnan(ERANGE));
+
+ /* Argument reduction: 1 <= g < 2; x/2^m = g; */
+ /* y = F*(1 + f/F) for |f| <= 2^-8 */
+
+ m = logb(x);
+ g = ldexp(x, -m);
+ if (_IEEE && m == -1022) {
+ j = logb(g), m += j;
+ g = ldexp(g, -j);
+ }
+ j = N*(g-1) + .5;
+ F = (1.0/N) * j + 1; /* F*128 is an integer in [128, 512] */
+ f = g - F;
+
+ /* Approximate expansion for log(1+f/F) ~= u + q */
+ g = 1/(2*F+f);
+ u = 2*f*g;
+ v = u*u;
+ q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
+
+ /* case 1: u1 = u rounded to 2^-43 absolute. Since u < 2^-8,
+ * u1 has at most 35 bits, and F*u1 is exact, as F has < 8 bits.
+ * It also adds exactly to |m*log2_hi + log_F_head[j] | < 750
+ */
+ if (m | j)
+ u1 = u + 513, u1 -= 513;
+
+ /* case 2: |1-x| < 1/256. The m- and j- dependent terms are zero;
+ * u1 = u to 24 bits.
+ */
+ else
+ u1 = u, TRUNC(u1);
+ u2 = (2.0*(f - F*u1) - u1*f) * g;
+ /* u1 + u2 = 2f/(2F+f) to extra precision. */
+
+ /* log(x) = log(2^m*F*(1+f/F)) = */
+ /* (m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q); */
+ /* (exact) + (tiny) */
+
+ u1 += m*logF_head[N] + logF_head[j]; /* exact */
+ u2 = (u2 + logF_tail[j]) + q; /* tiny */
+ u2 += logF_tail[N]*m;
+ return (u1 + u2);
+}
+
+/*
+ * Extra precision variant, returning struct {double a, b;};
+ * log(x) = a+b to 63 bits, with a is rounded to 26 bits.
+ */
+struct Double
+#ifdef _ANSI_SOURCE
+__log__D(double x)
+#else
+__log__D(x) double x;
+#endif
+{
+ int m, j;
+ double F, f, g, q, u, v, u2, one = 1.0;
+ volatile double u1;
+ struct Double r;
+
+ /* Argument reduction: 1 <= g < 2; x/2^m = g; */
+ /* y = F*(1 + f/F) for |f| <= 2^-8 */
+
+ m = logb(x);
+ g = ldexp(x, -m);
+ if (_IEEE && m == -1022) {
+ j = logb(g), m += j;
+ g = ldexp(g, -j);
+ }
+ j = N*(g-1) + .5;
+ F = (1.0/N) * j + 1;
+ f = g - F;
+
+ g = 1/(2*F+f);
+ u = 2*f*g;
+ v = u*u;
+ q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
+ if (m | j)
+ u1 = u + 513, u1 -= 513;
+ else
+ u1 = u, TRUNC(u1);
+ u2 = (2.0*(f - F*u1) - u1*f) * g;
+
+ u1 += m*logF_head[N] + logF_head[j];
+
+ u2 += logF_tail[j]; u2 += q;
+ u2 += logF_tail[N]*m;
+ r.a = u1 + u2; /* Only difference is here */
+ TRUNC(r.a);
+ r.b = (u1 - r.a) + u2;
+ return (r);
+}
diff --git a/lib/msun/bsdsrc/b_tgamma.c b/lib/msun/bsdsrc/b_tgamma.c
new file mode 100644
index 0000000..5d270f0
--- /dev/null
+++ b/lib/msun/bsdsrc/b_tgamma.c
@@ -0,0 +1,336 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)gamma.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/*
+ * This code by P. McIlroy, Oct 1992;
+ *
+ * The financial support of UUNET Communications Services is greatfully
+ * acknowledged.
+ */
+
+#include <math.h>
+#include "mathimpl.h"
+#include <errno.h>
+
+/* METHOD:
+ * x < 0: Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x))
+ * At negative integers, return +Inf, and set errno.
+ *
+ * x < 6.5:
+ * Use argument reduction G(x+1) = xG(x) to reach the
+ * range [1.066124,2.066124]. Use a rational
+ * approximation centered at the minimum (x0+1) to
+ * ensure monotonicity.
+ *
+ * x >= 6.5: Use the asymptotic approximation (Stirling's formula)
+ * adjusted for equal-ripples:
+ *
+ * log(G(x)) ~= (x-.5)*(log(x)-1) + .5(log(2*pi)-1) + 1/x*P(1/(x*x))
+ *
+ * Keep extra precision in multiplying (x-.5)(log(x)-1), to
+ * avoid premature round-off.
+ *
+ * Special values:
+ * non-positive integer: Set overflow trap; return +Inf;
+ * x > 171.63: Set overflow trap; return +Inf;
+ * NaN: Set invalid trap; return NaN
+ *
+ * Accuracy: Gamma(x) is accurate to within
+ * x > 0: error provably < 0.9ulp.
+ * Maximum observed in 1,000,000 trials was .87ulp.
+ * x < 0:
+ * Maximum observed error < 4ulp in 1,000,000 trials.
+ */
+
+static double neg_gam __P((double));
+static double small_gam __P((double));
+static double smaller_gam __P((double));
+static struct Double large_gam __P((double));
+static struct Double ratfun_gam __P((double, double));
+
+/*
+ * Rational approximation, A0 + x*x*P(x)/Q(x), on the interval
+ * [1.066.., 2.066..] accurate to 4.25e-19.
+ */
+#define LEFT -.3955078125 /* left boundary for rat. approx */
+#define x0 .461632144968362356785 /* xmin - 1 */
+
+#define a0_hi 0.88560319441088874992
+#define a0_lo -.00000000000000004996427036469019695
+#define P0 6.21389571821820863029017800727e-01
+#define P1 2.65757198651533466104979197553e-01
+#define P2 5.53859446429917461063308081748e-03
+#define P3 1.38456698304096573887145282811e-03
+#define P4 2.40659950032711365819348969808e-03
+#define Q0 1.45019531250000000000000000000e+00
+#define Q1 1.06258521948016171343454061571e+00
+#define Q2 -2.07474561943859936441469926649e-01
+#define Q3 -1.46734131782005422506287573015e-01
+#define Q4 3.07878176156175520361557573779e-02
+#define Q5 5.12449347980666221336054633184e-03
+#define Q6 -1.76012741431666995019222898833e-03
+#define Q7 9.35021023573788935372153030556e-05
+#define Q8 6.13275507472443958924745652239e-06
+/*
+ * Constants for large x approximation (x in [6, Inf])
+ * (Accurate to 2.8*10^-19 absolute)
+ */
+#define lns2pi_hi 0.418945312500000
+#define lns2pi_lo -.000006779295327258219670263595
+#define Pa0 8.33333333333333148296162562474e-02
+#define Pa1 -2.77777777774548123579378966497e-03
+#define Pa2 7.93650778754435631476282786423e-04
+#define Pa3 -5.95235082566672847950717262222e-04
+#define Pa4 8.41428560346653702135821806252e-04
+#define Pa5 -1.89773526463879200348872089421e-03
+#define Pa6 5.69394463439411649408050664078e-03
+#define Pa7 -1.44705562421428915453880392761e-02
+
+static const double zero = 0., one = 1.0, tiny = 1e-300;
+static int endian;
+/*
+ * TRUNC sets trailing bits in a floating-point number to zero.
+ * is a temporary variable.
+ */
+#if defined(vax) || defined(tahoe)
+#define _IEEE 0
+#define TRUNC(x) x = (double) (float) (x)
+#else
+#define _IEEE 1
+#define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000
+#define infnan(x) 0.0
+#endif
+
+double
+gamma(x)
+ double x;
+{
+ struct Double u;
+ endian = (*(int *) &one) ? 1 : 0;
+
+ if (x >= 6) {
+ if(x > 171.63)
+ return(one/zero);
+ u = large_gam(x);
+ return(__exp__D(u.a, u.b));
+ } else if (x >= 1.0 + LEFT + x0)
+ return (small_gam(x));
+ else if (x > 1.e-17)
+ return (smaller_gam(x));
+ else if (x > -1.e-17) {
+ if (x == 0.0)
+ if (!_IEEE) return (infnan(ERANGE));
+ else return (one/x);
+ one+1e-20; /* Raise inexact flag. */
+ return (one/x);
+ } else if (!finite(x)) {
+ if (_IEEE) /* x = NaN, -Inf */
+ return (x*x);
+ else
+ return (infnan(EDOM));
+ } else
+ return (neg_gam(x));
+}
+/*
+ * Accurate to max(ulp(1/128) absolute, 2^-66 relative) error.
+ */
+static struct Double
+large_gam(x)
+ double x;
+{
+ double z, p;
+ int i;
+ struct Double t, u, v;
+
+ z = one/(x*x);
+ p = Pa0+z*(Pa1+z*(Pa2+z*(Pa3+z*(Pa4+z*(Pa5+z*(Pa6+z*Pa7))))));
+ p = p/x;
+
+ u = __log__D(x);
+ u.a -= one;
+ v.a = (x -= .5);
+ TRUNC(v.a);
+ v.b = x - v.a;
+ t.a = v.a*u.a; /* t = (x-.5)*(log(x)-1) */
+ t.b = v.b*u.a + x*u.b;
+ /* return t.a + t.b + lns2pi_hi + lns2pi_lo + p */
+ t.b += lns2pi_lo; t.b += p;
+ u.a = lns2pi_hi + t.b; u.a += t.a;
+ u.b = t.a - u.a;
+ u.b += lns2pi_hi; u.b += t.b;
+ return (u);
+}
+/*
+ * Good to < 1 ulp. (provably .90 ulp; .87 ulp on 1,000,000 runs.)
+ * It also has correct monotonicity.
+ */
+static double
+small_gam(x)
+ double x;
+{
+ double y, ym1, t, x1;
+ struct Double yy, r;
+ y = x - one;
+ ym1 = y - one;
+ if (y <= 1.0 + (LEFT + x0)) {
+ yy = ratfun_gam(y - x0, 0);
+ return (yy.a + yy.b);
+ }
+ r.a = y;
+ TRUNC(r.a);
+ yy.a = r.a - one;
+ y = ym1;
+ yy.b = r.b = y - yy.a;
+ /* Argument reduction: G(x+1) = x*G(x) */
+ for (ym1 = y-one; ym1 > LEFT + x0; y = ym1--, yy.a--) {
+ t = r.a*yy.a;
+ r.b = r.a*yy.b + y*r.b;
+ r.a = t;
+ TRUNC(r.a);
+ r.b += (t - r.a);
+ }
+ /* Return r*gamma(y). */
+ yy = ratfun_gam(y - x0, 0);
+ y = r.b*(yy.a + yy.b) + r.a*yy.b;
+ y += yy.a*r.a;
+ return (y);
+}
+/*
+ * Good on (0, 1+x0+LEFT]. Accurate to 1ulp.
+ */
+static double
+smaller_gam(x)
+ double x;
+{
+ double t, d;
+ struct Double r, xx;
+ if (x < x0 + LEFT) {
+ t = x, TRUNC(t);
+ d = (t+x)*(x-t);
+ t *= t;
+ xx.a = (t + x), TRUNC(xx.a);
+ xx.b = x - xx.a; xx.b += t; xx.b += d;
+ t = (one-x0); t += x;
+ d = (one-x0); d -= t; d += x;
+ x = xx.a + xx.b;
+ } else {
+ xx.a = x, TRUNC(xx.a);
+ xx.b = x - xx.a;
+ t = x - x0;
+ d = (-x0 -t); d += x;
+ }
+ r = ratfun_gam(t, d);
+ d = r.a/x, TRUNC(d);
+ r.a -= d*xx.a; r.a -= d*xx.b; r.a += r.b;
+ return (d + r.a/x);
+}
+/*
+ * returns (z+c)^2 * P(z)/Q(z) + a0
+ */
+static struct Double
+ratfun_gam(z, c)
+ double z, c;
+{
+ int i;
+ double p, q;
+ struct Double r, t;
+
+ q = Q0 +z*(Q1+z*(Q2+z*(Q3+z*(Q4+z*(Q5+z*(Q6+z*(Q7+z*Q8)))))));
+ p = P0 + z*(P1 + z*(P2 + z*(P3 + z*P4)));
+
+ /* return r.a + r.b = a0 + (z+c)^2*p/q, with r.a truncated to 26 bits. */
+ p = p/q;
+ t.a = z, TRUNC(t.a); /* t ~= z + c */
+ t.b = (z - t.a) + c;
+ t.b *= (t.a + z);
+ q = (t.a *= t.a); /* t = (z+c)^2 */
+ TRUNC(t.a);
+ t.b += (q - t.a);
+ r.a = p, TRUNC(r.a); /* r = P/Q */
+ r.b = p - r.a;
+ t.b = t.b*p + t.a*r.b + a0_lo;
+ t.a *= r.a; /* t = (z+c)^2*(P/Q) */
+ r.a = t.a + a0_hi, TRUNC(r.a);
+ r.b = ((a0_hi-r.a) + t.a) + t.b;
+ return (r); /* r = a0 + t */
+}
+
+static double
+neg_gam(x)
+ double x;
+{
+ int sgn = 1;
+ struct Double lg, lsine;
+ double y, z;
+
+ y = floor(x + .5);
+ if (y == x) /* Negative integer. */
+ if(!_IEEE)
+ return (infnan(ERANGE));
+ else
+ return (one/zero);
+ z = fabs(x - y);
+ y = .5*ceil(x);
+ if (y == ceil(y))
+ sgn = -1;
+ if (z < .25)
+ z = sin(M_PI*z);
+ else
+ z = cos(M_PI*(0.5-z));
+ /* Special case: G(1-x) = Inf; G(x) may be nonzero. */
+ if (x < -170) {
+ if (x < -190)
+ return ((double)sgn*tiny*tiny);
+ y = one - x; /* exact: 128 < |x| < 255 */
+ lg = large_gam(y);
+ lsine = __log__D(M_PI/z); /* = TRUNC(log(u)) + small */
+ lg.a -= lsine.a; /* exact (opposite signs) */
+ lg.b -= lsine.b;
+ y = -(lg.a + lg.b);
+ z = (y + lg.a) + lg.b;
+ y = __exp__D(y, z);
+ if (sgn < 0) y = -y;
+ return (y);
+ }
+ y = one-x;
+ if (one-y == x)
+ y = gamma(y);
+ else /* 1-x is inexact */
+ y = -x*gamma(-x);
+ if (sgn < 0) y = -y;
+ return (M_PI / (y*z));
+}
diff --git a/lib/msun/bsdsrc/mathimpl.h b/lib/msun/bsdsrc/mathimpl.h
new file mode 100644
index 0000000..6a2a37d
--- /dev/null
+++ b/lib/msun/bsdsrc/mathimpl.h
@@ -0,0 +1,98 @@
+/*
+ * 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. 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.
+ *
+ * @(#)mathimpl.h 8.1 (Berkeley) 6/4/93
+ */
+
+#include <sys/cdefs.h>
+#include <math.h>
+
+#if defined(vax)||defined(tahoe)
+
+/* Deal with different ways to concatenate in cpp */
+# ifdef __STDC__
+# define cat3(a,b,c) a ## b ## c
+# else
+# define cat3(a,b,c) a/**/b/**/c
+# endif
+
+/* Deal with vax/tahoe byte order issues */
+# ifdef vax
+# define cat3t(a,b,c) cat3(a,b,c)
+# else
+# define cat3t(a,b,c) cat3(a,c,b)
+# endif
+
+# define vccast(name) (*(const double *)(cat3(name,,x)))
+
+ /*
+ * Define a constant to high precision on a Vax or Tahoe.
+ *
+ * Args are the name to define, the decimal floating point value,
+ * four 16-bit chunks of the float value in hex
+ * (because the vax and tahoe differ in float format!), the power
+ * of 2 of the hex-float exponent, and the hex-float mantissa.
+ * Most of these arguments are not used at compile time; they are
+ * used in a post-check to make sure the constants were compiled
+ * correctly.
+ *
+ * People who want to use the constant will have to do their own
+ * #define foo vccast(foo)
+ * since CPP cannot do this for them from inside another macro (sigh).
+ * We define "vccast" if this needs doing.
+ */
+# define vc(name, value, x1,x2,x3,x4, bexp, xval) \
+ const static long cat3(name,,x)[] = {cat3t(0x,x1,x2), cat3t(0x,x3,x4)};
+
+# define ic(name, value, bexp, xval) ;
+
+#else /* vax or tahoe */
+
+ /* Hooray, we have an IEEE machine */
+# undef vccast
+# define vc(name, value, x1,x2,x3,x4, bexp, xval) ;
+
+# define ic(name, value, bexp, xval) \
+ const static double name = value;
+
+#endif /* defined(vax)||defined(tahoe) */
+
+
+/*
+ * Functions internal to the math package, yet not static.
+ */
+extern double __exp__E();
+extern double __log__L();
+
+struct Double {double a, b;};
+double __exp__D __P((double, double));
+struct Double __log__D __P((double));
diff --git a/lib/msun/i387/e_acos.S b/lib/msun/i387/e_acos.S
new file mode 100644
index 0000000..9c0b286
--- /dev/null
+++ b/lib/msun/i387/e_acos.S
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: e_acos.S,v 1.5 1997/02/22 15:08:43 peter Exp $")
+
+/*
+ * acos(x) = atan2(sqrt(1 - x^2, x).
+ * Actually evaluate (1 - x^2) as (1 - x) * (1 + x) to avoid loss of
+ * precision when |x| is nearly 1.
+ */
+ENTRY(__ieee754_acos)
+ fldl 4(%esp) /* x */
+ fld1
+ fld %st(0)
+ fsub %st(2) /* 1 - x */
+ fxch %st(1)
+ fadd %st(2) /* 1 + x */
+ fmulp %st(1) /* (1 - x) * (1 + x) */
+ fsqrt
+ fxch %st(1)
+ fpatan
+ ret
diff --git a/lib/msun/i387/e_asin.S b/lib/msun/i387/e_asin.S
new file mode 100644
index 0000000..3c22226
--- /dev/null
+++ b/lib/msun/i387/e_asin.S
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: e_asin.S,v 1.5 1997/02/22 15:08:44 peter Exp $")
+
+/*
+ * asin(x) = atan2(x, sqrt(1 - x^2).
+ * Actually evaluate (1 - x^2) as (1 - x) * (1 + x) to avoid loss of
+ * precision when |x| is nearly 1.
+ */
+ENTRY(__ieee754_asin)
+ fldl 4(%esp) /* x */
+ fld1
+ fld %st(0)
+ fsub %st(2) /* 1 - x */
+ fxch %st(1)
+ fadd %st(2) /* 1 + x */
+ fmulp %st(1) /* (1 - x) * (1 + x) */
+ fsqrt
+ fpatan
+ ret
diff --git a/lib/msun/i387/e_atan2.S b/lib/msun/i387/e_atan2.S
new file mode 100644
index 0000000..1e20fd5
--- /dev/null
+++ b/lib/msun/i387/e_atan2.S
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: e_atan2.S,v 1.4 1997/02/22 15:08:45 peter Exp $")
+
+ENTRY(__ieee754_atan2)
+ fldl 4(%esp)
+ fldl 12(%esp)
+ fpatan
+ ret
diff --git a/lib/msun/i387/e_exp.S b/lib/msun/i387/e_exp.S
new file mode 100644
index 0000000..6145ffe
--- /dev/null
+++ b/lib/msun/i387/e_exp.S
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: e_exp.S,v 1.6 1997/02/22 15:08:46 peter Exp $")
+
+/* e^x = 2^(x * log2(e)) */
+ENTRY(__ieee754_exp)
+ /*
+ * If x is +-Inf, then the subtraction would give Inf-Inf = NaN.
+ * Avoid this. Also avoid it if x is NaN for convenience.
+ */
+ movl 8(%esp),%eax
+ andl $0x7fffffff,%eax
+ cmpl $0x7ff00000,%eax
+ jae x_Inf_or_NaN
+
+ fldl 4(%esp)
+
+ /*
+ * Ensure that the rounding mode is to nearest (to give the smallest
+ * possible fraction) and that the precision is as high as possible.
+ * We may as well mask interrupts if we switch the mode.
+ */
+ fstcw 4(%esp)
+ movl 4(%esp),%eax
+ andl $0x0300,%eax
+ cmpl $0x0300,%eax /* RC == 0 && PC == 3? */
+ je 1f /* jump if mode is good */
+ movl $0x137f,8(%esp)
+ fldcw 8(%esp)
+1:
+ fldl2e
+ fmulp /* x * log2(e) */
+ fstl %st(1)
+ frndint /* int(x * log2(e)) */
+ fstl %st(2)
+ fsubrp /* fract(x * log2(e)) */
+ f2xm1 /* 2^(fract(x * log2(e))) - 1 */
+ fld1
+ faddp /* 2^(fract(x * log2(e))) */
+ fscale /* e^x */
+ fstpl %st(1)
+ je 1f
+ fldcw 4(%esp)
+1:
+ ret
+
+x_Inf_or_NaN:
+ /*
+ * Return 0 if x is -Inf. Otherwise just return x, although the
+ * C version would return (x + x) (Real Indefinite) if x is a NaN.
+ */
+ cmpl $0xfff00000,8(%esp)
+ jne x_not_minus_Inf
+ cmpl $0,4(%esp)
+ jne x_not_minus_Inf
+ fldz
+ ret
+
+x_not_minus_Inf:
+ fldl 4(%esp)
+ ret
diff --git a/lib/msun/i387/e_fmod.S b/lib/msun/i387/e_fmod.S
new file mode 100644
index 0000000..6ecc716
--- /dev/null
+++ b/lib/msun/i387/e_fmod.S
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: e_fmod.S,v 1.4 1997/02/22 15:08:47 peter Exp $")
+
+ENTRY(__ieee754_fmod)
+ fldl 12(%esp)
+ fldl 4(%esp)
+1: fprem
+ fstsw %ax
+ sahf
+ jp 1b
+ fstpl %st(1)
+ ret
diff --git a/lib/msun/i387/e_log.S b/lib/msun/i387/e_log.S
new file mode 100644
index 0000000..d1415d3
--- /dev/null
+++ b/lib/msun/i387/e_log.S
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: e_log.S,v 1.4 1997/02/22 15:08:48 peter Exp $")
+
+ENTRY(__ieee754_log)
+ fldln2
+ fldl 4(%esp)
+ fyl2x
+ ret
diff --git a/lib/msun/i387/e_log10.S b/lib/msun/i387/e_log10.S
new file mode 100644
index 0000000..808af7b
--- /dev/null
+++ b/lib/msun/i387/e_log10.S
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: e_log10.S,v 1.4 1997/02/22 15:08:49 peter Exp $")
+
+ENTRY(__ieee754_log10)
+ fldlg2
+ fldl 4(%esp)
+ fyl2x
+ ret
diff --git a/lib/msun/i387/e_remainder.S b/lib/msun/i387/e_remainder.S
new file mode 100644
index 0000000..39289bc
--- /dev/null
+++ b/lib/msun/i387/e_remainder.S
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: e_remainder.S,v 1.4 1997/02/22 15:08:50 peter Exp $")
+
+ENTRY(__ieee754_remainder)
+ fldl 12(%esp)
+ fldl 4(%esp)
+1: fprem1
+ fstsw %ax
+ sahf
+ jp 1b
+ fstpl %st(1)
+ ret
diff --git a/lib/msun/i387/e_scalb.S b/lib/msun/i387/e_scalb.S
new file mode 100644
index 0000000..8b77980
--- /dev/null
+++ b/lib/msun/i387/e_scalb.S
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: e_scalb.S,v 1.5 1997/02/22 15:08:51 peter Exp $")
+
+ENTRY(__ieee754_scalb)
+ fldl 12(%esp)
+ fldl 4(%esp)
+ fscale
+ fstp %st(1)
+ ret
diff --git a/lib/msun/i387/e_sqrt.S b/lib/msun/i387/e_sqrt.S
new file mode 100644
index 0000000..b6ab4c9
--- /dev/null
+++ b/lib/msun/i387/e_sqrt.S
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: e_sqrt.S,v 1.4 1997/02/22 15:08:52 peter Exp $")
+
+ENTRY(__ieee754_sqrt)
+ fldl 4(%esp)
+ fsqrt
+ ret
diff --git a/lib/msun/i387/s_atan.S b/lib/msun/i387/s_atan.S
new file mode 100644
index 0000000..3625ece
--- /dev/null
+++ b/lib/msun/i387/s_atan.S
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_atan.S,v 1.4 1997/02/22 15:08:53 peter Exp $")
+
+ENTRY(atan)
+ fldl 4(%esp)
+ fld1
+ fpatan
+ ret
diff --git a/lib/msun/i387/s_ceil.S b/lib/msun/i387/s_ceil.S
new file mode 100644
index 0000000..b97345a
--- /dev/null
+++ b/lib/msun/i387/s_ceil.S
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_ceil.S,v 1.5 1997/02/22 15:08:54 peter Exp $")
+
+ENTRY(ceil)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $8,%esp
+
+ fstcw -4(%ebp) /* store fpu control word */
+ movw -4(%ebp),%dx
+ orw $0x0800,%dx /* round towards +oo */
+ andw $0xfbff,%dx
+ movw %dx,-8(%ebp)
+ fldcw -8(%ebp) /* load modfied control word */
+
+ fldl 8(%ebp); /* round */
+ frndint
+
+ fldcw -4(%ebp) /* restore original control word */
+
+ leave
+ ret
diff --git a/lib/msun/i387/s_copysign.S b/lib/msun/i387/s_copysign.S
new file mode 100644
index 0000000..eccdbb8
--- /dev/null
+++ b/lib/msun/i387/s_copysign.S
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_copysign.S,v 1.4 1997/02/22 15:08:55 peter Exp $")
+
+ENTRY(copysign)
+ movl 16(%esp),%edx
+ andl $0x80000000,%edx
+ movl 8(%esp),%eax
+ andl $0x7fffffff,%eax
+ orl %edx,%eax
+ movl %eax,8(%esp)
+ fldl 4(%esp)
+ ret
diff --git a/lib/msun/i387/s_cos.S b/lib/msun/i387/s_cos.S
new file mode 100644
index 0000000..9e4f139
--- /dev/null
+++ b/lib/msun/i387/s_cos.S
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_cos.S,v 1.4 1997/02/22 15:08:55 peter Exp $")
+
+ENTRY(cos)
+ fldl 4(%esp)
+ fcos
+ fnstsw %ax
+ andw $0x400,%ax
+ jnz 1f
+ ret
+1: fldpi
+ fadd %st(0)
+ fxch %st(1)
+2: fprem1
+ fnstsw %ax
+ andw $0x400,%ax
+ jnz 2b
+ fstp %st(1)
+ fcos
+ ret
diff --git a/lib/msun/i387/s_finite.S b/lib/msun/i387/s_finite.S
new file mode 100644
index 0000000..4f6db83
--- /dev/null
+++ b/lib/msun/i387/s_finite.S
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_finite.S,v 1.5 1997/03/09 14:00:50 bde Exp $")
+
+ENTRY(finite)
+ movl 8(%esp),%eax
+ andl $0x7ff00000, %eax
+ cmpl $0x7ff00000, %eax
+ setneb %al
+ andl $0x000000ff, %eax
+ ret
diff --git a/lib/msun/i387/s_floor.S b/lib/msun/i387/s_floor.S
new file mode 100644
index 0000000..13e79c0
--- /dev/null
+++ b/lib/msun/i387/s_floor.S
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_floor.S,v 1.5 1997/02/22 15:08:57 peter Exp $")
+
+ENTRY(floor)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $8,%esp
+
+ fstcw -4(%ebp) /* store fpu control word */
+ movw -4(%ebp),%dx
+ orw $0x0400,%dx /* round towards -oo */
+ andw $0xf7ff,%dx
+ movw %dx,-8(%ebp)
+ fldcw -8(%ebp) /* load modfied control word */
+
+ fldl 8(%ebp); /* round */
+ frndint
+
+ fldcw -4(%ebp) /* restore original control word */
+
+ leave
+ ret
diff --git a/lib/msun/i387/s_ilogb.S b/lib/msun/i387/s_ilogb.S
new file mode 100644
index 0000000..640bd28
--- /dev/null
+++ b/lib/msun/i387/s_ilogb.S
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_ilogb.S,v 1.5 1997/02/22 15:08:59 peter Exp $")
+
+ENTRY(ilogb)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $4,%esp
+
+ fldl 8(%ebp)
+ fxtract
+ fstpl %st
+
+ fistpl -4(%ebp)
+ movl -4(%ebp),%eax
+
+ leave
+ ret
diff --git a/lib/msun/i387/s_log1p.S b/lib/msun/i387/s_log1p.S
new file mode 100644
index 0000000..07f3c64
--- /dev/null
+++ b/lib/msun/i387/s_log1p.S
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_log1p.S,v 1.5 1997/02/22 15:08:59 peter Exp $")
+
+/*
+ * The fyl2xp1 instruction has such a limited range:
+ * -(1 - (sqrt(2) / 2)) <= x <= sqrt(2) - 1
+ * it's not worth trying to use it.
+ *
+ * Also, I'm not sure fyl2xp1's extra precision will
+ * matter once the result is converted from extended
+ * real (80 bits) back to double real (64 bits).
+ */
+ENTRY(log1p)
+ fldln2
+ fldl 4(%esp)
+ fld1
+ faddp
+ fyl2x
+ ret
diff --git a/lib/msun/i387/s_logb.S b/lib/msun/i387/s_logb.S
new file mode 100644
index 0000000..dedb853
--- /dev/null
+++ b/lib/msun/i387/s_logb.S
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_logb.S,v 1.4 1997/02/22 15:09:00 peter Exp $")
+
+ENTRY(logb)
+ fldl 4(%esp)
+ fxtract
+ fstpl %st
+ ret
diff --git a/lib/msun/i387/s_rint.S b/lib/msun/i387/s_rint.S
new file mode 100644
index 0000000..91a1ee0
--- /dev/null
+++ b/lib/msun/i387/s_rint.S
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_rint.S,v 1.4 1997/02/22 15:09:01 peter Exp $")
+
+ENTRY(rint)
+ fldl 4(%esp)
+ frndint
+ ret
diff --git a/lib/msun/i387/s_scalbn.S b/lib/msun/i387/s_scalbn.S
new file mode 100644
index 0000000..2678c39
--- /dev/null
+++ b/lib/msun/i387/s_scalbn.S
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_scalbn.S,v 1.5 1997/02/22 15:09:02 peter Exp $")
+
+ENTRY(scalbn)
+ fildl 12(%esp)
+ fldl 4(%esp)
+ fscale
+ fstp %st(1)
+ ret
diff --git a/lib/msun/i387/s_significand.S b/lib/msun/i387/s_significand.S
new file mode 100644
index 0000000..63ddd6b
--- /dev/null
+++ b/lib/msun/i387/s_significand.S
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_significand.S,v 1.4 1997/02/22 15:09:03 peter Exp $")
+
+ENTRY(significand)
+ fldl 4(%esp)
+ fxtract
+ fstpl %st(1)
+ ret
diff --git a/lib/msun/i387/s_sin.S b/lib/msun/i387/s_sin.S
new file mode 100644
index 0000000..9691edb
--- /dev/null
+++ b/lib/msun/i387/s_sin.S
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_sin.S,v 1.4 1997/02/22 15:09:05 peter Exp $")
+
+ENTRY(sin)
+ fldl 4(%esp)
+ fsin
+ fnstsw %ax
+ andw $0x400,%ax
+ jnz 1f
+ ret
+1: fldpi
+ fadd %st(0)
+ fxch %st(1)
+2: fprem1
+ fnstsw %ax
+ andw $0x400,%ax
+ jnz 2b
+ fstp %st(1)
+ fsin
+ ret
diff --git a/lib/msun/i387/s_tan.S b/lib/msun/i387/s_tan.S
new file mode 100644
index 0000000..4bf1985
--- /dev/null
+++ b/lib/msun/i387/s_tan.S
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+/*
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$Id: s_tan.S,v 1.4 1997/02/22 15:09:06 peter Exp $")
+
+ENTRY(tan)
+ fldl 4(%esp)
+ fptan
+ fnstsw %ax
+ andw $0x400,%ax
+ jnz 1f
+ fstp %st(0)
+ ret
+1: fldpi
+ fadd %st(0)
+ fxch %st(1)
+2: fprem1
+ fstsw %ax
+ andw $0x400,%ax
+ jnz 2b
+ fstp %st(1)
+ fptan
+ fstp %st(0)
+ ret
diff --git a/lib/msun/man/acos.3 b/lib/msun/man/acos.3
new file mode 100644
index 0000000..1af095e
--- /dev/null
+++ b/lib/msun/man/acos.3
@@ -0,0 +1,96 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)acos.3 5.1 (Berkeley) 5/2/91
+.\" $Id$
+.\"
+.Dd May 2, 1991
+.Dt ACOS 3
+.Os
+.Sh NAME
+.Nm acos ,
+.Nm acosf
+.Nd arc cosine functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn acos "double x"
+.Ft float
+.Fn acosf "float x"
+.Sh DESCRIPTION
+The
+.Fn acos
+and the
+.Fn acosf
+functions compute the principal value of the arc cosine of
+.Fa x .
+A domain error occurs for arguments not in the range [-1, +1].
+For a discussion of error due to roundoff, see
+.Xr math 3 .
+.Sh RETURN VALUES
+The
+.Fn acos
+and the
+.Fn acosf
+functions return the arc cosine in the range
+.Bq 0 , \*(Pi
+radians.
+On the
+.Tn VAX
+and
+.Tn Tahoe ,
+if:
+.Bd -unfilled -offset indent
+.Pf \&| Ns Ar x Ns \&| > 1 ,
+.Ed
+.Pp
+.Fn acos x
+sets the global variable
+.Va errno
+to
+.Dv EDOM
+and a reserved operand fault is generated.
+.Sh SEE ALSO
+.Xr asin 3 ,
+.Xr atan 3 ,
+.Xr atan2 3 ,
+.Xr cos 3 ,
+.Xr cosh 3 ,
+.Xr math 3 ,
+.Xr sin 3 ,
+.Xr sinh 3 ,
+.Xr tan 3 ,
+.Xr tanh 3
+.Sh STANDARDS
+The
+.Fn acos
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/man/acosh.3 b/lib/msun/man/acosh.3
new file mode 100644
index 0000000..9ac3247
--- /dev/null
+++ b/lib/msun/man/acosh.3
@@ -0,0 +1,88 @@
+.\" Copyright (c) 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.
+.\" 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: @(#)acosh.3 5.2 (Berkeley) 5/6/91
+.\" $Id$
+.\"
+.Dd May 6, 1991
+.Dt ACOSH 3
+.Os BSD 4.3
+.Sh NAME
+.Nm acosh ,
+.Nm acoshf
+.Nd inverse hyperbolic cosine functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn acosh "double x"
+.Ft float
+.Fn acoshf "float x"
+.Sh DESCRIPTION
+The
+.Fn acosh
+and the
+.Fn acoshf
+functions compute the inverse hyperbolic cosine
+of the real
+argument
+.Ar x .
+For a discussion of error due to roundoff, see
+.Xr math 3 .
+.Sh RETURN VALUES
+The
+.Fn acosh
+and the
+.Fn acoshf
+functions
+return the inverse hyperbolic cosine of
+.Ar x .
+On the
+.Tn VAX
+and
+.Tn Tahoe ,
+if the argument is less than one
+.Fn acosh
+sets the global variable
+.Va errno
+to
+.Er EDOM
+and
+causes a reserved operand fault.
+.Sh SEE ALSO
+.Xr asinh 3 ,
+.Xr atanh 3 ,
+.Xr exp 3 ,
+.Xr math 3
+.Sh HISTORY
+The
+.Fn acosh
+function appeared in
+.Bx 4.3 .
diff --git a/lib/msun/man/asin.3 b/lib/msun/man/asin.3
new file mode 100644
index 0000000..eeb4f7c
--- /dev/null
+++ b/lib/msun/man/asin.3
@@ -0,0 +1,98 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)asin.3 5.1 (Berkeley) 5/2/91
+.\" $Id$
+.\"
+.Dd May 2, 1991
+.Dt ASIN 3
+.Os
+.Sh NAME
+.Nm asin ,
+.Nm asinf
+.Nd arc sine functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn asin "double x"
+.Ft float
+.Fn asinf "float x"
+.Sh DESCRIPTION
+The
+.Fn asin
+and the
+.Fn asinf
+functions compute the principal value of the arc sine of
+.Fa x .
+A domain error occurs for arguments not in the range [-1, +1].
+For a discussion of error due to roundoff, see
+.Xr math 3 .
+.Sh RETURN VALUES
+The
+.Fn asin
+and the
+.Fn asinf
+functions return the arc sine in the range
+.Bk -words
+.Bq -\*(Pi/2, +\*(Pi/2
+.Ek
+radians.
+On the
+.Tn VAX ,
+and Tahoe ,
+if:
+.Bd -unfilled -offset indent
+.Pf \&| Ns Ar x Ns \&| > 1
+.Ed
+.Pp
+the
+global variable
+.Va errno
+is set to
+.Er EDOM
+and
+a reserved operand fault generated.
+.Sh SEE ALSO
+.Xr acos 3 ,
+.Xr atan 3 ,
+.Xr atan2 3 ,
+.Xr cos 3 ,
+.Xr cosh 3 ,
+.Xr math 3 ,
+.Xr sin 3 ,
+.Xr sinh 3 ,
+.Xr tan 3 ,
+.Xr tanh 3
+.Sh STANDARDS
+The
+.Fn asin
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/man/asinh.3 b/lib/msun/man/asinh.3
new file mode 100644
index 0000000..d122497
--- /dev/null
+++ b/lib/msun/man/asinh.3
@@ -0,0 +1,76 @@
+.\" Copyright (c) 1985, 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.
+.\" 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: @(#)asinh.3 6.4 (Berkeley) 5/6/91
+.\" $Id$
+.\"
+.Dd May 6, 1991
+.Dt ASINH 3
+.Os BSD 4.3
+.Sh NAME
+.Nm asinh ,
+.Nm asinhf
+.Nd inverse hyperbolic sine functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn asinh "double x"
+.Ft float
+.Fn asinhf "float x"
+.Sh DESCRIPTION
+The
+.Fn asinh
+and the
+.Fn asinhf
+functions compute the inverse hyperbolic sine
+of the real
+argument
+.Ar x .
+For a discussion of error due to roundoff, see
+.Xr math 3 .
+.Sh RETURN VALUES
+The
+.Fn asinh
+and the
+.Fn asinhf
+functions
+return the inverse hyperbolic sine of
+.Ar x .
+.Sh SEE ALSO
+.Xr acosh 3 ,
+.Xr atanh 3 ,
+.Xr exp 3 ,
+.Xr math 3
+.Sh HISTORY
+The
+.Fn asinh
+function appeared in
+.Bx 4.3 .
diff --git a/lib/msun/man/atan.3 b/lib/msun/man/atan.3
new file mode 100644
index 0000000..b68bf34
--- /dev/null
+++ b/lib/msun/man/atan.3
@@ -0,0 +1,82 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)atan.3 5.1 (Berkeley) 5/2/91
+.\" $Id$
+.\"
+.Dd May 2, 1991
+.Dt ATAN 3
+.Os
+.Sh NAME
+.Nm atan ,
+.Nm atanf
+.Nd arc tangent functions of one variable
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn atan "double x"
+.Ft float
+.Fn atanf "float x"
+.Sh DESCRIPTION
+The
+.Fn atan
+and the
+.Fn atanf
+functions compute the principal value of the arc tangent of
+.Fa x .
+For a discussion of error due to roundoff, see
+.Xr math 3 .
+.Sh RETURN VALUES
+The
+.Fn atan
+and the
+.Fn atanf
+function returns the arc tangent in the range
+.Bk -words
+.Bq -\*(Pi/2 , +\*(Pi/2
+.Ek
+radians.
+.Sh SEE ALSO
+.Xr acos 3 ,
+.Xr asin 3 ,
+.Xr atan2 3 ,
+.Xr cos 3 ,
+.Xr cosh 3 ,
+.Xr math 3 ,
+.Xr sin 3 ,
+.Xr sinh 3 ,
+.Xr tan 3 ,
+.Xr tanh 3
+.Sh STANDARDS
+The
+.Fn atan
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/man/atan2.3 b/lib/msun/man/atan2.3
new file mode 100644
index 0000000..75e556c
--- /dev/null
+++ b/lib/msun/man/atan2.3
@@ -0,0 +1,196 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)atan2.3 5.1 (Berkeley) 5/2/91
+.\" $Id$
+.\"
+.Dd May 2, 1991
+.Dt ATAN2 3
+.Os
+.Sh NAME
+.Nm atan2 ,
+.Nm atan2f
+.Nd arc tangent functions of two variables
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn atan2 "double y" "double x"
+.Ft float
+.Fn atan2f "float y" "float x"
+.Sh DESCRIPTION
+The
+.Fn atan2
+and the
+.Fn atan2f
+functions compute the principal value of the arc tangent of
+.Fa y/ Ns Ar x ,
+using the signs of both arguments to determine the quadrant of
+the return value.
+.Sh RETURN VALUES
+The
+.Fn atan2
+and the
+.Fn atan2f
+functions, if successful,
+return the arc tangent of
+.Fa y/ Ns Ar x
+in the range
+.Bk -words
+.Bq \&- Ns \*(Pi , \&+ Ns \*(Pi
+.Ek
+radians.
+If both
+.Fa x
+and
+.Fa y
+are zero, the global variable
+.Va errno
+is set to
+.Er EDOM .
+On the
+.Tn VAX :
+.Bl -column atan_(y,x)_:=____ sign(y)_(Pi_atan2(Xy_xX))___
+.It Fn atan2 y x No := Ta
+.Fn atan y/x Ta
+if
+.Ar x
+> 0,
+.It Ta sign( Ns Ar y Ns )*(\*(Pi -
+.Fn atan "\\*(Bay/x\\*(Ba" ) Ta
+if
+.Ar x
+< 0,
+.It Ta
+.No 0 Ta
+if x = y = 0, or
+.It Ta
+.Pf sign( Ar y Ns )*\\*(Pi/2 Ta
+if
+.Ar x
+= 0 \*(!=
+.Ar y .
+.El
+.Sh NOTES
+The function
+.Fn atan2
+defines "if x > 0,"
+.Fn atan2 0 0
+= 0 on a
+.Tn VAX
+despite that previously
+.Fn atan2 0 0
+may have generated an error message.
+The reasons for assigning a value to
+.Fn atan2 0 0
+are these:
+.Bl -enum -offset indent
+.It
+Programs that test arguments to avoid computing
+.Fn atan2 0 0
+must be indifferent to its value.
+Programs that require it to be invalid are vulnerable
+to diverse reactions to that invalidity on diverse computer systems.
+.It
+The
+.Fn atan2
+function is used mostly to convert from rectangular (x,y)
+to polar
+.if n\
+(r,theta)
+.if t\
+(r,\(*h)
+coordinates that must satisfy x =
+.if n\
+r\(**cos theta
+.if t\
+r\(**cos\(*h
+and y =
+.if n\
+r\(**sin theta.
+.if t\
+r\(**sin\(*h.
+These equations are satisfied when (x=0,y=0)
+is mapped to
+.if n \
+(r=0,theta=0)
+.if t \
+(r=0,\(*h=0)
+on a VAX. In general, conversions to polar coordinates
+should be computed thus:
+.Bd -unfilled -offset indent
+.if n \{\
+r := hypot(x,y); ... := sqrt(x\(**x+y\(**y)
+theta := atan2(y,x).
+.\}
+.if t \{\
+r := hypot(x,y); ... := \(sr(x\u\s82\s10\d+y\u\s82\s10\d)
+\(*h := atan2(y,x).
+.\}
+.Ed
+.It
+The foregoing formulas need not be altered to cope in a
+reasonable way with signed zeros and infinities
+on a machine that conforms to
+.Tn IEEE 754 ;
+the versions of
+.Xr hypot 3
+and
+.Fn atan2
+provided for
+such a machine are designed to handle all cases.
+That is why
+.Fn atan2 \(+-0 \-0
+= \(+-\*(Pi
+for instance.
+In general the formulas above are equivalent to these:
+.Bd -unfilled -offset indent
+.if n \
+r := sqrt(x\(**x+y\(**y); if r = 0 then x := copysign(1,x);
+.if t \
+r := \(sr(x\(**x+y\(**y);\0\0if r = 0 then x := copysign(1,x);
+.Ed
+.El
+.Sh SEE ALSO
+.Xr acos 3 ,
+.Xr asin 3 ,
+.Xr atan 3 ,
+.Xr cos 3 ,
+.Xr cosh 3 ,
+.Xr math 3 ,
+.Xr sin 3 ,
+.Xr sinh 3 ,
+.Xr tan 3 ,
+.Xr tanh 3
+.Sh STANDARDS
+The
+.Fn atan2
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/man/atanh.3 b/lib/msun/man/atanh.3
new file mode 100644
index 0000000..9c8acf3
--- /dev/null
+++ b/lib/msun/man/atanh.3
@@ -0,0 +1,90 @@
+.\" Copyright (c) 1985, 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.
+.\" 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: @(#)atanh.3 5.2 (Berkeley) 5/6/91
+.\" $Id$
+.\"
+.Dd May 6, 1991
+.Dt ATANH 3
+.Os BSD 4.3
+.Sh NAME
+.Nm atanh ,
+.Nm atanhf
+.Nd inverse hyperbolic tangent functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn atanh "double x"
+.Ft float
+.Fn atanhf "float x"
+.Sh DESCRIPTION
+The
+.Fn atanh
+and the
+.Fn atanhf
+functions compute the inverse hyperbolic tangent
+of the real
+argument
+.Ar x .
+For a discussion of error due to roundoff, see
+.Xr math 3 .
+.Sh RETURN VALUES
+The
+.Fn atanh
+and the
+.Fn atanhf
+functions
+return the inverse hyperbolic tangent of
+.Ar x
+if successful.
+On the
+.Tn VAX
+and
+.Tn Tahoe ,
+if the argument has absolute value
+bigger than or equal to 1,
+.Fn atanh
+sets the global variable
+.Va errno
+to
+.Er EDOM
+and
+a reserved operand fault is generated.
+.Sh SEE ALSO
+.Xr acosh 3 ,
+.Xr asinh 3 ,
+.Xr exp 3 ,
+.Xr math 3
+.Sh HISTORY
+The
+.Fn atanh
+function appeared in
+.Bx 4.3 .
diff --git a/lib/msun/man/ceil.3 b/lib/msun/man/ceil.3
new file mode 100644
index 0000000..8f17871
--- /dev/null
+++ b/lib/msun/man/ceil.3
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)ceil.3 5.1 (Berkeley) 5/2/91
+.\" $Id: ceil.3,v 1.6 1997/02/22 15:09:26 peter Exp $
+.\"
+.Dd March 10, 1994
+.Dt CEIL 3
+.Os
+.Sh NAME
+.Nm ceil ,
+.Nm ceilf
+.Nd round to smallest integral value >= x
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn ceil "double x"
+.Ft float
+.Fn ceilf "float x"
+.Sh DESCRIPTION
+The
+.Fn ceil
+and the
+.Fn ceilf
+functions return the smallest integral value
+(represented as a double precision number)
+greater than or equal to
+.Fa x .
+.Sh SEE ALSO
+.Xr abs 3 ,
+.Xr fabs 3 ,
+.Xr floor 3 ,
+.Xr ieee 3 ,
+.Xr math 3 ,
+.Xr rint 3
+.Sh STANDARDS
+The
+.Fn ceil
+function conforms to
+.St -ansiC .
diff --git a/lib/libc/stdlib/calloc.3 b/lib/msun/man/cos.3
index 0ca15e5..f9e4b27 100644
--- a/lib/libc/stdlib/calloc.3
+++ b/lib/msun/man/cos.3
@@ -1,9 +1,5 @@
-.\" 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.
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -33,38 +29,53 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)calloc.3 8.1 (Berkeley) 6/4/93
+.\" from: @(#)cos.3 5.1 (Berkeley) 5/2/91
+.\" $Id: cos.3,v 1.5 1997/02/22 15:09:27 peter Exp $
.\"
-.Dd June 4, 1993
-.Dt CALLOC 3
+.Dd May 2, 1991
+.Dt COS 3
.Os
.Sh NAME
-.Nm calloc
-.Nd allocate clean memory (zero initialized space)
+.Nm cos ,
+.Nm cosf
+.Nd cosine functions
.Sh SYNOPSIS
-.Fd #include <stdlib.h>
-.Ft void *
-.Fn calloc "size_t nmemb" "size_t size"
+.Fd #include <math.h>
+.Ft double
+.Fn cos "double x"
+.Ft float
+.Fn cosf "float x"
.Sh DESCRIPTION
The
-.Fn calloc
-function allocates space for an array of
-.Fa nmemb
-objects, each of whose size is
-.Fa size .
-The space is initialized to all bits zero.
+.Fn cos
+and the
+.Fn cosf
+functions compute the cosine of
+.Fa x
+(measured in radians).
+A large magnitude argument may yield a result with little or no
+significance.
+For a discussion of error due to roundoff, see
+.Xr math 3 .
.Sh RETURN VALUES
The
-.Fn calloc
-function returns
-a pointer to the
-the allocated space if successful; otherwise a null pointer is returned.
+.Fn cos
+and the
+.Fn cosf
+functions return the cosine value.
.Sh SEE ALSO
-.Xr malloc 3 ,
-.Xr realloc 3 ,
-.Xr free 3 ,
+.Xr acos 3 ,
+.Xr asin 3 ,
+.Xr atan 3 ,
+.Xr atan2 3 ,
+.Xr cosh 3 ,
+.Xr math 3 ,
+.Xr sin 3 ,
+.Xr sinh 3 ,
+.Xr tan 3 ,
+.Xr tanh 3
.Sh STANDARDS
The
-.Fn calloc
+.Fn cos
function conforms to
.St -ansiC .
diff --git a/lib/msun/man/cosh.3 b/lib/msun/man/cosh.3
new file mode 100644
index 0000000..9255ecc
--- /dev/null
+++ b/lib/msun/man/cosh.3
@@ -0,0 +1,82 @@
+.\" Copyright (c) 1989, 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)cosh.3 5.1 (Berkeley) 5/2/91
+.\" $Id: cosh.3,v 1.5 1997/02/22 15:09:28 peter Exp $
+.\"
+.Dd May 2, 1991
+.Dt COSH 3
+.Os
+.Sh NAME
+.Nm cosh ,
+.Nm coshf
+.Nd hyperbolic cosine functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn cosh "double x"
+.Ft float
+.Fn coshf "float x"
+.Sh DESCRIPTION
+The
+.Fn cosh
+and the
+.Fn coshf
+functions compute the hyperbolic cosine of
+.Fa x .
+.Sh RETURN VALUES
+The
+.Fn cosh
+and the
+.Fn coshf
+functions return the hyperbolic cosine unless the magnitude
+of
+.Fa x
+is too large; in this event, the global variable
+.Va errno
+is set to
+.Er ERANGE .
+.Sh SEE ALSO
+.Xr acos 3 ,
+.Xr asin 3 ,
+.Xr atan 3 ,
+.Xr atan2 3 ,
+.Xr cos 3 ,
+.Xr math 3 ,
+.Xr sin 3 ,
+.Xr sinh 3 ,
+.Xr tan 3 ,
+.Xr tanh 3
+.Sh STANDARDS
+The
+.Fn cosh
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/man/erf.3 b/lib/msun/man/erf.3
new file mode 100644
index 0000000..c63aacc
--- /dev/null
+++ b/lib/msun/man/erf.3
@@ -0,0 +1,93 @@
+.\" Copyright (c) 1985, 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.
+.\" 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: @(#)erf.3 6.4 (Berkeley) 4/20/91
+.\" $Id$
+.\"
+.Dd April 20, 1991
+.Dt ERF 3
+.Os BSD 4.3
+.Sh NAME
+.Nm erf ,
+.Nm erff ,
+.Nm erfc ,
+.Nm erfcf
+.Nd error function operators
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn erf "double x"
+.Ft float
+.Fn erff "float x"
+.Ft double
+.Fn erfc "double x"
+.Ft float
+.Fn erfcf "float x"
+.Sh DESCRIPTION
+These functions calculate the error function of
+.Fa x .
+.Pp
+The
+.Fn erf
+and the
+.Fn erff
+functions calculate the error function of x; where
+.Bd -filled -offset indent
+.if n \{\
+erf(x) = 2/sqrt(pi)\(**\|integral from 0 to x of exp(\-t\(**t) dt. \}
+.if t \{\
+erf\|(x) :=
+(2/\(sr\(*p)\|\(is\d\s8\z0\s10\u\u\s8x\s10\d\|exp(\-t\u\s82\s10\d)\|dt. \}
+.Ed
+.Pp
+The
+.Fn erfc
+and the
+.Fn erfcf
+functions calculate the complementary error function of
+.Fa x ;
+that is
+.Fn erfc
+subtracts the result of the error function
+.Fn erf x
+from 1.0.
+This is useful, since for large
+.Fa x
+places disappear.
+.Sh SEE ALSO
+.Xr math 3
+.Sh HISTORY
+The
+.Fn erf
+and
+.Fn erfc
+functions appeared in
+.Bx 4.3 .
diff --git a/lib/msun/man/exp.3 b/lib/msun/man/exp.3
new file mode 100644
index 0000000..9e38d643
--- /dev/null
+++ b/lib/msun/man/exp.3
@@ -0,0 +1,320 @@
+.\" Copyright (c) 1985, 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.
+.\" 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: @(#)exp.3 6.12 (Berkeley) 7/31/91
+.\" $Id$
+.\"
+.Dd July 31, 1991
+.Dt EXP 3
+.Os BSD 4
+.Sh NAME
+.Nm exp ,
+.Nm expf ,
+.Nm exp2 ,
+.Nm exp2f ,
+.Nm exp10 ,
+.Nm exp10f ,
+.Nm expm1 ,
+.Nm expm1f ,
+.Nm log ,
+.Nm logf ,
+.Nm log10 ,
+.Nm log10f ,
+.Nm log1p ,
+.Nm log1pf ,
+.Nm pow ,
+.Nm powf
+.Nd exponential, logarithm, power functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn exp "double x"
+.Ft float
+.Fn expf "float x"
+.Ft double
+.Fn expm1 "double x"
+.Ft float
+.Fn expm1f "float x"
+.Ft double
+.Fn log "double x"
+.Ft float
+.Fn logf "float x"
+.Ft double
+.Fn log10 "double x"
+.Ft float
+.Fn log10f "float x"
+.Ft double
+.Fn log1p "double x"
+.Ft float
+.Fn log1pf "float x"
+.Ft double
+.Fn pow "double x" "double y"
+.Ft float
+.Fn powf "float x" "float y"
+.Sh DESCRIPTION
+The
+.Fn exp
+and the
+.Fn expf
+functions compute the exponential value of the given argument
+.Fa x .
+.Pp
+The
+.Fn expm1
+and the
+.Fn expm1f
+functions compute the value exp(x)\-1 accurately even for tiny argument
+.Fa x .
+.Pp
+The
+.Fn log
+and the
+.Fn logf
+functions compute the value of the natural logarithm of argument
+.Fa x.
+.Pp
+The
+.Fn log10
+and the
+.Fn log10f
+functions compute the value of the logarithm of argument
+.Fa x
+to base 10.
+.Pp
+The
+.Fn log1p
+and the
+.Fn log1pf
+functions compute
+the value of log(1+x) accurately even for tiny argument
+.Fa x .
+.Pp
+The
+.Fn pow
+and the
+.Fn powf
+functions compute the value
+of
+.Ar x
+to the exponent
+.Ar y .
+.Sh ERROR (due to Roundoff etc.)
+.Fn exp(x) ,
+.Fn log(x) ,
+.Fn expm1(x) and
+.Fn log1p(x)
+are accurate to within
+an
+.Em ulp ,
+and log10(x) to within about 2
+.Em ulps ;
+an
+.Em ulp
+is one
+.Em Unit
+in the
+.Em Last
+.Em Place .
+The error in
+.Fn pow x y
+is below about 2
+.Em ulps
+when its
+magnitude is moderate, but increases as
+.Fn pow x y
+approaches
+the over/underflow thresholds until almost as many bits could be
+lost as are occupied by the floating\-point format's exponent
+field; that is 8 bits for
+.Tn "VAX D"
+and 11 bits for IEEE 754 Double.
+No such drastic loss has been exposed by testing; the worst
+errors observed have been below 20
+.Em ulps
+for
+.Tn "VAX D" ,
+300
+.Em ulps
+for
+.Tn IEEE
+754 Double.
+Moderate values of
+.Fn pow
+are accurate enough that
+.Fn pow integer integer
+is exact until it is bigger than 2**56 on a
+.Tn VAX ,
+2**53 for
+.Tn IEEE
+754.
+.Sh RETURN VALUES
+These functions will return the appropriate computation unless an error
+occurs or an argument is out of range.
+The functions
+.Fn exp ,
+.Fn expm1 ,
+.Fn pow
+detect if the computed value will overflow,
+set the global variable
+.Va errno to
+.Er ERANGE
+and cause a reserved operand fault on a
+.Tn VAX
+or
+.Tn Tahoe .
+The functions
+.Fn pow x y
+checks to see if
+.Fa x
+< 0 and
+.Fa y
+is not an integer, in the event this is true,
+the global variable
+.Va errno
+is set to
+.Er EDOM
+and on the
+.Tn VAX
+and
+.Tn Tahoe
+generate a reserved operand fault.
+On a
+.Tn VAX
+and
+.Tn Tahoe ,
+.Va errno
+is set to
+.Er EDOM
+and the reserved operand is returned
+by log unless
+.Fa x
+> 0, by
+.Fn log1p
+unless
+.Fa x
+> \-1.
+.Sh NOTES
+The functions exp(x)\-1 and log(1+x) are called
+expm1 and logp1 in
+.Tn BASIC
+on the Hewlett\-Packard
+.Tn HP Ns \-71B
+and
+.Tn APPLE
+Macintosh,
+.Tn EXP1
+and
+.Tn LN1
+in Pascal, exp1 and log1 in C
+on
+.Tn APPLE
+Macintoshes, where they have been provided to make
+sure financial calculations of ((1+x)**n\-1)/x, namely
+expm1(n\(**log1p(x))/x, will be accurate when x is tiny.
+They also provide accurate inverse hyperbolic functions.
+.Pp
+The function
+.Fn pow x 0
+returns x**0 = 1 for all x including x = 0,
+.if n \
+Infinity
+.if t \
+\(if
+(not found on a
+.Tn VAX ) ,
+and
+.Em NaN
+(the reserved
+operand on a
+.Tn VAX ) . Previous implementations of pow may
+have defined x**0 to be undefined in some or all of these
+cases. Here are reasons for returning x**0 = 1 always:
+.Bl -enum -width indent
+.It
+Any program that already tests whether x is zero (or
+infinite or \*(Na) before computing x**0 cannot care
+whether 0**0 = 1 or not. Any program that depends
+upon 0**0 to be invalid is dubious anyway since that
+expression's meaning and, if invalid, its consequences
+vary from one computer system to another.
+.It
+Some Algebra texts (e.g. Sigler's) define x**0 = 1 for
+all x, including x = 0.
+This is compatible with the convention that accepts a[0]
+as the value of polynomial
+.Bd -literal -offset indent
+p(x) = a[0]\(**x**0 + a[1]\(**x**1 + a[2]\(**x**2 +...+ a[n]\(**x**n
+.Ed
+.Pp
+at x = 0 rather than reject a[0]\(**0**0 as invalid.
+.It
+Analysts will accept 0**0 = 1 despite that x**y can
+approach anything or nothing as x and y approach 0
+independently.
+The reason for setting 0**0 = 1 anyway is this:
+.Bd -filled -offset indent
+If x(z) and y(z) are
+.Em any
+functions analytic (expandable
+in power series) in z around z = 0, and if there
+x(0) = y(0) = 0, then x(z)**y(z) \(-> 1 as z \(-> 0.
+.Ed
+.It
+If 0**0 = 1, then
+.if n \
+infinity**0 = 1/0**0 = 1 too; and
+.if t \
+\(if**0 = 1/0**0 = 1 too; and
+then \*(Na**0 = 1 too because x**0 = 1 for all finite
+and infinite x, i.e., independently of x.
+.El
+.Sh SEE ALSO
+.Xr math 3
+.Sh HISTORY
+A
+.Fn exp ,
+.Fn log
+and
+.Fn pow
+functions
+appeared in
+.At v6 .
+A
+.Fn log10
+function
+appeared in
+.At v7 .
+The
+.Fn log1p
+and
+.Fn expm1
+functions appeared in
+.Bx 4.3 .
diff --git a/lib/msun/man/fabs.3 b/lib/msun/man/fabs.3
new file mode 100644
index 0000000..e7cd317
--- /dev/null
+++ b/lib/msun/man/fabs.3
@@ -0,0 +1,74 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" @(#)fabs.3 5.1 (Berkeley) 5/2/91
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)fabs.3 5.1 (Berkeley) 5/2/91
+.\" $Id$
+.\"
+.Dd May 2, 1991
+.Dt FABS 3
+.Os
+.Sh NAME
+.Nm fabs ,
+.Nm fabsf
+.Nd floating-point absolute value functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn fabs "double x"
+.Ft float
+.Fn fabsf "float x"
+.Sh DESCRIPTION
+The
+.Fn fabs
+and the
+.Fn fabsf
+functions compute the absolute value of a floating-point number
+.Fa x .
+.Sh RETURN VALUES
+The
+.Fn fabs
+and the
+.Fn fabsf
+functions return the absolute value of
+.Fa x .
+.Sh SEE ALSO
+.Xr abs 3 ,
+.Xr ceil 3 ,
+.Xr floor 3 ,
+.Xr ieee 3 ,
+.Xr math 3 ,
+.Xr rint 3
+.Sh STANDARDS
+The
+.Fn fabs
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/man/floor.3 b/lib/msun/man/floor.3
new file mode 100644
index 0000000..71080f0
--- /dev/null
+++ b/lib/msun/man/floor.3
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1985, 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)floor.3 6.5 (Berkeley) 4/19/91
+.\" $Id$
+.\"
+.Dd March 10, 1994
+.Dt FLOOR 3
+.Os
+.Sh NAME
+.Nm floor ,
+.Nm floorf
+.Nd round to largest integral value <= x
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn floor "double x"
+.Ft float
+.Fn floorf "float x"
+.Sh DESCRIPTION
+The
+.Fn floor
+and the
+.Fn floorf
+function returns the largest integral value
+(represented as a double precision number)
+less than or equal to
+.Fa x .
+.Sh SEE ALSO
+.Xr abs 3 ,
+.Xr ceil 3 ,
+.Xr fabs 3 ,
+.Xr ieee 3 ,
+.Xr math 3 ,
+.Xr rint 3
+.Sh STANDARDS
+The
+.Fn floor
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/man/fmod.3 b/lib/msun/man/fmod.3
new file mode 100644
index 0000000..61cdfa0
--- /dev/null
+++ b/lib/msun/man/fmod.3
@@ -0,0 +1,85 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)fmod.3 5.1 (Berkeley) 5/2/91
+.\" $Id$
+.\"
+.Dd May 2, 1991
+.Dt FMOD 3
+.Os
+.Sh NAME
+.Nm fmod ,
+.Nm fmodf
+.Nd floating-point remainder functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn fmod "double x" "double y"
+.Ft float
+.Fn fmodf "float x" "float y"
+.Sh DESCRIPTION
+The
+.Fn fmod
+and the
+.Fn fmodf
+functions compute the floating-point remainder of
+.Fa x Ns / Fa y .
+.Sh RETURN VALUES
+The
+.Fn fmod
+and the
+.Fn fmodf
+functions return the value
+.Sm off
+.Fa x - Em i * Fa y ,
+.Sm on
+for some integer
+.Em i
+such that, if
+.Fa y
+is non-zero, the result has the same sign as
+.Fa x
+and magnitude less than the magnitude of
+.Fa y .
+If
+.Fa y
+is zero, whether a domain error occurs or the
+.Fn fmod
+and the
+.Fn fmodf
+function returns zero is implementation-defined.
+.Sh SEE ALSO
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn fmod
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/man/hypot.3 b/lib/msun/man/hypot.3
new file mode 100644
index 0000000..bebd1db
--- /dev/null
+++ b/lib/msun/man/hypot.3
@@ -0,0 +1,134 @@
+.\" Copyright (c) 1985, 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.
+.\" 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: @(#)hypot.3 6.7 (Berkeley) 5/6/91
+.\" $Id$
+.\"
+.Dd May 6, 1991
+.Dt HYPOT 3
+.Os BSD 4
+.Sh NAME
+.Nm hypot ,
+.Nm hypotf ,
+.Nm cabs ,
+.Nm cabsf
+.Nd euclidean distance and complex absolute value functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn hypot "double x" "double y"
+.Ft float
+.Fn hypotf "float x" "float y"
+.Fd struct {double x, y;} z;
+.Ft double
+.Fn cabs z
+.Fd struct {float x, y;} z;
+.Ft float
+.Fn cabsf z
+.Sh DESCRIPTION
+The
+.Fn hypot ,
+.Fn hypotf ,
+.Fn cabs
+and
+.Fn cabsf
+functions
+compute the
+sqrt(x*x+y*y)
+in such a way that underflow will not happen, and overflow
+occurs only if the final result deserves it.
+.Pp
+.Fn hypot "\*(If" "v"
+=
+.Fn hypot "v" "\*(If"
+= +\*(If for all
+.Ar v ,
+including \*(Na.
+.Sh ERROR (due to Roundoff, etc.)
+Below 0.97
+.Em ulps .
+Consequently
+.Fn hypot "5.0" "12.0"
+= 13.0
+exactly;
+in general, hypot and cabs return an integer whenever an
+integer might be expected.
+.Pp
+The same cannot be said for the shorter and faster version of hypot
+and cabs that is provided in the comments in cabs.c; its error can
+exceed 1.2
+.Em ulps .
+.Sh NOTES
+As might be expected,
+.Fn hypot "v" "\*(Na"
+and
+.Fn hypot "\*(Na" "v"
+are \*(Na for all
+.Em finite
+.Ar v ;
+with "reserved operand" in place of "\*(Na", the
+same is true on a
+.Tn VAX .
+But programmers on machines other than a
+.Tn VAX
+(if has no \*(If)
+might be surprised at first to discover that
+.Fn hypot "\(+-\*(If" "\*(Na"
+= +\*(If.
+This is intentional; it happens because
+.Fn hypot "\*(If" "v"
+= +\*(If
+for
+.Em all
+.Ar v ,
+finite or infinite.
+Hence
+.Fn hypot "\*(If" "v"
+is independent of
+.Ar v .
+Unlike the reserved operand fault on a
+.Tn VAX ,
+the
+.Tn IEEE
+\*(Na is designed to
+disappear when it turns out to be irrelevant, as it does in
+.Fn hypot "\*(If" "\*(Na" .
+.Sh SEE ALSO
+.Xr math 3 ,
+.Xr sqrt 3
+.Sh HISTORY
+Both a
+.Fn hypot
+function and a
+.Fn cabs
+function
+appeared in
+.At v7 .
diff --git a/lib/msun/man/ieee.3 b/lib/msun/man/ieee.3
new file mode 100644
index 0000000..c983a3f
--- /dev/null
+++ b/lib/msun/man/ieee.3
@@ -0,0 +1,182 @@
+.\" Copyright (c) 1985, 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.
+.\" 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: @(#)ieee.3 6.4 (Berkeley) 5/6/91
+.\" $Id$
+.\"
+.Dd Feb 25, 1994
+.Dt IEEE 3
+.Os
+.Sh NAME
+.Nm copysign ,
+.Nm copysignf ,
+.Nm finite ,
+.Nm finitef ,
+.Nm ilogb ,
+.Nm ilogbf ,
+.Nm nextafter ,
+.Nm nextafterf ,
+.Nm remainder ,
+.Nm remainderf ,
+.Nm scalbn ,
+.Nm scalbnf
+.Nd Functions for IEEE arithmetic
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn copysign "double x" "double y"
+.Ft float
+.Fn copysignf "float x" "float y"
+.Ft int
+.Fn finite "double x"
+.Ft int
+.Fn finitef "float x"
+.Ft int
+.Fn ilogb "double x"
+.Ft int
+.Fn ilogbf "float x"
+.Ft double
+.Fn nextafter "double x" "double y"
+.Ft float
+.Fn nextafterf "float x" "float y"
+.Ft double
+.Fn remainder "double x" "double y"
+.Ft float
+.Fn remainderf "float x" "float y"
+.Ft double
+.Fn scalbn "double x" "int n"
+.Ft float
+.Fn scalbnf "float x" "int n"
+.Sh DESCRIPTION
+These functions are required or recommended by
+.St -ieee754 .
+.Pp
+.Fn copysign
+and
+.Fn copysignf
+return
+.Fa x
+with its sign changed to
+.Fa y Ns 's.
+.Pp
+.Fn finite
+and
+.Fn finitef
+return the value 1 just when
+\-\*(If \*(Lt
+.Fa x
+\*(Lt +\*(If;
+otherwise a
+zero is returned
+(when
+.Pf \\*(Ba Ns Fa x Ns \\*(Ba
+= \*(If or
+.Fa x
+is \*(Na
+.Pp
+.Fn ilogb
+and
+.Fn ilogbf
+return
+.Fa x Ns 's exponent
+.Fa n ,
+in integer format.
+.Fn ilogb \*(Pm\*(If
+returns
+.Dv INT_MAX
+and
+.Fn ilogb 0
+returns
+.Dv INT_MIN .
+.Pp
+.Fn nextafter
+and
+.Fn nextafterf
+return the next machine representable number from
+.Fa x
+in direction
+.Fa y .
+.Pp
+.Fn remainder
+and
+.Fn remainderf
+return the remainder
+.Fa r
+:=
+.Fa x
+\-
+.Fa n\(**y
+where
+.Fa n
+is the integer nearest the exact value of
+.Bk -words
+.Fa x Ns / Ns Fa y ;
+.Ek
+moreover if
+.Pf \\*(Ba Fa n
+\-
+.Sm off
+.Fa x No / Fa y No \\*(Ba
+.Sm on
+=
+1/2
+then
+.Fa n
+is even. Consequently
+the remainder is computed exactly and
+.Sm off
+.Pf \\*(Ba Fa r No \\*(Ba
+.Sm on
+\*(Le
+.Sm off
+.Pf \\*(Ba Fa y No \\*(Ba/2.
+.Sm on
+But
+.Fn remainder x 0
+and
+.Fn remainder \*(If 0
+are invalid operations that produce a \*(Na.
+.Pp
+.Fn scalbn
+and
+.Fn scalbnf
+return
+.Fa x Ns \(**(2** Ns Fa n )
+computed by exponent manipulation.
+.Sh SEE ALSO
+.Xr math 3
+.Sh HISTORY
+The
+.Nm ieee
+functions appeared in
+.Bx 4.3 .
+.Sh STANDARDS
+.St -ieee754
diff --git a/lib/msun/man/ieee_test.3 b/lib/msun/man/ieee_test.3
new file mode 100644
index 0000000..c2c7e49
--- /dev/null
+++ b/lib/msun/man/ieee_test.3
@@ -0,0 +1,107 @@
+.\" Copyright (c) 1985, 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.
+.\" 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: @(#)ieee.3 6.4 (Berkeley) 5/6/91
+.\" $Id$
+.\"
+.Dd March 10, 1994
+.Dt IEEE_TEST 3
+.Os
+.Sh NAME
+.Nm logb ,
+.Nm logbf ,
+.Nm scalb ,
+.Nm scalbf ,
+.Nm significand ,
+.Nm significandf
+.Nd IEEE test functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn logb "double x"
+.Ft float
+.Fn logbf "float x"
+.Ft double
+.Fn scalb "double x" "double n"
+.Ft float
+.Fn scalbf "float x" "float n"
+.Ft double
+.Fn significand "double x"
+.Ft float
+.Fn significandf "float x"
+.Sh DESCRIPTION
+These functions allow users to test conformance to
+.St -ieee754 .
+Their use is not otherwise recommended.
+.Pp
+.Fn logb x
+and
+.Fn logbf x
+return
+.Fa x Ns 's exponent
+.Fa n ,
+a signed integer converted to double\-precision floating\-point.
+.Fn logb \*(Pm\*(If
+= +\*(If;
+.Fn logb 0
+= -\*(If with a division by zero exception.
+.Pp
+.Fn scalbn x n
+and
+.Fn scalbnf x n
+return
+.Fa x Ns \(**(2** Ns Fa n )
+computed by exponent manipulation.
+.Pp
+.Fn significand x
+and
+.Fn significandf x
+return
+.Fa sig ,
+where
+.Fa x
+:=
+.Fa sig No \(** 2** Ns Fa n
+with 1 \(<=
+.Fa sig
+< 2.
+.Fn significand x
+and
+.Fn significandf x
+are not defined when
+.Fa x
+is 0, \*(Pm\*(If, or \*(Na.
+.Sh SEE ALSO
+.Xr ieee 3 ,
+.Xr math 3
+
+.Sh STANDARDS
+.St -ieee754
diff --git a/lib/msun/man/j0.3 b/lib/msun/man/j0.3
new file mode 100644
index 0000000..54088c3
--- /dev/null
+++ b/lib/msun/man/j0.3
@@ -0,0 +1,155 @@
+.\" Copyright (c) 1985, 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.
+.\" 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: @(#)j0.3 6.7 (Berkeley) 4/19/91
+.\" $Id$
+.\"
+.Dd April 19, 1991
+.Dt J0 3
+.Os BSD 4
+.Sh NAME
+.Nm j0 ,
+.Nm j0f ,
+.Nm j1 ,
+.Nm j1f ,
+.Nm jn ,
+.Nm jnf ,
+.Nm y0 ,
+.Nm y0f ,
+.Nm y1 ,
+.Nm y1f ,
+.Nm yn ,
+.Nm ynf
+.Nd Bessel functions of first and second kind
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn j0 "double x"
+.Ft float
+.Fn j0f "float x"
+.Ft double
+.Fn j1 "double x"
+.Ft float
+.Fn j1f "float x"
+.Ft double
+.Fn jn "int n" "double x"
+.Ft float
+.Fn jnf "int n" "float x"
+.Ft double
+.Fn y0 "double x"
+.Ft float
+.Fn y0f "float x"
+.Ft double
+.Fn y1 "double x"
+.Ft float
+.Fn y1f "float x"
+.Ft double
+.Fn yn "int n" "double x"
+.Ft float
+.Fn ynf "int n" "float x"
+.Sh DESCRIPTION
+The functions
+.Fn j0 ,
+.Fn j0f ,
+.Fn j1
+and
+.Fn j1f
+compute the
+.Em Bessel function of the first kind of the order
+0 and the
+.Em order
+1, respectively,
+for the
+real value
+.Fa x ;
+the functions
+.Fn jn
+and
+.Fn jnf
+compute the
+.Em Bessel function of the first kind of the integer
+.Em order
+.Fa n
+for the real value
+.Fa x .
+.Pp
+The functions
+.Fn y0 ,
+.Fn y0f ,
+.Fn y1 ,
+and
+.Fn y1f
+compute the linearly independent
+.Em Bessel function of the second kind of the order
+0 and the
+.Em order
+1, respectively,
+for the
+positive
+.Em real
+value
+.Fa x ;
+the functions
+.Fn yn
+and
+.Fn ynf
+compute the
+.Em Bessel function of the second kind for the integer
+.Em order
+.Fa n
+for the positive
+.Em real
+value
+.Fa x .
+.Sh RETURN VALUES
+If these functions are successful,
+the computed value is returned. On the
+.Tn VAX
+and
+.Tn Tahoe
+architectures,
+for the Bessel functions of the second kind,
+a negative
+or zero
+.Fa x
+value
+results in an error; the global
+variable
+.Va errno
+is set to
+.Er EDOM
+and a reserve operand fault is generated.
+.Sh SEE ALSO
+.Xr math 3
+.Sh HISTORY
+This set of functions
+appeared in
+.At v7 .
diff --git a/lib/msun/man/lgamma.3 b/lib/msun/man/lgamma.3
new file mode 100644
index 0000000..e9bae12
--- /dev/null
+++ b/lib/msun/man/lgamma.3
@@ -0,0 +1,139 @@
+.\" Copyright (c) 1985, 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.
+.\" 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: @(#)lgamma.3 6.6 (Berkeley) 12/3/92
+.\" $Id$
+.\"
+.Dd December 3, 1992
+.Dt LGAMMA 3
+.Os BSD 4.3
+.Sh NAME
+.Nm lgamma ,
+.Nm lgammaf ,
+.Nm gamma ,
+.Nm gammaf
+.Nd log gamma functions, gamma functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft extern int
+.Fa signgam ;
+.sp
+.Ft double
+.Fn lgamma "double x"
+.Ft float
+.Fn lgammaf "float x"
+.Ft double
+.Fn gamma "double x"
+.Ft float
+.Fn gamma "float x"
+.Sh DESCRIPTION
+.Fn lgamma x
+and
+.Fn lgammaf x
+.if t \{\
+return ln\||\(*G(x)| where
+.Bd -unfilled -offset indent
+\(*G(x) = \(is\d\s8\z0\s10\u\u\s8\(if\s10\d t\u\s8x\-1\s10\d e\u\s8\-t\s10\d dt for x > 0 and
+.br
+\(*G(x) = \(*p/(\(*G(1\-x)\|sin(\(*px)) for x < 1.
+.Ed
+.\}
+.if n \
+returns ln\||\(*G(x)|.
+.Pp
+The external integer
+.Fa signgam
+returns the sign of \(*G(x).
+.Pp
+.Fn gamma x
+and
+.Fn gammaf x
+return \(*G(x), with no effect on
+.Fa signgam .
+.Sh IDIOSYNCRASIES
+Do not use the expression
+.Dq Li signgam\(**exp(lgamma(x))
+to compute g := \(*G(x).
+Instead use a program like this (in C):
+.Bd -literal -offset indent
+lg = lgamma(x); g = signgam\(**exp(lg);
+.Ed
+.Pp
+Only after
+.Fn lgamma
+or
+.Fn lgammaf
+has returned can signgam be correct.
+.Pp
+For arguments in its range,
+.Fn gamma
+and
+.Fn gammaf
+is preferred, as for positive arguments
+it is accurate to within one unit in the last place.
+Exponentiation of
+.Fn lgamma
+will lose up to 10 significant bits.
+.Sh RETURN VALUES
+.Fn gamma ,
+.Fn gammaf ,
+.Fn lgamma ,
+and
+.Fn lgammaf
+return appropriate values unless an argument is out of range.
+Overflow will occur for sufficiently large positive values, and
+non-positive integers.
+On the
+.Tn VAX,
+the reserved operator is returned,
+and
+.Va errno
+is set to
+.Er ERANGE
+For large non-integer negative values,
+.Fn gamma
+will underflow.
+.Sh SEE ALSO
+.Xr math 3
+.Sh HISTORY
+The
+.Nm lgamma
+function appeared in
+.Bx 4.3 .
+The
+.Nm gamma
+function appeared in
+.Bx 4.4 .
+The name
+.Fn gamma
+was originally dedicated to the
+.Fn lgamma
+function, so some old code may no longer be compatible.
diff --git a/lib/msun/man/math.3 b/lib/msun/man/math.3
new file mode 100644
index 0000000..a692b5f
--- /dev/null
+++ b/lib/msun/man/math.3
@@ -0,0 +1,635 @@
+.\" Copyright (c) 1985 Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)math.3 6.10 (Berkeley) 5/6/91
+.\" $Id$
+.\"
+.TH MATH 3M "May 6, 1991"
+.UC 4
+.ds up \fIulp\fR
+.ds nn \fINaN\fR
+.de If
+.if n \\
+\\$1Infinity\\$2
+.if t \\
+\\$1\\(if\\$2
+..
+.SH NAME
+math \- introduction to mathematical library functions
+.SH DESCRIPTION
+These functions constitute the C math library,
+.I libm.
+The link editor searches this library under the \*(lq\-lm\*(rq option.
+Declarations for these functions may be obtained from the include file
+.RI < math.h >.
+.\" The Fortran math library is described in ``man 3f intro''.
+.SH "LIST OF FUNCTIONS"
+Each of the following double functions has a float counterpart with the
+name ending in f, as an example the float counterpart of double acos(double
+x) is float acosf(float x).
+.sp 2
+.nf
+.ta \w'copysign'u+2n +\w'infnan.3m'u+10n +\w'inverse trigonometric func'u
+\fIName\fP \fIAppears on Page\fP \fIDescription\fP \fIError Bound (ULPs)\fP
+.ta \w'copysign'u+4n +\w'infnan.3m'u+4n +\w'inverse trigonometric function'u+6nC
+.sp 5p
+acos sin.3m inverse trigonometric function 3
+acosh asinh.3m inverse hyperbolic function 3
+asin sin.3m inverse trigonometric function 3
+asinh asinh.3m inverse hyperbolic function 3
+atan sin.3m inverse trigonometric function 1
+atanh asinh.3m inverse hyperbolic function 3
+atan2 sin.3m inverse trigonometric function 2
+cabs hypot.3m complex absolute value 1
+cbrt sqrt.3m cube root 1
+ceil floor.3m integer no less than 0
+copysign ieee.3m copy sign bit 0
+cos sin.3m trigonometric function 1
+cosh sinh.3m hyperbolic function 3
+erf erf.3m error function ???
+erfc erf.3m complementary error function ???
+exp exp.3m exponential 1
+expm1 exp.3m exp(x)\-1 1
+fabs floor.3m absolute value 0
+floor floor.3m integer no greater than 0
+hypot hypot.3m Euclidean distance 1
+ilogb ieee.3m exponent extraction 0
+j0 j0.3m bessel function ???
+j1 j0.3m bessel function ???
+jn j0.3m bessel function ???
+lgamma lgamma.3m log gamma function; (formerly gamma.3m)
+log exp.3m natural logarithm 1
+log10 exp.3m logarithm to base 10 3
+log1p exp.3m log(1+x) 1
+pow exp.3m exponential x**y 60\-500
+remainder ieee.3m remainder 0
+rint floor.3m round to nearest integer 0
+scalbn ieee.3m exponent adjustment 0
+sin sin.3m trigonometric function 1
+sinh sinh.3m hyperbolic function 3
+sqrt sqrt.3m square root 1
+tan sin.3m trigonometric function 3
+tanh sinh.3m hyperbolic function 3
+y0 j0.3m bessel function ???
+y1 j0.3m bessel function ???
+yn j0.3m bessel function ???
+.ta
+.fi
+.SH NOTES
+In 4.3 BSD, distributed from the University of California
+in late 1985, most of the foregoing functions come in two
+versions, one for the double\-precision "D" format in the
+DEC VAX\-11 family of computers, another for double\-precision
+arithmetic conforming to the IEEE Standard 754 for Binary
+Floating\-Point Arithmetic. The two versions behave very
+similarly, as should be expected from programs more accurate
+and robust than was the norm when UNIX was born. For
+instance, the programs are accurat ere accurn the numbers
+of \*(ups tabulated above; an \*(up is one \fIU\fRnit in the \fIL\fRast
+\fIP\fRlace. And the progrod the prbeen cured of anomalies that
+afflicted the older mat` older math library \fIlibm\fR in which incidents like
+the followineported:
+.RS
+sqrt(\-1.0) = 0.0 and log(\-1.0) = \-1.7e38.
+.br
+cos(1.0e\-11) > cos(0.0) > 1.0.
+.br
+pow(x,1.0)
+.if n \
+!=
+.if t \
+\(!=
+x when x = 2.0, 3.0, 4.0, ..., 9.0.
+.br
+pow(\-1.0,1.0e10) trapped on Integer Overflow.
+.br
+sqrt(1.0e30) and sqrt(1.0e\-30) were very slow.
+.RE
+However the two versions do differ in ways that have to be
+explained, to which end the following notes are provided.
+.PP
+\fBDEC VAX\-11 D_floating\-point:\fR
+.PP
+This is the format for which the original math library \fIlibm\fR
+was developed, and to which this manual is still principally
+dedicated. It is \fIthe\fR double\-precision format for the PDP\-11
+and the earlier VAX\-11 machines; VAX\-11s after 1983 were
+provided with an optional "G" format closer to the IEEE
+double\-precision format. The earlier DEC MicroVAXs have no
+D format, only G double\-precision. (Why? Why not?)
+.PP
+Properties of D_floating\-point:
+.RS
+Wordsize: 64 bits, 8 bytes. Radix: Binary.
+.br
+Precision: 56
+.if n \
+sig.
+.if t \
+significant
+bits, roughly like 17
+.if n \
+sig.
+.if t \
+significant
+decimals.
+.RS
+If x and x' are consecutive positive D_floating\-point
+numbers (they differ by 1 \*(up), then
+.br
+1.3e\-17 < 0.5**56 < (x'\-x)/x \(<= 0.5**55 < 2.8e\-17.
+.RE
+.nf
+.ta \w'Range:'u+1n +\w'Underflow threshold'u+1n +\w'= 2.0**127'u+1n
+Range: Overflow threshold = 2.0**127 = 1.7e38.
+ Underflow threshold = 0.5**128 = 2.9e\-39.
+ NOTE: THIS RANGE IS COMPARATIVELY NARROW.
+.ta
+.fi
+.RS
+Overflow customarily stops computation.
+.br
+Underflow is customarily flushed quietly to zero.
+.br
+CAUTION:
+.RS
+It is possible to have x
+.if n \
+!=
+.if t \
+\(!=
+y and yet
+x\-y = 0 because of underflow. Similarly
+x > y > 0 cannot prevent either x\(**y = 0
+or y/x = 0 from happening without warning.
+.RE
+.RE
+Zero is represented ambiguously.
+.RS
+Although 2**55 different representations of zero are accepted by
+the hardware, only the obvious representation is ever produced.
+There is no \-0 on a VAX.
+.RE
+.If
+is not part of the VAX architecture.
+.br
+Reserved operands:
+.RS
+of the 2**55 that the hardware
+recognizes, only one of them is ever produced.
+Any floating\-point operation upon a reserved
+operand, even a MOVF or MOVD, customarily stops
+computation, so they are not much used.
+.RE
+Exceptions:
+.RS
+Divisions by zero and operations that
+overflow are invalid operations that customarily
+stop computation or, in earlier machines, produce
+reserved operands that will stop computation.
+.RE
+Rounding:
+.RS
+Every rational operation (+, \-, \(**, /) on a
+VAX (but not necessarily on a PDP\-11), if not an
+over/underflow nor division by zero, is rounded to
+within half an \*(up, and when the rounding error is
+exactly half an \*(up then rounding is away from 0.
+.RE
+.RE
+.PP
+Except for its narrow range, D_floating\-point is one of the
+better computer arithmetics designed in the 1960's.
+Its properties are reflected fairly faithfully in the elementary
+functions for a VAX distributed in 4.3 BSD.
+They over/underflow only if their results have to lie out of range
+or very nearly so, and then they behave much as any rational
+arithmetic operation that over/underflowed would behave.
+Similarly, expressions like log(0) and atanh(1) behave
+like 1/0; and sqrt(\-3) and acos(3) behave like 0/0;
+they all produce reserved operands and/or stop computation!
+The situation is described in more detail in manual pages.
+.RS
+.ll -0.5i
+\fIThis response seems excessively punitive, so it is destined
+to be replaced at some time in the foreseeable future by a
+more flexible but still uniform scheme being developed to
+handle all floating\-point arithmetic exceptions neatly.
+.\" See infnan(3M) for the present state of affairs.\fR
+.ll +0.5i
+.RE
+.PP
+How do the functions in 4.3 BSD's new \fIlibm\fR for UNIX
+compare with their counterparts in DEC's VAX/VMS library?
+Some of the VMS functions are a little faster, some are
+a little more accurate, some are more puritanical about
+exceptions (like pow(0.0,0.0) and atan2(0.0,0.0)),
+and most occupy much more memory than their counterparts in
+\fIlibm\fR.
+The VMS codes interpolate in large table to achieve
+speed and accuracy; the \fIlibm\fR codes use tricky formulas
+compact enough that all of them may some day fit into a ROM.
+.PP
+More important, DEC regards the VMS codes as proprietary
+and guards them zealously against unauthorized use. But the
+\fIlibm\fR codes in 4.3 BSD are intended for the public domain;
+they may be copied freely provided their provenance is always
+acknowledged, and provided users assist the authors in their
+researches by reporting experience with the codes.
+Therefore no user of UNIX on a machine whose arithmetic resembles
+VAX D_floating\-point need use anything worse than the new \fIlibm\fR.
+.PP
+\fBIEEE STANDARD 754 Floating\-Point Arithmetic:\fR
+.PP
+This standard is on its way to becoming more widely adopted
+than any other design for computer arithmetic.
+VLSI chips that conform to some version of that standard have been
+produced by a host of manufacturers, among them ...
+.nf
+.ta 0.5i +\w'Intel i8070, i80287'u+6n
+ Intel i8087, i80287 National Semiconductor 32081
+ Motorola 68881 Weitek WTL-1032, ... , -1165
+ Zilog Z8070 Western Electric (AT&T) WE32106.
+.ta
+.fi
+Other implementations range from software, done thoroughly
+in the Apple Macintosh, through VLSI in the Hewlett\-Packard
+9000 series, to the ELXSI 6400 running ECL at 3 Megaflops.
+Several other companies have adopted the formats
+of IEEE 754 without, alas, adhering to the standard's way
+of handling rounding and exceptions like over/underflow.
+The DEC VAX G_floating\-point format is very similar to the IEEE
+754 Double format, so similar that the C programs for the
+IEEE versions of most of the elementary functions listed
+above could easily be converted to run on a MicroVAX, though
+nobody has volunteered to do that yet.
+.PP
+The codes in 4.3 BSD's \fIlibm\fR for machines that conform to
+IEEE 754 are intended primarily for the National Semi. 32081
+and WTL 1164/65. To use these codes with the Intel or Zilog
+chips, or with the Apple Macintosh or ELXSI 6400, is to
+forego the use of better codes provided (perhaps freely) by
+those companies and designed by some of the authors of the
+codes above.
+Except for \fIatan\fR, \fIcabs\fR, \fIcbrt\fR, \fIerf\fR,
+\fIerfc\fR, \fIhypot\fR, \fIj0\-jn\fR, \fIlgamma\fR, \fIpow\fR
+and \fIy0\-yn\fR,
+the Motorola 68881 has all the functions in \fIlibm\fR on chip,
+and faster and more accurate;
+it, Apple, the i8087, Z8070 and WE32106 all use 64
+.if n \
+sig.
+.if t \
+significant
+bits.
+The main virtue of 4.3 BSD's
+\fIlibm\fR codes is that they are intended for the public domain;
+they may be copied freely provided their provenance is always
+acknowledged, and provided users assist the authors in their
+researches by reporting experience with the codes.
+Therefore no user of UNIX on a machine that conforms to
+IEEE 754 need use anything worse than the new \fIlibm\fR.
+.PP
+Properties of IEEE 754 Double\-Precision:
+.RS
+Wordsize: 64 bits, 8 bytes. Radix: Binary.
+.br
+Precision: 53
+.if n \
+sig.
+.if t \
+significant
+bits, roughly like 16
+.if n \
+sig.
+.if t \
+significant
+decimals.
+.RS
+If x and x' are consecutive positive Double\-Precision
+numbers (they differ by 1 \*(up), then
+.br
+1.1e\-16 < 0.5**53 < (x'\-x)/x \(<= 0.5**52 < 2.3e\-16.
+.RE
+.nf
+.ta \w'Range:'u+1n +\w'Underflow threshold'u+1n +\w'= 2.0**1024'u+1n
+Range: Overflow threshold = 2.0**1024 = 1.8e308
+ Underflow threshold = 0.5**1022 = 2.2e\-308
+.ta
+.fi
+.RS
+Overflow goes by default to a signed
+.If "" .
+.br
+Underflow is \fIGradual,\fR rounding to the nearest
+integer multiple of 0.5**1074 = 4.9e\-324.
+.RE
+Zero is represented ambiguously as +0 or \-0.
+.RS
+Its sign transforms correctly through multiplication or
+division, and is preserved by addition of zeros
+with like signs; but x\-x yields +0 for every
+finite x. The only operations that reveal zero's
+sign are division by zero and copysign(x,\(+-0).
+In particular, comparison (x > y, x \(>= y, etc.)
+cannot be affected by the sign of zero; but if
+finite x = y then
+.If
+\&= 1/(x\-y)
+.if n \
+!=
+.if t \
+\(!=
+\-1/(y\-x) =
+.If \- .
+.RE
+.If
+is signed.
+.RS
+it persists when added to itself
+or to any finite number. Its sign transforms
+correctly through multiplication and division, and
+.If (finite)/\(+- \0=\0\(+-0
+(nonzero)/0 =
+.If \(+- .
+But
+.if n \
+Infinity\-Infinity, Infinity\(**0 and Infinity/Infinity
+.if t \
+\(if\-\(if, \(if\(**0 and \(if/\(if
+are, like 0/0 and sqrt(\-3),
+invalid operations that produce \*(nn. ...
+.RE
+Reserved operands:
+.RS
+there are 2**53\-2 of them, all
+called \*(nn (\fIN\fRot \fIa N\fRumber).
+Some, called Signaling \*(nns, trap any floating\-point operation
+performed upon them; they are used to mark missing
+or uninitialized values, or nonexistent elements
+of arrays. The rest are Quiet \*(nns; they are
+the default results of Invalid Operations, and
+propagate through subsequent arithmetic operations.
+If x
+.if n \
+!=
+.if t \
+\(!=
+x then x is \*(nn; every other predicate
+(x > y, x = y, x < y, ...) is FALSE if \*(nn is involved.
+.br
+NOTE: Trichotomy is violated by \*(nn.
+.RS
+Besides being FALSE, predicates that entail ordered
+comparison, rather than mere (in)equality,
+signal Invalid Operation when \*(nn is involved.
+.RE
+.RE
+Rounding:
+.RS
+Every algebraic operation (+, \-, \(**, /,
+.if n \
+sqrt)
+.if t \
+\(sr)
+is rounded by default to within half an \*(up, and
+when the rounding error is exactly half an \*(up then
+the rounded value's least significant bit is zero.
+This kind of rounding is usually the best kind,
+sometimes provably so; for instance, for every
+x = 1.0, 2.0, 3.0, 4.0, ..., 2.0**52, we find
+(x/3.0)\(**3.0 == x and (x/10.0)\(**10.0 == x and ...
+despite that both the quotients and the products
+have been rounded. Only rounding like IEEE 754
+can do that. But no single kind of rounding can be
+proved best for every circumstance, so IEEE 754
+provides rounding towards zero or towards
+.If +
+or towards
+.If \-
+at the programmer's option. And the
+same kinds of rounding are specified for
+Binary\-Decimal Conversions, at least for magnitudes
+between roughly 1.0e\-10 and 1.0e37.
+.RE
+Exceptions:
+.RS
+IEEE 754 recognizes five kinds of floating\-point exceptions,
+listed below in declining order of probable importance.
+.RS
+.nf
+.ta \w'Invalid Operation'u+6n +\w'Gradual Underflow'u+2n
+Exception Default Result
+.tc \(ru
+
+.tc
+Invalid Operation \*(nn, or FALSE
+.if n \{\
+Overflow \(+-Infinity
+Divide by Zero \(+-Infinity \}
+.if t \{\
+Overflow \(+-\(if
+Divide by Zero \(+-\(if \}
+Underflow Gradual Underflow
+Inexact Rounded value
+.ta
+.fi
+.RE
+NOTE: An Exception is not an Error unless handled
+badly. What makes a class of exceptions exceptional
+is that no single default response can be satisfactory
+in every instance. On the other hand, if a default
+response will serve most instances satisfactorily,
+the unsatisfactory instances cannot justify aborting
+computation every time the exception occurs.
+.RE
+.PP
+For each kind of floating\-point exception, IEEE 754
+provides a Flag that is raised each time its exception
+is signaled, and stays raised until the program resets
+it. Programs may also test, save and restore a flag.
+Thus, IEEE 754 provides three ways by which programs
+may cope with exceptions for which the default result
+might be unsatisfactory:
+.IP 1) \w'\0\0\0\0'u
+Test for a condition that might cause an exception
+later, and branch to avoid the exception.
+.IP 2) \w'\0\0\0\0'u
+Test a flag to see whether an exception has occurred
+since the program last reset its flag.
+.IP 3) \w'\0\0\0\0'u
+Test a result to see whether it is a value that only
+an exception could have produced.
+.RS
+CAUTION: The only reliable ways to discover
+whether Underflow has occurred are to test whether
+products or quotients lie closer to zero than the
+underflow threshold, or to test the Underflow
+flag. (Sums and differences cannot underflow in
+IEEE 754; if x
+.if n \
+!=
+.if t \
+\(!=
+y then x\-y is correct to
+full precision and certainly nonzero regardless of
+how tiny it may be.) Products and quotients that
+underflow gradually can lose accuracy gradually
+without vanishing, so comparing them with zero
+(as one might on a VAX) will not reveal the loss.
+Fortunately, if a gradually underflowed value is
+destined to be added to something bigger than the
+underflow threshold, as is almost always the case,
+digits lost to gradual underflow will not be missed
+because they would have been rounded off anyway.
+So gradual underflows are usually \fIprovably\fR ignorable.
+The same cannot be said of underflows flushed to 0.
+.RE
+.PP
+At the option of an implementor conforming to IEEE 754,
+other ways to cope with exceptions may be provided:
+.IP 4) \w'\0\0\0\0'u
+ABORT. This mechanism classifies an exception in
+advance as an incident to be handled by means
+traditionally associated with error\-handling
+statements like "ON ERROR GO TO ...". Different
+languages offer different forms of this statement,
+but most share the following characteristics:
+.IP \(em \w'\0\0\0\0'u
+No means is provided to substitute a value for
+the offending operation's result and resume
+computation from what may be the middle of an
+expression. An exceptional result is abandoned.
+.IP \(em \w'\0\0\0\0'u
+In a subprogram that lacks an error\-handling
+statement, an exception causes the subprogram to
+abort within whatever program called it, and so
+on back up the chain of calling subprograms until
+an error\-handling statement is encountered or the
+whole task is aborted and memory is dumped.
+.IP 5) \w'\0\0\0\0'u
+STOP. This mechanism, requiring an interactive
+debugging environment, is more for the programmer
+than the program. It classifies an exception in
+advance as a symptom of a programmer's error; the
+exception suspends execution as near as it can to
+the offending operation so that the programmer can
+look around to see how it happened. Quite often
+the first several exceptions turn out to be quite
+unexceptionable, so the programmer ought ideally
+to be able to resume execution after each one as if
+execution had not been stopped.
+.IP 6) \w'\0\0\0\0'u
+\&... Other ways lie beyond the scope of this document.
+.RE
+.PP
+The crucial problem for exception handling is the problem of
+Scope, and the problem's solution is understood, but not
+enough manpower was available to implement it fully in time
+to be distributed in 4.3 BSD's \fIlibm\fR. Ideally, each
+elementary function should act as if it were indivisible, or
+atomic, in the sense that ...
+.IP i) \w'iii)'u+2n
+No exception should be signaled that is not deserved by
+the data supplied to that function.
+.IP ii) \w'iii)'u+2n
+Any exception signaled should be identified with that
+function rather than with one of its subroutines.
+.IP iii) \w'iii)'u+2n
+The internal behavior of an atomic function should not
+be disrupted when a calling program changes from
+one to another of the five or so ways of handling
+exceptions listed above, although the definition
+of the function may be correlated intentionally
+with exception handling.
+.PP
+Ideally, every programmer should be able \fIconveniently\fR to
+turn a debugged subprogram into one that appears atomic to
+its users. But simulating all three characteristics of an
+atomic function is still a tedious affair, entailing hosts
+of tests and saves\-restores; work is under way to ameliorate
+the inconvenience.
+.PP
+Meanwhile, the functions in \fIlibm\fR are only approximately
+atomic. They signal no inappropriate exception except
+possibly ...
+.RS
+Over/Underflow
+.RS
+when a result, if properly computed, might have lain barely within range, and
+.RE
+Inexact in \fIcabs\fR, \fIcbrt\fR, \fIhypot\fR, \fIlog10\fR and \fIpow\fR
+.RS
+when it happens to be exact, thanks to fortuitous cancellation of errors.
+.RE
+.RE
+Otherwise, ...
+.RS
+Invalid Operation is signaled only when
+.RS
+any result but \*(nn would probably be misleading.
+.RE
+Overflow is signaled only when
+.RS
+the exact result would be finite but beyond the overflow threshold.
+.RE
+Divide\-by\-Zero is signaled only when
+.RS
+a function takes exactly infinite values at finite operands.
+.RE
+Underflow is signaled only when
+.RS
+the exact result would be nonzero but tinier than the underflow threshold.
+.RE
+Inexact is signaled only when
+.RS
+greater range or precision would be needed to represent the exact result.
+.RE
+.RE
+.SH BUGS
+When signals are appropriate, they are emitted by certain
+operations within the codes, so a subroutine\-trace may be
+needed to identify the function with its signal in case
+method 5) above is in use. And the codes all take the
+IEEE 754 defaults for granted; this means that a decision to
+trap all divisions by zero could disrupt a code that would
+otherwise get correct results despite division by zero.
+.SH SEE ALSO
+An explanation of IEEE 754 and its proposed extension p854
+was published in the IEEE magazine MICRO in August 1984 under
+the title "A Proposed Radix\- and Word\-length\-independent
+Standard for Floating\-point Arithmetic" by W. J. Cody et al.
+The manuals for Pascal, C and BASIC on the Apple Macintosh
+document the features of IEEE 754 pretty well.
+Articles in the IEEE magazine COMPUTER vol. 14 no. 3 (Mar.
+1981), and in the ACM SIGNUM Newsletter Special Issue of
+Oct. 1979, may be helpful although they pertain to
+superseded drafts of the standard.
diff --git a/lib/msun/man/rint.3 b/lib/msun/man/rint.3
new file mode 100644
index 0000000..5aa591d
--- /dev/null
+++ b/lib/msun/man/rint.3
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1985, 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.
+.\" 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: @(#)rint.3 5.1 (Berkeley) 5/2/91
+.\" $Id$
+.\"
+.Dd March 10, 1994
+.Dt RINT 3
+.Os
+.Sh NAME
+.Nm rint ,
+.Nm rintf
+.Nd round to integral value in floating-point format
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn rint "double x"
+.Ft float
+.Fn rintf "float x"
+.Sh DESCRIPTION
+The
+.Fn rint
+and the
+.Fn rintf
+functions return the integral value (represented as a double or float
+precision number) nearest to
+.Fa x
+according to the prevailing rounding mode.
+.Sh SEE ALSO
+.Xr abs 3 ,
+.Xr ceil 3 ,
+.Xr fabs 3 ,
+.Xr floor 3 ,
+.Xr ieee 3 ,
+.Xr math 3
+.Sh HISTORY
+A
+.Fn rint
+function appeared in
+.At v6 .
diff --git a/lib/msun/man/sin.3 b/lib/msun/man/sin.3
new file mode 100644
index 0000000..222f24b
--- /dev/null
+++ b/lib/msun/man/sin.3
@@ -0,0 +1,80 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" @(#)sin.3 6.7 (Berkeley) 4/19/91
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)sin.3 6.7 (Berkeley) 4/19/91
+.\" $Id$
+.\"
+.Dd April 19, 1991
+.Dt SIN 3
+.Os
+.Sh NAME
+.Nm sin ,
+.Nm sinf
+.Nd sine functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn sin "double x"
+.Ft float
+.Fn sinf "float x"
+.Sh DESCRIPTION
+The
+.Fn sin
+and the
+.Fn sinf
+functions compute the sine of
+.Fa x
+(measured in radians).
+A large magnitude argument may yield a result with little
+or no significance.
+.Sh RETURN VALUES
+The
+.Fn sin
+and the
+.Fn sinf
+functions return the sine value.
+.Sh SEE ALSO
+.Xr acos 3 ,
+.Xr asin 3 ,
+.Xr atan 3 ,
+.Xr atan2 3 ,
+.Xr cos 3 ,
+.Xr cosh 3 ,
+.Xr math 3 ,
+.Xr sinh 3 ,
+.Xr tan 3 ,
+.Xr tanh 3
+.Sh STANDARDS
+The
+.Fn sin
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/man/sinh.3 b/lib/msun/man/sinh.3
new file mode 100644
index 0000000..91b17f1
--- /dev/null
+++ b/lib/msun/man/sinh.3
@@ -0,0 +1,82 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)sinh.3 6.6 (Berkeley) 4/19/91
+.\" $Id$
+.Dd April 19, 1991
+.Dt SINH 3
+.Os
+.Sh NAME
+.Nm sinh ,
+.Nm sinhf
+.Nd hyperbolic sine function
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn sinh "double x"
+.Ft float
+.Fn sinhf "float x"
+.Sh DESCRIPTION
+The
+.Fn sinh
+and the
+.Fn sinhf
+functions compute the hyperbolic sine of
+.Fa x .
+.Sh RETURN VALUES
+The
+.Fn sinh
+and the
+.Fn sinhf
+functions return the hyperbolic sine value unless
+the magnitude
+of
+.Fa x
+is too large; in this event, the global variable
+.Va errno
+is set to
+.Er ERANGE .
+.Sh SEE ALSO
+.Xr acos 3 ,
+.Xr asin 3 ,
+.Xr atan 3 ,
+.Xr atan2 3 ,
+.Xr cos 3 ,
+.Xr cosh 3 ,
+.Xr math 3 ,
+.Xr sin 3 ,
+.Xr tan 3 ,
+.Xr tanh 3
+.Sh STANDARDS
+The
+.Fn sinh
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/man/sqrt.3 b/lib/msun/man/sqrt.3
new file mode 100644
index 0000000..d3e698d
--- /dev/null
+++ b/lib/msun/man/sqrt.3
@@ -0,0 +1,134 @@
+.\" Copyright (c) 1985, 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.
+.\" 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: @(#)sqrt.3 6.4 (Berkeley) 5/6/91
+.\" $Id$
+.\"
+.Dd May 6, 1991
+.Dt SQRT 3
+.Os
+.Sh NAME
+.Nm cbrt ,
+.Nm cbrtf ,
+.Nm sqrt ,
+.Nm sqrtf
+.Nd cube root and square root functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn cbrt "double x"
+.Ft float
+.Fn cbrtf "float x"
+.Ft double
+.Fn sqrt "double x"
+.Ft float
+.Fn sqrtf "float x"
+.Sh DESCRIPTION
+The
+.Fn cbrt
+and the
+.Fn cbrtf
+functions compute
+the cube root of
+.Ar x .
+.Pp
+The
+.Fn sqrt
+and the
+.Fn sqrtf
+functions compute the
+non-negative square root of x.
+.Sh RETURN VALUES
+The
+.Fn cbrt
+and the
+.Fn cbrtf
+functions return the requested cube root.
+The
+.Fn sqrt
+and the
+.Fn sqrtf
+functions return the requested square root
+unless an error occurs.
+On the
+.Tn VAX
+or
+.Tn Tahoe
+processor an attempt to take the
+.Fn sqrt
+of negative
+.Fa x
+causes an error; in this event,
+the global variable
+.Va errno
+is set to
+.Dv EDOM
+and a reserved operand fault is generated.
+.Sh ERROR (due to Roundoff etc.)
+The
+.Fn cbrt
+function
+is accurate to within 0.7
+.Em ulps .
+.Pp
+The
+.Fn sqrt
+function on a
+.Tn VAX
+is accurate to within 0.501
+.Em ulps .
+Sqrt on a machine that conforms to
+.Tn IEEE
+754 is correctly rounded
+in accordance with the rounding mode in force; the error is less than
+half an
+.Em ulp
+in the default mode (round\-to\-nearest).
+An
+.Em ulp
+is one
+.Em U Ns nit
+in the
+.Em L Ns ast
+.Em P Ns lace
+carried.
+.Sh SEE ALSO
+.Xr math 3
+.Sh STANDARDS
+The
+.Nm sqrt
+function conforms to
+.St -ansiC .
+.Sh HISTORY
+The
+.Nm cbrt
+function appeared in
+.Bx 4.3 .
diff --git a/lib/msun/man/tan.3 b/lib/msun/man/tan.3
new file mode 100644
index 0000000..21af639
--- /dev/null
+++ b/lib/msun/man/tan.3
@@ -0,0 +1,79 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)tan.3 5.1 (Berkeley) 5/2/91
+.\" $Id$
+.\"
+.Dd May 2, 1991
+.Dt TAN 3
+.Os
+.Sh NAME
+.Nm tan ,
+.Nm tanf
+.Nd tangent functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn tan "double x"
+.Ft float
+.Fn tanf "float x"
+.Sh DESCRIPTION
+The
+.Fn tan
+and the
+.Fn tanf
+functions compute the tangent of
+.Fa x
+(measured in radians).
+A large magnitude argument may yield a result
+with little or no significance.
+For a discussion of error due to roundoff, see
+.Xr math 3 .
+.Sh RETURN VALUES
+The
+.Fn tan
+function returns the tangent value.
+.Sh SEE ALSO
+.Xr acos 3 ,
+.Xr asin 3 ,
+.Xr atan 3 ,
+.Xr atan2 3 ,
+.Xr cos 3 ,
+.Xr cosh 3 ,
+.Xr math 3 ,
+.Xr sin 3 ,
+.Xr sinh 3 ,
+.Xr tanh 3
+.Sh STANDARDS
+The
+.Fn tan
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/man/tanh.3 b/lib/msun/man/tanh.3
new file mode 100644
index 0000000..3d5f902
--- /dev/null
+++ b/lib/msun/man/tanh.3
@@ -0,0 +1,78 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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: @(#)tanh.3 5.1 (Berkeley) 5/2/91
+.\" $Id$
+.\"
+.Dd May 2, 1991
+.Dt TANH 3
+.Os
+.Sh NAME
+.Nm tanh ,
+.Nm tanhf
+.Nd hyperbolic tangent functions
+.Sh SYNOPSIS
+.Fd #include <math.h>
+.Ft double
+.Fn tanh "double x"
+.Ft float
+.Fn tanhf "float x"
+.Sh DESCRIPTION
+The
+.Fn tanh
+and the
+.Fn tanhf
+functions compute the hyperbolic tangent of
+.Fa x .
+For a discussion of error due to roundoff, see
+.Xr math 3 .
+.Sh RETURN VALUES
+The
+.Fn tanh
+and the
+.Fn tanhf
+functions return the hyperbolic tangent value.
+.Sh SEE ALSO
+.Xr acos 3 ,
+.Xr asin 3 ,
+.Xr atan 3 ,
+.Xr atan2 3 ,
+.Xr cos 3 ,
+.Xr cosh 3 ,
+.Xr math 3 ,
+.Xr sin 3 ,
+.Xr sinh 3 ,
+.Xr tan 3
+.Sh STANDARDS
+The
+.Fn tanh
+function conforms to
+.St -ansiC .
diff --git a/lib/msun/src/e_acos.c b/lib/msun/src/e_acos.c
new file mode 100644
index 0000000..da965af
--- /dev/null
+++ b/lib/msun/src/e_acos.c
@@ -0,0 +1,111 @@
+/* @(#)e_acos.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: e_acos.c,v 1.5 1997/02/22 15:09:54 peter Exp $";
+#endif
+
+/* __ieee754_acos(x)
+ * Method :
+ * acos(x) = pi/2 - asin(x)
+ * acos(-x) = pi/2 + asin(x)
+ * For |x|<=0.5
+ * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c)
+ * For x>0.5
+ * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2)))
+ * = 2asin(sqrt((1-x)/2))
+ * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z)
+ * = 2f + (2c + 2s*z*R(z))
+ * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term
+ * for f so that f+c ~ sqrt(z).
+ * For x<-0.5
+ * acos(x) = pi - 2asin(sqrt((1-|x|)/2))
+ * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z)
+ *
+ * Special cases:
+ * if x is NaN, return x itself;
+ * if |x|>1, return NaN with invalid signal.
+ *
+ * Function needed: __ieee754_sqrt
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
+pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
+pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
+pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
+pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
+pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
+pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
+pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
+pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
+qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
+qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
+qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
+qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
+
+#ifdef __STDC__
+ double __generic___ieee754_acos(double x)
+#else
+ double __generic___ieee754_acos(x)
+ double x;
+#endif
+{
+ double z,p,q,r,w,s,c,df;
+ int32_t hx,ix;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x3ff00000) { /* |x| >= 1 */
+ u_int32_t lx;
+ GET_LOW_WORD(lx,x);
+ if(((ix-0x3ff00000)|lx)==0) { /* |x|==1 */
+ if(hx>0) return 0.0; /* acos(1) = 0 */
+ else return pi+2.0*pio2_lo; /* acos(-1)= pi */
+ }
+ return (x-x)/(x-x); /* acos(|x|>1) is NaN */
+ }
+ if(ix<0x3fe00000) { /* |x| < 0.5 */
+ if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/
+ z = x*x;
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ r = p/q;
+ return pio2_hi - (x - (pio2_lo-x*r));
+ } else if (hx<0) { /* x < -0.5 */
+ z = (one+x)*0.5;
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ s = __ieee754_sqrt(z);
+ r = p/q;
+ w = r*s-pio2_lo;
+ return pi - 2.0*(s+w);
+ } else { /* x > 0.5 */
+ z = (one-x)*0.5;
+ s = __ieee754_sqrt(z);
+ df = s;
+ SET_LOW_WORD(df,0);
+ c = (z-df*df)/(s+df);
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ r = p/q;
+ w = r*s+c;
+ return 2.0*(df+w);
+ }
+}
diff --git a/lib/msun/src/e_acosf.c b/lib/msun/src/e_acosf.c
new file mode 100644
index 0000000..f3c6a50
--- /dev/null
+++ b/lib/msun/src/e_acosf.c
@@ -0,0 +1,89 @@
+/* e_acosf.c -- float version of e_acos.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: e_acosf.c,v 1.4 1997/02/22 15:09:55 peter Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+one = 1.0000000000e+00, /* 0x3F800000 */
+pi = 3.1415925026e+00, /* 0x40490fda */
+pio2_hi = 1.5707962513e+00, /* 0x3fc90fda */
+pio2_lo = 7.5497894159e-08, /* 0x33a22168 */
+pS0 = 1.6666667163e-01, /* 0x3e2aaaab */
+pS1 = -3.2556581497e-01, /* 0xbea6b090 */
+pS2 = 2.0121252537e-01, /* 0x3e4e0aa8 */
+pS3 = -4.0055535734e-02, /* 0xbd241146 */
+pS4 = 7.9153501429e-04, /* 0x3a4f7f04 */
+pS5 = 3.4793309169e-05, /* 0x3811ef08 */
+qS1 = -2.4033949375e+00, /* 0xc019d139 */
+qS2 = 2.0209457874e+00, /* 0x4001572d */
+qS3 = -6.8828397989e-01, /* 0xbf303361 */
+qS4 = 7.7038154006e-02; /* 0x3d9dc62e */
+
+#ifdef __STDC__
+ float __ieee754_acosf(float x)
+#else
+ float __ieee754_acosf(x)
+ float x;
+#endif
+{
+ float z,p,q,r,w,s,c,df;
+ int32_t hx,ix;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix==0x3f800000) { /* |x|==1 */
+ if(hx>0) return 0.0; /* acos(1) = 0 */
+ else return pi+(float)2.0*pio2_lo; /* acos(-1)= pi */
+ } else if(ix>0x3f800000) { /* |x| >= 1 */
+ return (x-x)/(x-x); /* acos(|x|>1) is NaN */
+ }
+ if(ix<0x3f000000) { /* |x| < 0.5 */
+ if(ix<=0x23000000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/
+ z = x*x;
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ r = p/q;
+ return pio2_hi - (x - (pio2_lo-x*r));
+ } else if (hx<0) { /* x < -0.5 */
+ z = (one+x)*(float)0.5;
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ s = __ieee754_sqrtf(z);
+ r = p/q;
+ w = r*s-pio2_lo;
+ return pi - (float)2.0*(s+w);
+ } else { /* x > 0.5 */
+ int32_t idf;
+ z = (one-x)*(float)0.5;
+ s = __ieee754_sqrtf(z);
+ df = s;
+ GET_FLOAT_WORD(idf,df);
+ SET_FLOAT_WORD(df,idf&0xfffff000);
+ c = (z-df*df)/(s+df);
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ r = p/q;
+ w = r*s+c;
+ return (float)2.0*(df+w);
+ }
+}
diff --git a/lib/msun/src/e_acosh.c b/lib/msun/src/e_acosh.c
new file mode 100644
index 0000000..a471769
--- /dev/null
+++ b/lib/msun/src/e_acosh.c
@@ -0,0 +1,69 @@
+/* @(#)e_acosh.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: e_acosh.c,v 1.4 1997/02/22 15:09:56 peter Exp $";
+#endif
+
+/* __ieee754_acosh(x)
+ * Method :
+ * Based on
+ * acosh(x) = log [ x + sqrt(x*x-1) ]
+ * we have
+ * acosh(x) := log(x)+ln2, if x is large; else
+ * acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
+ * acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
+ *
+ * Special cases:
+ * acosh(x) is NaN with signal if x<1.
+ * acosh(NaN) is NaN without signal.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one = 1.0,
+ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */
+
+#ifdef __STDC__
+ double __ieee754_acosh(double x)
+#else
+ double __ieee754_acosh(x)
+ double x;
+#endif
+{
+ double t;
+ int32_t hx;
+ u_int32_t lx;
+ EXTRACT_WORDS(hx,lx,x);
+ if(hx<0x3ff00000) { /* x < 1 */
+ return (x-x)/(x-x);
+ } else if(hx >=0x41b00000) { /* x > 2**28 */
+ if(hx >=0x7ff00000) { /* x is inf of NaN */
+ return x+x;
+ } else
+ return __ieee754_log(x)+ln2; /* acosh(huge)=log(2x) */
+ } else if(((hx-0x3ff00000)|lx)==0) {
+ return 0.0; /* acosh(1) = 0 */
+ } else if (hx > 0x40000000) { /* 2**28 > x > 2 */
+ t=x*x;
+ return __ieee754_log(2.0*x-one/(x+__ieee754_sqrt(t-one)));
+ } else { /* 1<x<2 */
+ t = x-one;
+ return log1p(t+__ieee754_sqrt(2.0*t+t*t));
+ }
+}
diff --git a/lib/msun/src/e_acoshf.c b/lib/msun/src/e_acoshf.c
new file mode 100644
index 0000000..1d234d2
--- /dev/null
+++ b/lib/msun/src/e_acoshf.c
@@ -0,0 +1,57 @@
+/* e_acoshf.c -- float version of e_acosh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: e_acoshf.c,v 1.4 1997/02/22 15:09:56 peter Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+one = 1.0,
+ln2 = 6.9314718246e-01; /* 0x3f317218 */
+
+#ifdef __STDC__
+ float __ieee754_acoshf(float x)
+#else
+ float __ieee754_acoshf(x)
+ float x;
+#endif
+{
+ float t;
+ int32_t hx;
+ GET_FLOAT_WORD(hx,x);
+ if(hx<0x3f800000) { /* x < 1 */
+ return (x-x)/(x-x);
+ } else if(hx >=0x4d800000) { /* x > 2**28 */
+ if(hx >=0x7f800000) { /* x is inf of NaN */
+ return x+x;
+ } else
+ return __ieee754_logf(x)+ln2; /* acosh(huge)=log(2x) */
+ } else if (hx==0x3f800000) {
+ return 0.0; /* acosh(1) = 0 */
+ } else if (hx > 0x40000000) { /* 2**28 > x > 2 */
+ t=x*x;
+ return __ieee754_logf((float)2.0*x-one/(x+__ieee754_sqrtf(t-one)));
+ } else { /* 1<x<2 */
+ t = x-one;
+ return log1pf(t+__ieee754_sqrtf((float)2.0*t+t*t));
+ }
+}
diff --git a/lib/msun/src/e_asin.c b/lib/msun/src/e_asin.c
new file mode 100644
index 0000000..e7814c9
--- /dev/null
+++ b/lib/msun/src/e_asin.c
@@ -0,0 +1,120 @@
+/* @(#)e_asin.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: e_asin.c,v 1.6 1997/02/22 15:09:57 peter Exp $";
+#endif
+
+/* __ieee754_asin(x)
+ * Method :
+ * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
+ * we approximate asin(x) on [0,0.5] by
+ * asin(x) = x + x*x^2*R(x^2)
+ * where
+ * R(x^2) is a rational approximation of (asin(x)-x)/x^3
+ * and its remez error is bounded by
+ * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75)
+ *
+ * For x in [0.5,1]
+ * asin(x) = pi/2-2*asin(sqrt((1-x)/2))
+ * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
+ * then for x>0.98
+ * asin(x) = pi/2 - 2*(s+s*z*R(z))
+ * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
+ * For x<=0.98, let pio4_hi = pio2_hi/2, then
+ * f = hi part of s;
+ * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z)
+ * and
+ * asin(x) = pi/2 - 2*(s+s*z*R(z))
+ * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
+ * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
+ *
+ * Special cases:
+ * if x is NaN, return x itself;
+ * if |x|>1, return NaN with invalid signal.
+ *
+ */
+
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+huge = 1.000e+300,
+pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
+pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
+pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
+ /* coefficient for R(x^2) */
+pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
+pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
+pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
+pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
+pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
+pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
+qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
+qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
+qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
+qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
+
+#ifdef __STDC__
+ double __generic___ieee754_asin(double x)
+#else
+ double __generic___ieee754_asin(x)
+ double x;
+#endif
+{
+ double t=0.0,w,p,q,c,r,s;
+ int32_t hx,ix;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>= 0x3ff00000) { /* |x|>= 1 */
+ u_int32_t lx;
+ GET_LOW_WORD(lx,x);
+ if(((ix-0x3ff00000)|lx)==0)
+ /* asin(1)=+-pi/2 with inexact */
+ return x*pio2_hi+x*pio2_lo;
+ return (x-x)/(x-x); /* asin(|x|>1) is NaN */
+ } else if (ix<0x3fe00000) { /* |x|<0.5 */
+ if(ix<0x3e400000) { /* if |x| < 2**-27 */
+ if(huge+x>one) return x;/* return x with inexact if x!=0*/
+ } else
+ t = x*x;
+ p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+ q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+ w = p/q;
+ return x+x*w;
+ }
+ /* 1> |x|>= 0.5 */
+ w = one-fabs(x);
+ t = w*0.5;
+ p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+ q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+ s = __ieee754_sqrt(t);
+ if(ix>=0x3FEF3333) { /* if |x| > 0.975 */
+ w = p/q;
+ t = pio2_hi-(2.0*(s+s*w)-pio2_lo);
+ } else {
+ w = s;
+ SET_LOW_WORD(w,0);
+ c = (t-w*w)/(s+w);
+ r = p/q;
+ p = 2.0*s*r-(pio2_lo-2.0*c);
+ q = pio4_hi-2.0*w;
+ t = pio4_hi-(p-q);
+ }
+ if(hx>0) return t; else return -t;
+}
diff --git a/lib/msun/src/e_asinf.c b/lib/msun/src/e_asinf.c
new file mode 100644
index 0000000..593f2e5
--- /dev/null
+++ b/lib/msun/src/e_asinf.c
@@ -0,0 +1,92 @@
+/* e_asinf.c -- float version of e_asin.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: e_asinf.c,v 1.5 1997/02/22 15:09:58 peter Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+one = 1.0000000000e+00, /* 0x3F800000 */
+huge = 1.000e+30,
+pio2_hi = 1.5707962513e+00, /* 0x3fc90fda */
+pio2_lo = 7.5497894159e-08, /* 0x33a22168 */
+pio4_hi = 7.8539818525e-01, /* 0x3f490fdb */
+ /* coefficient for R(x^2) */
+pS0 = 1.6666667163e-01, /* 0x3e2aaaab */
+pS1 = -3.2556581497e-01, /* 0xbea6b090 */
+pS2 = 2.0121252537e-01, /* 0x3e4e0aa8 */
+pS3 = -4.0055535734e-02, /* 0xbd241146 */
+pS4 = 7.9153501429e-04, /* 0x3a4f7f04 */
+pS5 = 3.4793309169e-05, /* 0x3811ef08 */
+qS1 = -2.4033949375e+00, /* 0xc019d139 */
+qS2 = 2.0209457874e+00, /* 0x4001572d */
+qS3 = -6.8828397989e-01, /* 0xbf303361 */
+qS4 = 7.7038154006e-02; /* 0x3d9dc62e */
+
+#ifdef __STDC__
+ float __ieee754_asinf(float x)
+#else
+ float __ieee754_asinf(x)
+ float x;
+#endif
+{
+ float t=0.0,w,p,q,c,r,s;
+ int32_t hx,ix;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix==0x3f800000) {
+ /* asin(1)=+-pi/2 with inexact */
+ return x*pio2_hi+x*pio2_lo;
+ } else if(ix> 0x3f800000) { /* |x|>= 1 */
+ return (x-x)/(x-x); /* asin(|x|>1) is NaN */
+ } else if (ix<0x3f000000) { /* |x|<0.5 */
+ if(ix<0x32000000) { /* if |x| < 2**-27 */
+ if(huge+x>one) return x;/* return x with inexact if x!=0*/
+ } else
+ t = x*x;
+ p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+ q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+ w = p/q;
+ return x+x*w;
+ }
+ /* 1> |x|>= 0.5 */
+ w = one-fabsf(x);
+ t = w*(float)0.5;
+ p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+ q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+ s = __ieee754_sqrtf(t);
+ if(ix>=0x3F79999A) { /* if |x| > 0.975 */
+ w = p/q;
+ t = pio2_hi-((float)2.0*(s+s*w)-pio2_lo);
+ } else {
+ int32_t iw;
+ w = s;
+ GET_FLOAT_WORD(iw,w);
+ SET_FLOAT_WORD(w,iw&0xfffff000);
+ c = (t-w*w)/(s+w);
+ r = p/q;
+ p = (float)2.0*s*r-(pio2_lo-(float)2.0*c);
+ q = pio4_hi-(float)2.0*w;
+ t = pio4_hi-(p-q);
+ }
+ if(hx>0) return t; else return -t;
+}
diff --git a/lib/msun/src/e_atan2.c b/lib/msun/src/e_atan2.c
new file mode 100644
index 0000000..d85db89
--- /dev/null
+++ b/lib/msun/src/e_atan2.c
@@ -0,0 +1,130 @@
+/* @(#)e_atan2.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_atan2(y,x)
+ * Method :
+ * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
+ * 2. Reduce x to positive by (if x and y are unexceptional):
+ * ARG (x+iy) = arctan(y/x) ... if x > 0,
+ * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0,
+ *
+ * Special cases:
+ *
+ * ATAN2((anything), NaN ) is NaN;
+ * ATAN2(NAN , (anything) ) is NaN;
+ * ATAN2(+-0, +(anything but NaN)) is +-0 ;
+ * ATAN2(+-0, -(anything but NaN)) is +-pi ;
+ * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
+ * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
+ * ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
+ * ATAN2(+-INF,+INF ) is +-pi/4 ;
+ * ATAN2(+-INF,-INF ) is +-3pi/4;
+ * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+tiny = 1.0e-300,
+zero = 0.0,
+pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
+pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
+pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
+pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
+
+#ifdef __STDC__
+ double __generic___ieee754_atan2(double y, double x)
+#else
+ double __generic___ieee754_atan2(y,x)
+ double y,x;
+#endif
+{
+ double z;
+ int32_t k,m,hx,hy,ix,iy;
+ u_int32_t lx,ly;
+
+ EXTRACT_WORDS(hx,lx,x);
+ ix = hx&0x7fffffff;
+ EXTRACT_WORDS(hy,ly,y);
+ iy = hy&0x7fffffff;
+ if(((ix|((lx|-lx)>>31))>0x7ff00000)||
+ ((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */
+ return x+y;
+ if(((hx-0x3ff00000)|lx)==0) return atan(y); /* x=1.0 */
+ m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */
+
+ /* when y = 0 */
+ if((iy|ly)==0) {
+ switch(m) {
+ case 0:
+ case 1: return y; /* atan(+-0,+anything)=+-0 */
+ case 2: return pi+tiny;/* atan(+0,-anything) = pi */
+ case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
+ }
+ }
+ /* when x = 0 */
+ if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+ /* when x is INF */
+ if(ix==0x7ff00000) {
+ if(iy==0x7ff00000) {
+ switch(m) {
+ case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */
+ case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
+ case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
+ case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
+ }
+ } else {
+ switch(m) {
+ case 0: return zero ; /* atan(+...,+INF) */
+ case 1: return -zero ; /* atan(-...,+INF) */
+ case 2: return pi+tiny ; /* atan(+...,-INF) */
+ case 3: return -pi-tiny ; /* atan(-...,-INF) */
+ }
+ }
+ }
+ /* when y is INF */
+ if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+ /* compute y/x */
+ k = (iy-ix)>>20;
+ if(k > 60) z=pi_o_2+0.5*pi_lo; /* |y/x| > 2**60 */
+ else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */
+ else z=atan(fabs(y/x)); /* safe to do y/x */
+ switch (m) {
+ case 0: return z ; /* atan(+,+) */
+ case 1: {
+ u_int32_t zh;
+ GET_HIGH_WORD(zh,z);
+ SET_HIGH_WORD(z,zh ^ 0x80000000);
+ }
+ return z ; /* atan(-,+) */
+ case 2: return pi-(z-pi_lo);/* atan(+,-) */
+ default: /* case 3 */
+ return (z-pi_lo)-pi;/* atan(-,-) */
+ }
+}
diff --git a/lib/msun/src/e_atan2f.c b/lib/msun/src/e_atan2f.c
new file mode 100644
index 0000000..6742432
--- /dev/null
+++ b/lib/msun/src/e_atan2f.c
@@ -0,0 +1,105 @@
+/* e_atan2f.c -- float version of e_atan2.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+tiny = 1.0e-30,
+zero = 0.0,
+pi_o_4 = 7.8539818525e-01, /* 0x3f490fdb */
+pi_o_2 = 1.5707963705e+00, /* 0x3fc90fdb */
+pi = 3.1415925026e+00, /* 0x40490fda */
+pi_lo = 1.5099578832e-07; /* 0x34222168 */
+
+#ifdef __STDC__
+ float __ieee754_atan2f(float y, float x)
+#else
+ float __ieee754_atan2f(y,x)
+ float y,x;
+#endif
+{
+ float z;
+ int32_t k,m,hx,hy,ix,iy;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ GET_FLOAT_WORD(hy,y);
+ iy = hy&0x7fffffff;
+ if((ix>0x7f800000)||
+ (iy>0x7f800000)) /* x or y is NaN */
+ return x+y;
+ if(hx==0x3f800000) return atanf(y); /* x=1.0 */
+ m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */
+
+ /* when y = 0 */
+ if(iy==0) {
+ switch(m) {
+ case 0:
+ case 1: return y; /* atan(+-0,+anything)=+-0 */
+ case 2: return pi+tiny;/* atan(+0,-anything) = pi */
+ case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
+ }
+ }
+ /* when x = 0 */
+ if(ix==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+ /* when x is INF */
+ if(ix==0x7f800000) {
+ if(iy==0x7f800000) {
+ switch(m) {
+ case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */
+ case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
+ case 2: return (float)3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
+ case 3: return (float)-3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
+ }
+ } else {
+ switch(m) {
+ case 0: return zero ; /* atan(+...,+INF) */
+ case 1: return -zero ; /* atan(-...,+INF) */
+ case 2: return pi+tiny ; /* atan(+...,-INF) */
+ case 3: return -pi-tiny ; /* atan(-...,-INF) */
+ }
+ }
+ }
+ /* when y is INF */
+ if(iy==0x7f800000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+ /* compute y/x */
+ k = (iy-ix)>>23;
+ if(k > 60) z=pi_o_2+(float)0.5*pi_lo; /* |y/x| > 2**60 */
+ else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */
+ else z=atanf(fabsf(y/x)); /* safe to do y/x */
+ switch (m) {
+ case 0: return z ; /* atan(+,+) */
+ case 1: {
+ u_int32_t zh;
+ GET_FLOAT_WORD(zh,z);
+ SET_FLOAT_WORD(z,zh ^ 0x80000000);
+ }
+ return z ; /* atan(-,+) */
+ case 2: return pi-(z-pi_lo);/* atan(+,-) */
+ default: /* case 3 */
+ return (z-pi_lo)-pi;/* atan(-,-) */
+ }
+}
diff --git a/lib/msun/src/e_atanh.c b/lib/msun/src/e_atanh.c
new file mode 100644
index 0000000..0c683e1
--- /dev/null
+++ b/lib/msun/src/e_atanh.c
@@ -0,0 +1,74 @@
+/* @(#)e_atanh.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_atanh(x)
+ * Method :
+ * 1.Reduced x to positive by atanh(-x) = -atanh(x)
+ * 2.For x>=0.5
+ * 1 2x x
+ * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
+ * 2 1 - x 1 - x
+ *
+ * For x<0.5
+ * atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
+ *
+ * Special cases:
+ * atanh(x) is NaN if |x| > 1 with signal;
+ * atanh(NaN) is that NaN with no signal;
+ * atanh(+-1) is +-INF with signal.
+ *
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double one = 1.0, huge = 1e300;
+#else
+static double one = 1.0, huge = 1e300;
+#endif
+
+#ifdef __STDC__
+static const double zero = 0.0;
+#else
+static double zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ double __ieee754_atanh(double x)
+#else
+ double __ieee754_atanh(x)
+ double x;
+#endif
+{
+ double t;
+ int32_t hx,ix;
+ u_int32_t lx;
+ EXTRACT_WORDS(hx,lx,x);
+ ix = hx&0x7fffffff;
+ if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */
+ return (x-x)/(x-x);
+ if(ix==0x3ff00000)
+ return x/zero;
+ if(ix<0x3e300000&&(huge+x)>zero) return x; /* x<2**-28 */
+ SET_HIGH_WORD(x,ix);
+ if(ix<0x3fe00000) { /* x < 0.5 */
+ t = x+x;
+ t = 0.5*log1p(t+t*x/(one-x));
+ } else
+ t = 0.5*log1p((x+x)/(one-x));
+ if(hx>=0) return t; else return -t;
+}
diff --git a/lib/msun/src/e_atanhf.c b/lib/msun/src/e_atanhf.c
new file mode 100644
index 0000000..d4126af
--- /dev/null
+++ b/lib/msun/src/e_atanhf.c
@@ -0,0 +1,58 @@
+/* e_atanhf.c -- float version of e_atanh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float one = 1.0, huge = 1e30;
+#else
+static float one = 1.0, huge = 1e30;
+#endif
+
+#ifdef __STDC__
+static const float zero = 0.0;
+#else
+static float zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ float __ieee754_atanhf(float x)
+#else
+ float __ieee754_atanhf(x)
+ float x;
+#endif
+{
+ float t;
+ int32_t hx,ix;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if (ix>0x3f800000) /* |x|>1 */
+ return (x-x)/(x-x);
+ if(ix==0x3f800000)
+ return x/zero;
+ if(ix<0x31800000&&(huge+x)>zero) return x; /* x<2**-28 */
+ SET_FLOAT_WORD(x,ix);
+ if(ix<0x3f000000) { /* x < 0.5 */
+ t = x+x;
+ t = (float)0.5*log1pf(t+t*x/(one-x));
+ } else
+ t = (float)0.5*log1pf((x+x)/(one-x));
+ if(hx>=0) return t; else return -t;
+}
diff --git a/lib/msun/src/e_cosh.c b/lib/msun/src/e_cosh.c
new file mode 100644
index 0000000..3a7ac97
--- /dev/null
+++ b/lib/msun/src/e_cosh.c
@@ -0,0 +1,93 @@
+/* @(#)e_cosh.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_cosh(x)
+ * Method :
+ * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
+ * 1. Replace x by |x| (cosh(x) = cosh(-x)).
+ * 2.
+ * [ exp(x) - 1 ]^2
+ * 0 <= x <= ln2/2 : cosh(x) := 1 + -------------------
+ * 2*exp(x)
+ *
+ * exp(x) + 1/exp(x)
+ * ln2/2 <= x <= 22 : cosh(x) := -------------------
+ * 2
+ * 22 <= x <= lnovft : cosh(x) := exp(x)/2
+ * lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2)
+ * ln2ovft < x : cosh(x) := huge*huge (overflow)
+ *
+ * Special cases:
+ * cosh(x) is |x| if x is +INF, -INF, or NaN.
+ * only cosh(0)=1 is exact for finite x.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double one = 1.0, half=0.5, huge = 1.0e300;
+#else
+static double one = 1.0, half=0.5, huge = 1.0e300;
+#endif
+
+#ifdef __STDC__
+ double __ieee754_cosh(double x)
+#else
+ double __ieee754_cosh(x)
+ double x;
+#endif
+{
+ double t,w;
+ int32_t ix;
+ u_int32_t lx;
+
+ /* High word of |x|. */
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7ff00000) return x*x;
+
+ /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
+ if(ix<0x3fd62e43) {
+ t = expm1(fabs(x));
+ w = one+t;
+ if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */
+ return one+(t*t)/(w+w);
+ }
+
+ /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
+ if (ix < 0x40360000) {
+ t = __ieee754_exp(fabs(x));
+ return half*t+half/t;
+ }
+
+ /* |x| in [22, log(maxdouble)] return half*exp(|x|) */
+ if (ix < 0x40862E42) return half*__ieee754_exp(fabs(x));
+
+ /* |x| in [log(maxdouble), overflowthresold] */
+ GET_LOW_WORD(lx,x);
+ if (ix<0x408633CE ||
+ ((ix==0x408633ce)&&(lx<=(u_int32_t)0x8fb9f87d))) {
+ w = __ieee754_exp(half*fabs(x));
+ t = half*w;
+ return t*w;
+ }
+
+ /* |x| > overflowthresold, cosh(x) overflow */
+ return huge*huge;
+}
diff --git a/lib/msun/src/e_coshf.c b/lib/msun/src/e_coshf.c
new file mode 100644
index 0000000..501d87b
--- /dev/null
+++ b/lib/msun/src/e_coshf.c
@@ -0,0 +1,71 @@
+/* e_coshf.c -- float version of e_cosh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float one = 1.0, half=0.5, huge = 1.0e30;
+#else
+static float one = 1.0, half=0.5, huge = 1.0e30;
+#endif
+
+#ifdef __STDC__
+ float __ieee754_coshf(float x)
+#else
+ float __ieee754_coshf(x)
+ float x;
+#endif
+{
+ float t,w;
+ int32_t ix;
+
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7f800000) return x*x;
+
+ /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
+ if(ix<0x3eb17218) {
+ t = expm1f(fabsf(x));
+ w = one+t;
+ if (ix<0x24000000) return w; /* cosh(tiny) = 1 */
+ return one+(t*t)/(w+w);
+ }
+
+ /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
+ if (ix < 0x41b00000) {
+ t = __ieee754_expf(fabsf(x));
+ return half*t+half/t;
+ }
+
+ /* |x| in [22, log(maxdouble)] return half*exp(|x|) */
+ if (ix < 0x42b17180) return half*__ieee754_expf(fabsf(x));
+
+ /* |x| in [log(maxdouble), overflowthresold] */
+ if (ix<=0x42b2d4fc) {
+ w = __ieee754_expf(half*fabsf(x));
+ t = half*w;
+ return t*w;
+ }
+
+ /* |x| > overflowthresold, cosh(x) overflow */
+ return huge*huge;
+}
diff --git a/lib/msun/src/e_exp.c b/lib/msun/src/e_exp.c
new file mode 100644
index 0000000..e0d6469
--- /dev/null
+++ b/lib/msun/src/e_exp.c
@@ -0,0 +1,167 @@
+/* @(#)e_exp.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_exp(x)
+ * Returns the exponential of x.
+ *
+ * Method
+ * 1. Argument reduction:
+ * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+ * Given x, find r and integer k such that
+ *
+ * x = k*ln2 + r, |r| <= 0.5*ln2.
+ *
+ * Here r will be represented as r = hi-lo for better
+ * accuracy.
+ *
+ * 2. Approximation of exp(r) by a special rational function on
+ * the interval [0,0.34658]:
+ * Write
+ * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+ * We use a special Reme algorithm on [0,0.34658] to generate
+ * a polynomial of degree 5 to approximate R. The maximum error
+ * of this polynomial approximation is bounded by 2**-59. In
+ * other words,
+ * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+ * (where z=r*r, and the values of P1 to P5 are listed below)
+ * and
+ * | 5 | -59
+ * | 2.0+P1*z+...+P5*z - R(z) | <= 2
+ * | |
+ * The computation of exp(r) thus becomes
+ * 2*r
+ * exp(r) = 1 + -------
+ * R - r
+ * r*R1(r)
+ * = 1 + r + ----------- (for better accuracy)
+ * 2 - R1(r)
+ * where
+ * 2 4 10
+ * R1(r) = r - (P1*r + P2*r + ... + P5*r ).
+ *
+ * 3. Scale back to obtain exp(x):
+ * From step 1, we have
+ * exp(x) = 2^k * exp(r)
+ *
+ * Special cases:
+ * exp(INF) is INF, exp(NaN) is NaN;
+ * exp(-INF) is 0, and
+ * for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ * For IEEE double
+ * if x > 7.09782712893383973096e+02 then exp(x) overflow
+ * if x < -7.45133219101941108420e+02 then exp(x) underflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one = 1.0,
+halF[2] = {0.5,-0.5,},
+huge = 1.0e+300,
+twom1000= 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/
+o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
+u_threshold= -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */
+ln2HI[2] ={ 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */
+ -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */
+ln2LO[2] ={ 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */
+ -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */
+invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
+P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
+
+
+#ifdef __STDC__
+ double __generic___ieee754_exp(double x) /* default IEEE double exp */
+#else
+ double __generic___ieee754_exp(x) /* default IEEE double exp */
+ double x;
+#endif
+{
+ double y,hi=0.0,lo=0.0,c,t;
+ int32_t k=0,xsb;
+ u_int32_t hx;
+
+ GET_HIGH_WORD(hx,x);
+ xsb = (hx>>31)&1; /* sign bit of x */
+ hx &= 0x7fffffff; /* high word of |x| */
+
+ /* filter out non-finite argument */
+ if(hx >= 0x40862E42) { /* if |x|>=709.78... */
+ if(hx>=0x7ff00000) {
+ u_int32_t lx;
+ GET_LOW_WORD(lx,x);
+ if(((hx&0xfffff)|lx)!=0)
+ return x+x; /* NaN */
+ else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */
+ }
+ if(x > o_threshold) return huge*huge; /* overflow */
+ if(x < u_threshold) return twom1000*twom1000; /* underflow */
+ }
+
+ /* argument reduction */
+ if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
+ if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+ hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
+ } else {
+ k = invln2*x+halF[xsb];
+ t = k;
+ hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */
+ lo = t*ln2LO[0];
+ }
+ x = hi - lo;
+ }
+ else if(hx < 0x3e300000) { /* when |x|<2**-28 */
+ if(huge+x>one) return one+x;/* trigger inexact */
+ }
+ else k = 0;
+
+ /* x is now in primary range */
+ t = x*x;
+ c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+ if(k==0) return one-((x*c)/(c-2.0)-x);
+ else y = one-((lo-(x*c)/(2.0-c))-hi);
+ if(k >= -1021) {
+ u_int32_t hy;
+ GET_HIGH_WORD(hy,y);
+ SET_HIGH_WORD(y,hy+(k<<20)); /* add k to y's exponent */
+ return y;
+ } else {
+ u_int32_t hy;
+ GET_HIGH_WORD(hy,y);
+ SET_HIGH_WORD(y,hy+((k+1000)<<20)); /* add k to y's exponent */
+ return y*twom1000;
+ }
+}
diff --git a/lib/msun/src/e_expf.c b/lib/msun/src/e_expf.c
new file mode 100644
index 0000000..24e9096
--- /dev/null
+++ b/lib/msun/src/e_expf.c
@@ -0,0 +1,103 @@
+/* e_expf.c -- float version of e_exp.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+one = 1.0,
+halF[2] = {0.5,-0.5,},
+huge = 1.0e+30,
+twom100 = 7.8886090522e-31, /* 2**-100=0x0d800000 */
+o_threshold= 8.8721679688e+01, /* 0x42b17180 */
+u_threshold= -1.0397208405e+02, /* 0xc2cff1b5 */
+ln2HI[2] ={ 6.9313812256e-01, /* 0x3f317180 */
+ -6.9313812256e-01,}, /* 0xbf317180 */
+ln2LO[2] ={ 9.0580006145e-06, /* 0x3717f7d1 */
+ -9.0580006145e-06,}, /* 0xb717f7d1 */
+invln2 = 1.4426950216e+00, /* 0x3fb8aa3b */
+P1 = 1.6666667163e-01, /* 0x3e2aaaab */
+P2 = -2.7777778450e-03, /* 0xbb360b61 */
+P3 = 6.6137559770e-05, /* 0x388ab355 */
+P4 = -1.6533901999e-06, /* 0xb5ddea0e */
+P5 = 4.1381369442e-08; /* 0x3331bb4c */
+
+#ifdef __STDC__
+ float __ieee754_expf(float x) /* default IEEE double exp */
+#else
+ float __ieee754_expf(x) /* default IEEE double exp */
+ float x;
+#endif
+{
+ float y,hi=0.0,lo=0.0,c,t;
+ int32_t k=0,xsb;
+ u_int32_t hx;
+
+ GET_FLOAT_WORD(hx,x);
+ xsb = (hx>>31)&1; /* sign bit of x */
+ hx &= 0x7fffffff; /* high word of |x| */
+
+ /* filter out non-finite argument */
+ if(hx >= 0x42b17218) { /* if |x|>=88.721... */
+ if(hx>0x7f800000)
+ return x+x; /* NaN */
+ if(hx==0x7f800000)
+ return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */
+ if(x > o_threshold) return huge*huge; /* overflow */
+ if(x < u_threshold) return twom100*twom100; /* underflow */
+ }
+
+ /* argument reduction */
+ if(hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */
+ if(hx < 0x3F851592) { /* and |x| < 1.5 ln2 */
+ hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
+ } else {
+ k = invln2*x+halF[xsb];
+ t = k;
+ hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */
+ lo = t*ln2LO[0];
+ }
+ x = hi - lo;
+ }
+ else if(hx < 0x31800000) { /* when |x|<2**-28 */
+ if(huge+x>one) return one+x;/* trigger inexact */
+ }
+ else k = 0;
+
+ /* x is now in primary range */
+ t = x*x;
+ c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+ if(k==0) return one-((x*c)/(c-(float)2.0)-x);
+ else y = one-((lo-(x*c)/((float)2.0-c))-hi);
+ if(k >= -125) {
+ u_int32_t hy;
+ GET_FLOAT_WORD(hy,y);
+ SET_FLOAT_WORD(y,hy+(k<<23)); /* add k to y's exponent */
+ return y;
+ } else {
+ u_int32_t hy;
+ GET_FLOAT_WORD(hy,y);
+ SET_FLOAT_WORD(y,hy+((k+100)<<23)); /* add k to y's exponent */
+ return y*twom100;
+ }
+}
diff --git a/lib/msun/src/e_fmod.c b/lib/msun/src/e_fmod.c
new file mode 100644
index 0000000..4f65de1
--- /dev/null
+++ b/lib/msun/src/e_fmod.c
@@ -0,0 +1,140 @@
+/* @(#)e_fmod.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * __ieee754_fmod(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double one = 1.0, Zero[] = {0.0, -0.0,};
+#else
+static double one = 1.0, Zero[] = {0.0, -0.0,};
+#endif
+
+#ifdef __STDC__
+ double __generic___ieee754_fmod(double x, double y)
+#else
+ double __generic___ieee754_fmod(x,y)
+ double x,y ;
+#endif
+{
+ int32_t n,hx,hy,hz,ix,iy,sx,i;
+ u_int32_t lx,ly,lz;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hy,ly,y);
+ sx = hx&0x80000000; /* sign of x */
+ hx ^=sx; /* |x| */
+ hy &= 0x7fffffff; /* |y| */
+
+ /* purge off exception values */
+ if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */
+ ((hy|((ly|-ly)>>31))>0x7ff00000)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if(hx<=hy) {
+ if((hx<hy)||(lx<ly)) return x; /* |x|<|y| return x */
+ if(lx==ly)
+ return Zero[(u_int32_t)sx>>31]; /* |x|=|y| return x*0*/
+ }
+
+ /* determine ix = ilogb(x) */
+ if(hx<0x00100000) { /* subnormal x */
+ if(hx==0) {
+ for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
+ } else {
+ for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
+ }
+ } else ix = (hx>>20)-1023;
+
+ /* determine iy = ilogb(y) */
+ if(hy<0x00100000) { /* subnormal y */
+ if(hy==0) {
+ for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
+ } else {
+ for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
+ }
+ } else iy = (hy>>20)-1023;
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ if(ix >= -1022)
+ hx = 0x00100000|(0x000fffff&hx);
+ else { /* subnormal x, shift x to normal */
+ n = -1022-ix;
+ if(n<=31) {
+ hx = (hx<<n)|(lx>>(32-n));
+ lx <<= n;
+ } else {
+ hx = lx<<(n-32);
+ lx = 0;
+ }
+ }
+ if(iy >= -1022)
+ hy = 0x00100000|(0x000fffff&hy);
+ else { /* subnormal y, shift y to normal */
+ n = -1022-iy;
+ if(n<=31) {
+ hy = (hy<<n)|(ly>>(32-n));
+ ly <<= n;
+ } else {
+ hy = ly<<(n-32);
+ ly = 0;
+ }
+ }
+
+ /* fix point fmod */
+ n = ix - iy;
+ while(n--) {
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;}
+ else {
+ if((hz|lz)==0) /* return sign(x)*0 */
+ return Zero[(u_int32_t)sx>>31];
+ hx = hz+hz+(lz>>31); lx = lz+lz;
+ }
+ }
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz>=0) {hx=hz;lx=lz;}
+
+ /* convert back to floating value and restore the sign */
+ if((hx|lx)==0) /* return sign(x)*0 */
+ return Zero[(u_int32_t)sx>>31];
+ while(hx<0x00100000) { /* normalize x */
+ hx = hx+hx+(lx>>31); lx = lx+lx;
+ iy -= 1;
+ }
+ if(iy>= -1022) { /* normalize output */
+ hx = ((hx-0x00100000)|((iy+1023)<<20));
+ INSERT_WORDS(x,hx|sx,lx);
+ } else { /* subnormal output */
+ n = -1022 - iy;
+ if(n<=20) {
+ lx = (lx>>n)|((u_int32_t)hx<<(32-n));
+ hx >>= n;
+ } else if (n<=31) {
+ lx = (hx<<(32-n))|(lx>>n); hx = sx;
+ } else {
+ lx = hx>>(n-32); hx = sx;
+ }
+ INSERT_WORDS(x,hx|sx,lx);
+ x *= one; /* create necessary signal */
+ }
+ return x; /* exact output */
+}
diff --git a/lib/msun/src/e_fmodf.c b/lib/msun/src/e_fmodf.c
new file mode 100644
index 0000000..2c0bd81
--- /dev/null
+++ b/lib/msun/src/e_fmodf.c
@@ -0,0 +1,113 @@
+/* e_fmodf.c -- float version of e_fmod.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * __ieee754_fmodf(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float one = 1.0, Zero[] = {0.0, -0.0,};
+#else
+static float one = 1.0, Zero[] = {0.0, -0.0,};
+#endif
+
+#ifdef __STDC__
+ float __ieee754_fmodf(float x, float y)
+#else
+ float __ieee754_fmodf(x,y)
+ float x,y ;
+#endif
+{
+ int32_t n,hx,hy,hz,ix,iy,sx,i;
+
+ GET_FLOAT_WORD(hx,x);
+ GET_FLOAT_WORD(hy,y);
+ sx = hx&0x80000000; /* sign of x */
+ hx ^=sx; /* |x| */
+ hy &= 0x7fffffff; /* |y| */
+
+ /* purge off exception values */
+ if(hy==0||(hx>=0x7f800000)|| /* y=0,or x not finite */
+ (hy>0x7f800000)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if(hx<hy) return x; /* |x|<|y| return x */
+ if(hx==hy)
+ return Zero[(u_int32_t)sx>>31]; /* |x|=|y| return x*0*/
+
+ /* determine ix = ilogb(x) */
+ if(hx<0x00800000) { /* subnormal x */
+ for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
+ } else ix = (hx>>23)-127;
+
+ /* determine iy = ilogb(y) */
+ if(hy<0x00800000) { /* subnormal y */
+ for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1;
+ } else iy = (hy>>23)-127;
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ if(ix >= -126)
+ hx = 0x00800000|(0x007fffff&hx);
+ else { /* subnormal x, shift x to normal */
+ n = -126-ix;
+ hx = hx<<n;
+ }
+ if(iy >= -126)
+ hy = 0x00800000|(0x007fffff&hy);
+ else { /* subnormal y, shift y to normal */
+ n = -126-iy;
+ hy = hy<<n;
+ }
+
+ /* fix point fmod */
+ n = ix - iy;
+ while(n--) {
+ hz=hx-hy;
+ if(hz<0){hx = hx+hx;}
+ else {
+ if(hz==0) /* return sign(x)*0 */
+ return Zero[(u_int32_t)sx>>31];
+ hx = hz+hz;
+ }
+ }
+ hz=hx-hy;
+ if(hz>=0) {hx=hz;}
+
+ /* convert back to floating value and restore the sign */
+ if(hx==0) /* return sign(x)*0 */
+ return Zero[(u_int32_t)sx>>31];
+ while(hx<0x00800000) { /* normalize x */
+ hx = hx+hx;
+ iy -= 1;
+ }
+ if(iy>= -126) { /* normalize output */
+ hx = ((hx-0x00800000)|((iy+127)<<23));
+ SET_FLOAT_WORD(x,hx|sx);
+ } else { /* subnormal output */
+ n = -126 - iy;
+ hx >>= n;
+ SET_FLOAT_WORD(x,hx|sx);
+ x *= one; /* create necessary signal */
+ }
+ return x; /* exact output */
+}
diff --git a/lib/msun/src/e_gamma.c b/lib/msun/src/e_gamma.c
new file mode 100644
index 0000000..6401d59
--- /dev/null
+++ b/lib/msun/src/e_gamma.c
@@ -0,0 +1,37 @@
+/* @(#)e_gamma.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.
+ * ====================================================
+ *
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_gamma(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_gamma_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+#ifdef __STDC__
+ double __ieee754_gamma(double x)
+#else
+ double __ieee754_gamma(x)
+ double x;
+#endif
+{
+ return __ieee754_gamma_r(x,&signgam);
+}
diff --git a/lib/msun/src/e_gamma_r.c b/lib/msun/src/e_gamma_r.c
new file mode 100644
index 0000000..d1334f3
--- /dev/null
+++ b/lib/msun/src/e_gamma_r.c
@@ -0,0 +1,35 @@
+/* @(#)er_gamma.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_gamma_r(x, signgamp)
+ * Reentrant version of the logarithm of the Gamma function
+ * with user provide pointer for the sign of Gamma(x).
+ *
+ * Method: See __ieee754_lgamma_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double __ieee754_gamma_r(double x, int *signgamp)
+#else
+ double __ieee754_gamma_r(x,signgamp)
+ double x; int *signgamp;
+#endif
+{
+ return __ieee754_lgamma_r(x,signgamp);
+}
diff --git a/lib/msun/src/e_gammaf.c b/lib/msun/src/e_gammaf.c
new file mode 100644
index 0000000..97731d9
--- /dev/null
+++ b/lib/msun/src/e_gammaf.c
@@ -0,0 +1,39 @@
+/* e_gammaf.c -- float version of e_gamma.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_gammaf(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_gammaf_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+#ifdef __STDC__
+ float __ieee754_gammaf(float x)
+#else
+ float __ieee754_gammaf(x)
+ float x;
+#endif
+{
+ return __ieee754_gammaf_r(x,&signgam);
+}
diff --git a/lib/msun/src/e_gammaf_r.c b/lib/msun/src/e_gammaf_r.c
new file mode 100644
index 0000000..4e2e4a7
--- /dev/null
+++ b/lib/msun/src/e_gammaf_r.c
@@ -0,0 +1,38 @@
+/* e_gammaf_r.c -- float version of e_gamma_r.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_gammaf_r(x, signgamp)
+ * Reentrant version of the logarithm of the Gamma function
+ * with user provide pointer for the sign of Gamma(x).
+ *
+ * Method: See __ieee754_lgammaf_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float __ieee754_gammaf_r(float x, int *signgamp)
+#else
+ float __ieee754_gammaf_r(x,signgamp)
+ float x; int *signgamp;
+#endif
+{
+ return __ieee754_lgammaf_r(x,signgamp);
+}
diff --git a/lib/msun/src/e_hypot.c b/lib/msun/src/e_hypot.c
new file mode 100644
index 0000000..b2a577f
--- /dev/null
+++ b/lib/msun/src/e_hypot.c
@@ -0,0 +1,128 @@
+/* @(#)e_hypot.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: e_hypot.c,v 1.4 1997/02/22 15:10:12 peter Exp $";
+#endif
+
+/* __ieee754_hypot(x,y)
+ *
+ * Method :
+ * If (assume round-to-nearest) z=x*x+y*y
+ * has error less than sqrt(2)/2 ulp, than
+ * sqrt(z) has error less than 1 ulp (exercise).
+ *
+ * So, compute sqrt(x*x+y*y) with some care as
+ * follows to get the error below 1 ulp:
+ *
+ * Assume x>y>0;
+ * (if possible, set rounding to round-to-nearest)
+ * 1. if x > 2y use
+ * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
+ * where x1 = x with lower 32 bits cleared, x2 = x-x1; else
+ * 2. if x <= 2y use
+ * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y))
+ * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1,
+ * y1= y with lower 32 bits chopped, y2 = y-y1.
+ *
+ * NOTE: scaling may be necessary if some argument is too
+ * large or too tiny
+ *
+ * Special cases:
+ * hypot(x,y) is INF if x or y is +INF or -INF; else
+ * hypot(x,y) is NAN if x or y is NAN.
+ *
+ * Accuracy:
+ * hypot(x,y) returns sqrt(x^2+y^2) with error less
+ * than 1 ulps (units in the last place)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double __ieee754_hypot(double x, double y)
+#else
+ double __ieee754_hypot(x,y)
+ double x, y;
+#endif
+{
+ double a=x,b=y,t1,t2,y1,y2,w;
+ int32_t j,k,ha,hb;
+
+ GET_HIGH_WORD(ha,x);
+ ha &= 0x7fffffff;
+ GET_HIGH_WORD(hb,y);
+ hb &= 0x7fffffff;
+ if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+ SET_HIGH_WORD(a,ha); /* a <- |a| */
+ SET_HIGH_WORD(b,hb); /* b <- |b| */
+ if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */
+ k=0;
+ if(ha > 0x5f300000) { /* a>2**500 */
+ if(ha >= 0x7ff00000) { /* Inf or NaN */
+ u_int32_t low;
+ w = a+b; /* for sNaN */
+ GET_LOW_WORD(low,a);
+ if(((ha&0xfffff)|low)==0) w = a;
+ GET_LOW_WORD(low,b);
+ if(((hb^0x7ff00000)|low)==0) w = b;
+ return w;
+ }
+ /* scale a and b by 2**-600 */
+ ha -= 0x25800000; hb -= 0x25800000; k += 600;
+ SET_HIGH_WORD(a,ha);
+ SET_HIGH_WORD(b,hb);
+ }
+ if(hb < 0x20b00000) { /* b < 2**-500 */
+ if(hb <= 0x000fffff) { /* subnormal b or 0 */
+ u_int32_t low;
+ GET_LOW_WORD(low,b);
+ if((hb|low)==0) return a;
+ t1=0;
+ SET_HIGH_WORD(t1,0x7fd00000); /* t1=2^1022 */
+ b *= t1;
+ a *= t1;
+ k -= 1022;
+ } else { /* scale a and b by 2^600 */
+ ha += 0x25800000; /* a *= 2^600 */
+ hb += 0x25800000; /* b *= 2^600 */
+ k -= 600;
+ SET_HIGH_WORD(a,ha);
+ SET_HIGH_WORD(b,hb);
+ }
+ }
+ /* medium size a and b */
+ w = a-b;
+ if (w>b) {
+ t1 = 0;
+ SET_HIGH_WORD(t1,ha);
+ t2 = a-t1;
+ w = __ieee754_sqrt(t1*t1-(b*(-b)-t2*(a+t1)));
+ } else {
+ a = a+a;
+ y1 = 0;
+ SET_HIGH_WORD(y1,hb);
+ y2 = b - y1;
+ t1 = 0;
+ SET_HIGH_WORD(t1,ha+0x00100000);
+ t2 = a - t1;
+ w = __ieee754_sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+ }
+ if(k!=0) {
+ u_int32_t high;
+ t1 = 1.0;
+ GET_HIGH_WORD(high,t1);
+ SET_HIGH_WORD(t1,high+(k<<20));
+ return t1*w;
+ } else return w;
+}
diff --git a/lib/msun/src/e_hypotf.c b/lib/msun/src/e_hypotf.c
new file mode 100644
index 0000000..5a40918
--- /dev/null
+++ b/lib/msun/src/e_hypotf.c
@@ -0,0 +1,87 @@
+/* e_hypotf.c -- float version of e_hypot.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: e_hypotf.c,v 1.5 1997/03/05 11:54:00 bde Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float __ieee754_hypotf(float x, float y)
+#else
+ float __ieee754_hypot(x,y)
+ float x, y;
+#endif
+{
+ float a=x,b=y,t1,t2,y1,y2,w;
+ int32_t j,k,ha,hb;
+
+ GET_FLOAT_WORD(ha,x);
+ ha &= 0x7fffffff;
+ GET_FLOAT_WORD(hb,y);
+ hb &= 0x7fffffff;
+ if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+ SET_FLOAT_WORD(a,ha); /* a <- |a| */
+ SET_FLOAT_WORD(b,hb); /* b <- |b| */
+ if((ha-hb)>0xf000000) {return a+b;} /* x/y > 2**30 */
+ k=0;
+ if(ha > 0x58800000) { /* a>2**50 */
+ if(ha >= 0x7f800000) { /* Inf or NaN */
+ w = a+b; /* for sNaN */
+ if(ha == 0x7f800000) w = a;
+ if(hb == 0x7f800000) w = b;
+ return w;
+ }
+ /* scale a and b by 2**-68 */
+ ha -= 0x22000000; hb -= 0x22000000; k += 68;
+ SET_FLOAT_WORD(a,ha);
+ SET_FLOAT_WORD(b,hb);
+ }
+ if(hb < 0x26800000) { /* b < 2**-50 */
+ if(hb <= 0x007fffff) { /* subnormal b or 0 */
+ if(hb==0) return a;
+ SET_FLOAT_WORD(t1,0x7e800000); /* t1=2^126 */
+ b *= t1;
+ a *= t1;
+ k -= 126;
+ } else { /* scale a and b by 2^68 */
+ ha += 0x22000000; /* a *= 2^68 */
+ hb += 0x22000000; /* b *= 2^68 */
+ k -= 68;
+ SET_FLOAT_WORD(a,ha);
+ SET_FLOAT_WORD(b,hb);
+ }
+ }
+ /* medium size a and b */
+ w = a-b;
+ if (w>b) {
+ SET_FLOAT_WORD(t1,ha&0xfffff000);
+ t2 = a-t1;
+ w = __ieee754_sqrtf(t1*t1-(b*(-b)-t2*(a+t1)));
+ } else {
+ a = a+a;
+ SET_FLOAT_WORD(y1,hb&0xfffff000);
+ y2 = b - y1;
+ SET_FLOAT_WORD(t1,ha+0x00800000);
+ t2 = a - t1;
+ w = __ieee754_sqrtf(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+ }
+ if(k!=0) {
+ SET_FLOAT_WORD(t1,0x3f800000+(k<<23));
+ return t1*w;
+ } else return w;
+}
diff --git a/lib/msun/src/e_j0.c b/lib/msun/src/e_j0.c
new file mode 100644
index 0000000..ecbc9b7
--- /dev/null
+++ b/lib/msun/src/e_j0.c
@@ -0,0 +1,487 @@
+/* @(#)e_j0.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_j0(x), __ieee754_y0(x)
+ * Bessel function of the first and second kinds of order zero.
+ * Method -- j0(x):
+ * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ...
+ * 2. Reduce x to |x| since j0(x)=j0(-x), and
+ * for x in (0,2)
+ * j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x;
+ * (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 )
+ * for x in (2,inf)
+ * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0))
+ * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
+ * as follow:
+ * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+ * = 1/sqrt(2) * (cos(x) + sin(x))
+ * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * (To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.)
+ *
+ * 3 Special cases
+ * j0(nan)= nan
+ * j0(0) = 1
+ * j0(inf) = 0
+ *
+ * Method -- y0(x):
+ * 1. For x<2.
+ * Since
+ * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...)
+ * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function.
+ * We use the following function to approximate y0,
+ * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2
+ * where
+ * U(z) = u00 + u01*z + ... + u06*z^6
+ * V(z) = 1 + v01*z + ... + v04*z^4
+ * with absolute approximation error bounded by 2**-72.
+ * Note: For tiny x, U/V = u0 and j0(x)~1, hence
+ * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27)
+ * 2. For x>=2.
+ * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0))
+ * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
+ * by the method mentioned above.
+ * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static double pzero(double), qzero(double);
+#else
+static double pzero(), qzero();
+#endif
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+huge = 1e300,
+one = 1.0,
+invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
+tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+ /* R0/S0 on [0, 2.00] */
+R02 = 1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */
+R03 = -1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */
+R04 = 1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */
+R05 = -4.61832688532103189199e-09, /* 0xBE33D5E7, 0x73D63FCE */
+S01 = 1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */
+S02 = 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */
+S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */
+S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */
+
+#ifdef __STDC__
+static const double zero = 0.0;
+#else
+static double zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ double __ieee754_j0(double x)
+#else
+ double __ieee754_j0(x)
+ double x;
+#endif
+{
+ double z, s,c,ss,cc,r,u,v;
+ int32_t hx,ix;
+
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) return one/(x*x);
+ x = fabs(x);
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sin(x);
+ c = cos(x);
+ ss = s-c;
+ cc = s+c;
+ if(ix<0x7fe00000) { /* make sure x+x not overflow */
+ z = -cos(x+x);
+ if ((s*c)<zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /*
+ * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+ * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+ */
+ if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(x);
+ else {
+ u = pzero(x); v = qzero(x);
+ z = invsqrtpi*(u*cc-v*ss)/sqrt(x);
+ }
+ return z;
+ }
+ if(ix<0x3f200000) { /* |x| < 2**-13 */
+ if(huge+x>one) { /* raise inexact if x != 0 */
+ if(ix<0x3e400000) return one; /* |x|<2**-27 */
+ else return one - 0.25*x*x;
+ }
+ }
+ z = x*x;
+ r = z*(R02+z*(R03+z*(R04+z*R05)));
+ s = one+z*(S01+z*(S02+z*(S03+z*S04)));
+ if(ix < 0x3FF00000) { /* |x| < 1.00 */
+ return one + z*(-0.25+(r/s));
+ } else {
+ u = 0.5*x;
+ return((one+u)*(one-u)+z*(r/s));
+ }
+}
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */
+u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */
+u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */
+u03 = 3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */
+u04 = -3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */
+u05 = 1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */
+u06 = -3.98205194132103398453e-11, /* 0xBDC5E43D, 0x693FB3C8 */
+v01 = 1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */
+v02 = 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */
+v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */
+v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */
+
+#ifdef __STDC__
+ double __ieee754_y0(double x)
+#else
+ double __ieee754_y0(x)
+ double x;
+#endif
+{
+ double z, s,c,ss,cc,u,v;
+ int32_t hx,ix,lx;
+
+ EXTRACT_WORDS(hx,lx,x);
+ ix = 0x7fffffff&hx;
+ /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */
+ if(ix>=0x7ff00000) return one/(x+x*x);
+ if((ix|lx)==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0))
+ * where x0 = x-pi/4
+ * Better formula:
+ * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+ * = 1/sqrt(2) * (sin(x) + cos(x))
+ * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.
+ */
+ s = sin(x);
+ c = cos(x);
+ ss = s-c;
+ cc = s+c;
+ /*
+ * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+ * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+ */
+ if(ix<0x7fe00000) { /* make sure x+x not overflow */
+ z = -cos(x+x);
+ if ((s*c)<zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ if(ix>0x48000000) z = (invsqrtpi*ss)/sqrt(x);
+ else {
+ u = pzero(x); v = qzero(x);
+ z = invsqrtpi*(u*ss+v*cc)/sqrt(x);
+ }
+ return z;
+ }
+ if(ix<=0x3e400000) { /* x < 2**-27 */
+ return(u00 + tpi*__ieee754_log(x));
+ }
+ z = x*x;
+ u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06)))));
+ v = one+z*(v01+z*(v02+z*(v03+z*v04)));
+ return(u/v + tpi*(__ieee754_j0(x)*__ieee754_log(x)));
+}
+
+/* The asymptotic expansions of pzero is
+ * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x.
+ * For x >= 2, We approximate pzero by
+ * pzero(x) = 1 + (R/S)
+ * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10
+ * S = 1 + pS0*s^2 + ... + pS4*s^10
+ * and
+ * | pzero(x)-1-R/S | <= 2 ** ( -60.26)
+ */
+#ifdef __STDC__
+static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#else
+static double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#endif
+ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+ -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */
+ -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */
+ -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */
+ -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */
+ -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */
+};
+#ifdef __STDC__
+static const double pS8[5] = {
+#else
+static double pS8[5] = {
+#endif
+ 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */
+ 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */
+ 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */
+ 1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */
+ 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */
+};
+
+#ifdef __STDC__
+static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#else
+static double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#endif
+ -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */
+ -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */
+ -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */
+ -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */
+ -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */
+ -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */
+};
+#ifdef __STDC__
+static const double pS5[5] = {
+#else
+static double pS5[5] = {
+#endif
+ 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */
+ 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */
+ 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */
+ 9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */
+ 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */
+};
+
+#ifdef __STDC__
+static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#else
+static double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#endif
+ -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */
+ -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */
+ -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */
+ -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */
+ -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */
+ -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */
+};
+#ifdef __STDC__
+static const double pS3[5] = {
+#else
+static double pS3[5] = {
+#endif
+ 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */
+ 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */
+ 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */
+ 1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */
+ 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */
+};
+
+#ifdef __STDC__
+static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#else
+static double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#endif
+ -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */
+ -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */
+ -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */
+ -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */
+ -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */
+ -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */
+};
+#ifdef __STDC__
+static const double pS2[5] = {
+#else
+static double pS2[5] = {
+#endif
+ 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */
+ 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */
+ 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */
+ 1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */
+ 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */
+};
+
+#ifdef __STDC__
+ static double pzero(double x)
+#else
+ static double pzero(x)
+ double x;
+#endif
+{
+#ifdef __STDC__
+ const double *p,*q;
+#else
+ double *p,*q;
+#endif
+ double z,r,s;
+ int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x40200000) {p = pR8; q= pS8;}
+ else if(ix>=0x40122E8B){p = pR5; q= pS5;}
+ else if(ix>=0x4006DB6D){p = pR3; q= pS3;}
+ else if(ix>=0x40000000){p = pR2; q= pS2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+ return one+ r/s;
+}
+
+
+/* For x >= 8, the asymptotic expansions of qzero is
+ * -1/8 s + 75/1024 s^3 - ..., where s = 1/x.
+ * We approximate pzero by
+ * qzero(x) = s*(-1.25 + (R/S))
+ * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10
+ * S = 1 + qS0*s^2 + ... + qS5*s^12
+ * and
+ * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22)
+ */
+#ifdef __STDC__
+static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#else
+static double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#endif
+ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+ 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */
+ 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */
+ 5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */
+ 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */
+ 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */
+};
+#ifdef __STDC__
+static const double qS8[6] = {
+#else
+static double qS8[6] = {
+#endif
+ 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */
+ 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */
+ 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */
+ 8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */
+ 8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */
+ -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */
+};
+
+#ifdef __STDC__
+static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#else
+static double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#endif
+ 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */
+ 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */
+ 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */
+ 1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */
+ 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */
+ 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */
+};
+#ifdef __STDC__
+static const double qS5[6] = {
+#else
+static double qS5[6] = {
+#endif
+ 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */
+ 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */
+ 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */
+ 5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */
+ 3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */
+ -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */
+};
+
+#ifdef __STDC__
+static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#else
+static double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#endif
+ 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */
+ 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */
+ 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */
+ 4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */
+ 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */
+ 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */
+};
+#ifdef __STDC__
+static const double qS3[6] = {
+#else
+static double qS3[6] = {
+#endif
+ 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */
+ 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */
+ 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */
+ 6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */
+ 2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */
+ -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */
+};
+
+#ifdef __STDC__
+static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#else
+static double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#endif
+ 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */
+ 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */
+ 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */
+ 1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */
+ 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */
+ 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */
+};
+#ifdef __STDC__
+static const double qS2[6] = {
+#else
+static double qS2[6] = {
+#endif
+ 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */
+ 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */
+ 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */
+ 8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */
+ 2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */
+ -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */
+};
+
+#ifdef __STDC__
+ static double qzero(double x)
+#else
+ static double qzero(x)
+ double x;
+#endif
+{
+#ifdef __STDC__
+ const double *p,*q;
+#else
+ double *p,*q;
+#endif
+ double s,r,z;
+ int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x40200000) {p = qR8; q= qS8;}
+ else if(ix>=0x40122E8B){p = qR5; q= qS5;}
+ else if(ix>=0x4006DB6D){p = qR3; q= qS3;}
+ else if(ix>=0x40000000){p = qR2; q= qS2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+ return (-.125 + r/s)/x;
+}
diff --git a/lib/msun/src/e_j0f.c b/lib/msun/src/e_j0f.c
new file mode 100644
index 0000000..cdfedd9
--- /dev/null
+++ b/lib/msun/src/e_j0f.c
@@ -0,0 +1,444 @@
+/* e_j0f.c -- float version of e_j0.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static float pzerof(float), qzerof(float);
+#else
+static float pzerof(), qzerof();
+#endif
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+huge = 1e30,
+one = 1.0,
+invsqrtpi= 5.6418961287e-01, /* 0x3f106ebb */
+tpi = 6.3661974669e-01, /* 0x3f22f983 */
+ /* R0/S0 on [0, 2.00] */
+R02 = 1.5625000000e-02, /* 0x3c800000 */
+R03 = -1.8997929874e-04, /* 0xb947352e */
+R04 = 1.8295404516e-06, /* 0x35f58e88 */
+R05 = -4.6183270541e-09, /* 0xb19eaf3c */
+S01 = 1.5619102865e-02, /* 0x3c7fe744 */
+S02 = 1.1692678527e-04, /* 0x38f53697 */
+S03 = 5.1354652442e-07, /* 0x3509daa6 */
+S04 = 1.1661400734e-09; /* 0x30a045e8 */
+
+#ifdef __STDC__
+static const float zero = 0.0;
+#else
+static float zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ float __ieee754_j0f(float x)
+#else
+ float __ieee754_j0f(x)
+ float x;
+#endif
+{
+ float z, s,c,ss,cc,r,u,v;
+ int32_t hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) return one/(x*x);
+ x = fabsf(x);
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sinf(x);
+ c = cosf(x);
+ ss = s-c;
+ cc = s+c;
+ if(ix<0x7f000000) { /* make sure x+x not overflow */
+ z = -cosf(x+x);
+ if ((s*c)<zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /*
+ * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+ * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+ */
+ if(ix>0x80000000) z = (invsqrtpi*cc)/sqrtf(x);
+ else {
+ u = pzerof(x); v = qzerof(x);
+ z = invsqrtpi*(u*cc-v*ss)/sqrtf(x);
+ }
+ return z;
+ }
+ if(ix<0x39000000) { /* |x| < 2**-13 */
+ if(huge+x>one) { /* raise inexact if x != 0 */
+ if(ix<0x32000000) return one; /* |x|<2**-27 */
+ else return one - (float)0.25*x*x;
+ }
+ }
+ z = x*x;
+ r = z*(R02+z*(R03+z*(R04+z*R05)));
+ s = one+z*(S01+z*(S02+z*(S03+z*S04)));
+ if(ix < 0x3F800000) { /* |x| < 1.00 */
+ return one + z*((float)-0.25+(r/s));
+ } else {
+ u = (float)0.5*x;
+ return((one+u)*(one-u)+z*(r/s));
+ }
+}
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+u00 = -7.3804296553e-02, /* 0xbd9726b5 */
+u01 = 1.7666645348e-01, /* 0x3e34e80d */
+u02 = -1.3818567619e-02, /* 0xbc626746 */
+u03 = 3.4745343146e-04, /* 0x39b62a69 */
+u04 = -3.8140706238e-06, /* 0xb67ff53c */
+u05 = 1.9559013964e-08, /* 0x32a802ba */
+u06 = -3.9820518410e-11, /* 0xae2f21eb */
+v01 = 1.2730483897e-02, /* 0x3c509385 */
+v02 = 7.6006865129e-05, /* 0x389f65e0 */
+v03 = 2.5915085189e-07, /* 0x348b216c */
+v04 = 4.4111031494e-10; /* 0x2ff280c2 */
+
+#ifdef __STDC__
+ float __ieee754_y0f(float x)
+#else
+ float __ieee754_y0f(x)
+ float x;
+#endif
+{
+ float z, s,c,ss,cc,u,v;
+ int32_t hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = 0x7fffffff&hx;
+ /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */
+ if(ix>=0x7f800000) return one/(x+x*x);
+ if(ix==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0))
+ * where x0 = x-pi/4
+ * Better formula:
+ * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+ * = 1/sqrt(2) * (sin(x) + cos(x))
+ * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.
+ */
+ s = sinf(x);
+ c = cosf(x);
+ ss = s-c;
+ cc = s+c;
+ /*
+ * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+ * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+ */
+ if(ix<0x7f000000) { /* make sure x+x not overflow */
+ z = -cosf(x+x);
+ if ((s*c)<zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ if(ix>0x80000000) z = (invsqrtpi*ss)/sqrtf(x);
+ else {
+ u = pzerof(x); v = qzerof(x);
+ z = invsqrtpi*(u*ss+v*cc)/sqrtf(x);
+ }
+ return z;
+ }
+ if(ix<=0x32000000) { /* x < 2**-27 */
+ return(u00 + tpi*__ieee754_logf(x));
+ }
+ z = x*x;
+ u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06)))));
+ v = one+z*(v01+z*(v02+z*(v03+z*v04)));
+ return(u/v + tpi*(__ieee754_j0f(x)*__ieee754_logf(x)));
+}
+
+/* The asymptotic expansions of pzero is
+ * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x.
+ * For x >= 2, We approximate pzero by
+ * pzero(x) = 1 + (R/S)
+ * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10
+ * S = 1 + pS0*s^2 + ... + pS4*s^10
+ * and
+ * | pzero(x)-1-R/S | <= 2 ** ( -60.26)
+ */
+#ifdef __STDC__
+static const float pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#else
+static float pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#endif
+ 0.0000000000e+00, /* 0x00000000 */
+ -7.0312500000e-02, /* 0xbd900000 */
+ -8.0816707611e+00, /* 0xc1014e86 */
+ -2.5706311035e+02, /* 0xc3808814 */
+ -2.4852163086e+03, /* 0xc51b5376 */
+ -5.2530439453e+03, /* 0xc5a4285a */
+};
+#ifdef __STDC__
+static const float pS8[5] = {
+#else
+static float pS8[5] = {
+#endif
+ 1.1653436279e+02, /* 0x42e91198 */
+ 3.8337448730e+03, /* 0x456f9beb */
+ 4.0597855469e+04, /* 0x471e95db */
+ 1.1675296875e+05, /* 0x47e4087c */
+ 4.7627726562e+04, /* 0x473a0bba */
+};
+#ifdef __STDC__
+static const float pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#else
+static float pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#endif
+ -1.1412546255e-11, /* 0xad48c58a */
+ -7.0312492549e-02, /* 0xbd8fffff */
+ -4.1596107483e+00, /* 0xc0851b88 */
+ -6.7674766541e+01, /* 0xc287597b */
+ -3.3123129272e+02, /* 0xc3a59d9b */
+ -3.4643338013e+02, /* 0xc3ad3779 */
+};
+#ifdef __STDC__
+static const float pS5[5] = {
+#else
+static float pS5[5] = {
+#endif
+ 6.0753936768e+01, /* 0x42730408 */
+ 1.0512523193e+03, /* 0x44836813 */
+ 5.9789707031e+03, /* 0x45bad7c4 */
+ 9.6254453125e+03, /* 0x461665c8 */
+ 2.4060581055e+03, /* 0x451660ee */
+};
+
+#ifdef __STDC__
+static const float pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#else
+static float pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#endif
+ -2.5470459075e-09, /* 0xb12f081b */
+ -7.0311963558e-02, /* 0xbd8fffb8 */
+ -2.4090321064e+00, /* 0xc01a2d95 */
+ -2.1965976715e+01, /* 0xc1afba52 */
+ -5.8079170227e+01, /* 0xc2685112 */
+ -3.1447946548e+01, /* 0xc1fb9565 */
+};
+#ifdef __STDC__
+static const float pS3[5] = {
+#else
+static float pS3[5] = {
+#endif
+ 3.5856033325e+01, /* 0x420f6c94 */
+ 3.6151397705e+02, /* 0x43b4c1ca */
+ 1.1936077881e+03, /* 0x44953373 */
+ 1.1279968262e+03, /* 0x448cffe6 */
+ 1.7358093262e+02, /* 0x432d94b8 */
+};
+
+#ifdef __STDC__
+static const float pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#else
+static float pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#endif
+ -8.8753431271e-08, /* 0xb3be98b7 */
+ -7.0303097367e-02, /* 0xbd8ffb12 */
+ -1.4507384300e+00, /* 0xbfb9b1cc */
+ -7.6356959343e+00, /* 0xc0f4579f */
+ -1.1193166733e+01, /* 0xc1331736 */
+ -3.2336456776e+00, /* 0xc04ef40d */
+};
+#ifdef __STDC__
+static const float pS2[5] = {
+#else
+static float pS2[5] = {
+#endif
+ 2.2220300674e+01, /* 0x41b1c32d */
+ 1.3620678711e+02, /* 0x430834f0 */
+ 2.7047027588e+02, /* 0x43873c32 */
+ 1.5387539673e+02, /* 0x4319e01a */
+ 1.4657617569e+01, /* 0x416a859a */
+};
+
+#ifdef __STDC__
+ static float pzerof(float x)
+#else
+ static float pzerof(x)
+ float x;
+#endif
+{
+#ifdef __STDC__
+ const float *p,*q;
+#else
+ float *p,*q;
+#endif
+ float z,r,s;
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x41000000) {p = pR8; q= pS8;}
+ else if(ix>=0x40f71c58){p = pR5; q= pS5;}
+ else if(ix>=0x4036db68){p = pR3; q= pS3;}
+ else if(ix>=0x40000000){p = pR2; q= pS2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+ return one+ r/s;
+}
+
+
+/* For x >= 8, the asymptotic expansions of qzero is
+ * -1/8 s + 75/1024 s^3 - ..., where s = 1/x.
+ * We approximate pzero by
+ * qzero(x) = s*(-1.25 + (R/S))
+ * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10
+ * S = 1 + qS0*s^2 + ... + qS5*s^12
+ * and
+ * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22)
+ */
+#ifdef __STDC__
+static const float qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#else
+static float qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#endif
+ 0.0000000000e+00, /* 0x00000000 */
+ 7.3242187500e-02, /* 0x3d960000 */
+ 1.1768206596e+01, /* 0x413c4a93 */
+ 5.5767340088e+02, /* 0x440b6b19 */
+ 8.8591972656e+03, /* 0x460a6cca */
+ 3.7014625000e+04, /* 0x471096a0 */
+};
+#ifdef __STDC__
+static const float qS8[6] = {
+#else
+static float qS8[6] = {
+#endif
+ 1.6377603149e+02, /* 0x4323c6aa */
+ 8.0983447266e+03, /* 0x45fd12c2 */
+ 1.4253829688e+05, /* 0x480b3293 */
+ 8.0330925000e+05, /* 0x49441ed4 */
+ 8.4050156250e+05, /* 0x494d3359 */
+ -3.4389928125e+05, /* 0xc8a7eb69 */
+};
+
+#ifdef __STDC__
+static const float qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#else
+static float qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#endif
+ 1.8408595828e-11, /* 0x2da1ec79 */
+ 7.3242180049e-02, /* 0x3d95ffff */
+ 5.8356351852e+00, /* 0x40babd86 */
+ 1.3511157227e+02, /* 0x43071c90 */
+ 1.0272437744e+03, /* 0x448067cd */
+ 1.9899779053e+03, /* 0x44f8bf4b */
+};
+#ifdef __STDC__
+static const float qS5[6] = {
+#else
+static float qS5[6] = {
+#endif
+ 8.2776611328e+01, /* 0x42a58da0 */
+ 2.0778142090e+03, /* 0x4501dd07 */
+ 1.8847289062e+04, /* 0x46933e94 */
+ 5.6751113281e+04, /* 0x475daf1d */
+ 3.5976753906e+04, /* 0x470c88c1 */
+ -5.3543427734e+03, /* 0xc5a752be */
+};
+
+#ifdef __STDC__
+static const float qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#else
+static float qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#endif
+ 4.3774099900e-09, /* 0x3196681b */
+ 7.3241114616e-02, /* 0x3d95ff70 */
+ 3.3442313671e+00, /* 0x405607e3 */
+ 4.2621845245e+01, /* 0x422a7cc5 */
+ 1.7080809021e+02, /* 0x432acedf */
+ 1.6673394775e+02, /* 0x4326bbe4 */
+};
+#ifdef __STDC__
+static const float qS3[6] = {
+#else
+static float qS3[6] = {
+#endif
+ 4.8758872986e+01, /* 0x42430916 */
+ 7.0968920898e+02, /* 0x44316c1c */
+ 3.7041481934e+03, /* 0x4567825f */
+ 6.4604252930e+03, /* 0x45c9e367 */
+ 2.5163337402e+03, /* 0x451d4557 */
+ -1.4924745178e+02, /* 0xc3153f59 */
+};
+
+#ifdef __STDC__
+static const float qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#else
+static float qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#endif
+ 1.5044444979e-07, /* 0x342189db */
+ 7.3223426938e-02, /* 0x3d95f62a */
+ 1.9981917143e+00, /* 0x3fffc4bf */
+ 1.4495602608e+01, /* 0x4167edfd */
+ 3.1666231155e+01, /* 0x41fd5471 */
+ 1.6252708435e+01, /* 0x4182058c */
+};
+#ifdef __STDC__
+static const float qS2[6] = {
+#else
+static float qS2[6] = {
+#endif
+ 3.0365585327e+01, /* 0x41f2ecb8 */
+ 2.6934811401e+02, /* 0x4386ac8f */
+ 8.4478375244e+02, /* 0x44533229 */
+ 8.8293585205e+02, /* 0x445cbbe5 */
+ 2.1266638184e+02, /* 0x4354aa98 */
+ -5.3109550476e+00, /* 0xc0a9f358 */
+};
+
+#ifdef __STDC__
+ static float qzerof(float x)
+#else
+ static float qzerof(x)
+ float x;
+#endif
+{
+#ifdef __STDC__
+ const float *p,*q;
+#else
+ float *p,*q;
+#endif
+ float s,r,z;
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x41000000) {p = qR8; q= qS8;}
+ else if(ix>=0x40f71c58){p = qR5; q= qS5;}
+ else if(ix>=0x4036db68){p = qR3; q= qS3;}
+ else if(ix>=0x40000000){p = qR2; q= qS2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+ return (-(float).125 + r/s)/x;
+}
diff --git a/lib/msun/src/e_j1.c b/lib/msun/src/e_j1.c
new file mode 100644
index 0000000..8af4560
--- /dev/null
+++ b/lib/msun/src/e_j1.c
@@ -0,0 +1,486 @@
+/* @(#)e_j1.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_j1(x), __ieee754_y1(x)
+ * Bessel function of the first and second kinds of order zero.
+ * Method -- j1(x):
+ * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ...
+ * 2. Reduce x to |x| since j1(x)=-j1(-x), and
+ * for x in (0,2)
+ * j1(x) = x/2 + x*z*R0/S0, where z = x*x;
+ * (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 )
+ * for x in (2,inf)
+ * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1))
+ * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
+ * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
+ * as follow:
+ * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ * = -1/sqrt(2) * (sin(x) + cos(x))
+ * (To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.)
+ *
+ * 3 Special cases
+ * j1(nan)= nan
+ * j1(0) = 0
+ * j1(inf) = 0
+ *
+ * Method -- y1(x):
+ * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN
+ * 2. For x<2.
+ * Since
+ * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...)
+ * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function.
+ * We use the following function to approximate y1,
+ * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2
+ * where for x in [0,2] (abs err less than 2**-65.89)
+ * U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4
+ * V(z) = 1 + v0[0]*z + ... + v0[4]*z^5
+ * Note: For tiny x, 1/x dominate y1 and hence
+ * y1(tiny) = -2/pi/tiny, (choose tiny<2**-54)
+ * 3. For x>=2.
+ * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
+ * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
+ * by method mentioned above.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static double pone(double), qone(double);
+#else
+static double pone(), qone();
+#endif
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+huge = 1e300,
+one = 1.0,
+invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
+tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+ /* R0/S0 on [0,2] */
+r00 = -6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */
+r01 = 1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */
+r02 = -1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */
+r03 = 4.96727999609584448412e-08, /* 0x3E6AAAFA, 0x46CA0BD9 */
+s01 = 1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */
+s02 = 1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */
+s03 = 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */
+s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */
+s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */
+
+#ifdef __STDC__
+static const double zero = 0.0;
+#else
+static double zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ double __ieee754_j1(double x)
+#else
+ double __ieee754_j1(x)
+ double x;
+#endif
+{
+ double z, s,c,ss,cc,r,u,v,y;
+ int32_t hx,ix;
+
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) return one/x;
+ y = fabs(x);
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sin(y);
+ c = cos(y);
+ ss = -s-c;
+ cc = s-c;
+ if(ix<0x7fe00000) { /* make sure y+y not overflow */
+ z = cos(y+y);
+ if ((s*c)>zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /*
+ * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
+ * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
+ */
+ if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(y);
+ else {
+ u = pone(y); v = qone(y);
+ z = invsqrtpi*(u*cc-v*ss)/sqrt(y);
+ }
+ if(hx<0) return -z;
+ else return z;
+ }
+ if(ix<0x3e400000) { /* |x|<2**-27 */
+ if(huge+x>one) return 0.5*x;/* inexact if x!=0 necessary */
+ }
+ z = x*x;
+ r = z*(r00+z*(r01+z*(r02+z*r03)));
+ s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05))));
+ r *= x;
+ return(x*0.5+r/s);
+}
+
+#ifdef __STDC__
+static const double U0[5] = {
+#else
+static double U0[5] = {
+#endif
+ -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */
+ 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */
+ -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */
+ 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */
+ -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */
+};
+#ifdef __STDC__
+static const double V0[5] = {
+#else
+static double V0[5] = {
+#endif
+ 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */
+ 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */
+ 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */
+ 6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */
+ 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */
+};
+
+#ifdef __STDC__
+ double __ieee754_y1(double x)
+#else
+ double __ieee754_y1(x)
+ double x;
+#endif
+{
+ double z, s,c,ss,cc,u,v;
+ int32_t hx,ix,lx;
+
+ EXTRACT_WORDS(hx,lx,x);
+ ix = 0x7fffffff&hx;
+ /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
+ if(ix>=0x7ff00000) return one/(x+x*x);
+ if((ix|lx)==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sin(x);
+ c = cos(x);
+ ss = -s-c;
+ cc = s-c;
+ if(ix<0x7fe00000) { /* make sure x+x not overflow */
+ z = cos(x+x);
+ if ((s*c)>zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
+ * where x0 = x-3pi/4
+ * Better formula:
+ * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ * = -1/sqrt(2) * (cos(x) + sin(x))
+ * To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.
+ */
+ if(ix>0x48000000) z = (invsqrtpi*ss)/sqrt(x);
+ else {
+ u = pone(x); v = qone(x);
+ z = invsqrtpi*(u*ss+v*cc)/sqrt(x);
+ }
+ return z;
+ }
+ if(ix<=0x3c900000) { /* x < 2**-54 */
+ return(-tpi/x);
+ }
+ z = x*x;
+ u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4])));
+ v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4]))));
+ return(x*(u/v) + tpi*(__ieee754_j1(x)*__ieee754_log(x)-one/x));
+}
+
+/* For x >= 8, the asymptotic expansions of pone is
+ * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x.
+ * We approximate pone by
+ * pone(x) = 1 + (R/S)
+ * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10
+ * S = 1 + ps0*s^2 + ... + ps4*s^10
+ * and
+ * | pone(x)-1-R/S | <= 2 ** ( -60.06)
+ */
+
+#ifdef __STDC__
+static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#else
+static double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#endif
+ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+ 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */
+ 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */
+ 4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */
+ 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */
+ 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */
+};
+#ifdef __STDC__
+static const double ps8[5] = {
+#else
+static double ps8[5] = {
+#endif
+ 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */
+ 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */
+ 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */
+ 9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */
+ 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */
+};
+
+#ifdef __STDC__
+static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#else
+static double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#endif
+ 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */
+ 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */
+ 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */
+ 1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */
+ 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */
+ 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */
+};
+#ifdef __STDC__
+static const double ps5[5] = {
+#else
+static double ps5[5] = {
+#endif
+ 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */
+ 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */
+ 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */
+ 7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */
+ 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */
+};
+
+#ifdef __STDC__
+static const double pr3[6] = {
+#else
+static double pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#endif
+ 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */
+ 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */
+ 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */
+ 3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */
+ 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */
+ 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */
+};
+#ifdef __STDC__
+static const double ps3[5] = {
+#else
+static double ps3[5] = {
+#endif
+ 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */
+ 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */
+ 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */
+ 8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */
+ 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */
+};
+
+#ifdef __STDC__
+static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#else
+static double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#endif
+ 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */
+ 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */
+ 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */
+ 1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */
+ 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */
+ 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */
+};
+#ifdef __STDC__
+static const double ps2[5] = {
+#else
+static double ps2[5] = {
+#endif
+ 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */
+ 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */
+ 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */
+ 1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */
+ 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */
+};
+
+#ifdef __STDC__
+ static double pone(double x)
+#else
+ static double pone(x)
+ double x;
+#endif
+{
+#ifdef __STDC__
+ const double *p,*q;
+#else
+ double *p,*q;
+#endif
+ double z,r,s;
+ int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x40200000) {p = pr8; q= ps8;}
+ else if(ix>=0x40122E8B){p = pr5; q= ps5;}
+ else if(ix>=0x4006DB6D){p = pr3; q= ps3;}
+ else if(ix>=0x40000000){p = pr2; q= ps2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+ return one+ r/s;
+}
+
+
+/* For x >= 8, the asymptotic expansions of qone is
+ * 3/8 s - 105/1024 s^3 - ..., where s = 1/x.
+ * We approximate pone by
+ * qone(x) = s*(0.375 + (R/S))
+ * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10
+ * S = 1 + qs1*s^2 + ... + qs6*s^12
+ * and
+ * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13)
+ */
+
+#ifdef __STDC__
+static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#else
+static double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#endif
+ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+ -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */
+ -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */
+ -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */
+ -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */
+ -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */
+};
+#ifdef __STDC__
+static const double qs8[6] = {
+#else
+static double qs8[6] = {
+#endif
+ 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */
+ 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */
+ 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */
+ 7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */
+ 6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */
+ -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */
+};
+
+#ifdef __STDC__
+static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#else
+static double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#endif
+ -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */
+ -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */
+ -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */
+ -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */
+ -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */
+ -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */
+};
+#ifdef __STDC__
+static const double qs5[6] = {
+#else
+static double qs5[6] = {
+#endif
+ 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */
+ 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */
+ 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */
+ 4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */
+ 2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */
+ -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */
+};
+
+#ifdef __STDC__
+static const double qr3[6] = {
+#else
+static double qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#endif
+ -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */
+ -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */
+ -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */
+ -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */
+ -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */
+ -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */
+};
+#ifdef __STDC__
+static const double qs3[6] = {
+#else
+static double qs3[6] = {
+#endif
+ 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */
+ 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */
+ 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */
+ 5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */
+ 1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */
+ -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */
+};
+
+#ifdef __STDC__
+static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#else
+static double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#endif
+ -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */
+ -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */
+ -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */
+ -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */
+ -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */
+ -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */
+};
+#ifdef __STDC__
+static const double qs2[6] = {
+#else
+static double qs2[6] = {
+#endif
+ 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */
+ 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */
+ 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */
+ 7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */
+ 1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */
+ -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */
+};
+
+#ifdef __STDC__
+ static double qone(double x)
+#else
+ static double qone(x)
+ double x;
+#endif
+{
+#ifdef __STDC__
+ const double *p,*q;
+#else
+ double *p,*q;
+#endif
+ double s,r,z;
+ int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x40200000) {p = qr8; q= qs8;}
+ else if(ix>=0x40122E8B){p = qr5; q= qs5;}
+ else if(ix>=0x4006DB6D){p = qr3; q= qs3;}
+ else if(ix>=0x40000000){p = qr2; q= qs2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+ return (.375 + r/s)/x;
+}
diff --git a/lib/msun/src/e_j1f.c b/lib/msun/src/e_j1f.c
new file mode 100644
index 0000000..137b5f8
--- /dev/null
+++ b/lib/msun/src/e_j1f.c
@@ -0,0 +1,444 @@
+/* e_j1f.c -- float version of e_j1.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static float ponef(float), qonef(float);
+#else
+static float ponef(), qonef();
+#endif
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+huge = 1e30,
+one = 1.0,
+invsqrtpi= 5.6418961287e-01, /* 0x3f106ebb */
+tpi = 6.3661974669e-01, /* 0x3f22f983 */
+ /* R0/S0 on [0,2] */
+r00 = -6.2500000000e-02, /* 0xbd800000 */
+r01 = 1.4070566976e-03, /* 0x3ab86cfd */
+r02 = -1.5995563444e-05, /* 0xb7862e36 */
+r03 = 4.9672799207e-08, /* 0x335557d2 */
+s01 = 1.9153760746e-02, /* 0x3c9ce859 */
+s02 = 1.8594678841e-04, /* 0x3942fab6 */
+s03 = 1.1771846857e-06, /* 0x359dffc2 */
+s04 = 5.0463624390e-09, /* 0x31ad6446 */
+s05 = 1.2354227016e-11; /* 0x2d59567e */
+
+#ifdef __STDC__
+static const float zero = 0.0;
+#else
+static float zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ float __ieee754_j1f(float x)
+#else
+ float __ieee754_j1f(x)
+ float x;
+#endif
+{
+ float z, s,c,ss,cc,r,u,v,y;
+ int32_t hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) return one/x;
+ y = fabsf(x);
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sinf(y);
+ c = cosf(y);
+ ss = -s-c;
+ cc = s-c;
+ if(ix<0x7f000000) { /* make sure y+y not overflow */
+ z = cosf(y+y);
+ if ((s*c)>zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /*
+ * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
+ * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
+ */
+ if(ix>0x80000000) z = (invsqrtpi*cc)/sqrtf(y);
+ else {
+ u = ponef(y); v = qonef(y);
+ z = invsqrtpi*(u*cc-v*ss)/sqrtf(y);
+ }
+ if(hx<0) return -z;
+ else return z;
+ }
+ if(ix<0x32000000) { /* |x|<2**-27 */
+ if(huge+x>one) return (float)0.5*x;/* inexact if x!=0 necessary */
+ }
+ z = x*x;
+ r = z*(r00+z*(r01+z*(r02+z*r03)));
+ s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05))));
+ r *= x;
+ return(x*(float)0.5+r/s);
+}
+
+#ifdef __STDC__
+static const float U0[5] = {
+#else
+static float U0[5] = {
+#endif
+ -1.9605709612e-01, /* 0xbe48c331 */
+ 5.0443872809e-02, /* 0x3d4e9e3c */
+ -1.9125689287e-03, /* 0xbafaaf2a */
+ 2.3525259166e-05, /* 0x37c5581c */
+ -9.1909917899e-08, /* 0xb3c56003 */
+};
+#ifdef __STDC__
+static const float V0[5] = {
+#else
+static float V0[5] = {
+#endif
+ 1.9916731864e-02, /* 0x3ca3286a */
+ 2.0255257550e-04, /* 0x3954644b */
+ 1.3560879779e-06, /* 0x35b602d4 */
+ 6.2274145840e-09, /* 0x31d5f8eb */
+ 1.6655924903e-11, /* 0x2d9281cf */
+};
+
+#ifdef __STDC__
+ float __ieee754_y1f(float x)
+#else
+ float __ieee754_y1f(x)
+ float x;
+#endif
+{
+ float z, s,c,ss,cc,u,v;
+ int32_t hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = 0x7fffffff&hx;
+ /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
+ if(ix>=0x7f800000) return one/(x+x*x);
+ if(ix==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sinf(x);
+ c = cosf(x);
+ ss = -s-c;
+ cc = s-c;
+ if(ix<0x7f000000) { /* make sure x+x not overflow */
+ z = cosf(x+x);
+ if ((s*c)>zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
+ * where x0 = x-3pi/4
+ * Better formula:
+ * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ * = -1/sqrt(2) * (cos(x) + sin(x))
+ * To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.
+ */
+ if(ix>0x48000000) z = (invsqrtpi*ss)/sqrtf(x);
+ else {
+ u = ponef(x); v = qonef(x);
+ z = invsqrtpi*(u*ss+v*cc)/sqrtf(x);
+ }
+ return z;
+ }
+ if(ix<=0x24800000) { /* x < 2**-54 */
+ return(-tpi/x);
+ }
+ z = x*x;
+ u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4])));
+ v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4]))));
+ return(x*(u/v) + tpi*(__ieee754_j1f(x)*__ieee754_logf(x)-one/x));
+}
+
+/* For x >= 8, the asymptotic expansions of pone is
+ * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x.
+ * We approximate pone by
+ * pone(x) = 1 + (R/S)
+ * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10
+ * S = 1 + ps0*s^2 + ... + ps4*s^10
+ * and
+ * | pone(x)-1-R/S | <= 2 ** ( -60.06)
+ */
+
+#ifdef __STDC__
+static const float pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#else
+static float pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#endif
+ 0.0000000000e+00, /* 0x00000000 */
+ 1.1718750000e-01, /* 0x3df00000 */
+ 1.3239480972e+01, /* 0x4153d4ea */
+ 4.1205184937e+02, /* 0x43ce06a3 */
+ 3.8747453613e+03, /* 0x45722bed */
+ 7.9144794922e+03, /* 0x45f753d6 */
+};
+#ifdef __STDC__
+static const float ps8[5] = {
+#else
+static float ps8[5] = {
+#endif
+ 1.1420736694e+02, /* 0x42e46a2c */
+ 3.6509309082e+03, /* 0x45642ee5 */
+ 3.6956207031e+04, /* 0x47105c35 */
+ 9.7602796875e+04, /* 0x47bea166 */
+ 3.0804271484e+04, /* 0x46f0a88b */
+};
+
+#ifdef __STDC__
+static const float pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#else
+static float pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#endif
+ 1.3199052094e-11, /* 0x2d68333f */
+ 1.1718749255e-01, /* 0x3defffff */
+ 6.8027510643e+00, /* 0x40d9b023 */
+ 1.0830818176e+02, /* 0x42d89dca */
+ 5.1763616943e+02, /* 0x440168b7 */
+ 5.2871520996e+02, /* 0x44042dc6 */
+};
+#ifdef __STDC__
+static const float ps5[5] = {
+#else
+static float ps5[5] = {
+#endif
+ 5.9280597687e+01, /* 0x426d1f55 */
+ 9.9140142822e+02, /* 0x4477d9b1 */
+ 5.3532670898e+03, /* 0x45a74a23 */
+ 7.8446904297e+03, /* 0x45f52586 */
+ 1.5040468750e+03, /* 0x44bc0180 */
+};
+
+#ifdef __STDC__
+static const float pr3[6] = {
+#else
+static float pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#endif
+ 3.0250391081e-09, /* 0x314fe10d */
+ 1.1718686670e-01, /* 0x3defffab */
+ 3.9329774380e+00, /* 0x407bb5e7 */
+ 3.5119403839e+01, /* 0x420c7a45 */
+ 9.1055007935e+01, /* 0x42b61c2a */
+ 4.8559066772e+01, /* 0x42423c7c */
+};
+#ifdef __STDC__
+static const float ps3[5] = {
+#else
+static float ps3[5] = {
+#endif
+ 3.4791309357e+01, /* 0x420b2a4d */
+ 3.3676245117e+02, /* 0x43a86198 */
+ 1.0468714600e+03, /* 0x4482dbe3 */
+ 8.9081134033e+02, /* 0x445eb3ed */
+ 1.0378793335e+02, /* 0x42cf936c */
+};
+
+#ifdef __STDC__
+static const float pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#else
+static float pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#endif
+ 1.0771083225e-07, /* 0x33e74ea8 */
+ 1.1717621982e-01, /* 0x3deffa16 */
+ 2.3685150146e+00, /* 0x401795c0 */
+ 1.2242610931e+01, /* 0x4143e1bc */
+ 1.7693971634e+01, /* 0x418d8d41 */
+ 5.0735230446e+00, /* 0x40a25a4d */
+};
+#ifdef __STDC__
+static const float ps2[5] = {
+#else
+static float ps2[5] = {
+#endif
+ 2.1436485291e+01, /* 0x41ab7dec */
+ 1.2529022980e+02, /* 0x42fa9499 */
+ 2.3227647400e+02, /* 0x436846c7 */
+ 1.1767937469e+02, /* 0x42eb5bd7 */
+ 8.3646392822e+00, /* 0x4105d590 */
+};
+
+#ifdef __STDC__
+ static float ponef(float x)
+#else
+ static float ponef(x)
+ float x;
+#endif
+{
+#ifdef __STDC__
+ const float *p,*q;
+#else
+ float *p,*q;
+#endif
+ float z,r,s;
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x41000000) {p = pr8; q= ps8;}
+ else if(ix>=0x40f71c58){p = pr5; q= ps5;}
+ else if(ix>=0x4036db68){p = pr3; q= ps3;}
+ else if(ix>=0x40000000){p = pr2; q= ps2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+ return one+ r/s;
+}
+
+
+/* For x >= 8, the asymptotic expansions of qone is
+ * 3/8 s - 105/1024 s^3 - ..., where s = 1/x.
+ * We approximate pone by
+ * qone(x) = s*(0.375 + (R/S))
+ * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10
+ * S = 1 + qs1*s^2 + ... + qs6*s^12
+ * and
+ * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13)
+ */
+
+#ifdef __STDC__
+static const float qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#else
+static float qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+#endif
+ 0.0000000000e+00, /* 0x00000000 */
+ -1.0253906250e-01, /* 0xbdd20000 */
+ -1.6271753311e+01, /* 0xc1822c8d */
+ -7.5960174561e+02, /* 0xc43de683 */
+ -1.1849806641e+04, /* 0xc639273a */
+ -4.8438511719e+04, /* 0xc73d3683 */
+};
+#ifdef __STDC__
+static const float qs8[6] = {
+#else
+static float qs8[6] = {
+#endif
+ 1.6139537048e+02, /* 0x43216537 */
+ 7.8253862305e+03, /* 0x45f48b17 */
+ 1.3387534375e+05, /* 0x4802bcd6 */
+ 7.1965775000e+05, /* 0x492fb29c */
+ 6.6660125000e+05, /* 0x4922be94 */
+ -2.9449025000e+05, /* 0xc88fcb48 */
+};
+
+#ifdef __STDC__
+static const float qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#else
+static float qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+#endif
+ -2.0897993405e-11, /* 0xadb7d219 */
+ -1.0253904760e-01, /* 0xbdd1fffe */
+ -8.0564479828e+00, /* 0xc100e736 */
+ -1.8366960144e+02, /* 0xc337ab6b */
+ -1.3731937256e+03, /* 0xc4aba633 */
+ -2.6124443359e+03, /* 0xc523471c */
+};
+#ifdef __STDC__
+static const float qs5[6] = {
+#else
+static float qs5[6] = {
+#endif
+ 8.1276550293e+01, /* 0x42a28d98 */
+ 1.9917987061e+03, /* 0x44f8f98f */
+ 1.7468484375e+04, /* 0x468878f8 */
+ 4.9851425781e+04, /* 0x4742bb6d */
+ 2.7948074219e+04, /* 0x46da5826 */
+ -4.7191835938e+03, /* 0xc5937978 */
+};
+
+#ifdef __STDC__
+static const float qr3[6] = {
+#else
+static float qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+#endif
+ -5.0783124372e-09, /* 0xb1ae7d4f */
+ -1.0253783315e-01, /* 0xbdd1ff5b */
+ -4.6101160049e+00, /* 0xc0938612 */
+ -5.7847221375e+01, /* 0xc267638e */
+ -2.2824453735e+02, /* 0xc3643e9a */
+ -2.1921012878e+02, /* 0xc35b35cb */
+};
+#ifdef __STDC__
+static const float qs3[6] = {
+#else
+static float qs3[6] = {
+#endif
+ 4.7665153503e+01, /* 0x423ea91e */
+ 6.7386511230e+02, /* 0x4428775e */
+ 3.3801528320e+03, /* 0x45534272 */
+ 5.5477290039e+03, /* 0x45ad5dd5 */
+ 1.9031191406e+03, /* 0x44ede3d0 */
+ -1.3520118713e+02, /* 0xc3073381 */
+};
+
+#ifdef __STDC__
+static const float qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#else
+static float qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+#endif
+ -1.7838172539e-07, /* 0xb43f8932 */
+ -1.0251704603e-01, /* 0xbdd1f475 */
+ -2.7522056103e+00, /* 0xc0302423 */
+ -1.9663616180e+01, /* 0xc19d4f16 */
+ -4.2325313568e+01, /* 0xc2294d1f */
+ -2.1371921539e+01, /* 0xc1aaf9b2 */
+};
+#ifdef __STDC__
+static const float qs2[6] = {
+#else
+static float qs2[6] = {
+#endif
+ 2.9533363342e+01, /* 0x41ec4454 */
+ 2.5298155212e+02, /* 0x437cfb47 */
+ 7.5750280762e+02, /* 0x443d602e */
+ 7.3939318848e+02, /* 0x4438d92a */
+ 1.5594900513e+02, /* 0x431bf2f2 */
+ -4.9594988823e+00, /* 0xc09eb437 */
+};
+
+#ifdef __STDC__
+ static float qonef(float x)
+#else
+ static float qonef(x)
+ float x;
+#endif
+{
+#ifdef __STDC__
+ const float *p,*q;
+#else
+ float *p,*q;
+#endif
+ float s,r,z;
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x40200000) {p = qr8; q= qs8;}
+ else if(ix>=0x40f71c58){p = qr5; q= qs5;}
+ else if(ix>=0x4036db68){p = qr3; q= qs3;}
+ else if(ix>=0x40000000){p = qr2; q= qs2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+ return ((float).375 + r/s)/x;
+}
diff --git a/lib/msun/src/e_jn.c b/lib/msun/src/e_jn.c
new file mode 100644
index 0000000..2265639
--- /dev/null
+++ b/lib/msun/src/e_jn.c
@@ -0,0 +1,281 @@
+/* @(#)e_jn.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * __ieee754_jn(n, x), __ieee754_yn(n, x)
+ * floating point Bessel's function of the 1st and 2nd kind
+ * of order n
+ *
+ * Special cases:
+ * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal;
+ * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
+ * Note 2. About jn(n,x), yn(n,x)
+ * For n=0, j0(x) is called,
+ * for n=1, j1(x) is called,
+ * for n<x, forward recursion us used starting
+ * from values of j0(x) and j1(x).
+ * for n>x, a continued fraction approximation to
+ * j(n,x)/j(n-1,x) is evaluated and then backward
+ * recursion is used starting from a supposed value
+ * for j(n,x). The resulting value of j(0,x) is
+ * compared with the actual value to correct the
+ * supposed value of j(n,x).
+ *
+ * yn(n,x) is similar in all respects, except
+ * that forward recursion is used for all
+ * values of n>1.
+ *
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
+two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
+one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */
+
+#ifdef __STDC__
+static const double zero = 0.00000000000000000000e+00;
+#else
+static double zero = 0.00000000000000000000e+00;
+#endif
+
+#ifdef __STDC__
+ double __ieee754_jn(int n, double x)
+#else
+ double __ieee754_jn(n,x)
+ int n; double x;
+#endif
+{
+ int32_t i,hx,ix,lx, sgn;
+ double a, b, temp, di;
+ double z, w;
+
+ /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
+ * Thus, J(-n,x) = J(n,-x)
+ */
+ EXTRACT_WORDS(hx,lx,x);
+ ix = 0x7fffffff&hx;
+ /* if J(n,NaN) is NaN */
+ if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x;
+ if(n<0){
+ n = -n;
+ x = -x;
+ hx ^= 0x80000000;
+ }
+ if(n==0) return(__ieee754_j0(x));
+ if(n==1) return(__ieee754_j1(x));
+ sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */
+ x = fabs(x);
+ if((ix|lx)==0||ix>=0x7ff00000) /* if x is 0 or inf */
+ b = zero;
+ else if((double)n<=x) {
+ /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
+ if(ix>=0x52D00000) { /* x > 2**302 */
+ /* (x >> n**2)
+ * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+ * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+ * Let s=sin(x), c=cos(x),
+ * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
+ *
+ * n sin(xn)*sqt2 cos(xn)*sqt2
+ * ----------------------------------
+ * 0 s-c c+s
+ * 1 -s-c -c+s
+ * 2 -s+c -c-s
+ * 3 s+c c-s
+ */
+ switch(n&3) {
+ case 0: temp = cos(x)+sin(x); break;
+ case 1: temp = -cos(x)+sin(x); break;
+ case 2: temp = -cos(x)-sin(x); break;
+ case 3: temp = cos(x)-sin(x); break;
+ }
+ b = invsqrtpi*temp/sqrt(x);
+ } else {
+ a = __ieee754_j0(x);
+ b = __ieee754_j1(x);
+ for(i=1;i<n;i++){
+ temp = b;
+ b = b*((double)(i+i)/x) - a; /* avoid underflow */
+ a = temp;
+ }
+ }
+ } else {
+ if(ix<0x3e100000) { /* x < 2**-29 */
+ /* x is tiny, return the first Taylor expansion of J(n,x)
+ * J(n,x) = 1/n!*(x/2)^n - ...
+ */
+ if(n>33) /* underflow */
+ b = zero;
+ else {
+ temp = x*0.5; b = temp;
+ for (a=one,i=2;i<=n;i++) {
+ a *= (double)i; /* a = n! */
+ b *= temp; /* b = (x/2)^n */
+ }
+ b = b/a;
+ }
+ } else {
+ /* use backward recurrence */
+ /* x x^2 x^2
+ * J(n,x)/J(n-1,x) = ---- ------ ------ .....
+ * 2n - 2(n+1) - 2(n+2)
+ *
+ * 1 1 1
+ * (for large x) = ---- ------ ------ .....
+ * 2n 2(n+1) 2(n+2)
+ * -- - ------ - ------ -
+ * x x x
+ *
+ * Let w = 2n/x and h=2/x, then the above quotient
+ * is equal to the continued fraction:
+ * 1
+ * = -----------------------
+ * 1
+ * w - -----------------
+ * 1
+ * w+h - ---------
+ * w+2h - ...
+ *
+ * To determine how many terms needed, let
+ * Q(0) = w, Q(1) = w(w+h) - 1,
+ * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
+ * When Q(k) > 1e4 good for single
+ * When Q(k) > 1e9 good for double
+ * When Q(k) > 1e17 good for quadruple
+ */
+ /* determine k */
+ double t,v;
+ double q0,q1,h,tmp; int32_t k,m;
+ w = (n+n)/(double)x; h = 2.0/(double)x;
+ q0 = w; z = w+h; q1 = w*z - 1.0; k=1;
+ while(q1<1.0e9) {
+ k += 1; z += h;
+ tmp = z*q1 - q0;
+ q0 = q1;
+ q1 = tmp;
+ }
+ m = n+n;
+ for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
+ a = t;
+ b = one;
+ /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
+ * Hence, if n*(log(2n/x)) > ...
+ * single 8.8722839355e+01
+ * double 7.09782712893383973096e+02
+ * long double 1.1356523406294143949491931077970765006170e+04
+ * then recurrent value may overflow and the result is
+ * likely underflow to zero
+ */
+ tmp = n;
+ v = two/x;
+ tmp = tmp*__ieee754_log(fabs(v*tmp));
+ if(tmp<7.09782712893383973096e+02) {
+ for(i=n-1,di=(double)(i+i);i>0;i--){
+ temp = b;
+ b *= di;
+ b = b/x - a;
+ a = temp;
+ di -= two;
+ }
+ } else {
+ for(i=n-1,di=(double)(i+i);i>0;i--){
+ temp = b;
+ b *= di;
+ b = b/x - a;
+ a = temp;
+ di -= two;
+ /* scale b to avoid spurious overflow */
+ if(b>1e100) {
+ a /= b;
+ t /= b;
+ b = one;
+ }
+ }
+ }
+ b = (t*__ieee754_j0(x)/b);
+ }
+ }
+ if(sgn==1) return -b; else return b;
+}
+
+#ifdef __STDC__
+ double __ieee754_yn(int n, double x)
+#else
+ double __ieee754_yn(n,x)
+ int n; double x;
+#endif
+{
+ int32_t i,hx,ix,lx;
+ int32_t sign;
+ double a, b, temp;
+
+ EXTRACT_WORDS(hx,lx,x);
+ ix = 0x7fffffff&hx;
+ /* if Y(n,NaN) is NaN */
+ if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x;
+ if((ix|lx)==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ sign = 1;
+ if(n<0){
+ n = -n;
+ sign = 1 - ((n&1)<<1);
+ }
+ if(n==0) return(__ieee754_y0(x));
+ if(n==1) return(sign*__ieee754_y1(x));
+ if(ix==0x7ff00000) return zero;
+ if(ix>=0x52D00000) { /* x > 2**302 */
+ /* (x >> n**2)
+ * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+ * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+ * Let s=sin(x), c=cos(x),
+ * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
+ *
+ * n sin(xn)*sqt2 cos(xn)*sqt2
+ * ----------------------------------
+ * 0 s-c c+s
+ * 1 -s-c -c+s
+ * 2 -s+c -c-s
+ * 3 s+c c-s
+ */
+ switch(n&3) {
+ case 0: temp = sin(x)-cos(x); break;
+ case 1: temp = -sin(x)-cos(x); break;
+ case 2: temp = -sin(x)+cos(x); break;
+ case 3: temp = sin(x)+cos(x); break;
+ }
+ b = invsqrtpi*temp/sqrt(x);
+ } else {
+ u_int32_t high;
+ a = __ieee754_y0(x);
+ b = __ieee754_y1(x);
+ /* quit if b is -inf */
+ GET_HIGH_WORD(high,b);
+ for(i=1;i<n&&high!=0xfff00000;i++){
+ temp = b;
+ b = ((double)(i+i)/x)*b - a;
+ GET_HIGH_WORD(high,b);
+ a = temp;
+ }
+ }
+ if(sign>0) return b; else return -b;
+}
diff --git a/lib/msun/src/e_jnf.c b/lib/msun/src/e_jnf.c
new file mode 100644
index 0000000..544d6e5
--- /dev/null
+++ b/lib/msun/src/e_jnf.c
@@ -0,0 +1,212 @@
+/* e_jnf.c -- float version of e_jn.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+invsqrtpi= 5.6418961287e-01, /* 0x3f106ebb */
+two = 2.0000000000e+00, /* 0x40000000 */
+one = 1.0000000000e+00; /* 0x3F800000 */
+
+#ifdef __STDC__
+static const float zero = 0.0000000000e+00;
+#else
+static float zero = 0.0000000000e+00;
+#endif
+
+#ifdef __STDC__
+ float __ieee754_jnf(int n, float x)
+#else
+ float __ieee754_jnf(n,x)
+ int n; float x;
+#endif
+{
+ int32_t i,hx,ix, sgn;
+ float a, b, temp, di;
+ float z, w;
+
+ /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
+ * Thus, J(-n,x) = J(n,-x)
+ */
+ GET_FLOAT_WORD(hx,x);
+ ix = 0x7fffffff&hx;
+ /* if J(n,NaN) is NaN */
+ if(ix>0x7f800000) return x+x;
+ if(n<0){
+ n = -n;
+ x = -x;
+ hx ^= 0x80000000;
+ }
+ if(n==0) return(__ieee754_j0f(x));
+ if(n==1) return(__ieee754_j1f(x));
+ sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */
+ x = fabsf(x);
+ if(ix==0||ix>=0x7f800000) /* if x is 0 or inf */
+ b = zero;
+ else if((float)n<=x) {
+ /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
+ a = __ieee754_j0f(x);
+ b = __ieee754_j1f(x);
+ for(i=1;i<n;i++){
+ temp = b;
+ b = b*((float)(i+i)/x) - a; /* avoid underflow */
+ a = temp;
+ }
+ } else {
+ if(ix<0x30800000) { /* x < 2**-29 */
+ /* x is tiny, return the first Taylor expansion of J(n,x)
+ * J(n,x) = 1/n!*(x/2)^n - ...
+ */
+ if(n>33) /* underflow */
+ b = zero;
+ else {
+ temp = x*(float)0.5; b = temp;
+ for (a=one,i=2;i<=n;i++) {
+ a *= (float)i; /* a = n! */
+ b *= temp; /* b = (x/2)^n */
+ }
+ b = b/a;
+ }
+ } else {
+ /* use backward recurrence */
+ /* x x^2 x^2
+ * J(n,x)/J(n-1,x) = ---- ------ ------ .....
+ * 2n - 2(n+1) - 2(n+2)
+ *
+ * 1 1 1
+ * (for large x) = ---- ------ ------ .....
+ * 2n 2(n+1) 2(n+2)
+ * -- - ------ - ------ -
+ * x x x
+ *
+ * Let w = 2n/x and h=2/x, then the above quotient
+ * is equal to the continued fraction:
+ * 1
+ * = -----------------------
+ * 1
+ * w - -----------------
+ * 1
+ * w+h - ---------
+ * w+2h - ...
+ *
+ * To determine how many terms needed, let
+ * Q(0) = w, Q(1) = w(w+h) - 1,
+ * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
+ * When Q(k) > 1e4 good for single
+ * When Q(k) > 1e9 good for double
+ * When Q(k) > 1e17 good for quadruple
+ */
+ /* determine k */
+ float t,v;
+ float q0,q1,h,tmp; int32_t k,m;
+ w = (n+n)/(float)x; h = (float)2.0/(float)x;
+ q0 = w; z = w+h; q1 = w*z - (float)1.0; k=1;
+ while(q1<(float)1.0e9) {
+ k += 1; z += h;
+ tmp = z*q1 - q0;
+ q0 = q1;
+ q1 = tmp;
+ }
+ m = n+n;
+ for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
+ a = t;
+ b = one;
+ /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
+ * Hence, if n*(log(2n/x)) > ...
+ * single 8.8722839355e+01
+ * double 7.09782712893383973096e+02
+ * long double 1.1356523406294143949491931077970765006170e+04
+ * then recurrent value may overflow and the result is
+ * likely underflow to zero
+ */
+ tmp = n;
+ v = two/x;
+ tmp = tmp*__ieee754_logf(fabsf(v*tmp));
+ if(tmp<(float)8.8721679688e+01) {
+ for(i=n-1,di=(float)(i+i);i>0;i--){
+ temp = b;
+ b *= di;
+ b = b/x - a;
+ a = temp;
+ di -= two;
+ }
+ } else {
+ for(i=n-1,di=(float)(i+i);i>0;i--){
+ temp = b;
+ b *= di;
+ b = b/x - a;
+ a = temp;
+ di -= two;
+ /* scale b to avoid spurious overflow */
+ if(b>(float)1e10) {
+ a /= b;
+ t /= b;
+ b = one;
+ }
+ }
+ }
+ b = (t*__ieee754_j0f(x)/b);
+ }
+ }
+ if(sgn==1) return -b; else return b;
+}
+
+#ifdef __STDC__
+ float __ieee754_ynf(int n, float x)
+#else
+ float __ieee754_ynf(n,x)
+ int n; float x;
+#endif
+{
+ int32_t i,hx,ix,ib;
+ int32_t sign;
+ float a, b, temp;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = 0x7fffffff&hx;
+ /* if Y(n,NaN) is NaN */
+ if(ix>0x7f800000) return x+x;
+ if(ix==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ sign = 1;
+ if(n<0){
+ n = -n;
+ sign = 1 - ((n&1)<<1);
+ }
+ if(n==0) return(__ieee754_y0f(x));
+ if(n==1) return(sign*__ieee754_y1f(x));
+ if(ix==0x7f800000) return zero;
+
+ a = __ieee754_y0f(x);
+ b = __ieee754_y1f(x);
+ /* quit if b is -inf */
+ GET_FLOAT_WORD(ib,b);
+ for(i=1;i<n&&ib!=0xff800000;i++){
+ temp = b;
+ b = ((float)(i+i)/x)*b - a;
+ GET_FLOAT_WORD(ib,b);
+ a = temp;
+ }
+ if(sign>0) return b; else return -b;
+}
diff --git a/lib/msun/src/e_lgamma.c b/lib/msun/src/e_lgamma.c
new file mode 100644
index 0000000..1bf264b
--- /dev/null
+++ b/lib/msun/src/e_lgamma.c
@@ -0,0 +1,36 @@
+/* @(#)e_lgamma.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_lgamma(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_lgamma_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+#ifdef __STDC__
+ double __ieee754_lgamma(double x)
+#else
+ double __ieee754_lgamma(x)
+ double x;
+#endif
+{
+ return __ieee754_lgamma_r(x,&signgam);
+}
diff --git a/lib/msun/src/e_lgamma_r.c b/lib/msun/src/e_lgamma_r.c
new file mode 100644
index 0000000..ab6d2f0
--- /dev/null
+++ b/lib/msun/src/e_lgamma_r.c
@@ -0,0 +1,312 @@
+/* @(#)er_lgamma.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_lgamma_r(x, signgamp)
+ * Reentrant version of the logarithm of the Gamma function
+ * with user provide pointer for the sign of Gamma(x).
+ *
+ * Method:
+ * 1. Argument Reduction for 0 < x <= 8
+ * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may
+ * reduce x to a number in [1.5,2.5] by
+ * lgamma(1+s) = log(s) + lgamma(s)
+ * for example,
+ * lgamma(7.3) = log(6.3) + lgamma(6.3)
+ * = log(6.3*5.3) + lgamma(5.3)
+ * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3)
+ * 2. Polynomial approximation of lgamma around its
+ * minimun ymin=1.461632144968362245 to maintain monotonicity.
+ * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use
+ * Let z = x-ymin;
+ * lgamma(x) = -1.214862905358496078218 + z^2*poly(z)
+ * where
+ * poly(z) is a 14 degree polynomial.
+ * 2. Rational approximation in the primary interval [2,3]
+ * We use the following approximation:
+ * s = x-2.0;
+ * lgamma(x) = 0.5*s + s*P(s)/Q(s)
+ * with accuracy
+ * |P/Q - (lgamma(x)-0.5s)| < 2**-61.71
+ * Our algorithms are based on the following observation
+ *
+ * zeta(2)-1 2 zeta(3)-1 3
+ * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ...
+ * 2 3
+ *
+ * where Euler = 0.5771... is the Euler constant, which is very
+ * close to 0.5.
+ *
+ * 3. For x>=8, we have
+ * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+....
+ * (better formula:
+ * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...)
+ * Let z = 1/x, then we approximation
+ * f(z) = lgamma(x) - (x-0.5)(log(x)-1)
+ * by
+ * 3 5 11
+ * w = w0 + w1*z + w2*z + w3*z + ... + w6*z
+ * where
+ * |w - f(z)| < 2**-58.74
+ *
+ * 4. For negative x, since (G is gamma function)
+ * -x*G(-x)*G(x) = pi/sin(pi*x),
+ * we have
+ * G(x) = pi/(sin(pi*x)*(-x)*G(-x))
+ * since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0
+ * Hence, for x<0, signgam = sign(sin(pi*x)) and
+ * lgamma(x) = log(|Gamma(x)|)
+ * = log(pi/(|x*sin(pi*x)|)) - lgamma(-x);
+ * Note: one should avoid compute pi*(-x) directly in the
+ * computation of sin(pi*(-x)).
+ *
+ * 5. Special Cases
+ * lgamma(2+s) ~ s*(1-Euler) for tiny s
+ * lgamma(1)=lgamma(2)=0
+ * lgamma(x) ~ -log(x) for tiny x
+ * lgamma(0) = lgamma(inf) = inf
+ * lgamma(-integer) = +-inf
+ *
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
+a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */
+a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */
+a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */
+a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */
+a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */
+a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */
+a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */
+a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */
+a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */
+a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */
+a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */
+a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */
+tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */
+tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */
+/* tt = -(tail of tf) */
+tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */
+t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */
+t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */
+t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */
+t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */
+t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */
+t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */
+t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */
+t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */
+t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */
+t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */
+t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */
+t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */
+t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */
+t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */
+t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */
+u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */
+u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */
+u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */
+u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */
+u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */
+u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */
+v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */
+v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */
+v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */
+v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */
+v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */
+s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */
+s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */
+s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */
+s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */
+s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */
+s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */
+s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */
+r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */
+r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */
+r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */
+r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */
+r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */
+r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */
+w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */
+w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */
+w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */
+w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */
+w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */
+w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */
+w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */
+
+#ifdef __STDC__
+static const double zero= 0.00000000000000000000e+00;
+#else
+static double zero= 0.00000000000000000000e+00;
+#endif
+
+#ifdef __STDC__
+ static double sin_pi(double x)
+#else
+ static double sin_pi(x)
+ double x;
+#endif
+{
+ double y,z;
+ int n,ix;
+
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+
+ if(ix<0x3fd00000) return __kernel_sin(pi*x,zero,0);
+ y = -x; /* x is assume negative */
+
+ /*
+ * argument reduction, make sure inexact flag not raised if input
+ * is an integer
+ */
+ z = floor(y);
+ if(z!=y) { /* inexact anyway */
+ y *= 0.5;
+ y = 2.0*(y - floor(y)); /* y = |x| mod 2.0 */
+ n = (int) (y*4.0);
+ } else {
+ if(ix>=0x43400000) {
+ y = zero; n = 0; /* y must be even */
+ } else {
+ if(ix<0x43300000) z = y+two52; /* exact */
+ GET_LOW_WORD(n,z);
+ n &= 1;
+ y = n;
+ n<<= 2;
+ }
+ }
+ switch (n) {
+ case 0: y = __kernel_sin(pi*y,zero,0); break;
+ case 1:
+ case 2: y = __kernel_cos(pi*(0.5-y),zero); break;
+ case 3:
+ case 4: y = __kernel_sin(pi*(one-y),zero,0); break;
+ case 5:
+ case 6: y = -__kernel_cos(pi*(y-1.5),zero); break;
+ default: y = __kernel_sin(pi*(y-2.0),zero,0); break;
+ }
+ return -y;
+}
+
+
+#ifdef __STDC__
+ double __ieee754_lgamma_r(double x, int *signgamp)
+#else
+ double __ieee754_lgamma_r(x,signgamp)
+ double x; int *signgamp;
+#endif
+{
+ double t,y,z,nadj,p,p1,p2,p3,q,r,w;
+ int i,hx,lx,ix;
+
+ EXTRACT_WORDS(hx,lx,x);
+
+ /* purge off +-inf, NaN, +-0, and negative arguments */
+ *signgamp = 1;
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) return x*x;
+ if((ix|lx)==0) return one/zero;
+ if(ix<0x3b900000) { /* |x|<2**-70, return -log(|x|) */
+ if(hx<0) {
+ *signgamp = -1;
+ return -__ieee754_log(-x);
+ } else return -__ieee754_log(x);
+ }
+ if(hx<0) {
+ if(ix>=0x43300000) /* |x|>=2**52, must be -integer */
+ return one/zero;
+ t = sin_pi(x);
+ if(t==zero) return one/zero; /* -integer */
+ nadj = __ieee754_log(pi/fabs(t*x));
+ if(t<zero) *signgamp = -1;
+ x = -x;
+ }
+
+ /* purge off 1 and 2 */
+ if((((ix-0x3ff00000)|lx)==0)||(((ix-0x40000000)|lx)==0)) r = 0;
+ /* for x < 2.0 */
+ else if(ix<0x40000000) {
+ if(ix<=0x3feccccc) { /* lgamma(x) = lgamma(x+1)-log(x) */
+ r = -__ieee754_log(x);
+ if(ix>=0x3FE76944) {y = one-x; i= 0;}
+ else if(ix>=0x3FCDA661) {y= x-(tc-one); i=1;}
+ else {y = x; i=2;}
+ } else {
+ r = zero;
+ if(ix>=0x3FFBB4C3) {y=2.0-x;i=0;} /* [1.7316,2] */
+ else if(ix>=0x3FF3B4C4) {y=x-tc;i=1;} /* [1.23,1.73] */
+ else {y=x-one;i=2;}
+ }
+ switch(i) {
+ case 0:
+ z = y*y;
+ p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10))));
+ p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11)))));
+ p = y*p1+p2;
+ r += (p-0.5*y); break;
+ case 1:
+ z = y*y;
+ w = z*y;
+ p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */
+ p2 = t1+w*(t4+w*(t7+w*(t10+w*t13)));
+ p3 = t2+w*(t5+w*(t8+w*(t11+w*t14)));
+ p = z*p1-(tt-w*(p2+y*p3));
+ r += (tf + p); break;
+ case 2:
+ p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5)))));
+ p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5))));
+ r += (-0.5*y + p1/p2);
+ }
+ }
+ else if(ix<0x40200000) { /* x < 8.0 */
+ i = (int)x;
+ t = zero;
+ y = x-(double)i;
+ p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
+ q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6)))));
+ r = half*y+p/q;
+ z = one; /* lgamma(1+s) = log(s) + lgamma(s) */
+ switch(i) {
+ case 7: z *= (y+6.0); /* FALLTHRU */
+ case 6: z *= (y+5.0); /* FALLTHRU */
+ case 5: z *= (y+4.0); /* FALLTHRU */
+ case 4: z *= (y+3.0); /* FALLTHRU */
+ case 3: z *= (y+2.0); /* FALLTHRU */
+ r += __ieee754_log(z); break;
+ }
+ /* 8.0 <= x < 2**58 */
+ } else if (ix < 0x43900000) {
+ t = __ieee754_log(x);
+ z = one/x;
+ y = z*z;
+ w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6)))));
+ r = (x-half)*(t-one)+w;
+ } else
+ /* 2**58 <= x <= inf */
+ r = x*(__ieee754_log(x)-one);
+ if(hx<0) r = nadj - r;
+ return r;
+}
diff --git a/lib/msun/src/e_lgammaf.c b/lib/msun/src/e_lgammaf.c
new file mode 100644
index 0000000..c44054e
--- /dev/null
+++ b/lib/msun/src/e_lgammaf.c
@@ -0,0 +1,39 @@
+/* e_lgammaf.c -- float version of e_lgamma.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_lgammaf(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_lgammaf_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+#ifdef __STDC__
+ float __ieee754_lgammaf(float x)
+#else
+ float __ieee754_lgammaf(x)
+ float x;
+#endif
+{
+ return __ieee754_lgammaf_r(x,&signgam);
+}
diff --git a/lib/msun/src/e_lgammaf_r.c b/lib/msun/src/e_lgammaf_r.c
new file mode 100644
index 0000000..9fbe798
--- /dev/null
+++ b/lib/msun/src/e_lgammaf_r.c
@@ -0,0 +1,248 @@
+/* e_lgammaf_r.c -- float version of e_lgamma_r.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+two23= 8.3886080000e+06, /* 0x4b000000 */
+half= 5.0000000000e-01, /* 0x3f000000 */
+one = 1.0000000000e+00, /* 0x3f800000 */
+pi = 3.1415927410e+00, /* 0x40490fdb */
+a0 = 7.7215664089e-02, /* 0x3d9e233f */
+a1 = 3.2246702909e-01, /* 0x3ea51a66 */
+a2 = 6.7352302372e-02, /* 0x3d89f001 */
+a3 = 2.0580807701e-02, /* 0x3ca89915 */
+a4 = 7.3855509982e-03, /* 0x3bf2027e */
+a5 = 2.8905137442e-03, /* 0x3b3d6ec6 */
+a6 = 1.1927076848e-03, /* 0x3a9c54a1 */
+a7 = 5.1006977446e-04, /* 0x3a05b634 */
+a8 = 2.2086278477e-04, /* 0x39679767 */
+a9 = 1.0801156895e-04, /* 0x38e28445 */
+a10 = 2.5214456400e-05, /* 0x37d383a2 */
+a11 = 4.4864096708e-05, /* 0x383c2c75 */
+tc = 1.4616321325e+00, /* 0x3fbb16c3 */
+tf = -1.2148628384e-01, /* 0xbdf8cdcd */
+/* tt = -(tail of tf) */
+tt = 6.6971006518e-09, /* 0x31e61c52 */
+t0 = 4.8383611441e-01, /* 0x3ef7b95e */
+t1 = -1.4758771658e-01, /* 0xbe17213c */
+t2 = 6.4624942839e-02, /* 0x3d845a15 */
+t3 = -3.2788541168e-02, /* 0xbd064d47 */
+t4 = 1.7970675603e-02, /* 0x3c93373d */
+t5 = -1.0314224288e-02, /* 0xbc28fcfe */
+t6 = 6.1005386524e-03, /* 0x3bc7e707 */
+t7 = -3.6845202558e-03, /* 0xbb7177fe */
+t8 = 2.2596477065e-03, /* 0x3b141699 */
+t9 = -1.4034647029e-03, /* 0xbab7f476 */
+t10 = 8.8108185446e-04, /* 0x3a66f867 */
+t11 = -5.3859531181e-04, /* 0xba0d3085 */
+t12 = 3.1563205994e-04, /* 0x39a57b6b */
+t13 = -3.1275415677e-04, /* 0xb9a3f927 */
+t14 = 3.3552918467e-04, /* 0x39afe9f7 */
+u0 = -7.7215664089e-02, /* 0xbd9e233f */
+u1 = 6.3282704353e-01, /* 0x3f2200f4 */
+u2 = 1.4549225569e+00, /* 0x3fba3ae7 */
+u3 = 9.7771751881e-01, /* 0x3f7a4bb2 */
+u4 = 2.2896373272e-01, /* 0x3e6a7578 */
+u5 = 1.3381091878e-02, /* 0x3c5b3c5e */
+v1 = 2.4559779167e+00, /* 0x401d2ebe */
+v2 = 2.1284897327e+00, /* 0x4008392d */
+v3 = 7.6928514242e-01, /* 0x3f44efdf */
+v4 = 1.0422264785e-01, /* 0x3dd572af */
+v5 = 3.2170924824e-03, /* 0x3b52d5db */
+s0 = -7.7215664089e-02, /* 0xbd9e233f */
+s1 = 2.1498242021e-01, /* 0x3e5c245a */
+s2 = 3.2577878237e-01, /* 0x3ea6cc7a */
+s3 = 1.4635047317e-01, /* 0x3e15dce6 */
+s4 = 2.6642270386e-02, /* 0x3cda40e4 */
+s5 = 1.8402845599e-03, /* 0x3af135b4 */
+s6 = 3.1947532989e-05, /* 0x3805ff67 */
+r1 = 1.3920053244e+00, /* 0x3fb22d3b */
+r2 = 7.2193557024e-01, /* 0x3f38d0c5 */
+r3 = 1.7193385959e-01, /* 0x3e300f6e */
+r4 = 1.8645919859e-02, /* 0x3c98bf54 */
+r5 = 7.7794247773e-04, /* 0x3a4beed6 */
+r6 = 7.3266842264e-06, /* 0x36f5d7bd */
+w0 = 4.1893854737e-01, /* 0x3ed67f1d */
+w1 = 8.3333335817e-02, /* 0x3daaaaab */
+w2 = -2.7777778450e-03, /* 0xbb360b61 */
+w3 = 7.9365057172e-04, /* 0x3a500cfd */
+w4 = -5.9518753551e-04, /* 0xba1c065c */
+w5 = 8.3633989561e-04, /* 0x3a5b3dd2 */
+w6 = -1.6309292987e-03; /* 0xbad5c4e8 */
+
+#ifdef __STDC__
+static const float zero= 0.0000000000e+00;
+#else
+static float zero= 0.0000000000e+00;
+#endif
+
+#ifdef __STDC__
+ static float sin_pif(float x)
+#else
+ static float sin_pif(x)
+ float x;
+#endif
+{
+ float y,z;
+ int n,ix;
+
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+
+ if(ix<0x3e800000) return __kernel_sinf(pi*x,zero,0);
+ y = -x; /* x is assume negative */
+
+ /*
+ * argument reduction, make sure inexact flag not raised if input
+ * is an integer
+ */
+ z = floorf(y);
+ if(z!=y) { /* inexact anyway */
+ y *= (float)0.5;
+ y = (float)2.0*(y - floorf(y)); /* y = |x| mod 2.0 */
+ n = (int) (y*(float)4.0);
+ } else {
+ if(ix>=0x4b800000) {
+ y = zero; n = 0; /* y must be even */
+ } else {
+ if(ix<0x4b000000) z = y+two23; /* exact */
+ GET_FLOAT_WORD(n,z);
+ n &= 1;
+ y = n;
+ n<<= 2;
+ }
+ }
+ switch (n) {
+ case 0: y = __kernel_sinf(pi*y,zero,0); break;
+ case 1:
+ case 2: y = __kernel_cosf(pi*((float)0.5-y),zero); break;
+ case 3:
+ case 4: y = __kernel_sinf(pi*(one-y),zero,0); break;
+ case 5:
+ case 6: y = -__kernel_cosf(pi*(y-(float)1.5),zero); break;
+ default: y = __kernel_sinf(pi*(y-(float)2.0),zero,0); break;
+ }
+ return -y;
+}
+
+
+#ifdef __STDC__
+ float __ieee754_lgammaf_r(float x, int *signgamp)
+#else
+ float __ieee754_lgammaf_r(x,signgamp)
+ float x; int *signgamp;
+#endif
+{
+ float t,y,z,nadj,p,p1,p2,p3,q,r,w;
+ int i,hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+
+ /* purge off +-inf, NaN, +-0, and negative arguments */
+ *signgamp = 1;
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) return x*x;
+ if(ix==0) return one/zero;
+ if(ix<0x1c800000) { /* |x|<2**-70, return -log(|x|) */
+ if(hx<0) {
+ *signgamp = -1;
+ return -__ieee754_logf(-x);
+ } else return -__ieee754_logf(x);
+ }
+ if(hx<0) {
+ if(ix>=0x4b000000) /* |x|>=2**23, must be -integer */
+ return one/zero;
+ t = sin_pif(x);
+ if(t==zero) return one/zero; /* -integer */
+ nadj = __ieee754_logf(pi/fabsf(t*x));
+ if(t<zero) *signgamp = -1;
+ x = -x;
+ }
+
+ /* purge off 1 and 2 */
+ if (ix==0x3f800000||ix==0x40000000) r = 0;
+ /* for x < 2.0 */
+ else if(ix<0x40000000) {
+ if(ix<=0x3f666666) { /* lgamma(x) = lgamma(x+1)-log(x) */
+ r = -__ieee754_logf(x);
+ if(ix>=0x3f3b4a20) {y = one-x; i= 0;}
+ else if(ix>=0x3e6d3308) {y= x-(tc-one); i=1;}
+ else {y = x; i=2;}
+ } else {
+ r = zero;
+ if(ix>=0x3fdda618) {y=(float)2.0-x;i=0;} /* [1.7316,2] */
+ else if(ix>=0x3F9da620) {y=x-tc;i=1;} /* [1.23,1.73] */
+ else {y=x-one;i=2;}
+ }
+ switch(i) {
+ case 0:
+ z = y*y;
+ p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10))));
+ p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11)))));
+ p = y*p1+p2;
+ r += (p-(float)0.5*y); break;
+ case 1:
+ z = y*y;
+ w = z*y;
+ p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */
+ p2 = t1+w*(t4+w*(t7+w*(t10+w*t13)));
+ p3 = t2+w*(t5+w*(t8+w*(t11+w*t14)));
+ p = z*p1-(tt-w*(p2+y*p3));
+ r += (tf + p); break;
+ case 2:
+ p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5)))));
+ p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5))));
+ r += (-(float)0.5*y + p1/p2);
+ }
+ }
+ else if(ix<0x41000000) { /* x < 8.0 */
+ i = (int)x;
+ t = zero;
+ y = x-(float)i;
+ p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
+ q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6)))));
+ r = half*y+p/q;
+ z = one; /* lgamma(1+s) = log(s) + lgamma(s) */
+ switch(i) {
+ case 7: z *= (y+(float)6.0); /* FALLTHRU */
+ case 6: z *= (y+(float)5.0); /* FALLTHRU */
+ case 5: z *= (y+(float)4.0); /* FALLTHRU */
+ case 4: z *= (y+(float)3.0); /* FALLTHRU */
+ case 3: z *= (y+(float)2.0); /* FALLTHRU */
+ r += __ieee754_logf(z); break;
+ }
+ /* 8.0 <= x < 2**58 */
+ } else if (ix < 0x5c800000) {
+ t = __ieee754_logf(x);
+ z = one/x;
+ y = z*z;
+ w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6)))));
+ r = (x-half)*(t-one)+w;
+ } else
+ /* 2**58 <= x <= inf */
+ r = x*(__ieee754_logf(x)-one);
+ if(hx<0) r = nadj - r;
+ return r;
+}
diff --git a/lib/msun/src/e_log.c b/lib/msun/src/e_log.c
new file mode 100644
index 0000000..93294a2
--- /dev/null
+++ b/lib/msun/src/e_log.c
@@ -0,0 +1,146 @@
+/* @(#)e_log.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_log(x)
+ * Return the logrithm of x
+ *
+ * Method :
+ * 1. Argument Reduction: find k and f such that
+ * x = 2^k * (1+f),
+ * where sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ * 2. Approximation of log(1+f).
+ * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ * = 2s + s*R
+ * We use a special Reme algorithm on [0,0.1716] to generate
+ * a polynomial of degree 14 to approximate R The maximum error
+ * of this polynomial approximation is bounded by 2**-58.45. In
+ * other words,
+ * 2 4 6 8 10 12 14
+ * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
+ * (the values of Lg1 to Lg7 are listed in the program)
+ * and
+ * | 2 14 | -58.45
+ * | Lg1*s +...+Lg7*s - R(z) | <= 2
+ * | |
+ * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ * In order to guarantee error in log below 1ulp, we compute log
+ * by
+ * log(1+f) = f - s*(f - R) (if f is not too large)
+ * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
+ *
+ * 3. Finally, log(x) = k*ln2 + log(1+f).
+ * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ * Here ln2 is split into two floating point number:
+ * ln2_hi + ln2_lo,
+ * where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ * log(x) is NaN with signal if x < 0 (including -INF) ;
+ * log(+INF) is +INF; log(0) is -INF with signal;
+ * log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
+ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
+two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
+Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
+Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
+Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
+Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
+Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
+Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
+Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
+
+#ifdef __STDC__
+static const double zero = 0.0;
+#else
+static double zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ double __generic___ieee754_log(double x)
+#else
+ double __generic___ieee754_log(x)
+ double x;
+#endif
+{
+ double hfsq,f,s,z,R,w,t1,t2,dk;
+ int32_t k,hx,i,j;
+ u_int32_t lx;
+
+ EXTRACT_WORDS(hx,lx,x);
+
+ k=0;
+ if (hx < 0x00100000) { /* x < 2**-1022 */
+ if (((hx&0x7fffffff)|lx)==0)
+ return -two54/zero; /* log(+-0)=-inf */
+ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
+ k -= 54; x *= two54; /* subnormal number, scale up x */
+ GET_HIGH_WORD(hx,x);
+ }
+ if (hx >= 0x7ff00000) return x+x;
+ k += (hx>>20)-1023;
+ hx &= 0x000fffff;
+ i = (hx+0x95f64)&0x100000;
+ SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */
+ k += (i>>20);
+ f = x-1.0;
+ if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */
+ if(f==zero) if(k==0) return zero; else {dk=(double)k;
+ return dk*ln2_hi+dk*ln2_lo;}
+ R = f*f*(0.5-0.33333333333333333*f);
+ if(k==0) return f-R; else {dk=(double)k;
+ return dk*ln2_hi-((R-dk*ln2_lo)-f);}
+ }
+ s = f/(2.0+f);
+ dk = (double)k;
+ z = s*s;
+ i = hx-0x6147a;
+ w = z*z;
+ j = 0x6b851-hx;
+ t1= w*(Lg2+w*(Lg4+w*Lg6));
+ t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
+ i |= j;
+ R = t2+t1;
+ if(i>0) {
+ hfsq=0.5*f*f;
+ if(k==0) return f-(hfsq-s*(hfsq+R)); else
+ return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
+ } else {
+ if(k==0) return f-s*(f-R); else
+ return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
+ }
+}
diff --git a/lib/msun/src/e_log10.c b/lib/msun/src/e_log10.c
new file mode 100644
index 0000000..afc3376
--- /dev/null
+++ b/lib/msun/src/e_log10.c
@@ -0,0 +1,98 @@
+/* @(#)e_log10.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_log10(x)
+ * Return the base 10 logarithm of x
+ *
+ * Method :
+ * Let log10_2hi = leading 40 bits of log10(2) and
+ * log10_2lo = log10(2) - log10_2hi,
+ * ivln10 = 1/log(10) rounded.
+ * Then
+ * n = ilogb(x),
+ * if(n<0) n = n+1;
+ * x = scalbn(x,-n);
+ * log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x))
+ *
+ * Note 1:
+ * To guarantee log10(10**n)=n, where 10**n is normal, the rounding
+ * mode must set to Round-to-Nearest.
+ * Note 2:
+ * [1/log(10)] rounded to 53 bits has error .198 ulps;
+ * log10 is monotonic at all binary break points.
+ *
+ * Special cases:
+ * log10(x) is NaN with signal if x < 0;
+ * log10(+INF) is +INF with no signal; log10(0) is -INF with signal;
+ * log10(NaN) is that NaN with no signal;
+ * log10(10**N) = N for N=0,1,...,22.
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following constants.
+ * The decimal values may be used, provided that the compiler will convert
+ * from decimal to binary accurately enough to produce the hexadecimal values
+ * shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+ivln10 = 4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */
+log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
+log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
+
+#ifdef __STDC__
+static const double zero = 0.0;
+#else
+static double zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ double __generic___ieee754_log10(double x)
+#else
+ double __generic___ieee754_log10(x)
+ double x;
+#endif
+{
+ double y,z;
+ int32_t i,k,hx;
+ u_int32_t lx;
+
+ EXTRACT_WORDS(hx,lx,x);
+
+ k=0;
+ if (hx < 0x00100000) { /* x < 2**-1022 */
+ if (((hx&0x7fffffff)|lx)==0)
+ return -two54/zero; /* log(+-0)=-inf */
+ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
+ k -= 54; x *= two54; /* subnormal number, scale up x */
+ GET_HIGH_WORD(hx,x);
+ }
+ if (hx >= 0x7ff00000) return x+x;
+ k += (hx>>20)-1023;
+ i = ((u_int32_t)k&0x80000000)>>31;
+ hx = (hx&0x000fffff)|((0x3ff-i)<<20);
+ y = (double)(k+i);
+ SET_HIGH_WORD(x,hx);
+ z = y*log10_2lo + ivln10*__ieee754_log(x);
+ return z+y*log10_2hi;
+}
diff --git a/lib/msun/src/e_log10f.c b/lib/msun/src/e_log10f.c
new file mode 100644
index 0000000..ed5f3e7
--- /dev/null
+++ b/lib/msun/src/e_log10f.c
@@ -0,0 +1,67 @@
+/* e_log10f.c -- float version of e_log10.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+two25 = 3.3554432000e+07, /* 0x4c000000 */
+ivln10 = 4.3429449201e-01, /* 0x3ede5bd9 */
+log10_2hi = 3.0102920532e-01, /* 0x3e9a2080 */
+log10_2lo = 7.9034151668e-07; /* 0x355427db */
+
+#ifdef __STDC__
+static const float zero = 0.0;
+#else
+static float zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ float __ieee754_log10f(float x)
+#else
+ float __ieee754_log10f(x)
+ float x;
+#endif
+{
+ float y,z;
+ int32_t i,k,hx;
+
+ GET_FLOAT_WORD(hx,x);
+
+ k=0;
+ if (hx < 0x00800000) { /* x < 2**-126 */
+ if ((hx&0x7fffffff)==0)
+ return -two25/zero; /* log(+-0)=-inf */
+ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
+ k -= 25; x *= two25; /* subnormal number, scale up x */
+ GET_FLOAT_WORD(hx,x);
+ }
+ if (hx >= 0x7f800000) return x+x;
+ k += (hx>>23)-127;
+ i = ((u_int32_t)k&0x80000000)>>31;
+ hx = (hx&0x007fffff)|((0x7f-i)<<23);
+ y = (float)(k+i);
+ SET_FLOAT_WORD(x,hx);
+ z = y*log10_2lo + ivln10*__ieee754_logf(x);
+ return z+y*log10_2hi;
+}
diff --git a/lib/msun/src/e_logf.c b/lib/msun/src/e_logf.c
new file mode 100644
index 0000000..48a0d86
--- /dev/null
+++ b/lib/msun/src/e_logf.c
@@ -0,0 +1,97 @@
+/* e_logf.c -- float version of e_log.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
+ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
+two25 = 3.355443200e+07, /* 0x4c000000 */
+Lg1 = 6.6666668653e-01, /* 3F2AAAAB */
+Lg2 = 4.0000000596e-01, /* 3ECCCCCD */
+Lg3 = 2.8571429849e-01, /* 3E924925 */
+Lg4 = 2.2222198546e-01, /* 3E638E29 */
+Lg5 = 1.8183572590e-01, /* 3E3A3325 */
+Lg6 = 1.5313838422e-01, /* 3E1CD04F */
+Lg7 = 1.4798198640e-01; /* 3E178897 */
+
+#ifdef __STDC__
+static const float zero = 0.0;
+#else
+static float zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ float __ieee754_logf(float x)
+#else
+ float __ieee754_logf(x)
+ float x;
+#endif
+{
+ float hfsq,f,s,z,R,w,t1,t2,dk;
+ int32_t k,ix,i,j;
+
+ GET_FLOAT_WORD(ix,x);
+
+ k=0;
+ if (ix < 0x00800000) { /* x < 2**-126 */
+ if ((ix&0x7fffffff)==0)
+ return -two25/zero; /* log(+-0)=-inf */
+ if (ix<0) return (x-x)/zero; /* log(-#) = NaN */
+ k -= 25; x *= two25; /* subnormal number, scale up x */
+ GET_FLOAT_WORD(ix,x);
+ }
+ if (ix >= 0x7f800000) return x+x;
+ k += (ix>>23)-127;
+ ix &= 0x007fffff;
+ i = (ix+(0x95f64<<3))&0x800000;
+ SET_FLOAT_WORD(x,ix|(i^0x3f800000)); /* normalize x or x/2 */
+ k += (i>>23);
+ f = x-(float)1.0;
+ if((0x007fffff&(15+ix))<16) { /* |f| < 2**-20 */
+ if(f==zero) if(k==0) return zero; else {dk=(float)k;
+ return dk*ln2_hi+dk*ln2_lo;}
+ R = f*f*((float)0.5-(float)0.33333333333333333*f);
+ if(k==0) return f-R; else {dk=(float)k;
+ return dk*ln2_hi-((R-dk*ln2_lo)-f);}
+ }
+ s = f/((float)2.0+f);
+ dk = (float)k;
+ z = s*s;
+ i = ix-(0x6147a<<3);
+ w = z*z;
+ j = (0x6b851<<3)-ix;
+ t1= w*(Lg2+w*(Lg4+w*Lg6));
+ t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
+ i |= j;
+ R = t2+t1;
+ if(i>0) {
+ hfsq=(float)0.5*f*f;
+ if(k==0) return f-(hfsq-s*(hfsq+R)); else
+ return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
+ } else {
+ if(k==0) return f-s*(f-R); else
+ return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
+ }
+}
diff --git a/lib/msun/src/e_pow.c b/lib/msun/src/e_pow.c
new file mode 100644
index 0000000..1aa2f02
--- /dev/null
+++ b/lib/msun/src/e_pow.c
@@ -0,0 +1,312 @@
+/* @(#)e_pow.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: e_pow.c,v 1.4 1997/02/22 15:10:29 peter Exp $";
+#endif
+
+/* __ieee754_pow(x,y) return x**y
+ *
+ * n
+ * Method: Let x = 2 * (1+f)
+ * 1. Compute and return log2(x) in two pieces:
+ * log2(x) = w1 + w2,
+ * where w1 has 53-24 = 29 bit trailing zeros.
+ * 2. Perform y*log2(x) = n+y' by simulating muti-precision
+ * arithmetic, where |y'|<=0.5.
+ * 3. Return x**y = 2**n*exp(y'*log2)
+ *
+ * Special cases:
+ * 1. (anything) ** 0 is 1
+ * 2. (anything) ** 1 is itself
+ * 3. (anything) ** NAN is NAN
+ * 4. NAN ** (anything except 0) is NAN
+ * 5. +-(|x| > 1) ** +INF is +INF
+ * 6. +-(|x| > 1) ** -INF is +0
+ * 7. +-(|x| < 1) ** +INF is +0
+ * 8. +-(|x| < 1) ** -INF is +INF
+ * 9. +-1 ** +-INF is NAN
+ * 10. +0 ** (+anything except 0, NAN) is +0
+ * 11. -0 ** (+anything except 0, NAN, odd integer) is +0
+ * 12. +0 ** (-anything except 0, NAN) is +INF
+ * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF
+ * 14. -0 ** (odd integer) = -( +0 ** (odd integer) )
+ * 15. +INF ** (+anything except 0,NAN) is +INF
+ * 16. +INF ** (-anything except 0,NAN) is +0
+ * 17. -INF ** (anything) = -0 ** (-anything)
+ * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
+ * 19. (-anything except 0 and inf) ** (non-integer) is NAN
+ *
+ * Accuracy:
+ * pow(x,y) returns x**y nearly rounded. In particular
+ * pow(integer,integer)
+ * always returns the correct integer provided it is
+ * representable.
+ *
+ * Constants :
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
+dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
+zero = 0.0,
+one = 1.0,
+two = 2.0,
+two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
+huge = 1.0e300,
+tiny = 1.0e-300,
+ /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
+L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
+L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
+L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
+L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
+L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
+P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
+lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
+lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
+ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
+cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
+cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
+cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
+ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
+ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
+ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
+
+#ifdef __STDC__
+ double __ieee754_pow(double x, double y)
+#else
+ double __ieee754_pow(x,y)
+ double x, y;
+#endif
+{
+ double z,ax,z_h,z_l,p_h,p_l;
+ double y1,t1,t2,r,s,t,u,v,w;
+ int32_t i,j,k,yisint,n;
+ int32_t hx,hy,ix,iy;
+ u_int32_t lx,ly;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hy,ly,y);
+ ix = hx&0x7fffffff; iy = hy&0x7fffffff;
+
+ /* y==zero: x**0 = 1 */
+ if((iy|ly)==0) return one;
+
+ /* +-NaN return x+y */
+ if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
+ iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0)))
+ return x+y;
+
+ /* determine if y is an odd int when x < 0
+ * yisint = 0 ... y is not an integer
+ * yisint = 1 ... y is an odd int
+ * yisint = 2 ... y is an even int
+ */
+ yisint = 0;
+ if(hx<0) {
+ if(iy>=0x43400000) yisint = 2; /* even integer y */
+ else if(iy>=0x3ff00000) {
+ k = (iy>>20)-0x3ff; /* exponent */
+ if(k>20) {
+ j = ly>>(52-k);
+ if((j<<(52-k))==ly) yisint = 2-(j&1);
+ } else if(ly==0) {
+ j = iy>>(20-k);
+ if((j<<(20-k))==iy) yisint = 2-(j&1);
+ }
+ }
+ }
+
+ /* special value of y */
+ if(ly==0) {
+ if (iy==0x7ff00000) { /* y is +-inf */
+ if(((ix-0x3ff00000)|lx)==0)
+ return y - y; /* inf**+-1 is NaN */
+ else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
+ return (hy>=0)? y: zero;
+ else /* (|x|<1)**-,+inf = inf,0 */
+ return (hy<0)?-y: zero;
+ }
+ if(iy==0x3ff00000) { /* y is +-1 */
+ if(hy<0) return one/x; else return x;
+ }
+ if(hy==0x40000000) return x*x; /* y is 2 */
+ if(hy==0x3fe00000) { /* y is 0.5 */
+ if(hx>=0) /* x >= +0 */
+ return __ieee754_sqrt(x);
+ }
+ }
+
+ ax = fabs(x);
+ /* special value of x */
+ if(lx==0) {
+ if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
+ z = ax; /*x is +-0,+-inf,+-1*/
+ if(hy<0) z = one/z; /* z = (1/|x|) */
+ if(hx<0) {
+ if(((ix-0x3ff00000)|yisint)==0) {
+ z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+ } else if(yisint==1)
+ z = -z; /* (x<0)**odd = -(|x|**odd) */
+ }
+ return z;
+ }
+ }
+
+ /* (x<0)**(non-int) is NaN */
+ /* CYGNUS LOCAL: This used to be
+ if((((hx>>31)+1)|yisint)==0) return (x-x)/(x-x);
+ but ANSI C says a right shift of a signed negative quantity is
+ implementation defined. */
+ if(((((u_int32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x);
+
+ /* |y| is huge */
+ if(iy>0x41e00000) { /* if |y| > 2**31 */
+ if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */
+ if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
+ if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
+ }
+ /* over/underflow if x is not close to one */
+ if(ix<0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
+ if(ix>0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
+ /* now |1-x| is tiny <= 2**-20, suffice to compute
+ log(x) by x-x^2/2+x^3/3-x^4/4 */
+ t = x-1; /* t has 20 trailing zeros */
+ w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
+ u = ivln2_h*t; /* ivln2_h has 21 sig. bits */
+ v = t*ivln2_l-w*ivln2;
+ t1 = u+v;
+ SET_LOW_WORD(t1,0);
+ t2 = v-(t1-u);
+ } else {
+ double s2,s_h,s_l,t_h,t_l;
+ n = 0;
+ /* take care subnormal number */
+ if(ix<0x00100000)
+ {ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); }
+ n += ((ix)>>20)-0x3ff;
+ j = ix&0x000fffff;
+ /* determine interval */
+ ix = j|0x3ff00000; /* normalize ix */
+ if(j<=0x3988E) k=0; /* |x|<sqrt(3/2) */
+ else if(j<0xBB67A) k=1; /* |x|<sqrt(3) */
+ else {k=0;n+=1;ix -= 0x00100000;}
+ SET_HIGH_WORD(ax,ix);
+
+ /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+ u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
+ v = one/(ax+bp[k]);
+ s = u*v;
+ s_h = s;
+ SET_LOW_WORD(s_h,0);
+ /* t_h=ax+bp[k] High */
+ t_h = zero;
+ SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18));
+ t_l = ax - (t_h-bp[k]);
+ s_l = v*((u-s_h*t_h)-s_h*t_l);
+ /* compute log(ax) */
+ s2 = s*s;
+ r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+ r += s_l*(s_h+s);
+ s2 = s_h*s_h;
+ t_h = 3.0+s2+r;
+ SET_LOW_WORD(t_h,0);
+ t_l = r-((t_h-3.0)-s2);
+ /* u+v = s*(1+...) */
+ u = s_h*t_h;
+ v = s_l*t_h+t_l*s;
+ /* 2/(3log2)*(s+...) */
+ p_h = u+v;
+ SET_LOW_WORD(p_h,0);
+ p_l = v-(p_h-u);
+ z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
+ z_l = cp_l*p_h+p_l*cp+dp_l[k];
+ /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+ t = (double)n;
+ t1 = (((z_h+z_l)+dp_h[k])+t);
+ SET_LOW_WORD(t1,0);
+ t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+ }
+
+ s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+ if(((((u_int32_t)hx>>31)-1)|(yisint-1))==0)
+ s = -one;/* (-ve)**(odd int) */
+
+ /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+ y1 = y;
+ SET_LOW_WORD(y1,0);
+ p_l = (y-y1)*t1+y*t2;
+ p_h = y1*t1;
+ z = p_l+p_h;
+ EXTRACT_WORDS(j,i,z);
+ if (j>=0x40900000) { /* z >= 1024 */
+ if(((j-0x40900000)|i)!=0) /* if z > 1024 */
+ return s*huge*huge; /* overflow */
+ else {
+ if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */
+ }
+ } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */
+ if(((j-0xc090cc00)|i)!=0) /* z < -1075 */
+ return s*tiny*tiny; /* underflow */
+ else {
+ if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */
+ }
+ }
+ /*
+ * compute 2**(p_h+p_l)
+ */
+ i = j&0x7fffffff;
+ k = (i>>20)-0x3ff;
+ n = 0;
+ if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */
+ n = j+(0x00100000>>(k+1));
+ k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */
+ t = zero;
+ SET_HIGH_WORD(t,n&~(0x000fffff>>k));
+ n = ((n&0x000fffff)|0x00100000)>>(20-k);
+ if(j<0) n = -n;
+ p_h -= t;
+ }
+ t = p_l+p_h;
+ SET_LOW_WORD(t,0);
+ u = t*lg2_h;
+ v = (p_l-(t-p_h))*lg2+t*lg2_l;
+ z = u+v;
+ w = v-(z-u);
+ t = z*z;
+ t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+ r = (z*t1)/(t1-two)-(w+z*w);
+ z = one-(r-z);
+ GET_HIGH_WORD(j,z);
+ j += (n<<20);
+ if((j>>20)<=0) z = scalbn(z,n); /* subnormal output */
+ else SET_HIGH_WORD(z,j);
+ return s*z;
+}
diff --git a/lib/msun/src/e_powf.c b/lib/msun/src/e_powf.c
new file mode 100644
index 0000000..a68bb8b
--- /dev/null
+++ b/lib/msun/src/e_powf.c
@@ -0,0 +1,253 @@
+/* e_powf.c -- float version of e_pow.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: e_powf.c,v 1.4 1997/02/22 15:10:30 peter Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84960938e-01,}, /* 0x3f15c000 */
+dp_l[] = { 0.0, 1.56322085e-06,}, /* 0x35d1cfdc */
+zero = 0.0,
+one = 1.0,
+two = 2.0,
+two24 = 16777216.0, /* 0x4b800000 */
+huge = 1.0e30,
+tiny = 1.0e-30,
+ /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1 = 6.0000002384e-01, /* 0x3f19999a */
+L2 = 4.2857143283e-01, /* 0x3edb6db7 */
+L3 = 3.3333334327e-01, /* 0x3eaaaaab */
+L4 = 2.7272811532e-01, /* 0x3e8ba305 */
+L5 = 2.3066075146e-01, /* 0x3e6c3255 */
+L6 = 2.0697501302e-01, /* 0x3e53f142 */
+P1 = 1.6666667163e-01, /* 0x3e2aaaab */
+P2 = -2.7777778450e-03, /* 0xbb360b61 */
+P3 = 6.6137559770e-05, /* 0x388ab355 */
+P4 = -1.6533901999e-06, /* 0xb5ddea0e */
+P5 = 4.1381369442e-08, /* 0x3331bb4c */
+lg2 = 6.9314718246e-01, /* 0x3f317218 */
+lg2_h = 6.93145752e-01, /* 0x3f317200 */
+lg2_l = 1.42860654e-06, /* 0x35bfbe8c */
+ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */
+cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */
+cp_h = 9.6179199219e-01, /* 0x3f763800 =head of cp */
+cp_l = 4.7017383622e-06, /* 0x369dc3a0 =tail of cp_h */
+ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */
+ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/
+ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/
+
+#ifdef __STDC__
+ float __ieee754_powf(float x, float y)
+#else
+ float __ieee754_powf(x,y)
+ float x, y;
+#endif
+{
+ float z,ax,z_h,z_l,p_h,p_l;
+ float y1,t1,t2,r,s,t,u,v,w;
+ int32_t i,j,k,yisint,n;
+ int32_t hx,hy,ix,iy,is;
+
+ GET_FLOAT_WORD(hx,x);
+ GET_FLOAT_WORD(hy,y);
+ ix = hx&0x7fffffff; iy = hy&0x7fffffff;
+
+ /* y==zero: x**0 = 1 */
+ if(iy==0) return one;
+
+ /* +-NaN return x+y */
+ if(ix > 0x7f800000 ||
+ iy > 0x7f800000)
+ return x+y;
+
+ /* determine if y is an odd int when x < 0
+ * yisint = 0 ... y is not an integer
+ * yisint = 1 ... y is an odd int
+ * yisint = 2 ... y is an even int
+ */
+ yisint = 0;
+ if(hx<0) {
+ if(iy>=0x4b800000) yisint = 2; /* even integer y */
+ else if(iy>=0x3f800000) {
+ k = (iy>>23)-0x7f; /* exponent */
+ j = iy>>(23-k);
+ if((j<<(23-k))==iy) yisint = 2-(j&1);
+ }
+ }
+
+ /* special value of y */
+ if (iy==0x7f800000) { /* y is +-inf */
+ if (ix==0x3f800000)
+ return y - y; /* inf**+-1 is NaN */
+ else if (ix > 0x3f800000)/* (|x|>1)**+-inf = inf,0 */
+ return (hy>=0)? y: zero;
+ else /* (|x|<1)**-,+inf = inf,0 */
+ return (hy<0)?-y: zero;
+ }
+ if(iy==0x3f800000) { /* y is +-1 */
+ if(hy<0) return one/x; else return x;
+ }
+ if(hy==0x40000000) return x*x; /* y is 2 */
+ if(hy==0x3f000000) { /* y is 0.5 */
+ if(hx>=0) /* x >= +0 */
+ return __ieee754_sqrtf(x);
+ }
+
+ ax = fabsf(x);
+ /* special value of x */
+ if(ix==0x7f800000||ix==0||ix==0x3f800000){
+ z = ax; /*x is +-0,+-inf,+-1*/
+ if(hy<0) z = one/z; /* z = (1/|x|) */
+ if(hx<0) {
+ if(((ix-0x3f800000)|yisint)==0) {
+ z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+ } else if(yisint==1)
+ z = -z; /* (x<0)**odd = -(|x|**odd) */
+ }
+ return z;
+ }
+
+ /* (x<0)**(non-int) is NaN */
+ if(((((u_int32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x);
+
+ /* |y| is huge */
+ if(iy>0x4d000000) { /* if |y| > 2**27 */
+ /* over/underflow if x is not close to one */
+ if(ix<0x3f7ffff8) return (hy<0)? huge*huge:tiny*tiny;
+ if(ix>0x3f800007) return (hy>0)? huge*huge:tiny*tiny;
+ /* now |1-x| is tiny <= 2**-20, suffice to compute
+ log(x) by x-x^2/2+x^3/3-x^4/4 */
+ t = x-1; /* t has 20 trailing zeros */
+ w = (t*t)*((float)0.5-t*((float)0.333333333333-t*(float)0.25));
+ u = ivln2_h*t; /* ivln2_h has 16 sig. bits */
+ v = t*ivln2_l-w*ivln2;
+ t1 = u+v;
+ GET_FLOAT_WORD(is,t1);
+ SET_FLOAT_WORD(t1,is&0xfffff000);
+ t2 = v-(t1-u);
+ } else {
+ float s2,s_h,s_l,t_h,t_l;
+ n = 0;
+ /* take care subnormal number */
+ if(ix<0x00800000)
+ {ax *= two24; n -= 24; GET_FLOAT_WORD(ix,ax); }
+ n += ((ix)>>23)-0x7f;
+ j = ix&0x007fffff;
+ /* determine interval */
+ ix = j|0x3f800000; /* normalize ix */
+ if(j<=0x1cc471) k=0; /* |x|<sqrt(3/2) */
+ else if(j<0x5db3d7) k=1; /* |x|<sqrt(3) */
+ else {k=0;n+=1;ix -= 0x00800000;}
+ SET_FLOAT_WORD(ax,ix);
+
+ /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+ u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
+ v = one/(ax+bp[k]);
+ s = u*v;
+ s_h = s;
+ GET_FLOAT_WORD(is,s_h);
+ SET_FLOAT_WORD(s_h,is&0xfffff000);
+ /* t_h=ax+bp[k] High */
+ SET_FLOAT_WORD(t_h,((ix>>1)|0x20000000)+0x0040000+(k<<21));
+ t_l = ax - (t_h-bp[k]);
+ s_l = v*((u-s_h*t_h)-s_h*t_l);
+ /* compute log(ax) */
+ s2 = s*s;
+ r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+ r += s_l*(s_h+s);
+ s2 = s_h*s_h;
+ t_h = (float)3.0+s2+r;
+ GET_FLOAT_WORD(is,t_h);
+ SET_FLOAT_WORD(t_h,is&0xfffff000);
+ t_l = r-((t_h-(float)3.0)-s2);
+ /* u+v = s*(1+...) */
+ u = s_h*t_h;
+ v = s_l*t_h+t_l*s;
+ /* 2/(3log2)*(s+...) */
+ p_h = u+v;
+ GET_FLOAT_WORD(is,p_h);
+ SET_FLOAT_WORD(p_h,is&0xfffff000);
+ p_l = v-(p_h-u);
+ z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
+ z_l = cp_l*p_h+p_l*cp+dp_l[k];
+ /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+ t = (float)n;
+ t1 = (((z_h+z_l)+dp_h[k])+t);
+ GET_FLOAT_WORD(is,t1);
+ SET_FLOAT_WORD(t1,is&0xfffff000);
+ t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+ }
+
+ s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+ if(((((u_int32_t)hx>>31)-1)|(yisint-1))==0)
+ s = -one; /* (-ve)**(odd int) */
+
+ /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+ GET_FLOAT_WORD(is,y);
+ SET_FLOAT_WORD(y1,is&0xfffff000);
+ p_l = (y-y1)*t1+y*t2;
+ p_h = y1*t1;
+ z = p_l+p_h;
+ GET_FLOAT_WORD(j,z);
+ if (j>0x43000000) /* if z > 128 */
+ return s*huge*huge; /* overflow */
+ else if (j==0x43000000) { /* if z == 128 */
+ if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */
+ }
+ else if ((j&0x7fffffff)>0x43160000) /* z <= -150 */
+ return s*tiny*tiny; /* underflow */
+ else if (j==0xc3160000){ /* z == -150 */
+ if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */
+ }
+ /*
+ * compute 2**(p_h+p_l)
+ */
+ i = j&0x7fffffff;
+ k = (i>>23)-0x7f;
+ n = 0;
+ if(i>0x3f000000) { /* if |z| > 0.5, set n = [z+0.5] */
+ n = j+(0x00800000>>(k+1));
+ k = ((n&0x7fffffff)>>23)-0x7f; /* new k for n */
+ SET_FLOAT_WORD(t,n&~(0x007fffff>>k));
+ n = ((n&0x007fffff)|0x00800000)>>(23-k);
+ if(j<0) n = -n;
+ p_h -= t;
+ }
+ t = p_l+p_h;
+ GET_FLOAT_WORD(is,t);
+ SET_FLOAT_WORD(t,is&0xfffff000);
+ u = t*lg2_h;
+ v = (p_l-(t-p_h))*lg2+t*lg2_l;
+ z = u+v;
+ w = v-(z-u);
+ t = z*z;
+ t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+ r = (z*t1)/(t1-two)-(w+z*w);
+ z = one-(r-z);
+ GET_FLOAT_WORD(j,z);
+ j += (n<<23);
+ if((j>>23)<=0) z = scalbnf(z,n); /* subnormal output */
+ else SET_FLOAT_WORD(z,j);
+ return s*z;
+}
diff --git a/lib/msun/src/e_rem_pio2.c b/lib/msun/src/e_rem_pio2.c
new file mode 100644
index 0000000..1ee6ce3
--- /dev/null
+++ b/lib/msun/src/e_rem_pio2.c
@@ -0,0 +1,183 @@
+/* @(#)e_rem_pio2.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_rem_pio2(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2()
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+ */
+#ifdef __STDC__
+static const int32_t two_over_pi[] = {
+#else
+static int32_t two_over_pi[] = {
+#endif
+0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
+0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
+0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
+0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
+0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
+0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
+0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
+0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
+0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
+0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
+0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
+};
+
+#ifdef __STDC__
+static const int32_t npio2_hw[] = {
+#else
+static int32_t npio2_hw[] = {
+#endif
+0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
+0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
+0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
+0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
+0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
+0x404858EB, 0x404921FB,
+};
+
+/*
+ * invpio2: 53 bits of 2/pi
+ * pio2_1: first 33 bit of pi/2
+ * pio2_1t: pi/2 - pio2_1
+ * pio2_2: second 33 bit of pi/2
+ * pio2_2t: pi/2 - (pio2_1+pio2_2)
+ * pio2_3: third 33 bit of pi/2
+ * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
+pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
+pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
+pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
+pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
+pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
+
+#ifdef __STDC__
+ int32_t __ieee754_rem_pio2(double x, double *y)
+#else
+ int32_t __ieee754_rem_pio2(x,y)
+ double x,y[];
+#endif
+{
+ double z,w,t,r,fn;
+ double tx[3];
+ int32_t e0,i,j,nx,n,ix,hx;
+ u_int32_t low;
+
+ GET_HIGH_WORD(hx,x); /* high word of x */
+ ix = hx&0x7fffffff;
+ if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */
+ {y[0] = x; y[1] = 0; return 0;}
+ if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */
+ if(hx>0) {
+ z = x - pio2_1;
+ if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */
+ y[0] = z - pio2_1t;
+ y[1] = (z-y[0])-pio2_1t;
+ } else { /* near pi/2, use 33+33+53 bit pi */
+ z -= pio2_2;
+ y[0] = z - pio2_2t;
+ y[1] = (z-y[0])-pio2_2t;
+ }
+ return 1;
+ } else { /* negative x */
+ z = x + pio2_1;
+ if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */
+ y[0] = z + pio2_1t;
+ y[1] = (z-y[0])+pio2_1t;
+ } else { /* near pi/2, use 33+33+53 bit pi */
+ z += pio2_2;
+ y[0] = z + pio2_2t;
+ y[1] = (z-y[0])+pio2_2t;
+ }
+ return -1;
+ }
+ }
+ if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
+ t = fabs(x);
+ n = (int32_t) (t*invpio2+half);
+ fn = (double)n;
+ r = t-fn*pio2_1;
+ w = fn*pio2_1t; /* 1st round good to 85 bit */
+ if(n<32&&ix!=npio2_hw[n-1]) {
+ y[0] = r-w; /* quick check no cancellation */
+ } else {
+ u_int32_t high;
+ j = ix>>20;
+ y[0] = r-w;
+ GET_HIGH_WORD(high,y[0]);
+ i = j-((high>>20)&0x7ff);
+ if(i>16) { /* 2nd iteration needed, good to 118 */
+ t = r;
+ w = fn*pio2_2;
+ r = t-w;
+ w = fn*pio2_2t-((t-r)-w);
+ y[0] = r-w;
+ GET_HIGH_WORD(high,y[0]);
+ i = j-((high>>20)&0x7ff);
+ if(i>49) { /* 3rd iteration need, 151 bits acc */
+ t = r; /* will cover all possible cases */
+ w = fn*pio2_3;
+ r = t-w;
+ w = fn*pio2_3t-((t-r)-w);
+ y[0] = r-w;
+ }
+ }
+ }
+ y[1] = (r-y[0])-w;
+ if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+ else return n;
+ }
+ /*
+ * all other (large) arguments
+ */
+ if(ix>=0x7ff00000) { /* x is inf or NaN */
+ y[0]=y[1]=x-x; return 0;
+ }
+ /* set z = scalbn(|x|,ilogb(x)-23) */
+ GET_LOW_WORD(low,x);
+ SET_LOW_WORD(z,low);
+ e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */
+ SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20)));
+ for(i=0;i<2;i++) {
+ tx[i] = (double)((int32_t)(z));
+ z = (z-tx[i])*two24;
+ }
+ tx[2] = z;
+ nx = 3;
+ while(tx[nx-1]==zero) nx--; /* skip zero term */
+ n = __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi);
+ if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+ return n;
+}
diff --git a/lib/msun/src/e_rem_pio2f.c b/lib/msun/src/e_rem_pio2f.c
new file mode 100644
index 0000000..49e698f
--- /dev/null
+++ b/lib/msun/src/e_rem_pio2f.c
@@ -0,0 +1,196 @@
+/* e_rem_pio2f.c -- float version of e_rem_pio2.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_rem_pio2f(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2f()
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+ */
+#ifdef __STDC__
+static const int32_t two_over_pi[] = {
+#else
+static int32_t two_over_pi[] = {
+#endif
+0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC,
+0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62,
+0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63,
+0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A,
+0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09,
+0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29,
+0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44,
+0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41,
+0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C,
+0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8,
+0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11,
+0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF,
+0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E,
+0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5,
+0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92,
+0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08,
+0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0,
+0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3,
+0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85,
+0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80,
+0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA,
+0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B,
+};
+
+/* This array is like the one in e_rem_pio2.c, but the numbers are
+ single precision and the last 8 bits are forced to 0. */
+#ifdef __STDC__
+static const int32_t npio2_hw[] = {
+#else
+static int32_t npio2_hw[] = {
+#endif
+0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
+0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
+0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
+0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
+0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
+0x4242c700, 0x42490f00
+};
+
+/*
+ * invpio2: 24 bits of 2/pi
+ * pio2_1: first 17 bit of pi/2
+ * pio2_1t: pi/2 - pio2_1
+ * pio2_2: second 17 bit of pi/2
+ * pio2_2t: pi/2 - (pio2_1+pio2_2)
+ * pio2_3: third 17 bit of pi/2
+ * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+zero = 0.0000000000e+00, /* 0x00000000 */
+half = 5.0000000000e-01, /* 0x3f000000 */
+two8 = 2.5600000000e+02, /* 0x43800000 */
+invpio2 = 6.3661980629e-01, /* 0x3f22f984 */
+pio2_1 = 1.5707855225e+00, /* 0x3fc90f80 */
+pio2_1t = 1.0804334124e-05, /* 0x37354443 */
+pio2_2 = 1.0804273188e-05, /* 0x37354400 */
+pio2_2t = 6.0770999344e-11, /* 0x2e85a308 */
+pio2_3 = 6.0770943833e-11, /* 0x2e85a300 */
+pio2_3t = 6.1232342629e-17; /* 0x248d3132 */
+
+#ifdef __STDC__
+ int32_t __ieee754_rem_pio2f(float x, float *y)
+#else
+ int32_t __ieee754_rem_pio2f(x,y)
+ float x,y[];
+#endif
+{
+ float z,w,t,r,fn;
+ float tx[3];
+ int32_t e0,i,j,nx,n,ix,hx;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix<=0x3f490fd8) /* |x| ~<= pi/4 , no need for reduction */
+ {y[0] = x; y[1] = 0; return 0;}
+ if(ix<0x4016cbe4) { /* |x| < 3pi/4, special case with n=+-1 */
+ if(hx>0) {
+ z = x - pio2_1;
+ if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
+ y[0] = z - pio2_1t;
+ y[1] = (z-y[0])-pio2_1t;
+ } else { /* near pi/2, use 24+24+24 bit pi */
+ z -= pio2_2;
+ y[0] = z - pio2_2t;
+ y[1] = (z-y[0])-pio2_2t;
+ }
+ return 1;
+ } else { /* negative x */
+ z = x + pio2_1;
+ if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
+ y[0] = z + pio2_1t;
+ y[1] = (z-y[0])+pio2_1t;
+ } else { /* near pi/2, use 24+24+24 bit pi */
+ z += pio2_2;
+ y[0] = z + pio2_2t;
+ y[1] = (z-y[0])+pio2_2t;
+ }
+ return -1;
+ }
+ }
+ if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */
+ t = fabsf(x);
+ n = (int32_t) (t*invpio2+half);
+ fn = (float)n;
+ r = t-fn*pio2_1;
+ w = fn*pio2_1t; /* 1st round good to 40 bit */
+ if(n<32&&(ix&0xffffff00)!=npio2_hw[n-1]) {
+ y[0] = r-w; /* quick check no cancellation */
+ } else {
+ u_int32_t high;
+ j = ix>>23;
+ y[0] = r-w;
+ GET_FLOAT_WORD(high,y[0]);
+ i = j-((high>>23)&0xff);
+ if(i>8) { /* 2nd iteration needed, good to 57 */
+ t = r;
+ w = fn*pio2_2;
+ r = t-w;
+ w = fn*pio2_2t-((t-r)-w);
+ y[0] = r-w;
+ GET_FLOAT_WORD(high,y[0]);
+ i = j-((high>>23)&0xff);
+ if(i>25) { /* 3rd iteration need, 74 bits acc */
+ t = r; /* will cover all possible cases */
+ w = fn*pio2_3;
+ r = t-w;
+ w = fn*pio2_3t-((t-r)-w);
+ y[0] = r-w;
+ }
+ }
+ }
+ y[1] = (r-y[0])-w;
+ if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+ else return n;
+ }
+ /*
+ * all other (large) arguments
+ */
+ if(ix>=0x7f800000) { /* x is inf or NaN */
+ y[0]=y[1]=x-x; return 0;
+ }
+ /* set z = scalbn(|x|,ilogb(x)-7) */
+ e0 = (ix>>23)-134; /* e0 = ilogb(z)-7; */
+ SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23)));
+ for(i=0;i<2;i++) {
+ tx[i] = (float)((int32_t)(z));
+ z = (z-tx[i])*two8;
+ }
+ tx[2] = z;
+ nx = 3;
+ while(tx[nx-1]==zero) nx--; /* skip zero term */
+ n = __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi);
+ if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+ return n;
+}
diff --git a/lib/msun/src/e_remainder.c b/lib/msun/src/e_remainder.c
new file mode 100644
index 0000000..4b603a0
--- /dev/null
+++ b/lib/msun/src/e_remainder.c
@@ -0,0 +1,80 @@
+/* @(#)e_remainder.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_remainder(x,p)
+ * Return :
+ * returns x REM p = x - [x/p]*p as if in infinite
+ * precise arithmetic, where [x/p] is the (infinite bit)
+ * integer nearest x/p (in half way case choose the even one).
+ * Method :
+ * Based on fmod() return x-[x/p]chopped*p exactlp.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double zero = 0.0;
+#else
+static double zero = 0.0;
+#endif
+
+
+#ifdef __STDC__
+ double __generic___ieee754_remainder(double x, double p)
+#else
+ double __generic___ieee754_remainder(x,p)
+ double x,p;
+#endif
+{
+ int32_t hx,hp;
+ u_int32_t sx,lx,lp;
+ double p_half;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hp,lp,p);
+ sx = hx&0x80000000;
+ hp &= 0x7fffffff;
+ hx &= 0x7fffffff;
+
+ /* purge off exception values */
+ if((hp|lp)==0) return (x*p)/(x*p); /* p = 0 */
+ if((hx>=0x7ff00000)|| /* x not finite */
+ ((hp>=0x7ff00000)&& /* p is NaN */
+ (((hp-0x7ff00000)|lp)!=0)))
+ return (x*p)/(x*p);
+
+
+ if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p); /* now x < 2p */
+ if (((hx-hp)|(lx-lp))==0) return zero*x;
+ x = fabs(x);
+ p = fabs(p);
+ if (hp<0x00200000) {
+ if(x+x>p) {
+ x-=p;
+ if(x+x>=p) x -= p;
+ }
+ } else {
+ p_half = 0.5*p;
+ if(x>p_half) {
+ x-=p;
+ if(x>=p_half) x -= p;
+ }
+ }
+ GET_HIGH_WORD(hx,x);
+ SET_HIGH_WORD(x,hx^sx);
+ return x;
+}
diff --git a/lib/msun/src/e_remainderf.c b/lib/msun/src/e_remainderf.c
new file mode 100644
index 0000000..ddfc8de
--- /dev/null
+++ b/lib/msun/src/e_remainderf.c
@@ -0,0 +1,73 @@
+/* e_remainderf.c -- float version of e_remainder.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float zero = 0.0;
+#else
+static float zero = 0.0;
+#endif
+
+
+#ifdef __STDC__
+ float __ieee754_remainderf(float x, float p)
+#else
+ float __ieee754_remainderf(x,p)
+ float x,p;
+#endif
+{
+ int32_t hx,hp;
+ u_int32_t sx;
+ float p_half;
+
+ GET_FLOAT_WORD(hx,x);
+ GET_FLOAT_WORD(hp,p);
+ sx = hx&0x80000000;
+ hp &= 0x7fffffff;
+ hx &= 0x7fffffff;
+
+ /* purge off exception values */
+ if(hp==0) return (x*p)/(x*p); /* p = 0 */
+ if((hx>=0x7f800000)|| /* x not finite */
+ ((hp>0x7f800000))) /* p is NaN */
+ return (x*p)/(x*p);
+
+
+ if (hp<=0x7effffff) x = __ieee754_fmodf(x,p+p); /* now x < 2p */
+ if ((hx-hp)==0) return zero*x;
+ x = fabsf(x);
+ p = fabsf(p);
+ if (hp<0x01000000) {
+ if(x+x>p) {
+ x-=p;
+ if(x+x>=p) x -= p;
+ }
+ } else {
+ p_half = (float)0.5*p;
+ if(x>p_half) {
+ x-=p;
+ if(x>=p_half) x -= p;
+ }
+ }
+ GET_FLOAT_WORD(hx,x);
+ SET_FLOAT_WORD(x,hx^sx);
+ return x;
+}
diff --git a/lib/msun/src/e_scalb.c b/lib/msun/src/e_scalb.c
new file mode 100644
index 0000000..89a4127
--- /dev/null
+++ b/lib/msun/src/e_scalb.c
@@ -0,0 +1,55 @@
+/* @(#)e_scalb.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * __ieee754_scalb(x, fn) is provide for
+ * passing various standard test suite. One
+ * should use scalbn() instead.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef _SCALB_INT
+#ifdef __STDC__
+ double __generic___ieee754_scalb(double x, int fn)
+#else
+ double __generic___ieee754_scalb(x,fn)
+ double x; int fn;
+#endif
+#else
+#ifdef __STDC__
+ double __generic___ieee754_scalb(double x, double fn)
+#else
+ double __generic___ieee754_scalb(x,fn)
+ double x, fn;
+#endif
+#endif
+{
+#ifdef _SCALB_INT
+ return scalbn(x,fn);
+#else
+ if (isnan(x)||isnan(fn)) return x*fn;
+ if (!finite(fn)) {
+ if(fn>0.0) return x*fn;
+ else return x/(-fn);
+ }
+ if (rint(fn)!=fn) return (fn-fn)/(fn-fn);
+ if ( fn > 65000.0) return scalbn(x, 65000);
+ if (-fn > 65000.0) return scalbn(x,-65000);
+ return scalbn(x,(int)fn);
+#endif
+}
diff --git a/lib/msun/src/e_scalbf.c b/lib/msun/src/e_scalbf.c
new file mode 100644
index 0000000..df2a54d
--- /dev/null
+++ b/lib/msun/src/e_scalbf.c
@@ -0,0 +1,52 @@
+/* e_scalbf.c -- float version of e_scalb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef _SCALB_INT
+#ifdef __STDC__
+ float __ieee754_scalbf(float x, int fn)
+#else
+ float __ieee754_scalbf(x,fn)
+ float x; int fn;
+#endif
+#else
+#ifdef __STDC__
+ float __ieee754_scalbf(float x, float fn)
+#else
+ float __ieee754_scalbf(x,fn)
+ float x, fn;
+#endif
+#endif
+{
+#ifdef _SCALB_INT
+ return scalbnf(x,fn);
+#else
+ if (isnanf(x)||isnanf(fn)) return x*fn;
+ if (!finitef(fn)) {
+ if(fn>(float)0.0) return x*fn;
+ else return x/(-fn);
+ }
+ if (rintf(fn)!=fn) return (fn-fn)/(fn-fn);
+ if ( fn > (float)65000.0) return scalbnf(x, 65000);
+ if (-fn > (float)65000.0) return scalbnf(x,-65000);
+ return scalbnf(x,(int)fn);
+#endif
+}
diff --git a/lib/msun/src/e_sinh.c b/lib/msun/src/e_sinh.c
new file mode 100644
index 0000000..764fdc3
--- /dev/null
+++ b/lib/msun/src/e_sinh.c
@@ -0,0 +1,86 @@
+/* @(#)e_sinh.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_sinh(x)
+ * Method :
+ * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
+ * 1. Replace x by |x| (sinh(-x) = -sinh(x)).
+ * 2.
+ * E + E/(E+1)
+ * 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x)
+ * 2
+ *
+ * 22 <= x <= lnovft : sinh(x) := exp(x)/2
+ * lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2)
+ * ln2ovft < x : sinh(x) := x*shuge (overflow)
+ *
+ * Special cases:
+ * sinh(x) is |x| if x is +INF, -INF, or NaN.
+ * only sinh(0)=0 is exact for finite x.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double one = 1.0, shuge = 1.0e307;
+#else
+static double one = 1.0, shuge = 1.0e307;
+#endif
+
+#ifdef __STDC__
+ double __ieee754_sinh(double x)
+#else
+ double __ieee754_sinh(x)
+ double x;
+#endif
+{
+ double t,w,h;
+ int32_t ix,jx;
+ u_int32_t lx;
+
+ /* High word of |x|. */
+ GET_HIGH_WORD(jx,x);
+ ix = jx&0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7ff00000) return x+x;
+
+ h = 0.5;
+ if (jx<0) h = -h;
+ /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
+ if (ix < 0x40360000) { /* |x|<22 */
+ if (ix<0x3e300000) /* |x|<2**-28 */
+ if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
+ t = expm1(fabs(x));
+ if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one));
+ return h*(t+t/(t+one));
+ }
+
+ /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */
+ if (ix < 0x40862E42) return h*__ieee754_exp(fabs(x));
+
+ /* |x| in [log(maxdouble), overflowthresold] */
+ GET_LOW_WORD(lx,x);
+ if (ix<0x408633CE || ((ix==0x408633ce)&&(lx<=(u_int32_t)0x8fb9f87d))) {
+ w = __ieee754_exp(0.5*fabs(x));
+ t = h*w;
+ return t*w;
+ }
+
+ /* |x| > overflowthresold, sinh(x) overflow */
+ return x*shuge;
+}
diff --git a/lib/msun/src/e_sinhf.c b/lib/msun/src/e_sinhf.c
new file mode 100644
index 0000000..26db978
--- /dev/null
+++ b/lib/msun/src/e_sinhf.c
@@ -0,0 +1,68 @@
+/* e_sinhf.c -- float version of e_sinh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float one = 1.0, shuge = 1.0e37;
+#else
+static float one = 1.0, shuge = 1.0e37;
+#endif
+
+#ifdef __STDC__
+ float __ieee754_sinhf(float x)
+#else
+ float __ieee754_sinhf(x)
+ float x;
+#endif
+{
+ float t,w,h;
+ int32_t ix,jx;
+
+ GET_FLOAT_WORD(jx,x);
+ ix = jx&0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7f800000) return x+x;
+
+ h = 0.5;
+ if (jx<0) h = -h;
+ /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
+ if (ix < 0x41b00000) { /* |x|<22 */
+ if (ix<0x31800000) /* |x|<2**-28 */
+ if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
+ t = expm1f(fabsf(x));
+ if(ix<0x3f800000) return h*((float)2.0*t-t*t/(t+one));
+ return h*(t+t/(t+one));
+ }
+
+ /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */
+ if (ix < 0x42b17180) return h*__ieee754_expf(fabsf(x));
+
+ /* |x| in [log(maxdouble), overflowthresold] */
+ if (ix<=0x42b2d4fc) {
+ w = __ieee754_expf((float)0.5*fabsf(x));
+ t = h*w;
+ return t*w;
+ }
+
+ /* |x| > overflowthresold, sinh(x) overflow */
+ return x*shuge;
+}
diff --git a/lib/msun/src/e_sqrt.c b/lib/msun/src/e_sqrt.c
new file mode 100644
index 0000000..813017f
--- /dev/null
+++ b/lib/msun/src/e_sqrt.c
@@ -0,0 +1,453 @@
+/* @(#)e_sqrt.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __ieee754_sqrt(x)
+ * Return correctly rounded sqrt.
+ * ------------------------------------------
+ * | Use the hardware sqrt if you have one |
+ * ------------------------------------------
+ * Method:
+ * Bit by bit method using integer arithmetic. (Slow, but portable)
+ * 1. Normalization
+ * Scale x to y in [1,4) with even powers of 2:
+ * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then
+ * sqrt(x) = 2^k * sqrt(y)
+ * 2. Bit by bit computation
+ * Let q = sqrt(y) truncated to i bit after binary point (q = 1),
+ * i 0
+ * i+1 2
+ * s = 2*q , and y = 2 * ( y - q ). (1)
+ * i i i i
+ *
+ * To compute q from q , one checks whether
+ * i+1 i
+ *
+ * -(i+1) 2
+ * (q + 2 ) <= y. (2)
+ * i
+ * -(i+1)
+ * If (2) is false, then q = q ; otherwise q = q + 2 .
+ * i+1 i i+1 i
+ *
+ * With some algebric manipulation, it is not difficult to see
+ * that (2) is equivalent to
+ * -(i+1)
+ * s + 2 <= y (3)
+ * i i
+ *
+ * The advantage of (3) is that s and y can be computed by
+ * i i
+ * the following recurrence formula:
+ * if (3) is false
+ *
+ * s = s , y = y ; (4)
+ * i+1 i i+1 i
+ *
+ * otherwise,
+ * -i -(i+1)
+ * s = s + 2 , y = y - s - 2 (5)
+ * i+1 i i+1 i i
+ *
+ * One may easily use induction to prove (4) and (5).
+ * Note. Since the left hand side of (3) contain only i+2 bits,
+ * it does not necessary to do a full (53-bit) comparison
+ * in (3).
+ * 3. Final rounding
+ * After generating the 53 bits result, we compute one more bit.
+ * Together with the remainder, we can decide whether the
+ * result is exact, bigger than 1/2ulp, or less than 1/2ulp
+ * (it will never equal to 1/2ulp).
+ * The rounding mode can be detected by checking whether
+ * huge + tiny is equal to huge, and whether huge - tiny is
+ * equal to huge for some floating point number "huge" and "tiny".
+ *
+ * Special cases:
+ * sqrt(+-0) = +-0 ... exact
+ * sqrt(inf) = inf
+ * sqrt(-ve) = NaN ... with invalid signal
+ * sqrt(NaN) = NaN ... with invalid signal for signaling NaN
+ *
+ * Other methods : see the appended file at the end of the program below.
+ *---------------
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double one = 1.0, tiny=1.0e-300;
+#else
+static double one = 1.0, tiny=1.0e-300;
+#endif
+
+#ifdef __STDC__
+ double __generic___ieee754_sqrt(double x)
+#else
+ double __generic___ieee754_sqrt(x)
+ double x;
+#endif
+{
+ double z;
+ int32_t sign = (int)0x80000000;
+ int32_t ix0,s0,q,m,t,i;
+ u_int32_t r,t1,s1,ix1,q1;
+
+ EXTRACT_WORDS(ix0,ix1,x);
+
+ /* take care of Inf and NaN */
+ if((ix0&0x7ff00000)==0x7ff00000) {
+ return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+ sqrt(-inf)=sNaN */
+ }
+ /* take care of zero */
+ if(ix0<=0) {
+ if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
+ else if(ix0<0)
+ return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
+ }
+ /* normalize x */
+ m = (ix0>>20);
+ if(m==0) { /* subnormal x */
+ while(ix0==0) {
+ m -= 21;
+ ix0 |= (ix1>>11); ix1 <<= 21;
+ }
+ for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
+ m -= i-1;
+ ix0 |= (ix1>>(32-i));
+ ix1 <<= i;
+ }
+ m -= 1023; /* unbias exponent */
+ ix0 = (ix0&0x000fffff)|0x00100000;
+ if(m&1){ /* odd m, double x to make it even */
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ }
+ m >>= 1; /* m = [m/2] */
+
+ /* generate sqrt(x) bit by bit */
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
+ r = 0x00200000; /* r = moving bit from right to left */
+
+ while(r!=0) {
+ t = s0+r;
+ if(t<=ix0) {
+ s0 = t+r;
+ ix0 -= t;
+ q += r;
+ }
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ r>>=1;
+ }
+
+ r = sign;
+ while(r!=0) {
+ t1 = s1+r;
+ t = s0;
+ if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
+ s1 = t1+r;
+ if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
+ ix0 -= t;
+ if (ix1 < t1) ix0 -= 1;
+ ix1 -= t1;
+ q1 += r;
+ }
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ r>>=1;
+ }
+
+ /* use floating add to find out rounding direction */
+ if((ix0|ix1)!=0) {
+ z = one-tiny; /* trigger inexact flag */
+ if (z>=one) {
+ z = one+tiny;
+ if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;}
+ else if (z>one) {
+ if (q1==(u_int32_t)0xfffffffe) q+=1;
+ q1+=2;
+ } else
+ q1 += (q1&1);
+ }
+ }
+ ix0 = (q>>1)+0x3fe00000;
+ ix1 = q1>>1;
+ if ((q&1)==1) ix1 |= sign;
+ ix0 += (m <<20);
+ INSERT_WORDS(z,ix0,ix1);
+ return z;
+}
+
+/*
+Other methods (use floating-point arithmetic)
+-------------
+(This is a copy of a drafted paper by Prof W. Kahan
+and K.C. Ng, written in May, 1986)
+
+ Two algorithms are given here to implement sqrt(x)
+ (IEEE double precision arithmetic) in software.
+ Both supply sqrt(x) correctly rounded. The first algorithm (in
+ Section A) uses newton iterations and involves four divisions.
+ The second one uses reciproot iterations to avoid division, but
+ requires more multiplications. Both algorithms need the ability
+ to chop results of arithmetic operations instead of round them,
+ and the INEXACT flag to indicate when an arithmetic operation
+ is executed exactly with no roundoff error, all part of the
+ standard (IEEE 754-1985). The ability to perform shift, add,
+ subtract and logical AND operations upon 32-bit words is needed
+ too, though not part of the standard.
+
+A. sqrt(x) by Newton Iteration
+
+ (1) Initial approximation
+
+ Let x0 and x1 be the leading and the trailing 32-bit words of
+ a floating point number x (in IEEE double format) respectively
+
+ 1 11 52 ...widths
+ ------------------------------------------------------
+ x: |s| e | f |
+ ------------------------------------------------------
+ msb lsb msb lsb ...order
+
+
+ ------------------------ ------------------------
+ x0: |s| e | f1 | x1: | f2 |
+ ------------------------ ------------------------
+
+ By performing shifts and subtracts on x0 and x1 (both regarded
+ as integers), we obtain an 8-bit approximation of sqrt(x) as
+ follows.
+
+ k := (x0>>1) + 0x1ff80000;
+ y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits
+ Here k is a 32-bit integer and T1[] is an integer array containing
+ correction terms. Now magically the floating value of y (y's
+ leading 32-bit word is y0, the value of its trailing word is 0)
+ approximates sqrt(x) to almost 8-bit.
+
+ Value of T1:
+ static int T1[32]= {
+ 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592,
+ 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215,
+ 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581,
+ 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,};
+
+ (2) Iterative refinement
+
+ Apply Heron's rule three times to y, we have y approximates
+ sqrt(x) to within 1 ulp (Unit in the Last Place):
+
+ y := (y+x/y)/2 ... almost 17 sig. bits
+ y := (y+x/y)/2 ... almost 35 sig. bits
+ y := y-(y-x/y)/2 ... within 1 ulp
+
+
+ Remark 1.
+ Another way to improve y to within 1 ulp is:
+
+ y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x)
+ y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x)
+
+ 2
+ (x-y )*y
+ y := y + 2* ---------- ...within 1 ulp
+ 2
+ 3y + x
+
+
+ This formula has one division fewer than the one above; however,
+ it requires more multiplications and additions. Also x must be
+ scaled in advance to avoid spurious overflow in evaluating the
+ expression 3y*y+x. Hence it is not recommended uless division
+ is slow. If division is very slow, then one should use the
+ reciproot algorithm given in section B.
+
+ (3) Final adjustment
+
+ By twiddling y's last bit it is possible to force y to be
+ correctly rounded according to the prevailing rounding mode
+ as follows. Let r and i be copies of the rounding mode and
+ inexact flag before entering the square root program. Also we
+ use the expression y+-ulp for the next representable floating
+ numbers (up and down) of y. Note that y+-ulp = either fixed
+ point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+ mode.
+
+ I := FALSE; ... reset INEXACT flag I
+ R := RZ; ... set rounding mode to round-toward-zero
+ z := x/y; ... chopped quotient, possibly inexact
+ If(not I) then { ... if the quotient is exact
+ if(z=y) {
+ I := i; ... restore inexact flag
+ R := r; ... restore rounded mode
+ return sqrt(x):=y.
+ } else {
+ z := z - ulp; ... special rounding
+ }
+ }
+ i := TRUE; ... sqrt(x) is inexact
+ If (r=RN) then z=z+ulp ... rounded-to-nearest
+ If (r=RP) then { ... round-toward-+inf
+ y = y+ulp; z=z+ulp;
+ }
+ y := y+z; ... chopped sum
+ y0:=y0-0x00100000; ... y := y/2 is correctly rounded.
+ I := i; ... restore inexact flag
+ R := r; ... restore rounded mode
+ return sqrt(x):=y.
+
+ (4) Special cases
+
+ Square root of +inf, +-0, or NaN is itself;
+ Square root of a negative number is NaN with invalid signal.
+
+
+B. sqrt(x) by Reciproot Iteration
+
+ (1) Initial approximation
+
+ Let x0 and x1 be the leading and the trailing 32-bit words of
+ a floating point number x (in IEEE double format) respectively
+ (see section A). By performing shifs and subtracts on x0 and y0,
+ we obtain a 7.8-bit approximation of 1/sqrt(x) as follows.
+
+ k := 0x5fe80000 - (x0>>1);
+ y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits
+
+ Here k is a 32-bit integer and T2[] is an integer array
+ containing correction terms. Now magically the floating
+ value of y (y's leading 32-bit word is y0, the value of
+ its trailing word y1 is set to zero) approximates 1/sqrt(x)
+ to almost 7.8-bit.
+
+ Value of T2:
+ static int T2[64]= {
+ 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866,
+ 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f,
+ 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d,
+ 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0,
+ 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989,
+ 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd,
+ 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e,
+ 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,};
+
+ (2) Iterative refinement
+
+ Apply Reciproot iteration three times to y and multiply the
+ result by x to get an approximation z that matches sqrt(x)
+ to about 1 ulp. To be exact, we will have
+ -1ulp < sqrt(x)-z<1.0625ulp.
+
+ ... set rounding mode to Round-to-nearest
+ y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x)
+ y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x)
+ ... special arrangement for better accuracy
+ z := x*y ... 29 bits to sqrt(x), with z*y<1
+ z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x)
+
+ Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that
+ (a) the term z*y in the final iteration is always less than 1;
+ (b) the error in the final result is biased upward so that
+ -1 ulp < sqrt(x) - z < 1.0625 ulp
+ instead of |sqrt(x)-z|<1.03125ulp.
+
+ (3) Final adjustment
+
+ By twiddling y's last bit it is possible to force y to be
+ correctly rounded according to the prevailing rounding mode
+ as follows. Let r and i be copies of the rounding mode and
+ inexact flag before entering the square root program. Also we
+ use the expression y+-ulp for the next representable floating
+ numbers (up and down) of y. Note that y+-ulp = either fixed
+ point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+ mode.
+
+ R := RZ; ... set rounding mode to round-toward-zero
+ switch(r) {
+ case RN: ... round-to-nearest
+ if(x<= z*(z-ulp)...chopped) z = z - ulp; else
+ if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp;
+ break;
+ case RZ:case RM: ... round-to-zero or round-to--inf
+ R:=RP; ... reset rounding mod to round-to-+inf
+ if(x<z*z ... rounded up) z = z - ulp; else
+ if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp;
+ break;
+ case RP: ... round-to-+inf
+ if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else
+ if(x>z*z ...chopped) z = z+ulp;
+ break;
+ }
+
+ Remark 3. The above comparisons can be done in fixed point. For
+ example, to compare x and w=z*z chopped, it suffices to compare
+ x1 and w1 (the trailing parts of x and w), regarding them as
+ two's complement integers.
+
+ ...Is z an exact square root?
+ To determine whether z is an exact square root of x, let z1 be the
+ trailing part of z, and also let x0 and x1 be the leading and
+ trailing parts of x.
+
+ If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0
+ I := 1; ... Raise Inexact flag: z is not exact
+ else {
+ j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2
+ k := z1 >> 26; ... get z's 25-th and 26-th
+ fraction bits
+ I := i or (k&j) or ((k&(j+j+1))!=(x1&3));
+ }
+ R:= r ... restore rounded mode
+ return sqrt(x):=z.
+
+ If multiplication is cheaper then the foregoing red tape, the
+ Inexact flag can be evaluated by
+
+ I := i;
+ I := (z*z!=x) or I.
+
+ Note that z*z can overwrite I; this value must be sensed if it is
+ True.
+
+ Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be
+ zero.
+
+ --------------------
+ z1: | f2 |
+ --------------------
+ bit 31 bit 0
+
+ Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd
+ or even of logb(x) have the following relations:
+
+ -------------------------------------------------
+ bit 27,26 of z1 bit 1,0 of x1 logb(x)
+ -------------------------------------------------
+ 00 00 odd and even
+ 01 01 even
+ 10 10 odd
+ 10 00 even
+ 11 01 even
+ -------------------------------------------------
+
+ (4) Special cases (see (4) of Section A).
+
+ */
+
diff --git a/lib/msun/src/e_sqrtf.c b/lib/msun/src/e_sqrtf.c
new file mode 100644
index 0000000..d7748e2
--- /dev/null
+++ b/lib/msun/src/e_sqrtf.c
@@ -0,0 +1,97 @@
+/* e_sqrtf.c -- float version of e_sqrt.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float one = 1.0, tiny=1.0e-30;
+#else
+static float one = 1.0, tiny=1.0e-30;
+#endif
+
+#ifdef __STDC__
+ float __ieee754_sqrtf(float x)
+#else
+ float __ieee754_sqrtf(x)
+ float x;
+#endif
+{
+ float z;
+ int32_t sign = (int)0x80000000;
+ int32_t ix,s,q,m,t,i;
+ u_int32_t r;
+
+ GET_FLOAT_WORD(ix,x);
+
+ /* take care of Inf and NaN */
+ if((ix&0x7f800000)==0x7f800000) {
+ return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+ sqrt(-inf)=sNaN */
+ }
+ /* take care of zero */
+ if(ix<=0) {
+ if((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */
+ else if(ix<0)
+ return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
+ }
+ /* normalize x */
+ m = (ix>>23);
+ if(m==0) { /* subnormal x */
+ for(i=0;(ix&0x00800000)==0;i++) ix<<=1;
+ m -= i-1;
+ }
+ m -= 127; /* unbias exponent */
+ ix = (ix&0x007fffff)|0x00800000;
+ if(m&1) /* odd m, double x to make it even */
+ ix += ix;
+ m >>= 1; /* m = [m/2] */
+
+ /* generate sqrt(x) bit by bit */
+ ix += ix;
+ q = s = 0; /* q = sqrt(x) */
+ r = 0x01000000; /* r = moving bit from right to left */
+
+ while(r!=0) {
+ t = s+r;
+ if(t<=ix) {
+ s = t+r;
+ ix -= t;
+ q += r;
+ }
+ ix += ix;
+ r>>=1;
+ }
+
+ /* use floating add to find out rounding direction */
+ if(ix!=0) {
+ z = one-tiny; /* trigger inexact flag */
+ if (z>=one) {
+ z = one+tiny;
+ if (z>one)
+ q += 2;
+ else
+ q += (q&1);
+ }
+ }
+ ix = (q>>1)+0x3f000000;
+ ix += (m <<23);
+ SET_FLOAT_WORD(z,ix);
+ return z;
+}
diff --git a/lib/msun/src/get_hw_float.c b/lib/msun/src/get_hw_float.c
new file mode 100644
index 0000000..fea5c89
--- /dev/null
+++ b/lib/msun/src/get_hw_float.c
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 1997 Bruce D. Evans
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+int __get_hw_float __P((void));
+
+static int hw_float = -1;
+
+int
+__get_hw_float()
+{
+ size_t len;
+ int mib[2];
+
+ if (hw_float == -1) {
+ len = sizeof(hw_float);
+ mib[0] = CTL_HW;
+ mib[1] = HW_FLOATINGPT;
+ if (__sysctl(mib, 2, &hw_float, &len, (void *)0, 0) == -1)
+ hw_float = 0; /* shouldn't happen; assume the worst */
+ }
+ return (hw_float);
+}
diff --git a/lib/msun/src/k_cos.c b/lib/msun/src/k_cos.c
new file mode 100644
index 0000000..f2ba373
--- /dev/null
+++ b/lib/msun/src/k_cos.c
@@ -0,0 +1,96 @@
+/* @(#)k_cos.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * __kernel_cos( x, y )
+ * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ *
+ * Algorithm
+ * 1. Since cos(-x) = cos(x), we need only to consider positive x.
+ * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
+ * 3. cos(x) is approximated by a polynomial of degree 14 on
+ * [0,pi/4]
+ * 4 14
+ * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
+ * where the remez error is
+ *
+ * | 2 4 6 8 10 12 14 | -58
+ * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2
+ * | |
+ *
+ * 4 6 8 10 12 14
+ * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then
+ * cos(x) = 1 - x*x/2 + r
+ * since cos(x+y) ~ cos(x) - sin(x)*y
+ * ~ cos(x) - x*y,
+ * a correction term is necessary in cos(x) and hence
+ * cos(x+y) = 1 - (x*x/2 - (r - x*y))
+ * For better accuracy when x > 0.3, let qx = |x|/4 with
+ * the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
+ * Then
+ * cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)).
+ * Note that 1-qx and (x*x/2-qx) is EXACT here, and the
+ * magnitude of the latter is at least a quarter of x*x/2,
+ * thus, reducing the rounding error in the subtraction.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
+C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
+C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
+C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
+C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
+C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
+
+#ifdef __STDC__
+ double __kernel_cos(double x, double y)
+#else
+ double __kernel_cos(x, y)
+ double x,y;
+#endif
+{
+ double a,hz,z,r,qx;
+ int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff; /* ix = |x|'s high word*/
+ if(ix<0x3e400000) { /* if x < 2**27 */
+ if(((int)x)==0) return one; /* generate inexact */
+ }
+ z = x*x;
+ r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
+ if(ix < 0x3FD33333) /* if |x| < 0.3 */
+ return one - (0.5*z - (z*r - x*y));
+ else {
+ if(ix > 0x3fe90000) { /* x > 0.78125 */
+ qx = 0.28125;
+ } else {
+ INSERT_WORDS(qx,ix-0x00200000,0); /* x/4 */
+ }
+ hz = 0.5*z-qx;
+ a = one-qx;
+ return a - (hz - (z*r-x*y));
+ }
+}
diff --git a/lib/msun/src/k_cosf.c b/lib/msun/src/k_cosf.c
new file mode 100644
index 0000000..65f3192
--- /dev/null
+++ b/lib/msun/src/k_cosf.c
@@ -0,0 +1,64 @@
+/* k_cosf.c -- float version of k_cos.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+one = 1.0000000000e+00, /* 0x3f800000 */
+C1 = 4.1666667908e-02, /* 0x3d2aaaab */
+C2 = -1.3888889225e-03, /* 0xbab60b61 */
+C3 = 2.4801587642e-05, /* 0x37d00d01 */
+C4 = -2.7557314297e-07, /* 0xb493f27c */
+C5 = 2.0875723372e-09, /* 0x310f74f6 */
+C6 = -1.1359647598e-11; /* 0xad47d74e */
+
+#ifdef __STDC__
+ float __kernel_cosf(float x, float y)
+#else
+ float __kernel_cosf(x, y)
+ float x,y;
+#endif
+{
+ float a,hz,z,r,qx;
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff; /* ix = |x|'s high word*/
+ if(ix<0x32000000) { /* if x < 2**27 */
+ if(((int)x)==0) return one; /* generate inexact */
+ }
+ z = x*x;
+ r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
+ if(ix < 0x3e99999a) /* if |x| < 0.3 */
+ return one - ((float)0.5*z - (z*r - x*y));
+ else {
+ if(ix > 0x3f480000) { /* x > 0.78125 */
+ qx = (float)0.28125;
+ } else {
+ SET_FLOAT_WORD(qx,ix-0x01000000); /* x/4 */
+ }
+ hz = (float)0.5*z-qx;
+ a = one-qx;
+ return a - (hz - (z*r-x*y));
+ }
+}
diff --git a/lib/msun/src/k_rem_pio2.c b/lib/msun/src/k_rem_pio2.c
new file mode 100644
index 0000000..6e46a95
--- /dev/null
+++ b/lib/msun/src/k_rem_pio2.c
@@ -0,0 +1,320 @@
+/* @(#)k_rem_pio2.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
+ * double x[],y[]; int e0,nx,prec; int ipio2[];
+ *
+ * __kernel_rem_pio2 return the last three digits of N with
+ * y = x - N*pi/2
+ * so that |y| < pi/2.
+ *
+ * The method is to compute the integer (mod 8) and fraction parts of
+ * (2/pi)*x without doing the full multiplication. In general we
+ * skip the part of the product that are known to be a huge integer (
+ * more accurately, = 0 mod 8 ). Thus the number of operations are
+ * independent of the exponent of the input.
+ *
+ * (2/pi) is represented by an array of 24-bit integers in ipio2[].
+ *
+ * Input parameters:
+ * x[] The input value (must be positive) is broken into nx
+ * pieces of 24-bit integers in double precision format.
+ * x[i] will be the i-th 24 bit of x. The scaled exponent
+ * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
+ * match x's up to 24 bits.
+ *
+ * Example of breaking a double positive z into x[0]+x[1]+x[2]:
+ * e0 = ilogb(z)-23
+ * z = scalbn(z,-e0)
+ * for i = 0,1,2
+ * x[i] = floor(z)
+ * z = (z-x[i])*2**24
+ *
+ *
+ * y[] ouput result in an array of double precision numbers.
+ * The dimension of y[] is:
+ * 24-bit precision 1
+ * 53-bit precision 2
+ * 64-bit precision 2
+ * 113-bit precision 3
+ * The actual value is the sum of them. Thus for 113-bit
+ * precison, one may have to do something like:
+ *
+ * long double t,w,r_head, r_tail;
+ * t = (long double)y[2] + (long double)y[1];
+ * w = (long double)y[0];
+ * r_head = t+w;
+ * r_tail = w - (r_head - t);
+ *
+ * e0 The exponent of x[0]
+ *
+ * nx dimension of x[]
+ *
+ * prec an integer indicating the precision:
+ * 0 24 bits (single)
+ * 1 53 bits (double)
+ * 2 64 bits (extended)
+ * 3 113 bits (quad)
+ *
+ * ipio2[]
+ * integer array, contains the (24*i)-th to (24*i+23)-th
+ * bit of 2/pi after binary point. The corresponding
+ * floating value is
+ *
+ * ipio2[i] * 2^(-24(i+1)).
+ *
+ * External function:
+ * double scalbn(), floor();
+ *
+ *
+ * Here is the description of some local variables:
+ *
+ * jk jk+1 is the initial number of terms of ipio2[] needed
+ * in the computation. The recommended value is 2,3,4,
+ * 6 for single, double, extended,and quad.
+ *
+ * jz local integer variable indicating the number of
+ * terms of ipio2[] used.
+ *
+ * jx nx - 1
+ *
+ * jv index for pointing to the suitable ipio2[] for the
+ * computation. In general, we want
+ * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
+ * is an integer. Thus
+ * e0-3-24*jv >= 0 or (e0-3)/24 >= jv
+ * Hence jv = max(0,(e0-3)/24).
+ *
+ * jp jp+1 is the number of terms in PIo2[] needed, jp = jk.
+ *
+ * q[] double array with integral value, representing the
+ * 24-bits chunk of the product of x and 2/pi.
+ *
+ * q0 the corresponding exponent of q[0]. Note that the
+ * exponent for q[i] would be q0-24*i.
+ *
+ * PIo2[] double precision array, obtained by cutting pi/2
+ * into 24 bits chunks.
+ *
+ * f[] ipio2[] in floating point
+ *
+ * iq[] integer array by breaking up q[] in 24-bits chunk.
+ *
+ * fq[] final product of x*(2/pi) in fq[0],..,fq[jk]
+ *
+ * ih integer. If >0 it indicates q[] is >= 0.5, hence
+ * it also indicates the *sign* of the result.
+ *
+ */
+
+
+/*
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const int init_jk[] = {2,3,4,6}; /* initial value for jk */
+#else
+static int init_jk[] = {2,3,4,6};
+#endif
+
+#ifdef __STDC__
+static const double PIo2[] = {
+#else
+static double PIo2[] = {
+#endif
+ 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
+ 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
+ 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
+ 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
+ 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
+ 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
+ 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
+ 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
+};
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+zero = 0.0,
+one = 1.0,
+two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
+
+#ifdef __STDC__
+ int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2)
+#else
+ int __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
+ double x[], y[]; int e0,nx,prec; int32_t ipio2[];
+#endif
+{
+ int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
+ double z,fw,f[20],fq[20],q[20];
+
+ /* initialize jk*/
+ jk = init_jk[prec];
+ jp = jk;
+
+ /* determine jx,jv,q0, note that 3>q0 */
+ jx = nx-1;
+ jv = (e0-3)/24; if(jv<0) jv=0;
+ q0 = e0-24*(jv+1);
+
+ /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+ j = jv-jx; m = jx+jk;
+ for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j];
+
+ /* compute q[0],q[1],...q[jk] */
+ for (i=0;i<=jk;i++) {
+ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
+ }
+
+ jz = jk;
+recompute:
+ /* distill q[] into iq[] reversingly */
+ for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+ fw = (double)((int32_t)(twon24* z));
+ iq[i] = (int32_t)(z-two24*fw);
+ z = q[j-1]+fw;
+ }
+
+ /* compute n */
+ z = scalbn(z,q0); /* actual value of z */
+ z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */
+ n = (int32_t) z;
+ z -= (double)n;
+ ih = 0;
+ if(q0>0) { /* need iq[jz-1] to determine n */
+ i = (iq[jz-1]>>(24-q0)); n += i;
+ iq[jz-1] -= i<<(24-q0);
+ ih = iq[jz-1]>>(23-q0);
+ }
+ else if(q0==0) ih = iq[jz-1]>>23;
+ else if(z>=0.5) ih=2;
+
+ if(ih>0) { /* q > 0.5 */
+ n += 1; carry = 0;
+ for(i=0;i<jz ;i++) { /* compute 1-q */
+ j = iq[i];
+ if(carry==0) {
+ if(j!=0) {
+ carry = 1; iq[i] = 0x1000000- j;
+ }
+ } else iq[i] = 0xffffff - j;
+ }
+ if(q0>0) { /* rare case: chance is 1 in 12 */
+ switch(q0) {
+ case 1:
+ iq[jz-1] &= 0x7fffff; break;
+ case 2:
+ iq[jz-1] &= 0x3fffff; break;
+ }
+ }
+ if(ih==2) {
+ z = one - z;
+ if(carry!=0) z -= scalbn(one,q0);
+ }
+ }
+
+ /* check if recomputation is needed */
+ if(z==zero) {
+ j = 0;
+ for (i=jz-1;i>=jk;i--) j |= iq[i];
+ if(j==0) { /* need recomputation */
+ for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */
+
+ for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */
+ f[jx+i] = (double) ipio2[jv+i];
+ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+ q[i] = fw;
+ }
+ jz += k;
+ goto recompute;
+ }
+ }
+
+ /* chop off zero terms */
+ if(z==0.0) {
+ jz -= 1; q0 -= 24;
+ while(iq[jz]==0) { jz--; q0-=24;}
+ } else { /* break z into 24-bit if necessary */
+ z = scalbn(z,-q0);
+ if(z>=two24) {
+ fw = (double)((int32_t)(twon24*z));
+ iq[jz] = (int32_t)(z-two24*fw);
+ jz += 1; q0 += 24;
+ iq[jz] = (int32_t) fw;
+ } else iq[jz] = (int32_t) z ;
+ }
+
+ /* convert integer "bit" chunk to floating-point value */
+ fw = scalbn(one,q0);
+ for(i=jz;i>=0;i--) {
+ q[i] = fw*(double)iq[i]; fw*=twon24;
+ }
+
+ /* compute PIo2[0,...,jp]*q[jz,...,0] */
+ for(i=jz;i>=0;i--) {
+ for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+ fq[jz-i] = fw;
+ }
+
+ /* compress fq[] into y[] */
+ switch(prec) {
+ case 0:
+ fw = 0.0;
+ for (i=jz;i>=0;i--) fw += fq[i];
+ y[0] = (ih==0)? fw: -fw;
+ break;
+ case 1:
+ case 2:
+ fw = 0.0;
+ for (i=jz;i>=0;i--) fw += fq[i];
+ y[0] = (ih==0)? fw: -fw;
+ fw = fq[0]-fw;
+ for (i=1;i<=jz;i++) fw += fq[i];
+ y[1] = (ih==0)? fw: -fw;
+ break;
+ case 3: /* painful */
+ for (i=jz;i>0;i--) {
+ fw = fq[i-1]+fq[i];
+ fq[i] += fq[i-1]-fw;
+ fq[i-1] = fw;
+ }
+ for (i=jz;i>1;i--) {
+ fw = fq[i-1]+fq[i];
+ fq[i] += fq[i-1]-fw;
+ fq[i-1] = fw;
+ }
+ for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
+ if(ih==0) {
+ y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
+ } else {
+ y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
+ }
+ }
+ return n&7;
+}
diff --git a/lib/msun/src/k_rem_pio2f.c b/lib/msun/src/k_rem_pio2f.c
new file mode 100644
index 0000000..1ae7ade
--- /dev/null
+++ b/lib/msun/src/k_rem_pio2f.c
@@ -0,0 +1,213 @@
+/* k_rem_pio2f.c -- float version of k_rem_pio2.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+/* In the float version, the input parameter x contains 8 bit
+ integers, not 24 bit integers. 113 bit precision is not supported. */
+
+#ifdef __STDC__
+static const int init_jk[] = {4,7,9}; /* initial value for jk */
+#else
+static int init_jk[] = {4,7,9};
+#endif
+
+#ifdef __STDC__
+static const float PIo2[] = {
+#else
+static float PIo2[] = {
+#endif
+ 1.5703125000e+00, /* 0x3fc90000 */
+ 4.5776367188e-04, /* 0x39f00000 */
+ 2.5987625122e-05, /* 0x37da0000 */
+ 7.5437128544e-08, /* 0x33a20000 */
+ 6.0026650317e-11, /* 0x2e840000 */
+ 7.3896444519e-13, /* 0x2b500000 */
+ 5.3845816694e-15, /* 0x27c20000 */
+ 5.6378512969e-18, /* 0x22d00000 */
+ 8.3009228831e-20, /* 0x1fc40000 */
+ 3.2756352257e-22, /* 0x1bc60000 */
+ 6.3331015649e-25, /* 0x17440000 */
+};
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+zero = 0.0,
+one = 1.0,
+two8 = 2.5600000000e+02, /* 0x43800000 */
+twon8 = 3.9062500000e-03; /* 0x3b800000 */
+
+#ifdef __STDC__
+ int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const int32_t *ipio2)
+#else
+ int __kernel_rem_pio2f(x,y,e0,nx,prec,ipio2)
+ float x[], y[]; int e0,nx,prec; int32_t ipio2[];
+#endif
+{
+ int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
+ float z,fw,f[20],fq[20],q[20];
+
+ /* initialize jk*/
+ jk = init_jk[prec];
+ jp = jk;
+
+ /* determine jx,jv,q0, note that 3>q0 */
+ jx = nx-1;
+ jv = (e0-3)/8; if(jv<0) jv=0;
+ q0 = e0-8*(jv+1);
+
+ /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+ j = jv-jx; m = jx+jk;
+ for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j];
+
+ /* compute q[0],q[1],...q[jk] */
+ for (i=0;i<=jk;i++) {
+ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
+ }
+
+ jz = jk;
+recompute:
+ /* distill q[] into iq[] reversingly */
+ for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+ fw = (float)((int32_t)(twon8* z));
+ iq[i] = (int32_t)(z-two8*fw);
+ z = q[j-1]+fw;
+ }
+
+ /* compute n */
+ z = scalbnf(z,q0); /* actual value of z */
+ z -= (float)8.0*floorf(z*(float)0.125); /* trim off integer >= 8 */
+ n = (int32_t) z;
+ z -= (float)n;
+ ih = 0;
+ if(q0>0) { /* need iq[jz-1] to determine n */
+ i = (iq[jz-1]>>(8-q0)); n += i;
+ iq[jz-1] -= i<<(8-q0);
+ ih = iq[jz-1]>>(7-q0);
+ }
+ else if(q0==0) ih = iq[jz-1]>>8;
+ else if(z>=(float)0.5) ih=2;
+
+ if(ih>0) { /* q > 0.5 */
+ n += 1; carry = 0;
+ for(i=0;i<jz ;i++) { /* compute 1-q */
+ j = iq[i];
+ if(carry==0) {
+ if(j!=0) {
+ carry = 1; iq[i] = 0x100- j;
+ }
+ } else iq[i] = 0xff - j;
+ }
+ if(q0>0) { /* rare case: chance is 1 in 12 */
+ switch(q0) {
+ case 1:
+ iq[jz-1] &= 0x7f; break;
+ case 2:
+ iq[jz-1] &= 0x3f; break;
+ }
+ }
+ if(ih==2) {
+ z = one - z;
+ if(carry!=0) z -= scalbnf(one,q0);
+ }
+ }
+
+ /* check if recomputation is needed */
+ if(z==zero) {
+ j = 0;
+ for (i=jz-1;i>=jk;i--) j |= iq[i];
+ if(j==0) { /* need recomputation */
+ for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */
+
+ for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */
+ f[jx+i] = (float) ipio2[jv+i];
+ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+ q[i] = fw;
+ }
+ jz += k;
+ goto recompute;
+ }
+ }
+
+ /* chop off zero terms */
+ if(z==(float)0.0) {
+ jz -= 1; q0 -= 8;
+ while(iq[jz]==0) { jz--; q0-=8;}
+ } else { /* break z into 8-bit if necessary */
+ z = scalbnf(z,-q0);
+ if(z>=two8) {
+ fw = (float)((int32_t)(twon8*z));
+ iq[jz] = (int32_t)(z-two8*fw);
+ jz += 1; q0 += 8;
+ iq[jz] = (int32_t) fw;
+ } else iq[jz] = (int32_t) z ;
+ }
+
+ /* convert integer "bit" chunk to floating-point value */
+ fw = scalbnf(one,q0);
+ for(i=jz;i>=0;i--) {
+ q[i] = fw*(float)iq[i]; fw*=twon8;
+ }
+
+ /* compute PIo2[0,...,jp]*q[jz,...,0] */
+ for(i=jz;i>=0;i--) {
+ for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+ fq[jz-i] = fw;
+ }
+
+ /* compress fq[] into y[] */
+ switch(prec) {
+ case 0:
+ fw = 0.0;
+ for (i=jz;i>=0;i--) fw += fq[i];
+ y[0] = (ih==0)? fw: -fw;
+ break;
+ case 1:
+ case 2:
+ fw = 0.0;
+ for (i=jz;i>=0;i--) fw += fq[i];
+ y[0] = (ih==0)? fw: -fw;
+ fw = fq[0]-fw;
+ for (i=1;i<=jz;i++) fw += fq[i];
+ y[1] = (ih==0)? fw: -fw;
+ break;
+ case 3: /* painful */
+ for (i=jz;i>0;i--) {
+ fw = fq[i-1]+fq[i];
+ fq[i] += fq[i-1]-fw;
+ fq[i-1] = fw;
+ }
+ for (i=jz;i>1;i--) {
+ fw = fq[i-1]+fq[i];
+ fq[i] += fq[i-1]-fw;
+ fq[i-1] = fw;
+ }
+ for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
+ if(ih==0) {
+ y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
+ } else {
+ y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
+ }
+ }
+ return n&7;
+}
diff --git a/lib/msun/src/k_sin.c b/lib/msun/src/k_sin.c
new file mode 100644
index 0000000..b2f05e6
--- /dev/null
+++ b/lib/msun/src/k_sin.c
@@ -0,0 +1,79 @@
+/* @(#)k_sin.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __kernel_sin( x, y, iy)
+ * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
+ *
+ * Algorithm
+ * 1. Since sin(-x) = -sin(x), we need only to consider positive x.
+ * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
+ * 3. sin(x) is approximated by a polynomial of degree 13 on
+ * [0,pi/4]
+ * 3 13
+ * sin(x) ~ x + S1*x + ... + S6*x
+ * where
+ *
+ * |sin(x) 2 4 6 8 10 12 | -58
+ * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2
+ * | x |
+ *
+ * 4. sin(x+y) = sin(x) + sin'(x')*y
+ * ~ sin(x) + (1-x*x/2)*y
+ * For better accuracy, let
+ * 3 2 2 2 2
+ * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
+ * then 3 2
+ * sin(x) = x + (S1*x + (x *(r-y/2)+y))
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
+S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
+S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
+S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
+S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
+S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
+
+#ifdef __STDC__
+ double __kernel_sin(double x, double y, int iy)
+#else
+ double __kernel_sin(x, y, iy)
+ double x,y; int iy; /* iy=0 if y is zero */
+#endif
+{
+ double z,r,v;
+ int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff; /* high word of x */
+ if(ix<0x3e400000) /* |x| < 2**-27 */
+ {if((int)x==0) return x;} /* generate inexact */
+ z = x*x;
+ v = z*x;
+ r = S2+z*(S3+z*(S4+z*(S5+z*S6)));
+ if(iy==0) return x+v*(S1+z*r);
+ else return x-((z*(half*y-v*r)-y)-v*S1);
+}
diff --git a/lib/msun/src/k_sinf.c b/lib/msun/src/k_sinf.c
new file mode 100644
index 0000000..9317793
--- /dev/null
+++ b/lib/msun/src/k_sinf.c
@@ -0,0 +1,54 @@
+/* k_sinf.c -- float version of k_sin.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+half = 5.0000000000e-01,/* 0x3f000000 */
+S1 = -1.6666667163e-01, /* 0xbe2aaaab */
+S2 = 8.3333337680e-03, /* 0x3c088889 */
+S3 = -1.9841270114e-04, /* 0xb9500d01 */
+S4 = 2.7557314297e-06, /* 0x3638ef1b */
+S5 = -2.5050759689e-08, /* 0xb2d72f34 */
+S6 = 1.5896910177e-10; /* 0x2f2ec9d3 */
+
+#ifdef __STDC__
+ float __kernel_sinf(float x, float y, int iy)
+#else
+ float __kernel_sinf(x, y, iy)
+ float x,y; int iy; /* iy=0 if y is zero */
+#endif
+{
+ float z,r,v;
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff; /* high word of x */
+ if(ix<0x32000000) /* |x| < 2**-27 */
+ {if((int)x==0) return x;} /* generate inexact */
+ z = x*x;
+ v = z*x;
+ r = S2+z*(S3+z*(S4+z*(S5+z*S6)));
+ if(iy==0) return x+v*(S1+z*r);
+ else return x-((z*(half*y-v*r)-y)-v*S1);
+}
diff --git a/lib/msun/src/k_standard.c b/lib/msun/src/k_standard.c
new file mode 100644
index 0000000..84ee2a4
--- /dev/null
+++ b/lib/msun/src/k_standard.c
@@ -0,0 +1,782 @@
+/* @(#)k_standard.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+#include <errno.h>
+
+#ifndef _USE_WRITE
+#include <stdio.h> /* fputs(), stderr */
+#define WRITE2(u,v) fputs(u, stderr)
+#else /* !defined(_USE_WRITE) */
+#include <unistd.h> /* write */
+#define WRITE2(u,v) write(2, u, v)
+#undef fflush
+#endif /* !defined(_USE_WRITE) */
+
+#ifdef __STDC__
+static const double zero = 0.0; /* used as const */
+#else
+static double zero = 0.0; /* used as const */
+#endif
+
+/*
+ * Standard conformance (non-IEEE) on exception cases.
+ * Mapping:
+ * 1 -- acos(|x|>1)
+ * 2 -- asin(|x|>1)
+ * 3 -- atan2(+-0,+-0)
+ * 4 -- hypot overflow
+ * 5 -- cosh overflow
+ * 6 -- exp overflow
+ * 7 -- exp underflow
+ * 8 -- y0(0)
+ * 9 -- y0(-ve)
+ * 10-- y1(0)
+ * 11-- y1(-ve)
+ * 12-- yn(0)
+ * 13-- yn(-ve)
+ * 14-- lgamma(finite) overflow
+ * 15-- lgamma(-integer)
+ * 16-- log(0)
+ * 17-- log(x<0)
+ * 18-- log10(0)
+ * 19-- log10(x<0)
+ * 20-- pow(0.0,0.0)
+ * 21-- pow(x,y) overflow
+ * 22-- pow(x,y) underflow
+ * 23-- pow(0,negative)
+ * 24-- pow(neg,non-integral)
+ * 25-- sinh(finite) overflow
+ * 26-- sqrt(negative)
+ * 27-- fmod(x,0)
+ * 28-- remainder(x,0)
+ * 29-- acosh(x<1)
+ * 30-- atanh(|x|>1)
+ * 31-- atanh(|x|=1)
+ * 32-- scalb overflow
+ * 33-- scalb underflow
+ * 34-- j0(|x|>X_TLOSS)
+ * 35-- y0(x>X_TLOSS)
+ * 36-- j1(|x|>X_TLOSS)
+ * 37-- y1(x>X_TLOSS)
+ * 38-- jn(|x|>X_TLOSS, n)
+ * 39-- yn(x>X_TLOSS, n)
+ * 40-- gamma(finite) overflow
+ * 41-- gamma(-integer)
+ * 42-- pow(NaN,0.0)
+ */
+
+
+#ifdef __STDC__
+ double __kernel_standard(double x, double y, int type)
+#else
+ double __kernel_standard(x,y,type)
+ double x,y; int type;
+#endif
+{
+ struct exception exc;
+#ifndef HUGE_VAL /* this is the only routine that uses HUGE_VAL */
+#define HUGE_VAL inf
+ double inf = 0.0;
+
+ SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */
+#endif
+
+#ifdef _USE_WRITE
+ (void) fflush(stdout);
+#endif
+ exc.arg1 = x;
+ exc.arg2 = y;
+ switch(type) {
+ case 1:
+ case 101:
+ /* acos(|x|>1) */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "acos" : "acosf";
+ exc.retval = zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if(_LIB_VERSION == _SVID_) {
+ (void) WRITE2("acos: DOMAIN error\n", 19);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 2:
+ case 102:
+ /* asin(|x|>1) */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "asin" : "asinf";
+ exc.retval = zero;
+ if(_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if(_LIB_VERSION == _SVID_) {
+ (void) WRITE2("asin: DOMAIN error\n", 19);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 3:
+ case 103:
+ /* atan2(+-0,+-0) */
+ exc.arg1 = y;
+ exc.arg2 = x;
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "atan2" : "atan2f";
+ exc.retval = zero;
+ if(_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if(_LIB_VERSION == _SVID_) {
+ (void) WRITE2("atan2: DOMAIN error\n", 20);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 4:
+ case 104:
+ /* hypot(finite,finite) overflow */
+ exc.type = OVERFLOW;
+ exc.name = type < 100 ? "hypot" : "hypotf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = HUGE;
+ else
+ exc.retval = HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ break;
+ case 5:
+ case 105:
+ /* cosh(finite) overflow */
+ exc.type = OVERFLOW;
+ exc.name = type < 100 ? "cosh" : "coshf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = HUGE;
+ else
+ exc.retval = HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ break;
+ case 6:
+ case 106:
+ /* exp(finite) overflow */
+ exc.type = OVERFLOW;
+ exc.name = type < 100 ? "exp" : "expf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = HUGE;
+ else
+ exc.retval = HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ break;
+ case 7:
+ case 107:
+ /* exp(finite) underflow */
+ exc.type = UNDERFLOW;
+ exc.name = type < 100 ? "exp" : "expf";
+ exc.retval = zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ break;
+ case 8:
+ case 108:
+ /* y0(0) = -inf */
+ exc.type = DOMAIN; /* should be SING for IEEE */
+ exc.name = type < 100 ? "y0" : "y0f";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = -HUGE;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("y0: DOMAIN error\n", 17);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 9:
+ case 109:
+ /* y0(x<0) = NaN */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "y0" : "y0f";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = -HUGE;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("y0: DOMAIN error\n", 17);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 10:
+ case 110:
+ /* y1(0) = -inf */
+ exc.type = DOMAIN; /* should be SING for IEEE */
+ exc.name = type < 100 ? "y1" : "y1f";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = -HUGE;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("y1: DOMAIN error\n", 17);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 11:
+ case 111:
+ /* y1(x<0) = NaN */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "y1" : "y1f";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = -HUGE;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("y1: DOMAIN error\n", 17);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 12:
+ case 112:
+ /* yn(n,0) = -inf */
+ exc.type = DOMAIN; /* should be SING for IEEE */
+ exc.name = type < 100 ? "yn" : "ynf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = -HUGE;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("yn: DOMAIN error\n", 17);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 13:
+ case 113:
+ /* yn(x<0) = NaN */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "yn" : "ynf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = -HUGE;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("yn: DOMAIN error\n", 17);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 14:
+ case 114:
+ /* lgamma(finite) overflow */
+ exc.type = OVERFLOW;
+ exc.name = type < 100 ? "lgamma" : "lgammaf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = HUGE;
+ else
+ exc.retval = HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ break;
+ case 15:
+ case 115:
+ /* lgamma(-integer) or lgamma(0) */
+ exc.type = SING;
+ exc.name = type < 100 ? "lgamma" : "lgammaf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = HUGE;
+ else
+ exc.retval = HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("lgamma: SING error\n", 19);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 16:
+ case 116:
+ /* log(0) */
+ exc.type = SING;
+ exc.name = type < 100 ? "log" : "logf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = -HUGE;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("log: SING error\n", 16);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 17:
+ case 117:
+ /* log(x<0) */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "log" : "logf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = -HUGE;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("log: DOMAIN error\n", 18);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 18:
+ case 118:
+ /* log10(0) */
+ exc.type = SING;
+ exc.name = type < 100 ? "log10" : "log10f";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = -HUGE;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("log10: SING error\n", 18);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 19:
+ case 119:
+ /* log10(x<0) */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "log10" : "log10f";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = -HUGE;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("log10: DOMAIN error\n", 20);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 20:
+ case 120:
+ /* pow(0.0,0.0) */
+ /* error only if _LIB_VERSION == _SVID_ */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "pow" : "powf";
+ exc.retval = zero;
+ if (_LIB_VERSION != _SVID_) exc.retval = 1.0;
+ else if (!matherr(&exc)) {
+ (void) WRITE2("pow(0,0): DOMAIN error\n", 23);
+ errno = EDOM;
+ }
+ break;
+ case 21:
+ case 121:
+ /* pow(x,y) overflow */
+ exc.type = OVERFLOW;
+ exc.name = type < 100 ? "pow" : "powf";
+ if (_LIB_VERSION == _SVID_) {
+ exc.retval = HUGE;
+ y *= 0.5;
+ if(x<zero&&rint(y)!=y) exc.retval = -HUGE;
+ } else {
+ exc.retval = HUGE_VAL;
+ y *= 0.5;
+ if(x<zero&&rint(y)!=y) exc.retval = -HUGE_VAL;
+ }
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ break;
+ case 22:
+ case 122:
+ /* pow(x,y) underflow */
+ exc.type = UNDERFLOW;
+ exc.name = type < 100 ? "pow" : "powf";
+ exc.retval = zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ break;
+ case 23:
+ case 123:
+ /* 0**neg */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "pow" : "powf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = zero;
+ else
+ exc.retval = -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("pow(0,neg): DOMAIN error\n", 25);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 24:
+ case 124:
+ /* neg**non-integral */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "pow" : "powf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = zero;
+ else
+ exc.retval = zero/zero; /* X/Open allow NaN */
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("neg**non-integral: DOMAIN error\n", 32);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 25:
+ case 125:
+ /* sinh(finite) overflow */
+ exc.type = OVERFLOW;
+ exc.name = type < 100 ? "sinh" : "sinhf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = ( (x>zero) ? HUGE : -HUGE);
+ else
+ exc.retval = ( (x>zero) ? HUGE_VAL : -HUGE_VAL);
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ break;
+ case 26:
+ case 126:
+ /* sqrt(x<0) */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "sqrt" : "sqrtf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = zero;
+ else
+ exc.retval = zero/zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("sqrt: DOMAIN error\n", 19);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 27:
+ case 127:
+ /* fmod(x,0) */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "fmod" : "fmodf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = x;
+ else
+ exc.retval = zero/zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("fmod: DOMAIN error\n", 20);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 28:
+ case 128:
+ /* remainder(x,0) */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "remainder" : "remainderf";
+ exc.retval = zero/zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("remainder: DOMAIN error\n", 24);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 29:
+ case 129:
+ /* acosh(x<1) */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "acosh" : "acoshf";
+ exc.retval = zero/zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("acosh: DOMAIN error\n", 20);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 30:
+ case 130:
+ /* atanh(|x|>1) */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "atanh" : "atanhf";
+ exc.retval = zero/zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("atanh: DOMAIN error\n", 20);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 31:
+ case 131:
+ /* atanh(|x|=1) */
+ exc.type = SING;
+ exc.name = type < 100 ? "atanh" : "atanhf";
+ exc.retval = x/zero; /* sign(x)*inf */
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("atanh: SING error\n", 18);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 32:
+ case 132:
+ /* scalb overflow; SVID also returns +-HUGE_VAL */
+ exc.type = OVERFLOW;
+ exc.name = type < 100 ? "scalb" : "scalbf";
+ exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ break;
+ case 33:
+ case 133:
+ /* scalb underflow */
+ exc.type = UNDERFLOW;
+ exc.name = type < 100 ? "scalb" : "scalbf";
+ exc.retval = copysign(zero,x);
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ break;
+ case 34:
+ case 134:
+ /* j0(|x|>X_TLOSS) */
+ exc.type = TLOSS;
+ exc.name = type < 100 ? "j0" : "j0f";
+ exc.retval = zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2(exc.name, 2);
+ (void) WRITE2(": TLOSS error\n", 14);
+ }
+ errno = ERANGE;
+ }
+ break;
+ case 35:
+ case 135:
+ /* y0(x>X_TLOSS) */
+ exc.type = TLOSS;
+ exc.name = type < 100 ? "y0" : "y0f";
+ exc.retval = zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2(exc.name, 2);
+ (void) WRITE2(": TLOSS error\n", 14);
+ }
+ errno = ERANGE;
+ }
+ break;
+ case 36:
+ case 136:
+ /* j1(|x|>X_TLOSS) */
+ exc.type = TLOSS;
+ exc.name = type < 100 ? "j1" : "j1f";
+ exc.retval = zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2(exc.name, 2);
+ (void) WRITE2(": TLOSS error\n", 14);
+ }
+ errno = ERANGE;
+ }
+ break;
+ case 37:
+ case 137:
+ /* y1(x>X_TLOSS) */
+ exc.type = TLOSS;
+ exc.name = type < 100 ? "y1" : "y1f";
+ exc.retval = zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2(exc.name, 2);
+ (void) WRITE2(": TLOSS error\n", 14);
+ }
+ errno = ERANGE;
+ }
+ break;
+ case 38:
+ case 138:
+ /* jn(|x|>X_TLOSS) */
+ exc.type = TLOSS;
+ exc.name = type < 100 ? "jn" : "jnf";
+ exc.retval = zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2(exc.name, 2);
+ (void) WRITE2(": TLOSS error\n", 14);
+ }
+ errno = ERANGE;
+ }
+ break;
+ case 39:
+ case 139:
+ /* yn(x>X_TLOSS) */
+ exc.type = TLOSS;
+ exc.name = type < 100 ? "yn" : "ynf";
+ exc.retval = zero;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2(exc.name, 2);
+ (void) WRITE2(": TLOSS error\n", 14);
+ }
+ errno = ERANGE;
+ }
+ break;
+ case 40:
+ case 140:
+ /* gamma(finite) overflow */
+ exc.type = OVERFLOW;
+ exc.name = type < 100 ? "gamma" : "gammaf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = HUGE;
+ else
+ exc.retval = HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = ERANGE;
+ else if (!matherr(&exc)) {
+ errno = ERANGE;
+ }
+ break;
+ case 41:
+ case 141:
+ /* gamma(-integer) or gamma(0) */
+ exc.type = SING;
+ exc.name = type < 100 ? "gamma" : "gammaf";
+ if (_LIB_VERSION == _SVID_)
+ exc.retval = HUGE;
+ else
+ exc.retval = HUGE_VAL;
+ if (_LIB_VERSION == _POSIX_)
+ errno = EDOM;
+ else if (!matherr(&exc)) {
+ if (_LIB_VERSION == _SVID_) {
+ (void) WRITE2("gamma: SING error\n", 18);
+ }
+ errno = EDOM;
+ }
+ break;
+ case 42:
+ case 142:
+ /* pow(NaN,0.0) */
+ /* error only if _LIB_VERSION == _SVID_ & _XOPEN_ */
+ exc.type = DOMAIN;
+ exc.name = type < 100 ? "pow" : "powf";
+ exc.retval = x;
+ if (_LIB_VERSION == _IEEE_ ||
+ _LIB_VERSION == _POSIX_) exc.retval = 1.0;
+ else if (!matherr(&exc)) {
+ errno = EDOM;
+ }
+ break;
+ }
+ return exc.retval;
+}
diff --git a/lib/msun/src/k_tan.c b/lib/msun/src/k_tan.c
new file mode 100644
index 0000000..00ea9a4
--- /dev/null
+++ b/lib/msun/src/k_tan.c
@@ -0,0 +1,131 @@
+/* @(#)k_tan.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* __kernel_tan( x, y, k )
+ * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input k indicates whether tan (if k=1) or
+ * -1/tan (if k= -1) is returned.
+ *
+ * Algorithm
+ * 1. Since tan(-x) = -tan(x), we need only to consider positive x.
+ * 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
+ * 3. tan(x) is approximated by a odd polynomial of degree 27 on
+ * [0,0.67434]
+ * 3 27
+ * tan(x) ~ x + T1*x + ... + T13*x
+ * where
+ *
+ * |tan(x) 2 4 26 | -59.2
+ * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2
+ * | x |
+ *
+ * Note: tan(x+y) = tan(x) + tan'(x)*y
+ * ~ tan(x) + (1+x*x)*y
+ * Therefore, for better accuracy in computing tan(x+y), let
+ * 3 2 2 2 2
+ * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
+ * then
+ * 3 2
+ * tan(x+y) = x + (T1*x + (x *(r+y)+y))
+ *
+ * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then
+ * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
+ * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
+ */
+
+#include "math.h"
+#include "math_private.h"
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
+pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */
+T[] = {
+ 3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */
+ 1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */
+ 5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */
+ 2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */
+ 8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */
+ 3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */
+ 1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */
+ 5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */
+ 2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */
+ 7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */
+ 7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */
+ -1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */
+ 2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */
+};
+
+#ifdef __STDC__
+ double __kernel_tan(double x, double y, int iy)
+#else
+ double __kernel_tan(x, y, iy)
+ double x,y; int iy;
+#endif
+{
+ double z,r,v,w,s;
+ int32_t ix,hx;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff; /* high word of |x| */
+ if(ix<0x3e300000) /* x < 2**-28 */
+ {if((int)x==0) { /* generate inexact */
+ u_int32_t low;
+ GET_LOW_WORD(low,x);
+ if(((ix|low)|(iy+1))==0) return one/fabs(x);
+ else return (iy==1)? x: -one/x;
+ }
+ }
+ if(ix>=0x3FE59428) { /* |x|>=0.6744 */
+ if(hx<0) {x = -x; y = -y;}
+ z = pio4-x;
+ w = pio4lo-y;
+ x = z+w; y = 0.0;
+ }
+ z = x*x;
+ w = z*z;
+ /* Break x^5*(T[1]+x^2*T[2]+...) into
+ * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
+ * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
+ */
+ r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
+ v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
+ s = z*x;
+ r = y + z*(s*(r+v)+y);
+ r += T[0]*s;
+ w = x+r;
+ if(ix>=0x3FE59428) {
+ v = (double)iy;
+ return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r)));
+ }
+ if(iy==1) return w;
+ else { /* if allow error up to 2 ulp,
+ simply return -1.0/(x+r) here */
+ /* compute -1.0/(x+r) accurately */
+ double a,t;
+ z = w;
+ SET_LOW_WORD(z,0);
+ v = r-(z - x); /* z+v = r+x */
+ t = a = -1.0/w; /* a = -1.0/w */
+ SET_LOW_WORD(t,0);
+ s = 1.0+t*z;
+ return t+a*(s+t*v);
+ }
+}
diff --git a/lib/msun/src/k_tanf.c b/lib/msun/src/k_tanf.c
new file mode 100644
index 0000000..ad585f6
--- /dev/null
+++ b/lib/msun/src/k_tanf.c
@@ -0,0 +1,101 @@
+/* k_tanf.c -- float version of k_tan.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+one = 1.0000000000e+00, /* 0x3f800000 */
+pio4 = 7.8539812565e-01, /* 0x3f490fda */
+pio4lo= 3.7748947079e-08, /* 0x33222168 */
+T[] = {
+ 3.3333334327e-01, /* 0x3eaaaaab */
+ 1.3333334029e-01, /* 0x3e088889 */
+ 5.3968254477e-02, /* 0x3d5d0dd1 */
+ 2.1869488060e-02, /* 0x3cb327a4 */
+ 8.8632395491e-03, /* 0x3c11371f */
+ 3.5920790397e-03, /* 0x3b6b6916 */
+ 1.4562094584e-03, /* 0x3abede48 */
+ 5.8804126456e-04, /* 0x3a1a26c8 */
+ 2.4646313977e-04, /* 0x398137b9 */
+ 7.8179444245e-05, /* 0x38a3f445 */
+ 7.1407252108e-05, /* 0x3895c07a */
+ -1.8558637748e-05, /* 0xb79bae5f */
+ 2.5907305826e-05, /* 0x37d95384 */
+};
+
+#ifdef __STDC__
+ float __kernel_tanf(float x, float y, int iy)
+#else
+ float __kernel_tanf(x, y, iy)
+ float x,y; int iy;
+#endif
+{
+ float z,r,v,w,s;
+ int32_t ix,hx;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff; /* high word of |x| */
+ if(ix<0x31800000) /* x < 2**-28 */
+ {if((int)x==0) { /* generate inexact */
+ if((ix|(iy+1))==0) return one/fabsf(x);
+ else return (iy==1)? x: -one/x;
+ }
+ }
+ if(ix>=0x3f2ca140) { /* |x|>=0.6744 */
+ if(hx<0) {x = -x; y = -y;}
+ z = pio4-x;
+ w = pio4lo-y;
+ x = z+w; y = 0.0;
+ }
+ z = x*x;
+ w = z*z;
+ /* Break x^5*(T[1]+x^2*T[2]+...) into
+ * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
+ * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
+ */
+ r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
+ v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
+ s = z*x;
+ r = y + z*(s*(r+v)+y);
+ r += T[0]*s;
+ w = x+r;
+ if(ix>=0x3f2ca140) {
+ v = (float)iy;
+ return (float)(1-((hx>>30)&2))*(v-(float)2.0*(x-(w*w/(w+v)-r)));
+ }
+ if(iy==1) return w;
+ else { /* if allow error up to 2 ulp,
+ simply return -1.0/(x+r) here */
+ /* compute -1.0/(x+r) accurately */
+ float a,t;
+ int32_t i;
+ z = w;
+ GET_FLOAT_WORD(i,z);
+ SET_FLOAT_WORD(z,i&0xfffff000);
+ v = r-(z - x); /* z+v = r+x */
+ t = a = -(float)1.0/w; /* a = -1.0/w */
+ GET_FLOAT_WORD(i,t);
+ SET_FLOAT_WORD(t,i&0xfffff000);
+ s = (float)1.0+t*z;
+ return t+a*(s+t*v);
+ }
+}
diff --git a/lib/msun/src/math.h b/lib/msun/src/math.h
new file mode 100644
index 0000000..6282b10
--- /dev/null
+++ b/lib/msun/src/math.h
@@ -0,0 +1,273 @@
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+/*
+ * from: @(#)fdlibm.h 5.1 93/09/24
+ * $Id$
+ */
+
+#ifndef _MATH_H_
+#define _MATH_H_
+
+/*
+ * ANSI/POSIX
+ */
+extern char __infinity[];
+#define HUGE_VAL (*(double *) __infinity)
+
+/*
+ * XOPEN/SVID
+ */
+#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
+#define M_E 2.7182818284590452354 /* e */
+#define M_LOG2E 1.4426950408889634074 /* log 2e */
+#define M_LOG10E 0.43429448190325182765 /* log 10e */
+#define M_LN2 0.69314718055994530942 /* log e2 */
+#define M_LN10 2.30258509299404568402 /* log e10 */
+#define M_PI 3.14159265358979323846 /* pi */
+#define M_PI_2 1.57079632679489661923 /* pi/2 */
+#define M_PI_4 0.78539816339744830962 /* pi/4 */
+#define M_1_PI 0.31830988618379067154 /* 1/pi */
+#define M_2_PI 0.63661977236758134308 /* 2/pi */
+#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
+#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
+#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
+
+#define MAXFLOAT ((float)3.40282346638528860e+38)
+extern int signgam;
+
+#if !defined(_XOPEN_SOURCE)
+enum fdversion {fdlibm_ieee = -1, fdlibm_svid, fdlibm_xopen, fdlibm_posix};
+
+#define _LIB_VERSION_TYPE enum fdversion
+#define _LIB_VERSION _fdlib_version
+
+/* if global variable _LIB_VERSION is not desirable, one may
+ * change the following to be a constant by:
+ * #define _LIB_VERSION_TYPE const enum version
+ * In that case, after one initializes the value _LIB_VERSION (see
+ * s_lib_version.c) during compile time, it cannot be modified
+ * in the middle of a program
+ */
+extern _LIB_VERSION_TYPE _LIB_VERSION;
+
+#define _IEEE_ fdlibm_ieee
+#define _SVID_ fdlibm_svid
+#define _XOPEN_ fdlibm_xopen
+#define _POSIX_ fdlibm_posix
+
+struct exception {
+ int type;
+ char *name;
+ double arg1;
+ double arg2;
+ double retval;
+};
+
+#define HUGE MAXFLOAT
+
+/*
+ * set X_TLOSS = pi*2**52, which is possibly defined in <values.h>
+ * (one may replace the following line by "#include <values.h>")
+ */
+
+#define X_TLOSS 1.41484755040568800000e+16
+
+#define DOMAIN 1
+#define SING 2
+#define OVERFLOW 3
+#define UNDERFLOW 4
+#define TLOSS 5
+#define PLOSS 6
+
+#endif /* !_XOPEN_SOURCE */
+#endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */
+
+
+#include <sys/cdefs.h>
+__BEGIN_DECLS
+/*
+ * ANSI/POSIX
+ */
+extern double acos __P((double));
+extern double asin __P((double));
+extern double atan __P((double));
+extern double atan2 __P((double, double));
+extern double cos __P((double));
+extern double sin __P((double));
+extern double tan __P((double));
+
+extern double cosh __P((double));
+extern double sinh __P((double));
+extern double tanh __P((double));
+
+extern double exp __P((double));
+extern double frexp __P((double, int *));
+extern double ldexp __P((double, int));
+extern double log __P((double));
+extern double log10 __P((double));
+extern double modf __P((double, double *));
+
+extern double pow __P((double, double));
+extern double sqrt __P((double));
+
+extern double ceil __P((double));
+extern double fabs __P((double));
+extern double floor __P((double));
+extern double fmod __P((double, double));
+
+#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
+extern double erf __P((double));
+extern double erfc __P((double));
+extern double gamma __P((double));
+extern double hypot __P((double, double));
+extern int isinf __P((double));
+extern int isnan __P((double));
+extern int finite __P((double));
+extern double j0 __P((double));
+extern double j1 __P((double));
+extern double jn __P((int, double));
+extern double lgamma __P((double));
+extern double y0 __P((double));
+extern double y1 __P((double));
+extern double yn __P((int, double));
+
+#if !defined(_XOPEN_SOURCE)
+extern double acosh __P((double));
+extern double asinh __P((double));
+extern double atanh __P((double));
+extern double cbrt __P((double));
+extern double logb __P((double));
+extern double nextafter __P((double, double));
+extern double remainder __P((double, double));
+extern double scalb __P((double, double));
+
+extern int matherr __P((struct exception *));
+
+/*
+ * IEEE Test Vector
+ */
+extern double significand __P((double));
+
+/*
+ * Functions callable from C, intended to support IEEE arithmetic.
+ */
+extern double copysign __P((double, double));
+extern int ilogb __P((double));
+extern double rint __P((double));
+extern double scalbn __P((double, int));
+
+/*
+ * BSD math library entry points
+ */
+extern double cabs();
+extern double drem __P((double, double));
+extern double expm1 __P((double));
+extern double log1p __P((double));
+
+/*
+ * Reentrant version of gamma & lgamma; passes signgam back by reference
+ * as the second argument; user must allocate space for signgam.
+ */
+#ifdef _REENTRANT
+extern double gamma_r __P((double, int *));
+extern double lgamma_r __P((double, int *));
+#endif /* _REENTRANT */
+
+
+/* float versions of ANSI/POSIX functions */
+extern float acosf __P((float));
+extern float asinf __P((float));
+extern float atanf __P((float));
+extern float atan2f __P((float, float));
+extern float cosf __P((float));
+extern float sinf __P((float));
+extern float tanf __P((float));
+
+extern float coshf __P((float));
+extern float sinhf __P((float));
+extern float tanhf __P((float));
+
+extern float expf __P((float));
+extern float frexpf __P((float, int *));
+extern float ldexpf __P((float, int));
+extern float logf __P((float));
+extern float log10f __P((float));
+extern float modff __P((float, float *));
+
+extern float powf __P((float, float));
+extern float sqrtf __P((float));
+
+extern float ceilf __P((float));
+extern float fabsf __P((float));
+extern float floorf __P((float));
+extern float fmodf __P((float, float));
+
+extern float erff __P((float));
+extern float erfcf __P((float));
+extern float gammaf __P((float));
+extern float hypotf __P((float, float));
+extern int isnanf __P((float));
+extern int finitef __P((float));
+extern float j0f __P((float));
+extern float j1f __P((float));
+extern float jnf __P((int, float));
+extern float lgammaf __P((float));
+extern float y0f __P((float));
+extern float y1f __P((float));
+extern float ynf __P((int, float));
+
+extern float acoshf __P((float));
+extern float asinhf __P((float));
+extern float atanhf __P((float));
+extern float cbrtf __P((float));
+extern float logbf __P((float));
+extern float nextafterf __P((float, float));
+extern float remainderf __P((float, float));
+extern float scalbf __P((float, float));
+
+/*
+ * float version of IEEE Test Vector
+ */
+extern float significandf __P((float));
+
+/*
+ * Float versions of functions callable from C, intended to support
+ * IEEE arithmetic.
+ */
+extern float copysignf __P((float, float));
+extern int ilogbf __P((float));
+extern float rintf __P((float));
+extern float scalbnf __P((float, int));
+
+/*
+ * float versions of BSD math library entry points
+ */
+extern float cabsf ();
+extern float dremf __P((float, float));
+extern float expm1f __P((float));
+extern float log1pf __P((float));
+
+/*
+ * Float versions of reentrant version of gamma & lgamma; passes
+ * signgam back by reference as the second argument; user must
+ * allocate space for signgam.
+ */
+#ifdef _REENTRANT
+extern float gammaf_r __P((float, int *));
+extern float lgammaf_r __P((float, int *));
+#endif /* _REENTRANT */
+
+#endif /* !_XOPEN_SOURCE */
+#endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */
+__END_DECLS
+
+#endif /* _MATH_H_ */
diff --git a/lib/msun/src/math_private.h b/lib/msun/src/math_private.h
new file mode 100644
index 0000000..1d93957
--- /dev/null
+++ b/lib/msun/src/math_private.h
@@ -0,0 +1,223 @@
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+/*
+ * from: @(#)fdlibm.h 5.1 93/09/24
+ * $Id$
+ */
+
+#ifndef _MATH_PRIVATE_H_
+#define _MATH_PRIVATE_H_
+
+#include <machine/endian.h>
+#include <sys/types.h>
+
+/* The original fdlibm code used statements like:
+ n0 = ((*(int*)&one)>>29)^1; * index of high word *
+ ix0 = *(n0+(int*)&x); * high word of x *
+ ix1 = *((1-n0)+(int*)&x); * low word of x *
+ to dig two 32 bit words out of the 64 bit IEEE floating point
+ value. That is non-ANSI, and, moreover, the gcc instruction
+ scheduler gets it wrong. We instead use the following macros.
+ Unlike the original code, we determine the endianness at compile
+ time, not at run time; I don't see much benefit to selecting
+ endianness at run time. */
+
+/* A union which permits us to convert between a double and two 32 bit
+ ints. */
+
+#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)
+
+/* Get the less significant 32 bit int from a double. */
+
+#define GET_LOW_WORD(i,d) \
+do { \
+ ieee_double_shape_type gl_u; \
+ gl_u.value = (d); \
+ (i) = gl_u.parts.lsw; \
+} 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)
+
+/* 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)
+
+/* Set the less significant 32 bits of a double from an int. */
+
+#define SET_LOW_WORD(d,v) \
+do { \
+ ieee_double_shape_type sl_u; \
+ sl_u.value = (d); \
+ sl_u.parts.lsw = (v); \
+ (d) = sl_u.value; \
+} while (0)
+
+/* A union which permits us to convert between a float and a 32 bit
+ int. */
+
+typedef union
+{
+ float value;
+ /* FIXME: Assumes 32 bit int. */
+ unsigned int word;
+} ieee_float_shape_type;
+
+/* Get a 32 bit int from a float. */
+
+#define GET_FLOAT_WORD(i,d) \
+do { \
+ ieee_float_shape_type gf_u; \
+ gf_u.value = (d); \
+ (i) = gf_u.word; \
+} while (0)
+
+/* Set a float from a 32 bit int. */
+
+#define SET_FLOAT_WORD(d,i) \
+do { \
+ ieee_float_shape_type sf_u; \
+ sf_u.word = (i); \
+ (d) = sf_u.value; \
+} while (0)
+
+/* ieee style elementary functions */
+extern double __ieee754_sqrt __P((double));
+extern double __ieee754_acos __P((double));
+extern double __ieee754_acosh __P((double));
+extern double __ieee754_log __P((double));
+extern double __ieee754_atanh __P((double));
+extern double __ieee754_asin __P((double));
+extern double __ieee754_atan2 __P((double,double));
+extern double __ieee754_exp __P((double));
+extern double __ieee754_cosh __P((double));
+extern double __ieee754_fmod __P((double,double));
+extern double __ieee754_pow __P((double,double));
+extern double __ieee754_lgamma_r __P((double,int *));
+extern double __ieee754_gamma_r __P((double,int *));
+extern double __ieee754_lgamma __P((double));
+extern double __ieee754_gamma __P((double));
+extern double __ieee754_log10 __P((double));
+extern double __ieee754_sinh __P((double));
+extern double __ieee754_hypot __P((double,double));
+extern double __ieee754_j0 __P((double));
+extern double __ieee754_j1 __P((double));
+extern double __ieee754_y0 __P((double));
+extern double __ieee754_y1 __P((double));
+extern double __ieee754_jn __P((int,double));
+extern double __ieee754_yn __P((int,double));
+extern double __ieee754_remainder __P((double,double));
+extern int __ieee754_rem_pio2 __P((double,double*));
+extern double __ieee754_scalb __P((double,double));
+
+/* fdlibm kernel function */
+extern double __kernel_standard __P((double,double,int));
+extern double __kernel_sin __P((double,double,int));
+extern double __kernel_cos __P((double,double));
+extern double __kernel_tan __P((double,double,int));
+extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const int*));
+
+
+/* ieee style elementary float functions */
+extern float __ieee754_sqrtf __P((float));
+extern float __ieee754_acosf __P((float));
+extern float __ieee754_acoshf __P((float));
+extern float __ieee754_logf __P((float));
+extern float __ieee754_atanhf __P((float));
+extern float __ieee754_asinf __P((float));
+extern float __ieee754_atan2f __P((float,float));
+extern float __ieee754_expf __P((float));
+extern float __ieee754_coshf __P((float));
+extern float __ieee754_fmodf __P((float,float));
+extern float __ieee754_powf __P((float,float));
+extern float __ieee754_lgammaf_r __P((float,int *));
+extern float __ieee754_gammaf_r __P((float,int *));
+extern float __ieee754_lgammaf __P((float));
+extern float __ieee754_gammaf __P((float));
+extern float __ieee754_log10f __P((float));
+extern float __ieee754_sinhf __P((float));
+extern float __ieee754_hypotf __P((float,float));
+extern float __ieee754_j0f __P((float));
+extern float __ieee754_j1f __P((float));
+extern float __ieee754_y0f __P((float));
+extern float __ieee754_y1f __P((float));
+extern float __ieee754_jnf __P((int,float));
+extern float __ieee754_ynf __P((int,float));
+extern float __ieee754_remainderf __P((float,float));
+extern int __ieee754_rem_pio2f __P((float,float*));
+extern float __ieee754_scalbf __P((float,float));
+
+/* float versions of fdlibm kernel functions */
+extern float __kernel_sinf __P((float,float,int));
+extern float __kernel_cosf __P((float,float));
+extern float __kernel_tanf __P((float,float,int));
+extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const int*));
+
+#endif /* _MATH_PRIVATE_H_ */
diff --git a/lib/msun/src/s_asinh.c b/lib/msun/src/s_asinh.c
new file mode 100644
index 0000000..9276327
--- /dev/null
+++ b/lib/msun/src/s_asinh.c
@@ -0,0 +1,65 @@
+/* @(#)s_asinh.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: s_asinh.c,v 1.4 1997/02/22 15:10:56 peter Exp $";
+#endif
+
+/* asinh(x)
+ * Method :
+ * Based on
+ * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
+ * we have
+ * asinh(x) := x if 1+x*x=1,
+ * := sign(x)*(log(x)+ln2)) for large |x|, else
+ * := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
+ * := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+huge= 1.00000000000000000000e+300;
+
+#ifdef __STDC__
+ double asinh(double x)
+#else
+ double asinh(x)
+ double x;
+#endif
+{
+ double t,w;
+ int32_t hx,ix;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) return x+x; /* x is inf or NaN */
+ if(ix< 0x3e300000) { /* |x|<2**-28 */
+ if(huge+x>one) return x; /* return x inexact except 0 */
+ }
+ if(ix>0x41b00000) { /* |x| > 2**28 */
+ w = __ieee754_log(fabs(x))+ln2;
+ } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */
+ t = fabs(x);
+ w = __ieee754_log(2.0*t+one/(__ieee754_sqrt(x*x+one)+t));
+ } else { /* 2.0 > |x| > 2**-28 */
+ t = x*x;
+ w =log1p(fabs(x)+t/(one+__ieee754_sqrt(one+t)));
+ }
+ if(hx>0) return w; else return -w;
+}
diff --git a/lib/msun/src/s_asinhf.c b/lib/msun/src/s_asinhf.c
new file mode 100644
index 0000000..b14db85
--- /dev/null
+++ b/lib/msun/src/s_asinhf.c
@@ -0,0 +1,57 @@
+/* s_asinhf.c -- float version of s_asinh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: s_asinhf.c,v 1.4 1997/02/22 15:10:57 peter Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+one = 1.0000000000e+00, /* 0x3F800000 */
+ln2 = 6.9314718246e-01, /* 0x3f317218 */
+huge= 1.0000000000e+30;
+
+#ifdef __STDC__
+ float asinhf(float x)
+#else
+ float asinhf(x)
+ float x;
+#endif
+{
+ float t,w;
+ int32_t hx,ix;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) return x+x; /* x is inf or NaN */
+ if(ix< 0x31800000) { /* |x|<2**-28 */
+ if(huge+x>one) return x; /* return x inexact except 0 */
+ }
+ if(ix>0x4d800000) { /* |x| > 2**28 */
+ w = __ieee754_logf(fabsf(x))+ln2;
+ } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */
+ t = fabsf(x);
+ w = __ieee754_logf((float)2.0*t+one/(__ieee754_sqrtf(x*x+one)+t));
+ } else { /* 2.0 > |x| > 2**-28 */
+ t = x*x;
+ w =log1pf(fabsf(x)+t/(one+__ieee754_sqrtf(one+t)));
+ }
+ if(hx>0) return w; else return -w;
+}
diff --git a/lib/msun/src/s_atan.c b/lib/msun/src/s_atan.c
new file mode 100644
index 0000000..40e3de9
--- /dev/null
+++ b/lib/msun/src/s_atan.c
@@ -0,0 +1,139 @@
+/* @(#)s_atan.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* atan(x)
+ * Method
+ * 1. Reduce x to positive by atan(x) = -atan(-x).
+ * 2. According to the integer k=4t+0.25 chopped, t=x, the argument
+ * is further reduced to one of the following intervals and the
+ * arctangent of t is evaluated by the corresponding formula:
+ *
+ * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
+ * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) )
+ * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) )
+ * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) )
+ * [39/16,INF] atan(x) = atan(INF) + atan( -1/t )
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double atanhi[] = {
+#else
+static double atanhi[] = {
+#endif
+ 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
+ 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
+ 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
+ 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
+};
+
+#ifdef __STDC__
+static const double atanlo[] = {
+#else
+static double atanlo[] = {
+#endif
+ 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
+ 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
+ 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
+ 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
+};
+
+#ifdef __STDC__
+static const double aT[] = {
+#else
+static double aT[] = {
+#endif
+ 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
+ -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
+ 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
+ -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
+ 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */
+ -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
+ 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */
+ -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
+ 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */
+ -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
+ 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
+};
+
+#ifdef __STDC__
+ static const double
+#else
+ static double
+#endif
+one = 1.0,
+huge = 1.0e300;
+
+#ifdef __STDC__
+ double __generic_atan(double x)
+#else
+ double __generic_atan(x)
+ double x;
+#endif
+{
+ double w,s1,s2,z;
+ int32_t ix,hx,id;
+
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x44100000) { /* if |x| >= 2^66 */
+ u_int32_t low;
+ GET_LOW_WORD(low,x);
+ if(ix>0x7ff00000||
+ (ix==0x7ff00000&&(low!=0)))
+ return x+x; /* NaN */
+ if(hx>0) return atanhi[3]+atanlo[3];
+ else return -atanhi[3]-atanlo[3];
+ } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */
+ if (ix < 0x3e200000) { /* |x| < 2^-29 */
+ if(huge+x>one) return x; /* raise inexact */
+ }
+ id = -1;
+ } else {
+ x = fabs(x);
+ if (ix < 0x3ff30000) { /* |x| < 1.1875 */
+ if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */
+ id = 0; x = (2.0*x-one)/(2.0+x);
+ } else { /* 11/16<=|x|< 19/16 */
+ id = 1; x = (x-one)/(x+one);
+ }
+ } else {
+ if (ix < 0x40038000) { /* |x| < 2.4375 */
+ id = 2; x = (x-1.5)/(one+1.5*x);
+ } else { /* 2.4375 <= |x| < 2^66 */
+ id = 3; x = -1.0/x;
+ }
+ }}
+ /* end of argument reduction */
+ z = x*x;
+ w = z*z;
+ /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+ s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
+ s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
+ if (id<0) return x - x*(s1+s2);
+ else {
+ z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
+ return (hx<0)? -z:z;
+ }
+}
diff --git a/lib/msun/src/s_atanf.c b/lib/msun/src/s_atanf.c
new file mode 100644
index 0000000..f8e103d
--- /dev/null
+++ b/lib/msun/src/s_atanf.c
@@ -0,0 +1,119 @@
+/* s_atanf.c -- float version of s_atan.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float atanhi[] = {
+#else
+static float atanhi[] = {
+#endif
+ 4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */
+ 7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */
+ 9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */
+ 1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */
+};
+
+#ifdef __STDC__
+static const float atanlo[] = {
+#else
+static float atanlo[] = {
+#endif
+ 5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */
+ 3.7748947079e-08, /* atan(1.0)lo 0x33222168 */
+ 3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */
+ 7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
+};
+
+#ifdef __STDC__
+static const float aT[] = {
+#else
+static float aT[] = {
+#endif
+ 3.3333334327e-01, /* 0x3eaaaaaa */
+ -2.0000000298e-01, /* 0xbe4ccccd */
+ 1.4285714924e-01, /* 0x3e124925 */
+ -1.1111110449e-01, /* 0xbde38e38 */
+ 9.0908870101e-02, /* 0x3dba2e6e */
+ -7.6918758452e-02, /* 0xbd9d8795 */
+ 6.6610731184e-02, /* 0x3d886b35 */
+ -5.8335702866e-02, /* 0xbd6ef16b */
+ 4.9768779427e-02, /* 0x3d4bda59 */
+ -3.6531571299e-02, /* 0xbd15a221 */
+ 1.6285819933e-02, /* 0x3c8569d7 */
+};
+
+#ifdef __STDC__
+ static const float
+#else
+ static float
+#endif
+one = 1.0,
+huge = 1.0e30;
+
+#ifdef __STDC__
+ float atanf(float x)
+#else
+ float atanf(x)
+ float x;
+#endif
+{
+ float w,s1,s2,z;
+ int32_t ix,hx,id;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x50800000) { /* if |x| >= 2^34 */
+ if(ix>0x7f800000)
+ return x+x; /* NaN */
+ if(hx>0) return atanhi[3]+atanlo[3];
+ else return -atanhi[3]-atanlo[3];
+ } if (ix < 0x3ee00000) { /* |x| < 0.4375 */
+ if (ix < 0x31000000) { /* |x| < 2^-29 */
+ if(huge+x>one) return x; /* raise inexact */
+ }
+ id = -1;
+ } else {
+ x = fabsf(x);
+ if (ix < 0x3f980000) { /* |x| < 1.1875 */
+ if (ix < 0x3f300000) { /* 7/16 <=|x|<11/16 */
+ id = 0; x = ((float)2.0*x-one)/((float)2.0+x);
+ } else { /* 11/16<=|x|< 19/16 */
+ id = 1; x = (x-one)/(x+one);
+ }
+ } else {
+ if (ix < 0x401c0000) { /* |x| < 2.4375 */
+ id = 2; x = (x-(float)1.5)/(one+(float)1.5*x);
+ } else { /* 2.4375 <= |x| < 2^66 */
+ id = 3; x = -(float)1.0/x;
+ }
+ }}
+ /* end of argument reduction */
+ z = x*x;
+ w = z*z;
+ /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+ s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
+ s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
+ if (id<0) return x - x*(s1+s2);
+ else {
+ z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
+ return (hx<0)? -z:z;
+ }
+}
diff --git a/lib/msun/src/s_cbrt.c b/lib/msun/src/s_cbrt.c
new file mode 100644
index 0000000..09f8d08
--- /dev/null
+++ b/lib/msun/src/s_cbrt.c
@@ -0,0 +1,93 @@
+/* @(#)s_cbrt.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+/* cbrt(x)
+ * Return cube root of x
+ */
+#ifdef __STDC__
+static const u_int32_t
+#else
+static u_int32_t
+#endif
+ B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */
+ B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+C = 5.42857142857142815906e-01, /* 19/35 = 0x3FE15F15, 0xF15F15F1 */
+D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */
+E = 1.41428571428571436819e+00, /* 99/70 = 0x3FF6A0EA, 0x0EA0EA0F */
+F = 1.60714285714285720630e+00, /* 45/28 = 0x3FF9B6DB, 0x6DB6DB6E */
+G = 3.57142857142857150787e-01; /* 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 */
+
+#ifdef __STDC__
+ double cbrt(double x)
+#else
+ double cbrt(x)
+ double x;
+#endif
+{
+ int32_t hx;
+ double r,s,t=0.0,w;
+ u_int32_t sign;
+ u_int32_t high,low;
+
+ GET_HIGH_WORD(hx,x);
+ sign=hx&0x80000000; /* sign= sign(x) */
+ hx ^=sign;
+ if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */
+ GET_LOW_WORD(low,x);
+ if((hx|low)==0)
+ return(x); /* cbrt(0) is itself */
+
+ SET_HIGH_WORD(x,hx); /* x <- |x| */
+ /* rough cbrt to 5 bits */
+ if(hx<0x00100000) /* subnormal number */
+ {SET_HIGH_WORD(t,0x43500000); /* set t= 2**54 */
+ t*=x; GET_HIGH_WORD(high,t); SET_HIGH_WORD(t,high/3+B2);
+ }
+ else
+ SET_HIGH_WORD(t,hx/3+B1);
+
+
+ /* new cbrt to 23 bits, may be implemented in single precision */
+ r=t*t/x;
+ s=C+r*t;
+ t*=G+F/(s+E+D/s);
+
+ /* chopped to 20 bits and make it larger than cbrt(x) */
+ GET_HIGH_WORD(high,t);
+ INSERT_WORDS(t,high+0x00000001,0);
+
+
+ /* one step newton iteration to 53 bits with error less than 0.667 ulps */
+ s=t*t; /* t*t is exact */
+ r=x/s;
+ w=t+t;
+ r=(r-t)/(w+r); /* r-s is exact */
+ t=t+t*r;
+
+ /* retore the sign bit */
+ GET_HIGH_WORD(high,t);
+ SET_HIGH_WORD(t,high|sign);
+ return(t);
+}
diff --git a/lib/msun/src/s_cbrtf.c b/lib/msun/src/s_cbrtf.c
new file mode 100644
index 0000000..8bb1b89
--- /dev/null
+++ b/lib/msun/src/s_cbrtf.c
@@ -0,0 +1,83 @@
+/* s_cbrtf.c -- float version of s_cbrt.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+/* cbrtf(x)
+ * Return cube root of x
+ */
+#ifdef __STDC__
+static const unsigned
+#else
+static unsigned
+#endif
+ B1 = 709958130, /* B1 = (84+2/3-0.03306235651)*2**23 */
+ B2 = 642849266; /* B2 = (76+2/3-0.03306235651)*2**23 */
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+C = 5.4285717010e-01, /* 19/35 = 0x3f0af8b0 */
+D = -7.0530611277e-01, /* -864/1225 = 0xbf348ef1 */
+E = 1.4142856598e+00, /* 99/70 = 0x3fb50750 */
+F = 1.6071428061e+00, /* 45/28 = 0x3fcdb6db */
+G = 3.5714286566e-01; /* 5/14 = 0x3eb6db6e */
+
+#ifdef __STDC__
+ float cbrtf(float x)
+#else
+ float cbrtf(x)
+ float x;
+#endif
+{
+ float r,s,t;
+ int32_t hx;
+ u_int32_t sign;
+ u_int32_t high;
+
+ GET_FLOAT_WORD(hx,x);
+ sign=hx&0x80000000; /* sign= sign(x) */
+ hx ^=sign;
+ if(hx>=0x7f800000) return(x+x); /* cbrt(NaN,INF) is itself */
+ if(hx==0)
+ return(x); /* cbrt(0) is itself */
+
+ SET_FLOAT_WORD(x,hx); /* x <- |x| */
+ /* rough cbrt to 5 bits */
+ if(hx<0x00800000) /* subnormal number */
+ {SET_FLOAT_WORD(t,0x4b800000); /* set t= 2**24 */
+ t*=x; GET_FLOAT_WORD(high,t); SET_FLOAT_WORD(t,high/3+B2);
+ }
+ else
+ SET_FLOAT_WORD(t,hx/3+B1);
+
+
+ /* new cbrt to 23 bits */
+ r=t*t/x;
+ s=C+r*t;
+ t*=G+F/(s+E+D/s);
+
+ /* retore the sign bit */
+ GET_FLOAT_WORD(high,t);
+ SET_FLOAT_WORD(t,high|sign);
+ return(t);
+}
diff --git a/lib/msun/src/s_ceil.c b/lib/msun/src/s_ceil.c
new file mode 100644
index 0000000..2fc9bcc
--- /dev/null
+++ b/lib/msun/src/s_ceil.c
@@ -0,0 +1,80 @@
+/* @(#)s_ceil.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * ceil(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to ceil(x).
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double huge = 1.0e300;
+#else
+static double huge = 1.0e300;
+#endif
+
+#ifdef __STDC__
+ double __generic_ceil(double x)
+#else
+ double __generic_ceil(x)
+ double x;
+#endif
+{
+ int32_t i0,i1,j0;
+ u_int32_t i,j;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0<0) {i0=0x80000000;i1=0;}
+ else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
+ }
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0>0) i0 += (0x00100000)>>j0;
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((u_int32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0>0) {
+ if(j0==20) i0+=1;
+ else {
+ j = i1 + (1<<(52-j0));
+ if(j<i1) i0+=1; /* got a carry */
+ i1 = j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ INSERT_WORDS(x,i0,i1);
+ return x;
+}
diff --git a/lib/msun/src/s_ceilf.c b/lib/msun/src/s_ceilf.c
new file mode 100644
index 0000000..5925ee4
--- /dev/null
+++ b/lib/msun/src/s_ceilf.c
@@ -0,0 +1,61 @@
+/* s_ceilf.c -- float version of s_ceil.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float huge = 1.0e30;
+#else
+static float huge = 1.0e30;
+#endif
+
+#ifdef __STDC__
+ float ceilf(float x)
+#else
+ float ceilf(x)
+ float x;
+#endif
+{
+ int32_t i0,j0;
+ u_int32_t i;
+
+ GET_FLOAT_WORD(i0,x);
+ j0 = ((i0>>23)&0xff)-0x7f;
+ if(j0<23) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0<0) {i0=0x80000000;}
+ else if(i0!=0) { i0=0x3f800000;}
+ }
+ } else {
+ i = (0x007fffff)>>j0;
+ if((i0&i)==0) return x; /* x is integral */
+ if(huge+x>(float)0.0) { /* raise inexact flag */
+ if(i0>0) i0 += (0x00800000)>>j0;
+ i0 &= (~i);
+ }
+ }
+ } else {
+ if(j0==0x80) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ }
+ SET_FLOAT_WORD(x,i0);
+ return x;
+}
diff --git a/lib/msun/src/s_copysign.c b/lib/msun/src/s_copysign.c
new file mode 100644
index 0000000..c119edf
--- /dev/null
+++ b/lib/msun/src/s_copysign.c
@@ -0,0 +1,38 @@
+/* @(#)s_copysign.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * copysign(double x, double y)
+ * copysign(x,y) returns a value with the magnitude of x and
+ * with the sign bit of y.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double __generic_copysign(double x, double y)
+#else
+ double __generic_copysign(x,y)
+ double x,y;
+#endif
+{
+ 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;
+}
diff --git a/lib/msun/src/s_copysignf.c b/lib/msun/src/s_copysignf.c
new file mode 100644
index 0000000..d5eb48f
--- /dev/null
+++ b/lib/msun/src/s_copysignf.c
@@ -0,0 +1,41 @@
+/* s_copysignf.c -- float version of s_copysign.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * copysignf(float x, float y)
+ * copysignf(x,y) returns a value with the magnitude of x and
+ * with the sign bit of y.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float copysignf(float x, float y)
+#else
+ float copysignf(x,y)
+ float x,y;
+#endif
+{
+ u_int32_t ix,iy;
+ GET_FLOAT_WORD(ix,x);
+ GET_FLOAT_WORD(iy,y);
+ SET_FLOAT_WORD(x,(ix&0x7fffffff)|(iy&0x80000000));
+ return x;
+}
diff --git a/lib/msun/src/s_cos.c b/lib/msun/src/s_cos.c
new file mode 100644
index 0000000..7e4eda9
--- /dev/null
+++ b/lib/msun/src/s_cos.c
@@ -0,0 +1,82 @@
+/* @(#)s_cos.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* cos(x)
+ * Return cosine function of x.
+ *
+ * kernel function:
+ * __kernel_sin ... sine function on [-pi/4,pi/4]
+ * __kernel_cos ... cosine function on [-pi/4,pi/4]
+ * __ieee754_rem_pio2 ... argument reduction routine
+ *
+ * Method.
+ * Let S,C and T denote the sin, cos and tan respectively on
+ * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ * in [-pi/4 , +pi/4], and let n = k mod 4.
+ * We have
+ *
+ * n sin(x) cos(x) tan(x)
+ * ----------------------------------------------------------
+ * 0 S C T
+ * 1 C -S -1/T
+ * 2 -S -C T
+ * 3 -C S -1/T
+ * ----------------------------------------------------------
+ *
+ * Special cases:
+ * Let trig be any of sin, cos, or tan.
+ * trig(+-INF) is NaN, with signals;
+ * trig(NaN) is that NaN;
+ *
+ * Accuracy:
+ * TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double __generic_cos(double x)
+#else
+ double __generic_cos(x)
+ double x;
+#endif
+{
+ double y[2],z=0.0;
+ int32_t n, ix;
+
+ /* High word of x. */
+ GET_HIGH_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3fe921fb) return __kernel_cos(x,z);
+
+ /* cos(Inf or NaN) is NaN */
+ else if (ix>=0x7ff00000) return x-x;
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2(x,y);
+ switch(n&3) {
+ case 0: return __kernel_cos(y[0],y[1]);
+ case 1: return -__kernel_sin(y[0],y[1],1);
+ case 2: return -__kernel_cos(y[0],y[1]);
+ default:
+ return __kernel_sin(y[0],y[1],1);
+ }
+ }
+}
diff --git a/lib/msun/src/s_cosf.c b/lib/msun/src/s_cosf.c
new file mode 100644
index 0000000..18df5d0
--- /dev/null
+++ b/lib/msun/src/s_cosf.c
@@ -0,0 +1,59 @@
+/* s_cosf.c -- float version of s_cos.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float one=1.0;
+#else
+static float one=1.0;
+#endif
+
+#ifdef __STDC__
+ float cosf(float x)
+#else
+ float cosf(x)
+ float x;
+#endif
+{
+ float y[2],z=0.0;
+ int32_t n,ix;
+
+ GET_FLOAT_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3f490fd8) return __kernel_cosf(x,z);
+
+ /* cos(Inf or NaN) is NaN */
+ else if (ix>=0x7f800000) return x-x;
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2f(x,y);
+ switch(n&3) {
+ case 0: return __kernel_cosf(y[0],y[1]);
+ case 1: return -__kernel_sinf(y[0],y[1],1);
+ case 2: return -__kernel_cosf(y[0],y[1]);
+ default:
+ return __kernel_sinf(y[0],y[1],1);
+ }
+ }
+}
diff --git a/lib/msun/src/s_erf.c b/lib/msun/src/s_erf.c
new file mode 100644
index 0000000..07129a3
--- /dev/null
+++ b/lib/msun/src/s_erf.c
@@ -0,0 +1,314 @@
+/* @(#)s_erf.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* double erf(double x)
+ * double erfc(double x)
+ * x
+ * 2 |\
+ * erf(x) = --------- | exp(-t*t)dt
+ * sqrt(pi) \|
+ * 0
+ *
+ * erfc(x) = 1-erf(x)
+ * Note that
+ * erf(-x) = -erf(x)
+ * erfc(-x) = 2 - erfc(x)
+ *
+ * Method:
+ * 1. For |x| in [0, 0.84375]
+ * erf(x) = x + x*R(x^2)
+ * erfc(x) = 1 - erf(x) if x in [-.84375,0.25]
+ * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375]
+ * where R = P/Q where P is an odd poly of degree 8 and
+ * Q is an odd poly of degree 10.
+ * -57.90
+ * | R - (erf(x)-x)/x | <= 2
+ *
+ *
+ * Remark. The formula is derived by noting
+ * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
+ * and that
+ * 2/sqrt(pi) = 1.128379167095512573896158903121545171688
+ * is close to one. The interval is chosen because the fix
+ * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
+ * near 0.6174), and by some experiment, 0.84375 is chosen to
+ * guarantee the error is less than one ulp for erf.
+ *
+ * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and
+ * c = 0.84506291151 rounded to single (24 bits)
+ * erf(x) = sign(x) * (c + P1(s)/Q1(s))
+ * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0
+ * 1+(c+P1(s)/Q1(s)) if x < 0
+ * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06
+ * Remark: here we use the taylor series expansion at x=1.
+ * erf(1+s) = erf(1) + s*Poly(s)
+ * = 0.845.. + P1(s)/Q1(s)
+ * That is, we use rational approximation to approximate
+ * erf(1+s) - (c = (single)0.84506291151)
+ * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
+ * where
+ * P1(s) = degree 6 poly in s
+ * Q1(s) = degree 6 poly in s
+ *
+ * 3. For x in [1.25,1/0.35(~2.857143)],
+ * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1)
+ * erf(x) = 1 - erfc(x)
+ * where
+ * R1(z) = degree 7 poly in z, (z=1/x^2)
+ * S1(z) = degree 8 poly in z
+ *
+ * 4. For x in [1/0.35,28]
+ * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
+ * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6<x<0
+ * = 2.0 - tiny (if x <= -6)
+ * erf(x) = sign(x)*(1.0 - erfc(x)) if x < 6, else
+ * erf(x) = sign(x)*(1.0 - tiny)
+ * where
+ * R2(z) = degree 6 poly in z, (z=1/x^2)
+ * S2(z) = degree 7 poly in z
+ *
+ * Note1:
+ * To compute exp(-x*x-0.5625+R/S), let s be a single
+ * precision number and s := x; then
+ * -x*x = -s*s + (s-x)*(s+x)
+ * exp(-x*x-0.5626+R/S) =
+ * exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
+ * Note2:
+ * Here 4 and 5 make use of the asymptotic series
+ * exp(-x*x)
+ * erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
+ * x*sqrt(pi)
+ * We use rational approximation to approximate
+ * g(s)=f(1/x^2) = log(erfc(x)*x) - x*x + 0.5625
+ * Here is the error bound for R1/S1 and R2/S2
+ * |R1/S1 - f(x)| < 2**(-62.57)
+ * |R2/S2 - f(x)| < 2**(-61.52)
+ *
+ * 5. For inf > x >= 28
+ * erf(x) = sign(x) *(1 - tiny) (raise inexact)
+ * erfc(x) = tiny*tiny (raise underflow) if x > 0
+ * = 2 - tiny if x<0
+ *
+ * 7. Special case:
+ * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1,
+ * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
+ * erfc/erf(NaN) is NaN
+ */
+
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+tiny = 1e-300,
+half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
+ /* c = (float)0.84506291151 */
+erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */
+/*
+ * Coefficients for approximation to erf on [0,0.84375]
+ */
+efx = 1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */
+efx8= 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */
+pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */
+pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */
+pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */
+pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */
+pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */
+qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */
+qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */
+qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */
+qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */
+qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */
+/*
+ * Coefficients for approximation to erf in [0.84375,1.25]
+ */
+pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */
+pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */
+pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */
+pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */
+pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */
+pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */
+pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */
+qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */
+qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */
+qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */
+qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */
+qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */
+qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */
+/*
+ * Coefficients for approximation to erfc in [1.25,1/0.35]
+ */
+ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */
+ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */
+ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */
+ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */
+ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */
+ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */
+ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */
+ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */
+sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */
+sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */
+sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */
+sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */
+sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */
+sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */
+sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */
+sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */
+/*
+ * Coefficients for approximation to erfc in [1/.35,28]
+ */
+rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */
+rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */
+rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */
+rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */
+rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */
+rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */
+rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */
+sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */
+sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */
+sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */
+sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */
+sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */
+sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */
+sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */
+
+#ifdef __STDC__
+ double erf(double x)
+#else
+ double erf(x)
+ double x;
+#endif
+{
+ int32_t hx,ix,i;
+ double R,S,P,Q,s,y,z,r;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) { /* erf(nan)=nan */
+ i = ((u_int32_t)hx>>31)<<1;
+ return (double)(1-i)+one/x; /* erf(+-inf)=+-1 */
+ }
+
+ if(ix < 0x3feb0000) { /* |x|<0.84375 */
+ if(ix < 0x3e300000) { /* |x|<2**-28 */
+ if (ix < 0x00800000)
+ return 0.125*(8.0*x+efx8*x); /*avoid underflow */
+ return x + efx*x;
+ }
+ z = x*x;
+ r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+ s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+ y = r/s;
+ return x + x*y;
+ }
+ if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */
+ s = fabs(x)-one;
+ P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+ Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+ if(hx>=0) return erx + P/Q; else return -erx - P/Q;
+ }
+ if (ix >= 0x40180000) { /* inf>|x|>=6 */
+ if(hx>=0) return one-tiny; else return tiny-one;
+ }
+ x = fabs(x);
+ s = one/(x*x);
+ if(ix< 0x4006DB6E) { /* |x| < 1/0.35 */
+ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+ ra5+s*(ra6+s*ra7))))));
+ S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+ sa5+s*(sa6+s*(sa7+s*sa8)))))));
+ } else { /* |x| >= 1/0.35 */
+ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+ rb5+s*rb6)))));
+ S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+ sb5+s*(sb6+s*sb7))))));
+ }
+ z = x;
+ SET_LOW_WORD(z,0);
+ r = __ieee754_exp(-z*z-0.5625)*__ieee754_exp((z-x)*(z+x)+R/S);
+ if(hx>=0) return one-r/x; else return r/x-one;
+}
+
+#ifdef __STDC__
+ double erfc(double x)
+#else
+ double erfc(x)
+ double x;
+#endif
+{
+ int32_t hx,ix;
+ double R,S,P,Q,s,y,z,r;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) { /* erfc(nan)=nan */
+ /* erfc(+-inf)=0,2 */
+ return (double)(((u_int32_t)hx>>31)<<1)+one/x;
+ }
+
+ if(ix < 0x3feb0000) { /* |x|<0.84375 */
+ if(ix < 0x3c700000) /* |x|<2**-56 */
+ return one-x;
+ z = x*x;
+ r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+ s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+ y = r/s;
+ if(hx < 0x3fd00000) { /* x<1/4 */
+ return one-(x+x*y);
+ } else {
+ r = x*y;
+ r += (x-half);
+ return half - r ;
+ }
+ }
+ if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */
+ s = fabs(x)-one;
+ P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+ Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+ if(hx>=0) {
+ z = one-erx; return z - P/Q;
+ } else {
+ z = erx+P/Q; return one+z;
+ }
+ }
+ if (ix < 0x403c0000) { /* |x|<28 */
+ x = fabs(x);
+ s = one/(x*x);
+ if(ix< 0x4006DB6D) { /* |x| < 1/.35 ~ 2.857143*/
+ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+ ra5+s*(ra6+s*ra7))))));
+ S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+ sa5+s*(sa6+s*(sa7+s*sa8)))))));
+ } else { /* |x| >= 1/.35 ~ 2.857143 */
+ if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */
+ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+ rb5+s*rb6)))));
+ S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+ sb5+s*(sb6+s*sb7))))));
+ }
+ z = x;
+ SET_LOW_WORD(z,0);
+ r = __ieee754_exp(-z*z-0.5625)*
+ __ieee754_exp((z-x)*(z+x)+R/S);
+ if(hx>0) return r/x; else return two-r/x;
+ } else {
+ if(hx>0) return tiny*tiny; else return two-tiny;
+ }
+}
diff --git a/lib/msun/src/s_erff.c b/lib/msun/src/s_erff.c
new file mode 100644
index 0000000..1a3b3b2
--- /dev/null
+++ b/lib/msun/src/s_erff.c
@@ -0,0 +1,223 @@
+/* s_erff.c -- float version of s_erf.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+tiny = 1e-30,
+half= 5.0000000000e-01, /* 0x3F000000 */
+one = 1.0000000000e+00, /* 0x3F800000 */
+two = 2.0000000000e+00, /* 0x40000000 */
+ /* c = (subfloat)0.84506291151 */
+erx = 8.4506291151e-01, /* 0x3f58560b */
+/*
+ * Coefficients for approximation to erf on [0,0.84375]
+ */
+efx = 1.2837916613e-01, /* 0x3e0375d4 */
+efx8= 1.0270333290e+00, /* 0x3f8375d4 */
+pp0 = 1.2837916613e-01, /* 0x3e0375d4 */
+pp1 = -3.2504209876e-01, /* 0xbea66beb */
+pp2 = -2.8481749818e-02, /* 0xbce9528f */
+pp3 = -5.7702702470e-03, /* 0xbbbd1489 */
+pp4 = -2.3763017452e-05, /* 0xb7c756b1 */
+qq1 = 3.9791721106e-01, /* 0x3ecbbbce */
+qq2 = 6.5022252500e-02, /* 0x3d852a63 */
+qq3 = 5.0813062117e-03, /* 0x3ba68116 */
+qq4 = 1.3249473704e-04, /* 0x390aee49 */
+qq5 = -3.9602282413e-06, /* 0xb684e21a */
+/*
+ * Coefficients for approximation to erf in [0.84375,1.25]
+ */
+pa0 = -2.3621185683e-03, /* 0xbb1acdc6 */
+pa1 = 4.1485610604e-01, /* 0x3ed46805 */
+pa2 = -3.7220788002e-01, /* 0xbebe9208 */
+pa3 = 3.1834661961e-01, /* 0x3ea2fe54 */
+pa4 = -1.1089469492e-01, /* 0xbde31cc2 */
+pa5 = 3.5478305072e-02, /* 0x3d1151b3 */
+pa6 = -2.1663755178e-03, /* 0xbb0df9c0 */
+qa1 = 1.0642088205e-01, /* 0x3dd9f331 */
+qa2 = 5.4039794207e-01, /* 0x3f0a5785 */
+qa3 = 7.1828655899e-02, /* 0x3d931ae7 */
+qa4 = 1.2617121637e-01, /* 0x3e013307 */
+qa5 = 1.3637083583e-02, /* 0x3c5f6e13 */
+qa6 = 1.1984500103e-02, /* 0x3c445aa3 */
+/*
+ * Coefficients for approximation to erfc in [1.25,1/0.35]
+ */
+ra0 = -9.8649440333e-03, /* 0xbc21a093 */
+ra1 = -6.9385856390e-01, /* 0xbf31a0b7 */
+ra2 = -1.0558626175e+01, /* 0xc128f022 */
+ra3 = -6.2375331879e+01, /* 0xc2798057 */
+ra4 = -1.6239666748e+02, /* 0xc322658c */
+ra5 = -1.8460508728e+02, /* 0xc3389ae7 */
+ra6 = -8.1287437439e+01, /* 0xc2a2932b */
+ra7 = -9.8143291473e+00, /* 0xc11d077e */
+sa1 = 1.9651271820e+01, /* 0x419d35ce */
+sa2 = 1.3765776062e+02, /* 0x4309a863 */
+sa3 = 4.3456588745e+02, /* 0x43d9486f */
+sa4 = 6.4538726807e+02, /* 0x442158c9 */
+sa5 = 4.2900814819e+02, /* 0x43d6810b */
+sa6 = 1.0863500214e+02, /* 0x42d9451f */
+sa7 = 6.5702495575e+00, /* 0x40d23f7c */
+sa8 = -6.0424413532e-02, /* 0xbd777f97 */
+/*
+ * Coefficients for approximation to erfc in [1/.35,28]
+ */
+rb0 = -9.8649431020e-03, /* 0xbc21a092 */
+rb1 = -7.9928326607e-01, /* 0xbf4c9dd4 */
+rb2 = -1.7757955551e+01, /* 0xc18e104b */
+rb3 = -1.6063638306e+02, /* 0xc320a2ea */
+rb4 = -6.3756646729e+02, /* 0xc41f6441 */
+rb5 = -1.0250950928e+03, /* 0xc480230b */
+rb6 = -4.8351919556e+02, /* 0xc3f1c275 */
+sb1 = 3.0338060379e+01, /* 0x41f2b459 */
+sb2 = 3.2579251099e+02, /* 0x43a2e571 */
+sb3 = 1.5367296143e+03, /* 0x44c01759 */
+sb4 = 3.1998581543e+03, /* 0x4547fdbb */
+sb5 = 2.5530502930e+03, /* 0x451f90ce */
+sb6 = 4.7452853394e+02, /* 0x43ed43a7 */
+sb7 = -2.2440952301e+01; /* 0xc1b38712 */
+
+#ifdef __STDC__
+ float erff(float x)
+#else
+ float erff(x)
+ float x;
+#endif
+{
+ int32_t hx,ix,i;
+ float R,S,P,Q,s,y,z,r;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) { /* erf(nan)=nan */
+ i = ((u_int32_t)hx>>31)<<1;
+ return (float)(1-i)+one/x; /* erf(+-inf)=+-1 */
+ }
+
+ if(ix < 0x3f580000) { /* |x|<0.84375 */
+ if(ix < 0x31800000) { /* |x|<2**-28 */
+ if (ix < 0x04000000)
+ /*avoid underflow */
+ return (float)0.125*((float)8.0*x+efx8*x);
+ return x + efx*x;
+ }
+ z = x*x;
+ r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+ s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+ y = r/s;
+ return x + x*y;
+ }
+ if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */
+ s = fabsf(x)-one;
+ P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+ Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+ if(hx>=0) return erx + P/Q; else return -erx - P/Q;
+ }
+ if (ix >= 0x40c00000) { /* inf>|x|>=6 */
+ if(hx>=0) return one-tiny; else return tiny-one;
+ }
+ x = fabsf(x);
+ s = one/(x*x);
+ if(ix< 0x4036DB6E) { /* |x| < 1/0.35 */
+ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+ ra5+s*(ra6+s*ra7))))));
+ S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+ sa5+s*(sa6+s*(sa7+s*sa8)))))));
+ } else { /* |x| >= 1/0.35 */
+ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+ rb5+s*rb6)))));
+ S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+ sb5+s*(sb6+s*sb7))))));
+ }
+ GET_FLOAT_WORD(ix,x);
+ SET_FLOAT_WORD(z,ix&0xfffff000);
+ r = __ieee754_expf(-z*z-(float)0.5625)*__ieee754_expf((z-x)*(z+x)+R/S);
+ if(hx>=0) return one-r/x; else return r/x-one;
+}
+
+#ifdef __STDC__
+ float erfcf(float x)
+#else
+ float erfcf(x)
+ float x;
+#endif
+{
+ int32_t hx,ix;
+ float R,S,P,Q,s,y,z,r;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) { /* erfc(nan)=nan */
+ /* erfc(+-inf)=0,2 */
+ return (float)(((u_int32_t)hx>>31)<<1)+one/x;
+ }
+
+ if(ix < 0x3f580000) { /* |x|<0.84375 */
+ if(ix < 0x23800000) /* |x|<2**-56 */
+ return one-x;
+ z = x*x;
+ r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+ s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+ y = r/s;
+ if(hx < 0x3e800000) { /* x<1/4 */
+ return one-(x+x*y);
+ } else {
+ r = x*y;
+ r += (x-half);
+ return half - r ;
+ }
+ }
+ if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */
+ s = fabsf(x)-one;
+ P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+ Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+ if(hx>=0) {
+ z = one-erx; return z - P/Q;
+ } else {
+ z = erx+P/Q; return one+z;
+ }
+ }
+ if (ix < 0x41e00000) { /* |x|<28 */
+ x = fabsf(x);
+ s = one/(x*x);
+ if(ix< 0x4036DB6D) { /* |x| < 1/.35 ~ 2.857143*/
+ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+ ra5+s*(ra6+s*ra7))))));
+ S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+ sa5+s*(sa6+s*(sa7+s*sa8)))))));
+ } else { /* |x| >= 1/.35 ~ 2.857143 */
+ if(hx<0&&ix>=0x40c00000) return two-tiny;/* x < -6 */
+ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+ rb5+s*rb6)))));
+ S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+ sb5+s*(sb6+s*sb7))))));
+ }
+ GET_FLOAT_WORD(ix,x);
+ SET_FLOAT_WORD(z,ix&0xfffff000);
+ r = __ieee754_expf(-z*z-(float)0.5625)*
+ __ieee754_expf((z-x)*(z+x)+R/S);
+ if(hx>0) return r/x; else return two-r/x;
+ } else {
+ if(hx>0) return tiny*tiny; else return two-tiny;
+ }
+}
diff --git a/lib/msun/src/s_expm1.c b/lib/msun/src/s_expm1.c
new file mode 100644
index 0000000..bff3492
--- /dev/null
+++ b/lib/msun/src/s_expm1.c
@@ -0,0 +1,228 @@
+/* @(#)s_expm1.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* expm1(x)
+ * Returns exp(x)-1, the exponential of x minus 1.
+ *
+ * Method
+ * 1. Argument reduction:
+ * Given x, find r and integer k such that
+ *
+ * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658
+ *
+ * Here a correction term c will be computed to compensate
+ * the error in r when rounded to a floating-point number.
+ *
+ * 2. Approximating expm1(r) by a special rational function on
+ * the interval [0,0.34658]:
+ * Since
+ * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ...
+ * we define R1(r*r) by
+ * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r)
+ * That is,
+ * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
+ * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
+ * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
+ * We use a special Reme algorithm on [0,0.347] to generate
+ * a polynomial of degree 5 in r*r to approximate R1. The
+ * maximum error of this polynomial approximation is bounded
+ * by 2**-61. In other words,
+ * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
+ * where Q1 = -1.6666666666666567384E-2,
+ * Q2 = 3.9682539681370365873E-4,
+ * Q3 = -9.9206344733435987357E-6,
+ * Q4 = 2.5051361420808517002E-7,
+ * Q5 = -6.2843505682382617102E-9;
+ * (where z=r*r, and the values of Q1 to Q5 are listed below)
+ * with error bounded by
+ * | 5 | -61
+ * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2
+ * | |
+ *
+ * expm1(r) = exp(r)-1 is then computed by the following
+ * specific way which minimize the accumulation rounding error:
+ * 2 3
+ * r r [ 3 - (R1 + R1*r/2) ]
+ * expm1(r) = r + --- + --- * [--------------------]
+ * 2 2 [ 6 - r*(3 - R1*r/2) ]
+ *
+ * To compensate the error in the argument reduction, we use
+ * expm1(r+c) = expm1(r) + c + expm1(r)*c
+ * ~ expm1(r) + c + r*c
+ * Thus c+r*c will be added in as the correction terms for
+ * expm1(r+c). Now rearrange the term to avoid optimization
+ * screw up:
+ * ( 2 2 )
+ * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r )
+ * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
+ * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 )
+ * ( )
+ *
+ * = r - E
+ * 3. Scale back to obtain expm1(x):
+ * From step 1, we have
+ * expm1(x) = either 2^k*[expm1(r)+1] - 1
+ * = or 2^k*[expm1(r) + (1-2^-k)]
+ * 4. Implementation notes:
+ * (A). To save one multiplication, we scale the coefficient Qi
+ * to Qi*2^i, and replace z by (x^2)/2.
+ * (B). To achieve maximum accuracy, we compute expm1(x) by
+ * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
+ * (ii) if k=0, return r-E
+ * (iii) if k=-1, return 0.5*(r-E)-0.5
+ * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E)
+ * else return 1.0+2.0*(r-E);
+ * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
+ * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else
+ * (vii) return 2^k(1-((E+2^-k)-r))
+ *
+ * Special cases:
+ * expm1(INF) is INF, expm1(NaN) is NaN;
+ * expm1(-INF) is -1, and
+ * for finite argument, only expm1(0)=0 is exact.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ * For IEEE double
+ * if x > 7.09782712893383973096e+02 then expm1(x) overflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+one = 1.0,
+huge = 1.0e+300,
+tiny = 1.0e-300,
+o_threshold = 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */
+ln2_hi = 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */
+ln2_lo = 1.90821492927058770002e-10,/* 0x3dea39ef, 0x35793c76 */
+invln2 = 1.44269504088896338700e+00,/* 0x3ff71547, 0x652b82fe */
+ /* scaled coefficients related to expm1 */
+Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */
+Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */
+Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */
+Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */
+Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */
+
+#ifdef __STDC__
+ double expm1(double x)
+#else
+ double expm1(x)
+ double x;
+#endif
+{
+ double y,hi,lo,c,t,e,hxs,hfx,r1;
+ int32_t k,xsb;
+ u_int32_t hx;
+
+ GET_HIGH_WORD(hx,x);
+ xsb = hx&0x80000000; /* sign bit of x */
+ if(xsb==0) y=x; else y= -x; /* y = |x| */
+ hx &= 0x7fffffff; /* high word of |x| */
+
+ /* filter out huge and non-finite argument */
+ if(hx >= 0x4043687A) { /* if |x|>=56*ln2 */
+ if(hx >= 0x40862E42) { /* if |x|>=709.78... */
+ if(hx>=0x7ff00000) {
+ u_int32_t low;
+ GET_LOW_WORD(low,x);
+ if(((hx&0xfffff)|low)!=0)
+ return x+x; /* NaN */
+ else return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */
+ }
+ if(x > o_threshold) return huge*huge; /* overflow */
+ }
+ if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */
+ if(x+tiny<0.0) /* raise inexact */
+ return tiny-one; /* return -1 */
+ }
+ }
+
+ /* argument reduction */
+ if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
+ if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+ if(xsb==0)
+ {hi = x - ln2_hi; lo = ln2_lo; k = 1;}
+ else
+ {hi = x + ln2_hi; lo = -ln2_lo; k = -1;}
+ } else {
+ k = invln2*x+((xsb==0)?0.5:-0.5);
+ t = k;
+ hi = x - t*ln2_hi; /* t*ln2_hi is exact here */
+ lo = t*ln2_lo;
+ }
+ x = hi - lo;
+ c = (hi-x)-lo;
+ }
+ else if(hx < 0x3c900000) { /* when |x|<2**-54, return x */
+ t = huge+x; /* return x with inexact flags when x!=0 */
+ return x - (t-(huge+x));
+ }
+ else k = 0;
+
+ /* x is now in primary range */
+ hfx = 0.5*x;
+ hxs = x*hfx;
+ r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
+ t = 3.0-r1*hfx;
+ e = hxs*((r1-t)/(6.0 - x*t));
+ if(k==0) return x - (x*e-hxs); /* c is 0 */
+ else {
+ e = (x*(e-c)-c);
+ e -= hxs;
+ if(k== -1) return 0.5*(x-e)-0.5;
+ if(k==1)
+ if(x < -0.25) return -2.0*(e-(x+0.5));
+ else return one+2.0*(x-e);
+ if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */
+ u_int32_t high;
+ y = one-(e-x);
+ GET_HIGH_WORD(high,y);
+ SET_HIGH_WORD(y,high+(k<<20)); /* add k to y's exponent */
+ return y-one;
+ }
+ t = one;
+ if(k<20) {
+ u_int32_t high;
+ SET_HIGH_WORD(t,0x3ff00000 - (0x200000>>k)); /* t=1-2^-k */
+ y = t-(e-x);
+ GET_HIGH_WORD(high,y);
+ SET_HIGH_WORD(y,high+(k<<20)); /* add k to y's exponent */
+ } else {
+ u_int32_t high;
+ SET_HIGH_WORD(t,((0x3ff-k)<<20)); /* 2^-k */
+ y = x-(e+t);
+ y += one;
+ GET_HIGH_WORD(high,y);
+ SET_HIGH_WORD(y,high+(k<<20)); /* add k to y's exponent */
+ }
+ }
+ return y;
+}
diff --git a/lib/msun/src/s_expm1f.c b/lib/msun/src/s_expm1f.c
new file mode 100644
index 0000000..e6d8709
--- /dev/null
+++ b/lib/msun/src/s_expm1f.c
@@ -0,0 +1,133 @@
+/* s_expm1f.c -- float version of s_expm1.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+one = 1.0,
+huge = 1.0e+30,
+tiny = 1.0e-30,
+o_threshold = 8.8721679688e+01,/* 0x42b17180 */
+ln2_hi = 6.9313812256e-01,/* 0x3f317180 */
+ln2_lo = 9.0580006145e-06,/* 0x3717f7d1 */
+invln2 = 1.4426950216e+00,/* 0x3fb8aa3b */
+ /* scaled coefficients related to expm1 */
+Q1 = -3.3333335072e-02, /* 0xbd088889 */
+Q2 = 1.5873016091e-03, /* 0x3ad00d01 */
+Q3 = -7.9365076090e-05, /* 0xb8a670cd */
+Q4 = 4.0082177293e-06, /* 0x36867e54 */
+Q5 = -2.0109921195e-07; /* 0xb457edbb */
+
+#ifdef __STDC__
+ float expm1f(float x)
+#else
+ float expm1f(x)
+ float x;
+#endif
+{
+ float y,hi,lo,c,t,e,hxs,hfx,r1;
+ int32_t k,xsb;
+ u_int32_t hx;
+
+ GET_FLOAT_WORD(hx,x);
+ xsb = hx&0x80000000; /* sign bit of x */
+ if(xsb==0) y=x; else y= -x; /* y = |x| */
+ hx &= 0x7fffffff; /* high word of |x| */
+
+ /* filter out huge and non-finite argument */
+ if(hx >= 0x4195b844) { /* if |x|>=27*ln2 */
+ if(hx >= 0x42b17218) { /* if |x|>=88.721... */
+ if(hx>0x7f800000)
+ return x+x; /* NaN */
+ if(hx==0x7f800000)
+ return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */
+ if(x > o_threshold) return huge*huge; /* overflow */
+ }
+ if(xsb!=0) { /* x < -27*ln2, return -1.0 with inexact */
+ if(x+tiny<(float)0.0) /* raise inexact */
+ return tiny-one; /* return -1 */
+ }
+ }
+
+ /* argument reduction */
+ if(hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */
+ if(hx < 0x3F851592) { /* and |x| < 1.5 ln2 */
+ if(xsb==0)
+ {hi = x - ln2_hi; lo = ln2_lo; k = 1;}
+ else
+ {hi = x + ln2_hi; lo = -ln2_lo; k = -1;}
+ } else {
+ k = invln2*x+((xsb==0)?(float)0.5:(float)-0.5);
+ t = k;
+ hi = x - t*ln2_hi; /* t*ln2_hi is exact here */
+ lo = t*ln2_lo;
+ }
+ x = hi - lo;
+ c = (hi-x)-lo;
+ }
+ else if(hx < 0x33000000) { /* when |x|<2**-25, return x */
+ t = huge+x; /* return x with inexact flags when x!=0 */
+ return x - (t-(huge+x));
+ }
+ else k = 0;
+
+ /* x is now in primary range */
+ hfx = (float)0.5*x;
+ hxs = x*hfx;
+ r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
+ t = (float)3.0-r1*hfx;
+ e = hxs*((r1-t)/((float)6.0 - x*t));
+ if(k==0) return x - (x*e-hxs); /* c is 0 */
+ else {
+ e = (x*(e-c)-c);
+ e -= hxs;
+ if(k== -1) return (float)0.5*(x-e)-(float)0.5;
+ if(k==1)
+ if(x < (float)-0.25) return -(float)2.0*(e-(x+(float)0.5));
+ else return one+(float)2.0*(x-e);
+ if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */
+ int32_t i;
+ y = one-(e-x);
+ GET_FLOAT_WORD(i,y);
+ SET_FLOAT_WORD(y,i+(k<<23)); /* add k to y's exponent */
+ return y-one;
+ }
+ t = one;
+ if(k<23) {
+ int32_t i;
+ SET_FLOAT_WORD(t,0x3f800000 - (0x1000000>>k)); /* t=1-2^-k */
+ y = t-(e-x);
+ GET_FLOAT_WORD(i,y);
+ SET_FLOAT_WORD(y,i+(k<<23)); /* add k to y's exponent */
+ } else {
+ int32_t i;
+ SET_FLOAT_WORD(t,((0x7f-k)<<23)); /* 2^-k */
+ y = x-(e+t);
+ y += one;
+ GET_FLOAT_WORD(i,y);
+ SET_FLOAT_WORD(y,i+(k<<23)); /* add k to y's exponent */
+ }
+ }
+ return y;
+}
diff --git a/lib/msun/src/s_fabs.c b/lib/msun/src/s_fabs.c
new file mode 100644
index 0000000..ef15a69
--- /dev/null
+++ b/lib/msun/src/s_fabs.c
@@ -0,0 +1,35 @@
+/* @(#)s_fabs.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * fabs(x) returns the absolute value of x.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double fabs(double x)
+#else
+ double fabs(x)
+ double x;
+#endif
+{
+ u_int32_t high;
+ GET_HIGH_WORD(high,x);
+ SET_HIGH_WORD(x,high&0x7fffffff);
+ return x;
+}
diff --git a/lib/msun/src/s_fabsf.c b/lib/msun/src/s_fabsf.c
new file mode 100644
index 0000000..d064ba0
--- /dev/null
+++ b/lib/msun/src/s_fabsf.c
@@ -0,0 +1,38 @@
+/* s_fabsf.c -- float version of s_fabs.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * fabsf(x) returns the absolute value of x.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float fabsf(float x)
+#else
+ float fabsf(x)
+ float x;
+#endif
+{
+ u_int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ SET_FLOAT_WORD(x,ix&0x7fffffff);
+ return x;
+}
diff --git a/lib/msun/src/s_finite.c b/lib/msun/src/s_finite.c
new file mode 100644
index 0000000..b5429b4
--- /dev/null
+++ b/lib/msun/src/s_finite.c
@@ -0,0 +1,35 @@
+/* @(#)s_finite.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * finite(x) returns 1 is x is finite, else 0;
+ * no branching!
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ int __generic_finite(double x)
+#else
+ int __generic_finite(x)
+ double x;
+#endif
+{
+ int32_t hx;
+ GET_HIGH_WORD(hx,x);
+ return (int)((u_int32_t)((hx&0x7fffffff)-0x7ff00000)>>31);
+}
diff --git a/lib/msun/src/s_finitef.c b/lib/msun/src/s_finitef.c
new file mode 100644
index 0000000..0243993
--- /dev/null
+++ b/lib/msun/src/s_finitef.c
@@ -0,0 +1,38 @@
+/* s_finitef.c -- float version of s_finite.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * finitef(x) returns 1 is x is finite, else 0;
+ * no branching!
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ int finitef(float x)
+#else
+ int finitef(x)
+ float x;
+#endif
+{
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ return (int)((u_int32_t)((ix&0x7fffffff)-0x7f800000)>>31);
+}
diff --git a/lib/msun/src/s_floor.c b/lib/msun/src/s_floor.c
new file mode 100644
index 0000000..37f0e1d
--- /dev/null
+++ b/lib/msun/src/s_floor.c
@@ -0,0 +1,81 @@
+/* @(#)s_floor.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * floor(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to floor(x).
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double huge = 1.0e300;
+#else
+static double huge = 1.0e300;
+#endif
+
+#ifdef __STDC__
+ double __generic_floor(double x)
+#else
+ double __generic_floor(x)
+ double x;
+#endif
+{
+ int32_t i0,i1,j0;
+ u_int32_t i,j;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0>=0) {i0=i1=0;}
+ else if(((i0&0x7fffffff)|i1)!=0)
+ { i0=0xbff00000;i1=0;}
+ }
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0<0) i0 += (0x00100000)>>j0;
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((u_int32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0<0) {
+ if(j0==20) i0+=1;
+ else {
+ j = i1+(1<<(52-j0));
+ if(j<i1) i0 +=1 ; /* got a carry */
+ i1=j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ INSERT_WORDS(x,i0,i1);
+ return x;
+}
diff --git a/lib/msun/src/s_floorf.c b/lib/msun/src/s_floorf.c
new file mode 100644
index 0000000..caa6427
--- /dev/null
+++ b/lib/msun/src/s_floorf.c
@@ -0,0 +1,70 @@
+/* s_floorf.c -- float version of s_floor.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * floorf(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to floorf(x).
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float huge = 1.0e30;
+#else
+static float huge = 1.0e30;
+#endif
+
+#ifdef __STDC__
+ float floorf(float x)
+#else
+ float floorf(x)
+ float x;
+#endif
+{
+ int32_t i0,j0;
+ u_int32_t i;
+ GET_FLOAT_WORD(i0,x);
+ j0 = ((i0>>23)&0xff)-0x7f;
+ if(j0<23) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0>=0) {i0=0;}
+ else if((i0&0x7fffffff)!=0)
+ { i0=0xbf800000;}
+ }
+ } else {
+ i = (0x007fffff)>>j0;
+ if((i0&i)==0) return x; /* x is integral */
+ if(huge+x>(float)0.0) { /* raise inexact flag */
+ if(i0<0) i0 += (0x00800000)>>j0;
+ i0 &= (~i);
+ }
+ }
+ } else {
+ if(j0==0x80) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ }
+ SET_FLOAT_WORD(x,i0);
+ return x;
+}
diff --git a/lib/msun/src/s_frexp.c b/lib/msun/src/s_frexp.c
new file mode 100644
index 0000000..c6b5244
--- /dev/null
+++ b/lib/msun/src/s_frexp.c
@@ -0,0 +1,59 @@
+/* @(#)s_frexp.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * for non-zero x
+ * x = frexp(arg,&exp);
+ * return a double fp quantity x such that 0.5 <= |x| <1.0
+ * and the corresponding binary exponent "exp". That is
+ * arg = x*2^exp.
+ * If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg
+ * with *exp=0.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */
+
+#ifdef __STDC__
+ double frexp(double x, int *eptr)
+#else
+ double frexp(x, eptr)
+ double x; int *eptr;
+#endif
+{
+ int32_t hx, ix, lx;
+ EXTRACT_WORDS(hx,lx,x);
+ ix = 0x7fffffff&hx;
+ *eptr = 0;
+ if(ix>=0x7ff00000||((ix|lx)==0)) return x; /* 0,inf,nan */
+ if (ix<0x00100000) { /* subnormal */
+ x *= two54;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ *eptr = -54;
+ }
+ *eptr += (ix>>20)-1022;
+ hx = (hx&0x800fffff)|0x3fe00000;
+ SET_HIGH_WORD(x,hx);
+ return x;
+}
diff --git a/lib/msun/src/s_frexpf.c b/lib/msun/src/s_frexpf.c
new file mode 100644
index 0000000..1a1df34
--- /dev/null
+++ b/lib/msun/src/s_frexpf.c
@@ -0,0 +1,52 @@
+/* s_frexpf.c -- float version of s_frexp.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+two25 = 3.3554432000e+07; /* 0x4c000000 */
+
+#ifdef __STDC__
+ float frexpf(float x, int *eptr)
+#else
+ float frexpf(x, eptr)
+ float x; int *eptr;
+#endif
+{
+ int32_t hx,ix;
+ GET_FLOAT_WORD(hx,x);
+ ix = 0x7fffffff&hx;
+ *eptr = 0;
+ if(ix>=0x7f800000||(ix==0)) return x; /* 0,inf,nan */
+ if (ix<0x00800000) { /* subnormal */
+ x *= two25;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ *eptr = -25;
+ }
+ *eptr += (ix>>23)-126;
+ hx = (hx&0x807fffff)|0x3f000000;
+ *(int*)&x = hx;
+ return x;
+}
diff --git a/lib/msun/src/s_ilogb.c b/lib/msun/src/s_ilogb.c
new file mode 100644
index 0000000..9a10666
--- /dev/null
+++ b/lib/msun/src/s_ilogb.c
@@ -0,0 +1,50 @@
+/* @(#)s_ilogb.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* ilogb(double x)
+ * return the binary exponent of non-zero x
+ * ilogb(0) = 0x80000001
+ * ilogb(inf/NaN) = 0x7fffffff (no signal is raised)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ int __generic_ilogb(double x)
+#else
+ int __generic_ilogb(x)
+ double x;
+#endif
+{
+ int32_t hx,lx,ix;
+
+ EXTRACT_WORDS(hx,lx,x);
+ hx &= 0x7fffffff;
+ if(hx<0x00100000) {
+ if((hx|lx)==0)
+ return 0x80000001; /* ilogb(0) = 0x80000001 */
+ else /* subnormal x */
+ if(hx==0) {
+ for (ix = -1043; lx>0; lx<<=1) ix -=1;
+ } else {
+ for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1;
+ }
+ return ix;
+ }
+ else if (hx<0x7ff00000) return (hx>>20)-1023;
+ else return 0x7fffffff;
+}
diff --git a/lib/msun/src/s_ilogbf.c b/lib/msun/src/s_ilogbf.c
new file mode 100644
index 0000000..31c0443
--- /dev/null
+++ b/lib/msun/src/s_ilogbf.c
@@ -0,0 +1,43 @@
+/* s_ilogbf.c -- float version of s_ilogb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ int ilogbf(float x)
+#else
+ int ilogbf(x)
+ float x;
+#endif
+{
+ int32_t hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+ hx &= 0x7fffffff;
+ if(hx<0x00800000) {
+ if(hx==0)
+ return 0x80000001; /* ilogb(0) = 0x80000001 */
+ else /* subnormal x */
+ for (ix = -126,hx<<=8; hx>0; hx<<=1) ix -=1;
+ return ix;
+ }
+ else if (hx<0x7f800000) return (hx>>23)-127;
+ else return 0x7fffffff;
+}
diff --git a/lib/msun/src/s_isnan.c b/lib/msun/src/s_isnan.c
new file mode 100644
index 0000000..212a5ee
--- /dev/null
+++ b/lib/msun/src/s_isnan.c
@@ -0,0 +1,38 @@
+/* @(#)s_isnan.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * isnan(x) returns 1 is x is nan, else 0;
+ * no branching!
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ int isnan(double x)
+#else
+ int isnan(x)
+ double x;
+#endif
+{
+ int32_t hx,lx;
+ EXTRACT_WORDS(hx,lx,x);
+ hx &= 0x7fffffff;
+ hx |= (u_int32_t)(lx|(-lx))>>31;
+ hx = 0x7ff00000 - hx;
+ return (int)((u_int32_t)(hx))>>31;
+}
diff --git a/lib/msun/src/s_isnanf.c b/lib/msun/src/s_isnanf.c
new file mode 100644
index 0000000..8432c0e
--- /dev/null
+++ b/lib/msun/src/s_isnanf.c
@@ -0,0 +1,40 @@
+/* s_isnanf.c -- float version of s_isnan.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * isnanf(x) returns 1 is x is nan, else 0;
+ * no branching!
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ int isnanf(float x)
+#else
+ int isnanf(x)
+ float x;
+#endif
+{
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+ ix = 0x7f800000 - ix;
+ return (int)(((u_int32_t)(ix))>>31);
+}
diff --git a/lib/msun/src/s_ldexp.c b/lib/msun/src/s_ldexp.c
new file mode 100644
index 0000000..8fe2d4b
--- /dev/null
+++ b/lib/msun/src/s_ldexp.c
@@ -0,0 +1,32 @@
+/* @(#)s_ldexp.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+#include <errno.h>
+
+#ifdef __STDC__
+ double ldexp(double value, int exp)
+#else
+ double ldexp(value, exp)
+ double value; int exp;
+#endif
+{
+ if(!finite(value)||value==0.0) return value;
+ value = scalbn(value,exp);
+ if(!finite(value)||value==0.0) errno = ERANGE;
+ return value;
+}
diff --git a/lib/msun/src/s_ldexpf.c b/lib/msun/src/s_ldexpf.c
new file mode 100644
index 0000000..ff01c1d
--- /dev/null
+++ b/lib/msun/src/s_ldexpf.c
@@ -0,0 +1,35 @@
+/* s_ldexpf.c -- float version of s_ldexp.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+#include <errno.h>
+
+#ifdef __STDC__
+ float ldexpf(float value, int exp)
+#else
+ float ldexpf(value, exp)
+ float value; int exp;
+#endif
+{
+ if(!finitef(value)||value==(float)0.0) return value;
+ value = scalbnf(value,exp);
+ if(!finitef(value)||value==(float)0.0) errno = ERANGE;
+ return value;
+}
diff --git a/lib/msun/src/s_lib_version.c b/lib/msun/src/s_lib_version.c
new file mode 100644
index 0000000..b9ca845
--- /dev/null
+++ b/lib/msun/src/s_lib_version.c
@@ -0,0 +1,39 @@
+/* @(#)s_lib_ver.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * MACRO for standards
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+/*
+ * define and initialize _LIB_VERSION
+ */
+#ifdef _POSIX_MODE
+_LIB_VERSION_TYPE _LIB_VERSION = _POSIX_;
+#else
+#ifdef _XOPEN_MODE
+_LIB_VERSION_TYPE _LIB_VERSION = _XOPEN_;
+#else
+#ifdef _SVID3_MODE
+_LIB_VERSION_TYPE _LIB_VERSION = _SVID_;
+#else /* default _IEEE_MODE */
+_LIB_VERSION_TYPE _LIB_VERSION = _IEEE_;
+#endif
+#endif
+#endif
diff --git a/lib/msun/src/s_log1p.c b/lib/msun/src/s_log1p.c
new file mode 100644
index 0000000..07bc93a
--- /dev/null
+++ b/lib/msun/src/s_log1p.c
@@ -0,0 +1,173 @@
+/* @(#)s_log1p.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* double log1p(double x)
+ *
+ * Method :
+ * 1. Argument Reduction: find k and f such that
+ * 1+x = 2^k * (1+f),
+ * where sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ * Note. If k=0, then f=x is exact. However, if k!=0, then f
+ * may not be representable exactly. In that case, a correction
+ * term is need. Let u=1+x rounded. Let c = (1+x)-u, then
+ * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
+ * and add back the correction term c/u.
+ * (Note: when x > 2**53, one can simply return log(x))
+ *
+ * 2. Approximation of log1p(f).
+ * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ * = 2s + s*R
+ * We use a special Reme algorithm on [0,0.1716] to generate
+ * a polynomial of degree 14 to approximate R The maximum error
+ * of this polynomial approximation is bounded by 2**-58.45. In
+ * other words,
+ * 2 4 6 8 10 12 14
+ * R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s
+ * (the values of Lp1 to Lp7 are listed in the program)
+ * and
+ * | 2 14 | -58.45
+ * | Lp1*s +...+Lp7*s - R(z) | <= 2
+ * | |
+ * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ * In order to guarantee error in log below 1ulp, we compute log
+ * by
+ * log1p(f) = f - (hfsq - s*(hfsq+R)).
+ *
+ * 3. Finally, log1p(x) = k*ln2 + log1p(f).
+ * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ * Here ln2 is split into two floating point number:
+ * ln2_hi + ln2_lo,
+ * where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ * log1p(x) is NaN with signal if x < -1 (including -INF) ;
+ * log1p(+INF) is +INF; log1p(-1) is -INF with signal;
+ * log1p(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ *
+ * Note: Assuming log() return accurate answer, the following
+ * algorithm can be used to compute log1p(x) to within a few ULP:
+ *
+ * u = 1+x;
+ * if(u==1.0) return x ; else
+ * return log(u)*(x/(u-1.0));
+ *
+ * See HP-15C Advanced Functions Handbook, p.193.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
+ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
+two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
+Lp1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
+Lp2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
+Lp3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
+Lp4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
+Lp5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
+Lp6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
+Lp7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
+
+#ifdef __STDC__
+static const double zero = 0.0;
+#else
+static double zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ double log1p(double x)
+#else
+ double log1p(x)
+ double x;
+#endif
+{
+ double hfsq,f,c,s,z,R,u;
+ int32_t k,hx,hu,ax;
+
+ GET_HIGH_WORD(hx,x);
+ ax = hx&0x7fffffff;
+
+ k = 1;
+ if (hx < 0x3FDA827A) { /* x < 0.41422 */
+ if(ax>=0x3ff00000) { /* x <= -1.0 */
+ if(x==-1.0) return -two54/zero; /* log1p(-1)=+inf */
+ else return (x-x)/(x-x); /* log1p(x<-1)=NaN */
+ }
+ if(ax<0x3e200000) { /* |x| < 2**-29 */
+ if(two54+x>zero /* raise inexact */
+ &&ax<0x3c900000) /* |x| < 2**-54 */
+ return x;
+ else
+ return x - x*x*0.5;
+ }
+ if(hx>0||hx<=((int32_t)0xbfd2bec3)) {
+ k=0;f=x;hu=1;} /* -0.2929<x<0.41422 */
+ }
+ if (hx >= 0x7ff00000) return x+x;
+ if(k!=0) {
+ if(hx<0x43400000) {
+ u = 1.0+x;
+ GET_HIGH_WORD(hu,u);
+ k = (hu>>20)-1023;
+ c = (k>0)? 1.0-(u-x):x-(u-1.0);/* correction term */
+ c /= u;
+ } else {
+ u = x;
+ GET_HIGH_WORD(hu,u);
+ k = (hu>>20)-1023;
+ c = 0;
+ }
+ hu &= 0x000fffff;
+ if(hu<0x6a09e) {
+ SET_HIGH_WORD(u,hu|0x3ff00000); /* normalize u */
+ } else {
+ k += 1;
+ SET_HIGH_WORD(u,hu|0x3fe00000); /* normalize u/2 */
+ hu = (0x00100000-hu)>>2;
+ }
+ f = u-1.0;
+ }
+ hfsq=0.5*f*f;
+ if(hu==0) { /* |f| < 2**-20 */
+ if(f==zero) if(k==0) return zero;
+ else {c += k*ln2_lo; return k*ln2_hi+c;}
+ R = hfsq*(1.0-0.66666666666666666*f);
+ if(k==0) return f-R; else
+ return k*ln2_hi-((R-(k*ln2_lo+c))-f);
+ }
+ s = f/(2.0+f);
+ z = s*s;
+ R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
+ if(k==0) return f-(hfsq-s*(hfsq+R)); else
+ return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
+}
diff --git a/lib/msun/src/s_log1pf.c b/lib/msun/src/s_log1pf.c
new file mode 100644
index 0000000..54b3c61
--- /dev/null
+++ b/lib/msun/src/s_log1pf.c
@@ -0,0 +1,112 @@
+/* s_log1pf.c -- float version of s_log1p.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
+ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
+two25 = 3.355443200e+07, /* 0x4c000000 */
+Lp1 = 6.6666668653e-01, /* 3F2AAAAB */
+Lp2 = 4.0000000596e-01, /* 3ECCCCCD */
+Lp3 = 2.8571429849e-01, /* 3E924925 */
+Lp4 = 2.2222198546e-01, /* 3E638E29 */
+Lp5 = 1.8183572590e-01, /* 3E3A3325 */
+Lp6 = 1.5313838422e-01, /* 3E1CD04F */
+Lp7 = 1.4798198640e-01; /* 3E178897 */
+
+#ifdef __STDC__
+static const float zero = 0.0;
+#else
+static float zero = 0.0;
+#endif
+
+#ifdef __STDC__
+ float log1pf(float x)
+#else
+ float log1pf(x)
+ float x;
+#endif
+{
+ float hfsq,f,c,s,z,R,u;
+ int32_t k,hx,hu,ax;
+
+ GET_FLOAT_WORD(hx,x);
+ ax = hx&0x7fffffff;
+
+ k = 1;
+ if (hx < 0x3ed413d7) { /* x < 0.41422 */
+ if(ax>=0x3f800000) { /* x <= -1.0 */
+ if(x==(float)-1.0) return -two25/zero; /* log1p(-1)=+inf */
+ else return (x-x)/(x-x); /* log1p(x<-1)=NaN */
+ }
+ if(ax<0x31000000) { /* |x| < 2**-29 */
+ if(two25+x>zero /* raise inexact */
+ &&ax<0x24800000) /* |x| < 2**-54 */
+ return x;
+ else
+ return x - x*x*(float)0.5;
+ }
+ if(hx>0||hx<=((int32_t)0xbe95f61f)) {
+ k=0;f=x;hu=1;} /* -0.2929<x<0.41422 */
+ }
+ if (hx >= 0x7f800000) return x+x;
+ if(k!=0) {
+ if(hx<0x5a000000) {
+ u = (float)1.0+x;
+ GET_FLOAT_WORD(hu,u);
+ k = (hu>>23)-127;
+ /* correction term */
+ c = (k>0)? (float)1.0-(u-x):x-(u-(float)1.0);
+ c /= u;
+ } else {
+ u = x;
+ GET_FLOAT_WORD(hu,u);
+ k = (hu>>23)-127;
+ c = 0;
+ }
+ hu &= 0x007fffff;
+ if(hu<0x3504f7) {
+ SET_FLOAT_WORD(u,hu|0x3f800000);/* normalize u */
+ } else {
+ k += 1;
+ SET_FLOAT_WORD(u,hu|0x3f000000); /* normalize u/2 */
+ hu = (0x00800000-hu)>>2;
+ }
+ f = u-(float)1.0;
+ }
+ hfsq=(float)0.5*f*f;
+ if(hu==0) { /* |f| < 2**-20 */
+ if(f==zero) if(k==0) return zero;
+ else {c += k*ln2_lo; return k*ln2_hi+c;}
+ R = hfsq*((float)1.0-(float)0.66666666666666666*f);
+ if(k==0) return f-R; else
+ return k*ln2_hi-((R-(k*ln2_lo+c))-f);
+ }
+ s = f/((float)2.0+f);
+ z = s*s;
+ R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
+ if(k==0) return f-(hfsq-s*(hfsq+R)); else
+ return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
+}
diff --git a/lib/msun/src/s_logb.c b/lib/msun/src/s_logb.c
new file mode 100644
index 0000000..aac20e3
--- /dev/null
+++ b/lib/msun/src/s_logb.c
@@ -0,0 +1,42 @@
+/* @(#)s_logb.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * double logb(x)
+ * IEEE 754 logb. Included to pass IEEE test suite. Not recommend.
+ * Use ilogb instead.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double __generic_logb(double x)
+#else
+ double __generic_logb(x)
+ double x;
+#endif
+{
+ int32_t lx,ix;
+ EXTRACT_WORDS(ix,lx,x);
+ ix &= 0x7fffffff; /* high |x| */
+ if((ix|lx)==0) return -1.0/fabs(x);
+ if(ix>=0x7ff00000) return x*x;
+ if((ix>>=20)==0) /* IEEE 754 logb */
+ return -1022.0;
+ else
+ return (double) (ix-1023);
+}
diff --git a/lib/msun/src/s_logbf.c b/lib/msun/src/s_logbf.c
new file mode 100644
index 0000000..5769e2d
--- /dev/null
+++ b/lib/msun/src/s_logbf.c
@@ -0,0 +1,39 @@
+/* s_logbf.c -- float version of s_logb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float logbf(float x)
+#else
+ float logbf(x)
+ float x;
+#endif
+{
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff; /* high |x| */
+ if(ix==0) return (float)-1.0/fabsf(x);
+ if(ix>=0x7f800000) return x*x;
+ if((ix>>=23)==0) /* IEEE 754 logb */
+ return -126.0;
+ else
+ return (float) (ix-127);
+}
diff --git a/lib/msun/src/s_matherr.c b/lib/msun/src/s_matherr.c
new file mode 100644
index 0000000..fbc5664
--- /dev/null
+++ b/lib/msun/src/s_matherr.c
@@ -0,0 +1,30 @@
+/* @(#)s_matherr.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ int matherr(struct exception *x)
+#else
+ int matherr(x)
+ struct exception *x;
+#endif
+{
+ int n=0;
+ if(x->arg1!=x->arg1) return 0;
+ return n;
+}
diff --git a/lib/msun/src/s_modf.c b/lib/msun/src/s_modf.c
new file mode 100644
index 0000000..d82cda3
--- /dev/null
+++ b/lib/msun/src/s_modf.c
@@ -0,0 +1,83 @@
+/* @(#)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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * 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 "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double one = 1.0;
+#else
+static double one = 1.0;
+#endif
+
+#ifdef __STDC__
+ double modf(double x, double *iptr)
+#else
+ double modf(x, iptr)
+ double x,*iptr;
+#endif
+{
+ 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;
+ *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/msun/src/s_modff.c b/lib/msun/src/s_modff.c
new file mode 100644
index 0000000..8fd9bb0
--- /dev/null
+++ b/lib/msun/src/s_modff.c
@@ -0,0 +1,64 @@
+/* s_modff.c -- float version of s_modf.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float one = 1.0;
+#else
+static float one = 1.0;
+#endif
+
+#ifdef __STDC__
+ float modff(float x, float *iptr)
+#else
+ float modff(x, iptr)
+ float x,*iptr;
+#endif
+{
+ int32_t i0,j0;
+ u_int32_t i;
+ GET_FLOAT_WORD(i0,x);
+ j0 = ((i0>>23)&0xff)-0x7f; /* exponent of x */
+ if(j0<23) { /* integer part in x */
+ if(j0<0) { /* |x|<1 */
+ SET_FLOAT_WORD(*iptr,i0&0x80000000); /* *iptr = +-0 */
+ return x;
+ } else {
+ i = (0x007fffff)>>j0;
+ if((i0&i)==0) { /* x is integral */
+ u_int32_t ix;
+ *iptr = x;
+ GET_FLOAT_WORD(ix,x);
+ SET_FLOAT_WORD(x,ix&0x80000000); /* return +-0 */
+ return x;
+ } else {
+ SET_FLOAT_WORD(*iptr,i0&(~i));
+ return x - *iptr;
+ }
+ }
+ } else { /* no fraction part */
+ u_int32_t ix;
+ *iptr = x*one;
+ GET_FLOAT_WORD(ix,x);
+ SET_FLOAT_WORD(x,ix&0x80000000); /* return +-0 */
+ return x;
+ }
+}
diff --git a/lib/msun/src/s_nextafter.c b/lib/msun/src/s_nextafter.c
new file mode 100644
index 0000000..877f7b8
--- /dev/null
+++ b/lib/msun/src/s_nextafter.c
@@ -0,0 +1,79 @@
+/* @(#)s_nextafter.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* IEEE functions
+ * nextafter(x,y)
+ * return the next machine floating-point number of x in the
+ * direction toward y.
+ * Special cases:
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double nextafter(double x, double y)
+#else
+ double nextafter(x,y)
+ double x,y;
+#endif
+{
+ int32_t hx,hy,ix,iy;
+ u_int32_t lx,ly;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hy,ly,y);
+ ix = hx&0x7fffffff; /* |x| */
+ iy = hy&0x7fffffff; /* |y| */
+
+ if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */
+ ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */
+ return x+y;
+ if(x==y) return x; /* x=y, return x */
+ if((ix|lx)==0) { /* x == 0 */
+ INSERT_WORDS(x,hy&0x80000000,1); /* return +-minsubnormal */
+ y = x*x;
+ if(y==x) return y; else return x; /* raise underflow flag */
+ }
+ if(hx>=0) { /* x > 0 */
+ if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */
+ if(lx==0) hx -= 1;
+ lx -= 1;
+ } else { /* x < y, x += ulp */
+ lx += 1;
+ if(lx==0) hx += 1;
+ }
+ } else { /* x < 0 */
+ if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
+ if(lx==0) hx -= 1;
+ lx -= 1;
+ } else { /* x > y, x += ulp */
+ lx += 1;
+ if(lx==0) hx += 1;
+ }
+ }
+ hy = hx&0x7ff00000;
+ if(hy>=0x7ff00000) return x+x; /* overflow */
+ if(hy<0x00100000) { /* underflow */
+ y = x*x;
+ if(y!=x) { /* raise underflow flag */
+ INSERT_WORDS(y,hx,lx);
+ return y;
+ }
+ }
+ INSERT_WORDS(x,hx,lx);
+ return x;
+}
diff --git a/lib/msun/src/s_nextafterf.c b/lib/msun/src/s_nextafterf.c
new file mode 100644
index 0000000..e9fd541
--- /dev/null
+++ b/lib/msun/src/s_nextafterf.c
@@ -0,0 +1,70 @@
+/* s_nextafterf.c -- float version of s_nextafter.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float nextafterf(float x, float y)
+#else
+ float nextafterf(x,y)
+ float x,y;
+#endif
+{
+ int32_t hx,hy,ix,iy;
+
+ GET_FLOAT_WORD(hx,x);
+ GET_FLOAT_WORD(hy,y);
+ ix = hx&0x7fffffff; /* |x| */
+ iy = hy&0x7fffffff; /* |y| */
+
+ if((ix>0x7f800000) || /* x is nan */
+ (iy>0x7f800000)) /* y is nan */
+ return x+y;
+ if(x==y) return x; /* x=y, return x */
+ if(ix==0) { /* x == 0 */
+ SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */
+ y = x*x;
+ if(y==x) return y; else return x; /* raise underflow flag */
+ }
+ if(hx>=0) { /* x > 0 */
+ if(hx>hy) { /* x > y, x -= ulp */
+ hx -= 1;
+ } else { /* x < y, x += ulp */
+ hx += 1;
+ }
+ } else { /* x < 0 */
+ if(hy>=0||hx>hy){ /* x < y, x -= ulp */
+ hx -= 1;
+ } else { /* x > y, x += ulp */
+ hx += 1;
+ }
+ }
+ hy = hx&0x7f800000;
+ if(hy>=0x7f800000) return x+x; /* overflow */
+ if(hy<0x00800000) { /* underflow */
+ y = x*x;
+ if(y!=x) { /* raise underflow flag */
+ SET_FLOAT_WORD(y,hx);
+ return y;
+ }
+ }
+ SET_FLOAT_WORD(x,hx);
+ return x;
+}
diff --git a/lib/msun/src/s_rint.c b/lib/msun/src/s_rint.c
new file mode 100644
index 0000000..a289102
--- /dev/null
+++ b/lib/msun/src/s_rint.c
@@ -0,0 +1,93 @@
+/* @(#)s_rint.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * rint(x)
+ * Return x rounded to integral value according to the prevailing
+ * rounding mode.
+ * Method:
+ * Using floating addition.
+ * Exception:
+ * Inexact flag raised if x not equal to rint(x).
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+/*
+ * TWO23 is long double instead of double to avoid a bug in gcc. Without
+ * this, gcc thinks that TWO23[sx]+x and w-TWO23[sx] already have double
+ * precision and doesn't clip them to double precision when they are
+ * assigned and returned. Use long double even in the !__STDC__ case in
+ * case this is compiled with gcc -traditional.
+ */
+#ifdef __STDC__
+static const long double
+#else
+static long double
+#endif
+TWO52[2]={
+ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+};
+
+#ifdef __STDC__
+ double __generic_rint(double x)
+#else
+ double __generic_rint(x)
+ double x;
+#endif
+{
+ int32_t i0,j0,sx;
+ u_int32_t i,i1;
+ double w,t;
+ EXTRACT_WORDS(i0,i1,x);
+ sx = (i0>>31)&1;
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) {
+ if(((i0&0x7fffffff)|i1)==0) return x;
+ i1 |= (i0&0x0fffff);
+ i0 &= 0xfffe0000;
+ i0 |= ((i1|-i1)>>12)&0x80000;
+ SET_HIGH_WORD(x,i0);
+ w = TWO52[sx]+x;
+ t = w-TWO52[sx];
+ GET_HIGH_WORD(i0,t);
+ SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
+ return t;
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ i>>=1;
+ if(((i0&i)|i1)!=0) {
+ if(j0==19) i1 = 0x40000000; else
+ i0 = (i0&(~i))|((0x20000)>>j0);
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((u_int32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) return x; /* x is integral */
+ i>>=1;
+ if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
+ }
+ INSERT_WORDS(x,i0,i1);
+ w = TWO52[sx]+x;
+ return w-TWO52[sx];
+}
diff --git a/lib/msun/src/s_rintf.c b/lib/msun/src/s_rintf.c
new file mode 100644
index 0000000..9db496a
--- /dev/null
+++ b/lib/msun/src/s_rintf.c
@@ -0,0 +1,77 @@
+/* s_rintf.c -- float version of s_rint.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+/*
+ * TWO23 is double instead of float to avoid a bug in gcc. Without
+ * this, gcc thinks that TWO23[sx]+x and w-TWO23[sx] already have float
+ * precision and doesn't clip them to float precision when they are
+ * assigned and returned.
+ */
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+TWO23[2]={
+ 8.3886080000e+06, /* 0x4b000000 */
+ -8.3886080000e+06, /* 0xcb000000 */
+};
+
+#ifdef __STDC__
+ float rintf(float x)
+#else
+ float rintf(x)
+ float x;
+#endif
+{
+ int32_t i0,j0,sx;
+ u_int32_t i,i1;
+ float w,t;
+ GET_FLOAT_WORD(i0,x);
+ sx = (i0>>31)&1;
+ j0 = ((i0>>23)&0xff)-0x7f;
+ if(j0<23) {
+ if(j0<0) {
+ if((i0&0x7fffffff)==0) return x;
+ i1 = (i0&0x07fffff);
+ i0 &= 0xfff00000;
+ i0 |= ((i1|-i1)>>9)&0x400000;
+ SET_FLOAT_WORD(x,i0);
+ w = TWO23[sx]+x;
+ t = w-TWO23[sx];
+ GET_FLOAT_WORD(i0,t);
+ SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31));
+ return t;
+ } else {
+ i = (0x007fffff)>>j0;
+ if((i0&i)==0) return x; /* x is integral */
+ i>>=1;
+ if((i0&i)!=0) i0 = (i0&(~i))|((0x100000)>>j0);
+ }
+ } else {
+ if(j0==0x80) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ }
+ SET_FLOAT_WORD(x,i0);
+ w = TWO23[sx]+x;
+ return w-TWO23[sx];
+}
diff --git a/lib/msun/src/s_scalbn.c b/lib/msun/src/s_scalbn.c
new file mode 100644
index 0000000..3159215
--- /dev/null
+++ b/lib/msun/src/s_scalbn.c
@@ -0,0 +1,66 @@
+/* @(#)s_scalbn.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * scalbn (double x, int n)
+ * scalbn(x,n) returns x* 2**n computed by exponent
+ * manipulation rather than by actually performing an
+ * exponentiation or a multiplication.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
+huge = 1.0e+300,
+tiny = 1.0e-300;
+
+#ifdef __STDC__
+ double __generic_scalbn (double x, int n)
+#else
+ double __generic_scalbn (x,n)
+ double x; int n;
+#endif
+{
+ 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/msun/src/s_scalbnf.c b/lib/msun/src/s_scalbnf.c
new file mode 100644
index 0000000..af1b099
--- /dev/null
+++ b/lib/msun/src/s_scalbnf.c
@@ -0,0 +1,62 @@
+/* s_scalbnf.c -- float version of s_scalbn.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+two25 = 3.355443200e+07, /* 0x4c000000 */
+twom25 = 2.9802322388e-08, /* 0x33000000 */
+huge = 1.0e+30,
+tiny = 1.0e-30;
+
+#ifdef __STDC__
+ float scalbnf (float x, int n)
+#else
+ float scalbn (x,n)
+ float x; int n;
+#endif
+{
+ int32_t k,ix;
+ GET_FLOAT_WORD(ix,x);
+ k = (ix&0x7f800000)>>23; /* extract exponent */
+ if (k==0) { /* 0 or subnormal x */
+ if ((ix&0x7fffffff)==0) return x; /* +-0 */
+ x *= two25;
+ GET_FLOAT_WORD(ix,x);
+ k = ((ix&0x7f800000)>>23) - 25;
+ if (n< -50000) return tiny*x; /*underflow*/
+ }
+ if (k==0xff) return x+x; /* NaN or Inf */
+ k = k+n;
+ if (k > 0xfe) return huge*copysignf(huge,x); /* overflow */
+ if (k > 0) /* normal result */
+ {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
+ if (k <= -25)
+ if (n > 50000) /* in case integer overflow in n+k */
+ return huge*copysignf(huge,x); /*overflow*/
+ else return tiny*copysignf(tiny,x); /*underflow*/
+ k += 25; /* subnormal result */
+ SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
+ return x*twom25;
+}
diff --git a/lib/msun/src/s_signgam.c b/lib/msun/src/s_signgam.c
new file mode 100644
index 0000000..d67d591
--- /dev/null
+++ b/lib/msun/src/s_signgam.c
@@ -0,0 +1,3 @@
+#include "math.h"
+#include "math_private.h"
+int signgam = 0;
diff --git a/lib/msun/src/s_significand.c b/lib/msun/src/s_significand.c
new file mode 100644
index 0000000..4bbf36d
--- /dev/null
+++ b/lib/msun/src/s_significand.c
@@ -0,0 +1,34 @@
+/* @(#)s_signif.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * significand(x) computes just
+ * scalb(x, (double) -ilogb(x)),
+ * for exercising the fraction-part(F) IEEE 754-1985 test vector.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double __generic_significand(double x)
+#else
+ double __generic_significand(x)
+ double x;
+#endif
+{
+ return __ieee754_scalb(x,(double) -ilogb(x));
+}
diff --git a/lib/msun/src/s_significandf.c b/lib/msun/src/s_significandf.c
new file mode 100644
index 0000000..ce46be8
--- /dev/null
+++ b/lib/msun/src/s_significandf.c
@@ -0,0 +1,31 @@
+/* s_significandf.c -- float version of s_significand.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float significandf(float x)
+#else
+ float significandf(x)
+ float x;
+#endif
+{
+ return __ieee754_scalbf(x,(float) -ilogbf(x));
+}
diff --git a/lib/msun/src/s_sin.c b/lib/msun/src/s_sin.c
new file mode 100644
index 0000000..d12a495
--- /dev/null
+++ b/lib/msun/src/s_sin.c
@@ -0,0 +1,82 @@
+/* @(#)s_sin.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* sin(x)
+ * Return sine function of x.
+ *
+ * kernel function:
+ * __kernel_sin ... sine function on [-pi/4,pi/4]
+ * __kernel_cos ... cose function on [-pi/4,pi/4]
+ * __ieee754_rem_pio2 ... argument reduction routine
+ *
+ * Method.
+ * Let S,C and T denote the sin, cos and tan respectively on
+ * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ * in [-pi/4 , +pi/4], and let n = k mod 4.
+ * We have
+ *
+ * n sin(x) cos(x) tan(x)
+ * ----------------------------------------------------------
+ * 0 S C T
+ * 1 C -S -1/T
+ * 2 -S -C T
+ * 3 -C S -1/T
+ * ----------------------------------------------------------
+ *
+ * Special cases:
+ * Let trig be any of sin, cos, or tan.
+ * trig(+-INF) is NaN, with signals;
+ * trig(NaN) is that NaN;
+ *
+ * Accuracy:
+ * TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double __generic_sin(double x)
+#else
+ double __generic_sin(x)
+ double x;
+#endif
+{
+ double y[2],z=0.0;
+ int32_t n, ix;
+
+ /* High word of x. */
+ GET_HIGH_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0);
+
+ /* sin(Inf or NaN) is NaN */
+ else if (ix>=0x7ff00000) return x-x;
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2(x,y);
+ switch(n&3) {
+ case 0: return __kernel_sin(y[0],y[1],1);
+ case 1: return __kernel_cos(y[0],y[1]);
+ case 2: return -__kernel_sin(y[0],y[1],1);
+ default:
+ return -__kernel_cos(y[0],y[1]);
+ }
+ }
+}
diff --git a/lib/msun/src/s_sinf.c b/lib/msun/src/s_sinf.c
new file mode 100644
index 0000000..d6ac1a0
--- /dev/null
+++ b/lib/msun/src/s_sinf.c
@@ -0,0 +1,53 @@
+/* s_sinf.c -- float version of s_sin.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float sinf(float x)
+#else
+ float sinf(x)
+ float x;
+#endif
+{
+ float y[2],z=0.0;
+ int32_t n, ix;
+
+ GET_FLOAT_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0);
+
+ /* sin(Inf or NaN) is NaN */
+ else if (ix>=0x7f800000) return x-x;
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2f(x,y);
+ switch(n&3) {
+ case 0: return __kernel_sinf(y[0],y[1],1);
+ case 1: return __kernel_cosf(y[0],y[1]);
+ case 2: return -__kernel_sinf(y[0],y[1],1);
+ default:
+ return -__kernel_cosf(y[0],y[1]);
+ }
+ }
+}
diff --git a/lib/msun/src/s_tan.c b/lib/msun/src/s_tan.c
new file mode 100644
index 0000000..f63a213
--- /dev/null
+++ b/lib/msun/src/s_tan.c
@@ -0,0 +1,76 @@
+/* @(#)s_tan.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* tan(x)
+ * Return tangent function of x.
+ *
+ * kernel function:
+ * __kernel_tan ... tangent function on [-pi/4,pi/4]
+ * __ieee754_rem_pio2 ... argument reduction routine
+ *
+ * Method.
+ * Let S,C and T denote the sin, cos and tan respectively on
+ * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ * in [-pi/4 , +pi/4], and let n = k mod 4.
+ * We have
+ *
+ * n sin(x) cos(x) tan(x)
+ * ----------------------------------------------------------
+ * 0 S C T
+ * 1 C -S -1/T
+ * 2 -S -C T
+ * 3 -C S -1/T
+ * ----------------------------------------------------------
+ *
+ * Special cases:
+ * Let trig be any of sin, cos, or tan.
+ * trig(+-INF) is NaN, with signals;
+ * trig(NaN) is that NaN;
+ *
+ * Accuracy:
+ * TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double __generic_tan(double x)
+#else
+ double __generic_tan(x)
+ double x;
+#endif
+{
+ double y[2],z=0.0;
+ int32_t n, ix;
+
+ /* High word of x. */
+ GET_HIGH_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1);
+
+ /* tan(Inf or NaN) is NaN */
+ else if (ix>=0x7ff00000) return x-x; /* NaN */
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2(x,y);
+ return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even
+ -1 -- n odd */
+ }
+}
diff --git a/lib/msun/src/s_tanf.c b/lib/msun/src/s_tanf.c
new file mode 100644
index 0000000..e7f51c7
--- /dev/null
+++ b/lib/msun/src/s_tanf.c
@@ -0,0 +1,48 @@
+/* s_tanf.c -- float version of s_tan.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float tanf(float x)
+#else
+ float tanf(x)
+ float x;
+#endif
+{
+ float y[2],z=0.0;
+ int32_t n, ix;
+
+ GET_FLOAT_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3f490fda) return __kernel_tanf(x,z,1);
+
+ /* tan(Inf or NaN) is NaN */
+ else if (ix>=0x7f800000) return x-x; /* NaN */
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2f(x,y);
+ return __kernel_tanf(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even
+ -1 -- n odd */
+ }
+}
diff --git a/lib/msun/src/s_tanh.c b/lib/msun/src/s_tanh.c
new file mode 100644
index 0000000..8eb3197
--- /dev/null
+++ b/lib/msun/src/s_tanh.c
@@ -0,0 +1,86 @@
+/* @(#)s_tanh.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* Tanh(x)
+ * Return the Hyperbolic Tangent of x
+ *
+ * Method :
+ * x -x
+ * e - e
+ * 0. tanh(x) is defined to be -----------
+ * x -x
+ * e + e
+ * 1. reduce x to non-negative by tanh(-x) = -tanh(x).
+ * 2. 0 <= x <= 2**-55 : tanh(x) := x*(one+x)
+ * -t
+ * 2**-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x)
+ * t + 2
+ * 2
+ * 1 <= x <= 22.0 : tanh(x) := 1- ----- ; t=expm1(2x)
+ * t + 2
+ * 22.0 < x <= INF : tanh(x) := 1.
+ *
+ * Special cases:
+ * tanh(NaN) is NaN;
+ * only tanh(0)=0 is exact for finite argument.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double one=1.0, two=2.0, tiny = 1.0e-300;
+#else
+static double one=1.0, two=2.0, tiny = 1.0e-300;
+#endif
+
+#ifdef __STDC__
+ double tanh(double x)
+#else
+ double tanh(x)
+ double x;
+#endif
+{
+ double t,z;
+ int32_t jx,ix;
+
+ /* High word of |x|. */
+ GET_HIGH_WORD(jx,x);
+ ix = jx&0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7ff00000) {
+ if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */
+ else return one/x-one; /* tanh(NaN) = NaN */
+ }
+
+ /* |x| < 22 */
+ if (ix < 0x40360000) { /* |x|<22 */
+ if (ix<0x3c800000) /* |x|<2**-55 */
+ return x*(one+x); /* tanh(small) = small */
+ if (ix>=0x3ff00000) { /* |x|>=1 */
+ t = expm1(two*fabs(x));
+ z = one - two/(t+two);
+ } else {
+ t = expm1(-two*fabs(x));
+ z= -t/(t+two);
+ }
+ /* |x| > 22, return +-1 */
+ } else {
+ z = one - tiny; /* raised inexact flag */
+ }
+ return (jx>=0)? z: -z;
+}
diff --git a/lib/msun/src/s_tanhf.c b/lib/msun/src/s_tanhf.c
new file mode 100644
index 0000000..f8b41c8
--- /dev/null
+++ b/lib/msun/src/s_tanhf.c
@@ -0,0 +1,64 @@
+/* s_tanhf.c -- float version of s_tanh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float one=1.0, two=2.0, tiny = 1.0e-30;
+#else
+static float one=1.0, two=2.0, tiny = 1.0e-30;
+#endif
+
+#ifdef __STDC__
+ float tanhf(float x)
+#else
+ float tanhf(x)
+ float x;
+#endif
+{
+ float t,z;
+ int32_t jx,ix;
+
+ GET_FLOAT_WORD(jx,x);
+ ix = jx&0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7f800000) {
+ if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */
+ else return one/x-one; /* tanh(NaN) = NaN */
+ }
+
+ /* |x| < 22 */
+ if (ix < 0x41b00000) { /* |x|<22 */
+ if (ix<0x24000000) /* |x|<2**-55 */
+ return x*(one+x); /* tanh(small) = small */
+ if (ix>=0x3f800000) { /* |x|>=1 */
+ t = expm1f(two*fabsf(x));
+ z = one - two/(t+two);
+ } else {
+ t = expm1f(-two*fabsf(x));
+ z= -t/(t+two);
+ }
+ /* |x| > 22, return +-1 */
+ } else {
+ z = one - tiny; /* raised inexact flag */
+ }
+ return (jx>=0)? z: -z;
+}
diff --git a/lib/msun/src/w_acos.c b/lib/msun/src/w_acos.c
new file mode 100644
index 0000000..21f2ff4
--- /dev/null
+++ b/lib/msun/src/w_acos.c
@@ -0,0 +1,43 @@
+/* @(#)w_acos.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrap_acos(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ double acos(double x) /* wrapper acos */
+#else
+ double acos(x) /* wrapper acos */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_acos(x);
+#else
+ double z;
+ z = __ieee754_acos(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
+ if(fabs(x)>1.0) {
+ return __kernel_standard(x,x,1); /* acos(|x|>1) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_acosf.c b/lib/msun/src/w_acosf.c
new file mode 100644
index 0000000..70d2f13
--- /dev/null
+++ b/lib/msun/src/w_acosf.c
@@ -0,0 +1,47 @@
+/* w_acosf.c -- float version of w_acos.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrap_acosf(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ float acosf(float x) /* wrapper acosf */
+#else
+ float acosf(x) /* wrapper acosf */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_acosf(x);
+#else
+ float z;
+ z = __ieee754_acosf(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x)) return z;
+ if(fabsf(x)>(float)1.0) {
+ /* acosf(|x|>1) */
+ return (float)__kernel_standard((double)x,(double)x,101);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_acosh.c b/lib/msun/src/w_acosh.c
new file mode 100644
index 0000000..5533f22
--- /dev/null
+++ b/lib/msun/src/w_acosh.c
@@ -0,0 +1,42 @@
+/* @(#)w_acosh.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper acosh(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double acosh(double x) /* wrapper acosh */
+#else
+ double acosh(x) /* wrapper acosh */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_acosh(x);
+#else
+ double z;
+ z = __ieee754_acosh(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
+ if(x<1.0) {
+ return __kernel_standard(x,x,29); /* acosh(x<1) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_acoshf.c b/lib/msun/src/w_acoshf.c
new file mode 100644
index 0000000..73b2f06c
--- /dev/null
+++ b/lib/msun/src/w_acoshf.c
@@ -0,0 +1,47 @@
+/* w_acoshf.c -- float version of w_acosh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ *
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper acoshf(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float acoshf(float x) /* wrapper acoshf */
+#else
+ float acoshf(x) /* wrapper acoshf */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_acoshf(x);
+#else
+ float z;
+ z = __ieee754_acoshf(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x)) return z;
+ if(x<(float)1.0) {
+ /* acosh(x<1) */
+ return (float)__kernel_standard((double)x,(double)x,129);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_asin.c b/lib/msun/src/w_asin.c
new file mode 100644
index 0000000..3620c00
--- /dev/null
+++ b/lib/msun/src/w_asin.c
@@ -0,0 +1,44 @@
+/* @(#)w_asin.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper asin(x)
+ */
+
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ double asin(double x) /* wrapper asin */
+#else
+ double asin(x) /* wrapper asin */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_asin(x);
+#else
+ double z;
+ z = __ieee754_asin(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
+ if(fabs(x)>1.0) {
+ return __kernel_standard(x,x,2); /* asin(|x|>1) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_asinf.c b/lib/msun/src/w_asinf.c
new file mode 100644
index 0000000..02392bb
--- /dev/null
+++ b/lib/msun/src/w_asinf.c
@@ -0,0 +1,48 @@
+/* w_asinf.c -- float version of w_asin.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper asinf(x)
+ */
+
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ float asinf(float x) /* wrapper asinf */
+#else
+ float asinf(x) /* wrapper asinf */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_asinf(x);
+#else
+ float z;
+ z = __ieee754_asinf(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x)) return z;
+ if(fabsf(x)>(float)1.0) {
+ /* asinf(|x|>1) */
+ return (float)__kernel_standard((double)x,(double)x,102);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_atan2.c b/lib/msun/src/w_atan2.c
new file mode 100644
index 0000000..1405d1c
--- /dev/null
+++ b/lib/msun/src/w_atan2.c
@@ -0,0 +1,43 @@
+/* @(#)w_atan2.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper atan2(y,x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ double atan2(double y, double x) /* wrapper atan2 */
+#else
+ double atan2(y,x) /* wrapper atan2 */
+ double y,x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_atan2(y,x);
+#else
+ double z;
+ z = __ieee754_atan2(y,x);
+ if(_LIB_VERSION == _IEEE_||isnan(x)||isnan(y)) return z;
+ if(x==0.0&&y==0.0) {
+ return __kernel_standard(y,x,3); /* atan2(+-0,+-0) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_atan2f.c b/lib/msun/src/w_atan2f.c
new file mode 100644
index 0000000..bba9f3b
--- /dev/null
+++ b/lib/msun/src/w_atan2f.c
@@ -0,0 +1,47 @@
+/* w_atan2f.c -- float version of w_atan2.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper atan2f(y,x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ float atan2f(float y, float x) /* wrapper atan2f */
+#else
+ float atan2f(y,x) /* wrapper atan2 */
+ float y,x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_atan2f(y,x);
+#else
+ float z;
+ z = __ieee754_atan2f(y,x);
+ if(_LIB_VERSION == _IEEE_||isnanf(x)||isnanf(y)) return z;
+ if(x==(float)0.0&&y==(float)0.0) {
+ /* atan2f(+-0,+-0) */
+ return (float)__kernel_standard((double)y,(double)x,103);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_atanh.c b/lib/msun/src/w_atanh.c
new file mode 100644
index 0000000..ba2aca9
--- /dev/null
+++ b/lib/msun/src/w_atanh.c
@@ -0,0 +1,47 @@
+/* @(#)w_atanh.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper atanh(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ double atanh(double x) /* wrapper atanh */
+#else
+ double atanh(x) /* wrapper atanh */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_atanh(x);
+#else
+ double z,y;
+ z = __ieee754_atanh(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
+ y = fabs(x);
+ if(y>=1.0) {
+ if(y>1.0)
+ return __kernel_standard(x,x,30); /* atanh(|x|>1) */
+ else
+ return __kernel_standard(x,x,31); /* atanh(|x|==1) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_atanhf.c b/lib/msun/src/w_atanhf.c
new file mode 100644
index 0000000..9556e34
--- /dev/null
+++ b/lib/msun/src/w_atanhf.c
@@ -0,0 +1,52 @@
+/* w_atanhf.c -- float version of w_atanh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper atanhf(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ float atanhf(float x) /* wrapper atanhf */
+#else
+ float atanhf(x) /* wrapper atanhf */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_atanhf(x);
+#else
+ float z,y;
+ z = __ieee754_atanhf(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x)) return z;
+ y = fabsf(x);
+ if(y>=(float)1.0) {
+ if(y>(float)1.0)
+ /* atanhf(|x|>1) */
+ return (float)__kernel_standard((double)x,(double)x,130);
+ else
+ /* atanhf(|x|==1) */
+ return (float)__kernel_standard((double)x,(double)x,131);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_cabs.c b/lib/msun/src/w_cabs.c
new file mode 100644
index 0000000..b140515
--- /dev/null
+++ b/lib/msun/src/w_cabs.c
@@ -0,0 +1,27 @@
+/*
+ * cabs() wrapper for hypot().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ */
+
+#include <math.h>
+
+struct complex {
+ double x;
+ double y;
+};
+
+double
+cabs(z)
+ struct complex z;
+{
+ return hypot(z.x, z.y);
+}
+
+double
+z_abs(z)
+ struct complex *z;
+{
+ return hypot(z->x, z->y);
+}
diff --git a/lib/msun/src/w_cabsf.c b/lib/msun/src/w_cabsf.c
new file mode 100644
index 0000000..6336d6d
--- /dev/null
+++ b/lib/msun/src/w_cabsf.c
@@ -0,0 +1,21 @@
+/*
+ * cabsf() wrapper for hypotf().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+struct complex {
+ float x;
+ float y;
+};
+
+float
+cabsf(z)
+ struct complex z;
+{
+ return hypotf(z.x, z.y);
+}
diff --git a/lib/msun/src/w_cosh.c b/lib/msun/src/w_cosh.c
new file mode 100644
index 0000000..0711687
--- /dev/null
+++ b/lib/msun/src/w_cosh.c
@@ -0,0 +1,42 @@
+/* @(#)w_cosh.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper cosh(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double cosh(double x) /* wrapper cosh */
+#else
+ double cosh(x) /* wrapper cosh */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_cosh(x);
+#else
+ double z;
+ z = __ieee754_cosh(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
+ if(fabs(x)>7.10475860073943863426e+02) {
+ return __kernel_standard(x,x,5); /* cosh overflow */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_coshf.c b/lib/msun/src/w_coshf.c
new file mode 100644
index 0000000..385bcfa
--- /dev/null
+++ b/lib/msun/src/w_coshf.c
@@ -0,0 +1,46 @@
+/* w_coshf.c -- float version of w_cosh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper coshf(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float coshf(float x) /* wrapper coshf */
+#else
+ float coshf(x) /* wrapper coshf */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_coshf(x);
+#else
+ float z;
+ z = __ieee754_coshf(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x)) return z;
+ if(fabsf(x)>(float)8.9415985107e+01) {
+ /* cosh overflow */
+ return (float)__kernel_standard((double)x,(double)x,105);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_drem.c b/lib/msun/src/w_drem.c
new file mode 100644
index 0000000..0f68409
--- /dev/null
+++ b/lib/msun/src/w_drem.c
@@ -0,0 +1,15 @@
+/*
+ * drem() wrapper for remainder().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ */
+
+#include <math.h>
+
+double
+drem(x, y)
+ double x, y;
+{
+ return remainder(x, y);
+}
diff --git a/lib/msun/src/w_dremf.c b/lib/msun/src/w_dremf.c
new file mode 100644
index 0000000..92079a9
--- /dev/null
+++ b/lib/msun/src/w_dremf.c
@@ -0,0 +1,16 @@
+/*
+ * dremf() wrapper for remainderf().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+float
+dremf(x, y)
+ float x, y;
+{
+ return remainderf(x, y);
+}
diff --git a/lib/msun/src/w_exp.c b/lib/msun/src/w_exp.c
new file mode 100644
index 0000000..4496acb
--- /dev/null
+++ b/lib/msun/src/w_exp.c
@@ -0,0 +1,53 @@
+/* @(#)w_exp.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper exp(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
+u_threshold= -7.45133219101941108420e+02; /* 0xc0874910, 0xD52D3051 */
+
+#ifdef __STDC__
+ double exp(double x) /* wrapper exp */
+#else
+ double exp(x) /* wrapper exp */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_exp(x);
+#else
+ double z;
+ z = __ieee754_exp(x);
+ if(_LIB_VERSION == _IEEE_) return z;
+ if(finite(x)) {
+ if(x>o_threshold)
+ return __kernel_standard(x,x,6); /* exp overflow */
+ else if(x<u_threshold)
+ return __kernel_standard(x,x,7); /* exp underflow */
+ }
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_expf.c b/lib/msun/src/w_expf.c
new file mode 100644
index 0000000..a775ac6
--- /dev/null
+++ b/lib/msun/src/w_expf.c
@@ -0,0 +1,58 @@
+/* w_expf.c -- float version of w_exp.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper expf(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+static const float
+#else
+static float
+#endif
+o_threshold= 8.8721679688e+01, /* 0x42b17180 */
+u_threshold= -1.0397208405e+02; /* 0xc2cff1b5 */
+
+#ifdef __STDC__
+ float expf(float x) /* wrapper expf */
+#else
+ float expf(x) /* wrapper expf */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_expf(x);
+#else
+ float z;
+ z = __ieee754_expf(x);
+ if(_LIB_VERSION == _IEEE_) return z;
+ if(finitef(x)) {
+ if(x>o_threshold)
+ /* exp overflow */
+ return (float)__kernel_standard((double)x,(double)x,106);
+ else if(x<u_threshold)
+ /* exp underflow */
+ return (float)__kernel_standard((double)x,(double)x,107);
+ }
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_fmod.c b/lib/msun/src/w_fmod.c
new file mode 100644
index 0000000..b420063
--- /dev/null
+++ b/lib/msun/src/w_fmod.c
@@ -0,0 +1,43 @@
+/* @(#)w_fmod.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper fmod(x,y)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ double fmod(double x, double y) /* wrapper fmod */
+#else
+ double fmod(x,y) /* wrapper fmod */
+ double x,y;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_fmod(x,y);
+#else
+ double z;
+ z = __ieee754_fmod(x,y);
+ if(_LIB_VERSION == _IEEE_ ||isnan(y)||isnan(x)) return z;
+ if(y==0.0) {
+ return __kernel_standard(x,y,27); /* fmod(x,0) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_fmodf.c b/lib/msun/src/w_fmodf.c
new file mode 100644
index 0000000..3cf05ed
--- /dev/null
+++ b/lib/msun/src/w_fmodf.c
@@ -0,0 +1,47 @@
+/* w_fmodf.c -- float version of w_fmod.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper fmodf(x,y)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ float fmodf(float x, float y) /* wrapper fmodf */
+#else
+ float fmodf(x,y) /* wrapper fmodf */
+ float x,y;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_fmodf(x,y);
+#else
+ float z;
+ z = __ieee754_fmodf(x,y);
+ if(_LIB_VERSION == _IEEE_ ||isnanf(y)||isnanf(x)) return z;
+ if(y==(float)0.0) {
+ /* fmodf(x,0) */
+ return (float)__kernel_standard((double)x,(double)y,127);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_gamma.c b/lib/msun/src/w_gamma.c
new file mode 100644
index 0000000..fd44c1c
--- /dev/null
+++ b/lib/msun/src/w_gamma.c
@@ -0,0 +1,49 @@
+/* @(#)w_gamma.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* double gamma(double x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call gamma_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+#ifdef __STDC__
+ double gamma(double x)
+#else
+ double gamma(x)
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_gamma_r(x,&signgam);
+#else
+ double y;
+ y = __ieee754_gamma_r(x,&signgam);
+ if(_LIB_VERSION == _IEEE_) return y;
+ if(!finite(y)&&finite(x)) {
+ if(floor(x)==x&&x<=0.0)
+ return __kernel_standard(x,x,41); /* gamma pole */
+ else
+ return __kernel_standard(x,x,40); /* gamma overflow */
+ } else
+ return y;
+#endif
+}
diff --git a/lib/msun/src/w_gamma_r.c b/lib/msun/src/w_gamma_r.c
new file mode 100644
index 0000000..fa59f8d
--- /dev/null
+++ b/lib/msun/src/w_gamma_r.c
@@ -0,0 +1,46 @@
+/* @(#)wr_gamma.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper double gamma_r(double x, int *signgamp)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ double gamma_r(double x, int *signgamp) /* wrapper lgamma_r */
+#else
+ double gamma_r(x,signgamp) /* wrapper lgamma_r */
+ double x; int *signgamp;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_gamma_r(x,signgamp);
+#else
+ double y;
+ y = __ieee754_gamma_r(x,signgamp);
+ if(_LIB_VERSION == _IEEE_) return y;
+ if(!finite(y)&&finite(x)) {
+ if(floor(x)==x&&x<=0.0)
+ return __kernel_standard(x,x,41); /* gamma pole */
+ else
+ return __kernel_standard(x,x,40); /* gamma overflow */
+ } else
+ return y;
+#endif
+}
diff --git a/lib/msun/src/w_gammaf.c b/lib/msun/src/w_gammaf.c
new file mode 100644
index 0000000..e956f51
--- /dev/null
+++ b/lib/msun/src/w_gammaf.c
@@ -0,0 +1,48 @@
+/* w_gammaf.c -- float version of w_gamma.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+#ifdef __STDC__
+ float gammaf(float x)
+#else
+ float gammaf(x)
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_gammaf_r(x,&signgam);
+#else
+ float y;
+ y = __ieee754_gammaf_r(x,&signgam);
+ if(_LIB_VERSION == _IEEE_) return y;
+ if(!finitef(y)&&finitef(x)) {
+ if(floorf(x)==x&&x<=(float)0.0)
+ /* gammaf pole */
+ return (float)__kernel_standard((double)x,(double)x,141);
+ else
+ /* gammaf overflow */
+ return (float)__kernel_standard((double)x,(double)x,140);
+ } else
+ return y;
+#endif
+}
diff --git a/lib/msun/src/w_gammaf_r.c b/lib/msun/src/w_gammaf_r.c
new file mode 100644
index 0000000..b8c1e12
--- /dev/null
+++ b/lib/msun/src/w_gammaf_r.c
@@ -0,0 +1,51 @@
+/* w_gammaf_r.c -- float version of w_gamma_r.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper float gammaf_r(float x, int *signgamp)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ float gammaf_r(float x, int *signgamp) /* wrapper lgammaf_r */
+#else
+ float gammaf_r(x,signgamp) /* wrapper lgammaf_r */
+ float x; int *signgamp;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_gammaf_r(x,signgamp);
+#else
+ float y;
+ y = __ieee754_gammaf_r(x,signgamp);
+ if(_LIB_VERSION == _IEEE_) return y;
+ if(!finitef(y)&&finitef(x)) {
+ if(floorf(x)==x&&x<=(float)0.0)
+ /* gammaf pole */
+ return (float)__kernel_standard((double)x,(double)x,141);
+ else
+ /* gamma overflow */
+ return (float)__kernel_standard((double)x,(double)x,140);
+ } else
+ return y;
+#endif
+}
diff --git a/lib/msun/src/w_hypot.c b/lib/msun/src/w_hypot.c
new file mode 100644
index 0000000..a434a1d
--- /dev/null
+++ b/lib/msun/src/w_hypot.c
@@ -0,0 +1,43 @@
+/* @(#)w_hypot.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper hypot(x,y)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ double hypot(double x, double y)/* wrapper hypot */
+#else
+ double hypot(x,y) /* wrapper hypot */
+ double x,y;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_hypot(x,y);
+#else
+ double z;
+ z = __ieee754_hypot(x,y);
+ if(_LIB_VERSION == _IEEE_) return z;
+ if((!finite(z))&&finite(x)&&finite(y))
+ return __kernel_standard(x,y,4); /* hypot overflow */
+ else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_hypotf.c b/lib/msun/src/w_hypotf.c
new file mode 100644
index 0000000..7987740
--- /dev/null
+++ b/lib/msun/src/w_hypotf.c
@@ -0,0 +1,47 @@
+/* w_hypotf.c -- float version of w_hypot.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper hypotf(x,y)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ float hypotf(float x, float y) /* wrapper hypotf */
+#else
+ float hypotf(x,y) /* wrapper hypotf */
+ float x,y;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_hypotf(x,y);
+#else
+ float z;
+ z = __ieee754_hypotf(x,y);
+ if(_LIB_VERSION == _IEEE_) return z;
+ if((!finitef(z))&&finitef(x)&&finitef(y))
+ /* hypot overflow */
+ return (float)__kernel_standard((double)x,(double)y,104);
+ else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_j0.c b/lib/msun/src/w_j0.c
new file mode 100644
index 0000000..1b2260b
--- /dev/null
+++ b/lib/msun/src/w_j0.c
@@ -0,0 +1,41 @@
+/* @(#)w_j0.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper j0(double x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double j0(double x) /* wrapper j0 */
+#else
+ double j0(x) /* wrapper j0 */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_j0(x);
+#else
+ double z = __ieee754_j0(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
+ if(fabs(x)>X_TLOSS) {
+ return __kernel_standard(x,x,34); /* j0(|x|>X_TLOSS) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_j0f.c b/lib/msun/src/w_j0f.c
new file mode 100644
index 0000000..f332e2d
--- /dev/null
+++ b/lib/msun/src/w_j0f.c
@@ -0,0 +1,45 @@
+/* w_j0f.c -- float version of w_j0.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper j0f(float x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float j0f(float x) /* wrapper j0f */
+#else
+ float j0f(x) /* wrapper j0f */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_j0f(x);
+#else
+ float z = __ieee754_j0f(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x)) return z;
+ if(fabsf(x)>(float)X_TLOSS) {
+ /* j0f(|x|>X_TLOSS) */
+ return (float)__kernel_standard((double)x,(double)x,134);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_j1.c b/lib/msun/src/w_j1.c
new file mode 100644
index 0000000..068ac94
--- /dev/null
+++ b/lib/msun/src/w_j1.c
@@ -0,0 +1,42 @@
+/* @(#)w_j1.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper of j1
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double j1(double x) /* wrapper j1 */
+#else
+ double j1(x) /* wrapper j1 */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_j1(x);
+#else
+ double z;
+ z = __ieee754_j1(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z;
+ if(fabs(x)>X_TLOSS) {
+ return __kernel_standard(x,x,36); /* j1(|x|>X_TLOSS) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_j1f.c b/lib/msun/src/w_j1f.c
new file mode 100644
index 0000000..87995e3
--- /dev/null
+++ b/lib/msun/src/w_j1f.c
@@ -0,0 +1,46 @@
+/* w_j1f.c -- float version of w_j1.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper of j1f
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float j1f(float x) /* wrapper j1f */
+#else
+ float j1f(x) /* wrapper j1f */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_j1f(x);
+#else
+ float z;
+ z = __ieee754_j1f(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x) ) return z;
+ if(fabsf(x)>(float)X_TLOSS) {
+ /* j1(|x|>X_TLOSS) */
+ return (float)__kernel_standard((double)x,(double)x,136);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_jn.c b/lib/msun/src/w_jn.c
new file mode 100644
index 0000000..a575700
--- /dev/null
+++ b/lib/msun/src/w_jn.c
@@ -0,0 +1,42 @@
+/* @(#)w_jn.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper jn(int n, double x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double jn(int n, double x) /* wrapper jn */
+#else
+ double jn(n,x) /* wrapper jn */
+ double x; int n;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_jn(n,x);
+#else
+ double z;
+ z = __ieee754_jn(n,x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z;
+ if(fabs(x)>X_TLOSS) {
+ return __kernel_standard((double)n,x,38); /* jn(|x|>X_TLOSS,n) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_jnf.c b/lib/msun/src/w_jnf.c
new file mode 100644
index 0000000..3d1a3d5
--- /dev/null
+++ b/lib/msun/src/w_jnf.c
@@ -0,0 +1,42 @@
+/* w_jnf.c -- float version of w_jn.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float jnf(int n, float x) /* wrapper jnf */
+#else
+ float jnf(n,x) /* wrapper jnf */
+ float x; int n;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_jnf(n,x);
+#else
+ float z;
+ z = __ieee754_jnf(n,x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x) ) return z;
+ if(fabsf(x)>(float)X_TLOSS) {
+ /* jn(|x|>X_TLOSS,n) */
+ return (float)__kernel_standard((double)n,(double)x,138);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_lgamma.c b/lib/msun/src/w_lgamma.c
new file mode 100644
index 0000000..88ab418
--- /dev/null
+++ b/lib/msun/src/w_lgamma.c
@@ -0,0 +1,49 @@
+/* @(#)w_lgamma.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/* double lgamma(double x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_lgamma_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+#ifdef __STDC__
+ double lgamma(double x)
+#else
+ double lgamma(x)
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_lgamma_r(x,&signgam);
+#else
+ double y;
+ y = __ieee754_lgamma_r(x,&signgam);
+ if(_LIB_VERSION == _IEEE_) return y;
+ if(!finite(y)&&finite(x)) {
+ if(floor(x)==x&&x<=0.0)
+ return __kernel_standard(x,x,15); /* lgamma pole */
+ else
+ return __kernel_standard(x,x,14); /* lgamma overflow */
+ } else
+ return y;
+#endif
+}
diff --git a/lib/msun/src/w_lgamma_r.c b/lib/msun/src/w_lgamma_r.c
new file mode 100644
index 0000000..74cdfba
--- /dev/null
+++ b/lib/msun/src/w_lgamma_r.c
@@ -0,0 +1,46 @@
+/* @(#)wr_lgamma.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper double lgamma_r(double x, int *signgamp)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ double lgamma_r(double x, int *signgamp) /* wrapper lgamma_r */
+#else
+ double lgamma_r(x,signgamp) /* wrapper lgamma_r */
+ double x; int *signgamp;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_lgamma_r(x,signgamp);
+#else
+ double y;
+ y = __ieee754_lgamma_r(x,signgamp);
+ if(_LIB_VERSION == _IEEE_) return y;
+ if(!finite(y)&&finite(x)) {
+ if(floor(x)==x&&x<=0.0)
+ return __kernel_standard(x,x,15); /* lgamma pole */
+ else
+ return __kernel_standard(x,x,14); /* lgamma overflow */
+ } else
+ return y;
+#endif
+}
diff --git a/lib/msun/src/w_lgammaf.c b/lib/msun/src/w_lgammaf.c
new file mode 100644
index 0000000..b8f66e6
--- /dev/null
+++ b/lib/msun/src/w_lgammaf.c
@@ -0,0 +1,48 @@
+/* w_lgammaf.c -- float version of w_lgamma.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+#ifdef __STDC__
+ float lgammaf(float x)
+#else
+ float lgammaf(x)
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_lgammaf_r(x,&signgam);
+#else
+ float y;
+ y = __ieee754_lgammaf_r(x,&signgam);
+ if(_LIB_VERSION == _IEEE_) return y;
+ if(!finitef(y)&&finitef(x)) {
+ if(floorf(x)==x&&x<=(float)0.0)
+ /* lgamma pole */
+ return (float)__kernel_standard((double)x,(double)x,115);
+ else
+ /* lgamma overflow */
+ return (float)__kernel_standard((double)x,(double)x,114);
+ } else
+ return y;
+#endif
+}
diff --git a/lib/msun/src/w_lgammaf_r.c b/lib/msun/src/w_lgammaf_r.c
new file mode 100644
index 0000000..f955dfb
--- /dev/null
+++ b/lib/msun/src/w_lgammaf_r.c
@@ -0,0 +1,51 @@
+/* w_lgammaf_r.c -- float version of w_lgamma_r.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper float lgammaf_r(float x, int *signgamp)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ float lgammaf_r(float x, int *signgamp) /* wrapper lgammaf_r */
+#else
+ float lgammaf_r(x,signgamp) /* wrapper lgammaf_r */
+ float x; int *signgamp;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_lgammaf_r(x,signgamp);
+#else
+ float y;
+ y = __ieee754_lgammaf_r(x,signgamp);
+ if(_LIB_VERSION == _IEEE_) return y;
+ if(!finitef(y)&&finitef(x)) {
+ if(floorf(x)==x&&x<=(float)0.0)
+ /* lgamma pole */
+ return (float)__kernel_standard((double)x,(double)x,115);
+ else
+ /* lgamma overflow */
+ return (float)__kernel_standard((double)x,(double)x,114);
+ } else
+ return y;
+#endif
+}
diff --git a/lib/msun/src/w_log.c b/lib/msun/src/w_log.c
new file mode 100644
index 0000000..9440eb6
--- /dev/null
+++ b/lib/msun/src/w_log.c
@@ -0,0 +1,43 @@
+/* @(#)w_log.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper log(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ double log(double x) /* wrapper log */
+#else
+ double log(x) /* wrapper log */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_log(x);
+#else
+ double z;
+ z = __ieee754_log(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x) || x > 0.0) return z;
+ if(x==0.0)
+ return __kernel_standard(x,x,16); /* log(0) */
+ else
+ return __kernel_standard(x,x,17); /* log(x<0) */
+#endif
+}
diff --git a/lib/msun/src/w_log10.c b/lib/msun/src/w_log10.c
new file mode 100644
index 0000000..c6910b3
--- /dev/null
+++ b/lib/msun/src/w_log10.c
@@ -0,0 +1,46 @@
+/* @(#)w_log10.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper log10(X)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ double log10(double x) /* wrapper log10 */
+#else
+ double log10(x) /* wrapper log10 */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_log10(x);
+#else
+ double z;
+ z = __ieee754_log10(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
+ if(x<=0.0) {
+ if(x==0.0)
+ return __kernel_standard(x,x,18); /* log10(0) */
+ else
+ return __kernel_standard(x,x,19); /* log10(x<0) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_log10f.c b/lib/msun/src/w_log10f.c
new file mode 100644
index 0000000..96057e1
--- /dev/null
+++ b/lib/msun/src/w_log10f.c
@@ -0,0 +1,51 @@
+/* w_log10f.c -- float version of w_log10.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper log10f(X)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ float log10f(float x) /* wrapper log10f */
+#else
+ float log10f(x) /* wrapper log10f */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_log10f(x);
+#else
+ float z;
+ z = __ieee754_log10f(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x)) return z;
+ if(x<=(float)0.0) {
+ if(x==(float)0.0)
+ /* log10(0) */
+ return (float)__kernel_standard((double)x,(double)x,118);
+ else
+ /* log10(x<0) */
+ return (float)__kernel_standard((double)x,(double)x,119);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_logf.c b/lib/msun/src/w_logf.c
new file mode 100644
index 0000000..5e66a7d
--- /dev/null
+++ b/lib/msun/src/w_logf.c
@@ -0,0 +1,48 @@
+/* w_logf.c -- float version of w_log.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper logf(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ float logf(float x) /* wrapper logf */
+#else
+ float logf(x) /* wrapper logf */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_logf(x);
+#else
+ float z;
+ z = __ieee754_logf(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x) || x > (float)0.0) return z;
+ if(x==(float)0.0)
+ /* logf(0) */
+ return (float)__kernel_standard((double)x,(double)x,116);
+ else
+ /* logf(x<0) */
+ return (float)__kernel_standard((double)x,(double)x,117);
+#endif
+}
diff --git a/lib/msun/src/w_pow.c b/lib/msun/src/w_pow.c
new file mode 100644
index 0000000..571897c
--- /dev/null
+++ b/lib/msun/src/w_pow.c
@@ -0,0 +1,61 @@
+
+
+/* @(#)w_pow.c 5.2 93/10/01 */
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+/*
+ * wrapper pow(x,y) return x**y
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ double pow(double x, double y) /* wrapper pow */
+#else
+ double pow(x,y) /* wrapper pow */
+ double x,y;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_pow(x,y);
+#else
+ double z;
+ z=__ieee754_pow(x,y);
+ if(_LIB_VERSION == _IEEE_|| isnan(y)) return z;
+ if(isnan(x)) {
+ if(y==0.0)
+ return __kernel_standard(x,y,42); /* pow(NaN,0.0) */
+ else
+ return z;
+ }
+ if(x==0.0){
+ if(y==0.0)
+ return __kernel_standard(x,y,20); /* pow(0.0,0.0) */
+ if(finite(y)&&y<0.0)
+ return __kernel_standard(x,y,23); /* pow(0.0,negative) */
+ return z;
+ }
+ if(!finite(z)) {
+ if(finite(x)&&finite(y)) {
+ if(isnan(z))
+ return __kernel_standard(x,y,24); /* pow neg**non-int */
+ else
+ return __kernel_standard(x,y,21); /* pow overflow */
+ }
+ }
+ if(z==0.0&&finite(x)&&finite(y))
+ return __kernel_standard(x,y,22); /* pow underflow */
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_powf.c b/lib/msun/src/w_powf.c
new file mode 100644
index 0000000..d6e48d8
--- /dev/null
+++ b/lib/msun/src/w_powf.c
@@ -0,0 +1,72 @@
+/* w_powf.c -- float version of w_pow.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper powf(x,y) return x**y
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+
+#ifdef __STDC__
+ float powf(float x, float y) /* wrapper powf */
+#else
+ float powf(x,y) /* wrapper powf */
+ float x,y;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_powf(x,y);
+#else
+ float z;
+ z=__ieee754_powf(x,y);
+ if(_LIB_VERSION == _IEEE_|| isnanf(y)) return z;
+ if(isnanf(x)) {
+ if(y==(float)0.0)
+ /* powf(NaN,0.0) */
+ return (float)__kernel_standard((double)x,(double)y,142);
+ else
+ return z;
+ }
+ if(x==(float)0.0){
+ if(y==(float)0.0)
+ /* powf(0.0,0.0) */
+ return (float)__kernel_standard((double)x,(double)y,120);
+ if(finitef(y)&&y<(float)0.0)
+ /* powf(0.0,negative) */
+ return (float)__kernel_standard((double)x,(double)y,123);
+ return z;
+ }
+ if(!finitef(z)) {
+ if(finitef(x)&&finitef(y)) {
+ if(isnanf(z))
+ /* powf neg**non-int */
+ return (float)__kernel_standard((double)x,(double)y,124);
+ else
+ /* powf overflow */
+ return (float)__kernel_standard((double)x,(double)y,121);
+ }
+ }
+ if(z==(float)0.0&&finitef(x)&&finitef(y))
+ /* powf underflow */
+ return (float)__kernel_standard((double)x,(double)y,122);
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_remainder.c b/lib/msun/src/w_remainder.c
new file mode 100644
index 0000000..26b0a2e
--- /dev/null
+++ b/lib/msun/src/w_remainder.c
@@ -0,0 +1,42 @@
+/* @(#)w_remainder.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper remainder(x,p)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double remainder(double x, double y) /* wrapper remainder */
+#else
+ double remainder(x,y) /* wrapper remainder */
+ double x,y;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_remainder(x,y);
+#else
+ double z;
+ z = __ieee754_remainder(x,y);
+ if(_LIB_VERSION == _IEEE_ || isnan(y)) return z;
+ if(y==0.0)
+ return __kernel_standard(x,y,28); /* remainder(x,0) */
+ else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_remainderf.c b/lib/msun/src/w_remainderf.c
new file mode 100644
index 0000000..496bb1f
--- /dev/null
+++ b/lib/msun/src/w_remainderf.c
@@ -0,0 +1,46 @@
+/* w_remainderf.c -- float version of w_remainder.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper remainderf(x,p)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float remainderf(float x, float y) /* wrapper remainder */
+#else
+ float remainderf(x,y) /* wrapper remainder */
+ float x,y;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_remainderf(x,y);
+#else
+ float z;
+ z = __ieee754_remainderf(x,y);
+ if(_LIB_VERSION == _IEEE_ || isnanf(y)) return z;
+ if(y==(float)0.0)
+ /* remainder(x,0) */
+ return (float)__kernel_standard((double)x,(double)y,128);
+ else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_scalb.c b/lib/msun/src/w_scalb.c
new file mode 100644
index 0000000..5fe8033
--- /dev/null
+++ b/lib/msun/src/w_scalb.c
@@ -0,0 +1,60 @@
+/* @(#)w_scalb.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper scalb(double x, double fn) is provide for
+ * passing various standard test suite. One
+ * should use scalbn() instead.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#include <errno.h>
+
+#ifdef __STDC__
+#ifdef _SCALB_INT
+ double scalb(double x, int fn) /* wrapper scalb */
+#else
+ double scalb(double x, double fn) /* wrapper scalb */
+#endif
+#else
+ double scalb(x,fn) /* wrapper scalb */
+#ifdef _SCALB_INT
+ double x; int fn;
+#else
+ double x,fn;
+#endif
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_scalb(x,fn);
+#else
+ double z;
+ z = __ieee754_scalb(x,fn);
+ if(_LIB_VERSION == _IEEE_) return z;
+ if(!(finite(z)||isnan(z))&&finite(x)) {
+ return __kernel_standard(x,(double)fn,32); /* scalb overflow */
+ }
+ if(z==0.0&&z!=x) {
+ return __kernel_standard(x,(double)fn,33); /* scalb underflow */
+ }
+#ifndef _SCALB_INT
+ if(!finite(fn)) errno = ERANGE;
+#endif
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_scalbf.c b/lib/msun/src/w_scalbf.c
new file mode 100644
index 0000000..64a6994
--- /dev/null
+++ b/lib/msun/src/w_scalbf.c
@@ -0,0 +1,65 @@
+/* w_scalbf.c -- float version of w_scalb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper scalbf(float x, float fn) is provide for
+ * passing various standard test suite. One
+ * should use scalbn() instead.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#include <errno.h>
+
+#ifdef __STDC__
+#ifdef _SCALB_INT
+ float scalbf(float x, int fn) /* wrapper scalbf */
+#else
+ float scalbf(float x, float fn) /* wrapper scalbf */
+#endif
+#else
+ float scalbf(x,fn) /* wrapper scalbf */
+#ifdef _SCALB_INT
+ float x; int fn;
+#else
+ float x,fn;
+#endif
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_scalbf(x,fn);
+#else
+ float z;
+ z = __ieee754_scalbf(x,fn);
+ if(_LIB_VERSION == _IEEE_) return z;
+ if(!(finitef(z)||isnanf(z))&&finitef(x)) {
+ /* scalbf overflow */
+ return (float)__kernel_standard((double)x,(double)fn,132);
+ }
+ if(z==(float)0.0&&z!=x) {
+ /* scalbf underflow */
+ return (float)__kernel_standard((double)x,(double)fn,133);
+ }
+#ifndef _SCALB_INT
+ if(!finitef(fn)) errno = ERANGE;
+#endif
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_sinh.c b/lib/msun/src/w_sinh.c
new file mode 100644
index 0000000..e222a02
--- /dev/null
+++ b/lib/msun/src/w_sinh.c
@@ -0,0 +1,42 @@
+/* @(#)w_sinh.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper sinh(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double sinh(double x) /* wrapper sinh */
+#else
+ double sinh(x) /* wrapper sinh */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_sinh(x);
+#else
+ double z;
+ z = __ieee754_sinh(x);
+ if(_LIB_VERSION == _IEEE_) return z;
+ if(!finite(z)&&finite(x)) {
+ return __kernel_standard(x,x,25); /* sinh overflow */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_sinhf.c b/lib/msun/src/w_sinhf.c
new file mode 100644
index 0000000..4bcd9ae
--- /dev/null
+++ b/lib/msun/src/w_sinhf.c
@@ -0,0 +1,46 @@
+/* w_sinhf.c -- float version of w_sinh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper sinhf(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float sinhf(float x) /* wrapper sinhf */
+#else
+ float sinhf(x) /* wrapper sinhf */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_sinhf(x);
+#else
+ float z;
+ z = __ieee754_sinhf(x);
+ if(_LIB_VERSION == _IEEE_) return z;
+ if(!finitef(z)&&finitef(x)) {
+ /* sinhf overflow */
+ return (float)__kernel_standard((double)x,(double)x,125);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_sqrt.c b/lib/msun/src/w_sqrt.c
new file mode 100644
index 0000000..b4cf0a6
--- /dev/null
+++ b/lib/msun/src/w_sqrt.c
@@ -0,0 +1,42 @@
+/* @(#)w_sqrt.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper sqrt(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double sqrt(double x) /* wrapper sqrt */
+#else
+ double sqrt(x) /* wrapper sqrt */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_sqrt(x);
+#else
+ double z;
+ z = __ieee754_sqrt(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
+ if(x<0.0) {
+ return __kernel_standard(x,x,26); /* sqrt(negative) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_sqrtf.c b/lib/msun/src/w_sqrtf.c
new file mode 100644
index 0000000..d24fc8c
--- /dev/null
+++ b/lib/msun/src/w_sqrtf.c
@@ -0,0 +1,46 @@
+/* w_sqrtf.c -- float version of w_sqrt.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper sqrtf(x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float sqrtf(float x) /* wrapper sqrtf */
+#else
+ float sqrt(x) /* wrapper sqrtf */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_sqrtf(x);
+#else
+ float z;
+ z = __ieee754_sqrtf(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x)) return z;
+ if(x<(float)0.0) {
+ /* sqrtf(negative) */
+ return (float)__kernel_standard((double)x,(double)x,126);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_y0.c b/lib/msun/src/w_y0.c
new file mode 100644
index 0000000..91b9760
--- /dev/null
+++ b/lib/msun/src/w_y0.c
@@ -0,0 +1,50 @@
+/* from: @(#)w_j0.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper y0(double x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double y0(double x) /* wrapper y0 */
+#else
+ double y0(x) /* wrapper y0 */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_y0(x);
+#else
+ double z;
+ z = __ieee754_y0(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z;
+ if(x <= 0.0){
+ if(x==0.0)
+ /* d= -one/(x-x); */
+ return __kernel_standard(x,x,8);
+ else
+ /* d = zero/(x-x); */
+ return __kernel_standard(x,x,9);
+ }
+ if(x>X_TLOSS) {
+ return __kernel_standard(x,x,35); /* y0(x>X_TLOSS) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_y0f.c b/lib/msun/src/w_y0f.c
new file mode 100644
index 0000000..52ed041
--- /dev/null
+++ b/lib/msun/src/w_y0f.c
@@ -0,0 +1,54 @@
+/* w_y0f.c -- float version of w_y0.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper y0f(float x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float y0f(float x) /* wrapper y0f */
+#else
+ float y0f(x) /* wrapper y0f */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_y0f(x);
+#else
+ float z;
+ z = __ieee754_y0f(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x) ) return z;
+ if(x <= (float)0.0){
+ if(x==(float)0.0)
+ /* d= -one/(x-x); */
+ return (float)__kernel_standard((double)x,(double)x,108);
+ else
+ /* d = zero/(x-x); */
+ return (float)__kernel_standard((double)x,(double)x,109);
+ }
+ if(x>(float)X_TLOSS) {
+ /* y0(x>X_TLOSS) */
+ return (float)__kernel_standard((double)x,(double)x,135);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_y1.c b/lib/msun/src/w_y1.c
new file mode 100644
index 0000000..b46d81e
--- /dev/null
+++ b/lib/msun/src/w_y1.c
@@ -0,0 +1,50 @@
+/* from: @(#)w_j1.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper of y1
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double y1(double x) /* wrapper y1 */
+#else
+ double y1(x) /* wrapper y1 */
+ double x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_y1(x);
+#else
+ double z;
+ z = __ieee754_y1(x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z;
+ if(x <= 0.0){
+ if(x==0.0)
+ /* d= -one/(x-x); */
+ return __kernel_standard(x,x,10);
+ else
+ /* d = zero/(x-x); */
+ return __kernel_standard(x,x,11);
+ }
+ if(x>X_TLOSS) {
+ return __kernel_standard(x,x,37); /* y1(x>X_TLOSS) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_y1f.c b/lib/msun/src/w_y1f.c
new file mode 100644
index 0000000..b4e4633
--- /dev/null
+++ b/lib/msun/src/w_y1f.c
@@ -0,0 +1,54 @@
+/* w_y1f.c -- float version of w_y1.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper of y1f
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float y1f(float x) /* wrapper y1f */
+#else
+ float y1f(x) /* wrapper y1f */
+ float x;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_y1f(x);
+#else
+ float z;
+ z = __ieee754_y1f(x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x) ) return z;
+ if(x <= (float)0.0){
+ if(x==(float)0.0)
+ /* d= -one/(x-x); */
+ return (float)__kernel_standard((double)x,(double)x,110);
+ else
+ /* d = zero/(x-x); */
+ return (float)__kernel_standard((double)x,(double)x,111);
+ }
+ if(x>(float)X_TLOSS) {
+ /* y1(x>X_TLOSS) */
+ return (float)__kernel_standard((double)x,(double)x,137);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_yn.c b/lib/msun/src/w_yn.c
new file mode 100644
index 0000000..af03376
--- /dev/null
+++ b/lib/msun/src/w_yn.c
@@ -0,0 +1,50 @@
+/* from: @(#)w_jn.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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+/*
+ * wrapper yn(int n, double x)
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ double yn(int n, double x) /* wrapper yn */
+#else
+ double yn(n,x) /* wrapper yn */
+ double x; int n;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_yn(n,x);
+#else
+ double z;
+ z = __ieee754_yn(n,x);
+ if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z;
+ if(x <= 0.0){
+ if(x==0.0)
+ /* d= -one/(x-x); */
+ return __kernel_standard((double)n,x,12);
+ else
+ /* d = zero/(x-x); */
+ return __kernel_standard((double)n,x,13);
+ }
+ if(x>X_TLOSS) {
+ return __kernel_standard((double)n,x,39); /* yn(x>X_TLOSS,n) */
+ } else
+ return z;
+#endif
+}
diff --git a/lib/msun/src/w_ynf.c b/lib/msun/src/w_ynf.c
new file mode 100644
index 0000000..0597b92
--- /dev/null
+++ b/lib/msun/src/w_ynf.c
@@ -0,0 +1,50 @@
+/* w_ynf.c -- float version of w_yn.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id$";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+ float ynf(int n, float x) /* wrapper ynf */
+#else
+ float ynf(n,x) /* wrapper ynf */
+ float x; int n;
+#endif
+{
+#ifdef _IEEE_LIBM
+ return __ieee754_ynf(n,x);
+#else
+ float z;
+ z = __ieee754_ynf(n,x);
+ if(_LIB_VERSION == _IEEE_ || isnanf(x) ) return z;
+ if(x <= (float)0.0){
+ if(x==(float)0.0)
+ /* d= -one/(x-x); */
+ return (float)__kernel_standard((double)n,(double)x,112);
+ else
+ /* d = zero/(x-x); */
+ return (float)__kernel_standard((double)n,(double)x,113);
+ }
+ if(x>(float)X_TLOSS) {
+ /* yn(x>X_TLOSS,n) */
+ return (float)__kernel_standard((double)n,(double)x,139);
+ } else
+ return z;
+#endif
+}
diff --git a/lib/ncurses/ncurses/Makefile b/lib/ncurses/ncurses/Makefile
new file mode 100644
index 0000000..c0e7b35
--- /dev/null
+++ b/lib/ncurses/ncurses/Makefile
@@ -0,0 +1,209 @@
+# Makefile for ncurses
+# $Id$
+
+LIB= ncurses
+SHLIB_MAJOR= 3
+SHLIB_MINOR= 0
+SRCS= lib_kernel.c lib_pad.c lib_bkgd.c \
+ lib_unctrl.c lib_raw.c lib_vidattr.c lib_trace.c lib_beep.c \
+ lib_doupdate.c lib_refresh.c lib_initscr.c lib_newwin.c lib_addch.c \
+ lib_addstr.c lib_scroll.c lib_clreol.c lib_touch.c lib_mvcur.c lib_keyname.c\
+ lib_delwin.c lib_endwin.c lib_clrbot.c lib_move.c lib_printw.c \
+ lib_scanw.c lib_erase.c lib_getch.c lib_options.c lib_acs.c lib_slk.c\
+ lib_box.c lib_clear.c lib_delch.c lib_insch.c \
+ lib_getstr.c lib_mvwin.c lib_longname.c lib_tstp.c \
+ lib_newterm.c lib_set_term.c lib_overlay.c lib_scrreg.c lib_color.c \
+ lib_insstr.c lib_insdel.c lib_twait.c lib_window.c copyright.c
+
+CFLAGS+= -I. -I${.CURDIR} -Wall -DMYTINFO
+DPADD= ${LIBMYTINFO}
+LDADD= -lmytinfo
+
+CLEANFILES+= lib_keyname.c keys.tries
+
+beforedepend: keys.tries
+
+beforeinstall:
+ ${INSTALL} -C -m 444 -o $(BINOWN) -g $(BINGRP) ${.CURDIR}/unctrl.h \
+ ${DESTDIR}/usr/include
+ ${INSTALL} -C -m 444 -o $(BINOWN) -g $(BINGRP) ${.CURDIR}/curses.h \
+ ${DESTDIR}/usr/include/ncurses.h
+
+keys.tries: ${.CURDIR}/keys.list ${.CURDIR}/MKkeys.awk
+ awk -f ${.CURDIR}/MKkeys.awk ${.CURDIR}/keys.list > keys.tries
+
+# in case you don't run make depend
+lib_options.o lib_options.so lib_options.po: keys.tries
+
+lib_keyname.c: ${.CURDIR}/keys.list ${.CURDIR}/MKkeyname.awk
+ awk -f ${.CURDIR}/MKkeyname.awk ${.CURDIR}/keys.list > lib_keyname.c
+
+MAN3 = curs_addch.3 \
+ curs_addchst.3 \
+ curs_addstr.3 \
+ curs_attr.3 \
+ curs_beep.3 \
+ curs_bkgd.3 \
+ curs_border.3 \
+ curs_clear.3 \
+ curs_color.3 \
+ curs_delch.3 \
+ curs_delln.3 \
+ curs_getch.3 \
+ curs_getstr.3 \
+ curs_getyx.3 \
+ curs_inch.3 \
+ curs_inchstr.3 \
+ curs_initscr.3 \
+ curs_inopts.3 \
+ curs_insch.3 \
+ curs_insstr.3 \
+ curs_instr.3 \
+ curs_kernel.3 \
+ curs_move.3 \
+ curs_outopts.3 \
+ curs_overlay.3 \
+ curs_pad.3 \
+ curs_printw.3 \
+ curs_refresh.3 \
+ curs_scanw.3 \
+ curs_scr_dmp.3 \
+ curs_scroll.3 \
+ curs_slk.3 \
+ curs_termatt.3 \
+ curs_termin.3 \
+ curs_touch.3 \
+ curs_util.3 \
+ curs_window.3 \
+ ncurses.3
+
+MAN5 = term.5 terminfo.5
+
+MLINKS+=curs_addch.3 addch.3 curs_addch.3 waddch.3 curs_addch.3 echochar.3 \
+ curs_addch.3 wechochar.3 curs_addch.3 mvaddch.3 \
+ curs_addch.3 mvwaddch.3
+MLINKS+=curs_addchst.3 addchstr.3 curs_addchst.3 addchnstr.3 \
+ curs_addchst.3 waddchstr.3 curs_addchst.3 waddchnstr.3 \
+ curs_addchst.3 mvaddchstr.3 curs_addchst.3 mvaddchnstr.3 \
+ curs_addchst.3 mvwaddchstr.3 curs_addchst.3 mvwaddchnstr.3
+MLINKS+=curs_addstr.3 addstr.3 curs_addstr.3 addnstr.3 \
+ curs_addstr.3 waddstr.3 curs_addstr.3 waddnstr.3 \
+ curs_addstr.3 mvaddstr.3 curs_addstr.3 mvaddnstr.3 \
+ curs_addstr.3 mvwaddstr.3 curs_addstr.3 mvwaddnstr.3
+MLINKS+=curs_attr.3 attroff.3 curs_attr.3 wattroff.3 \
+ curs_attr.3 attron.3 curs_attr.3 wattron.3 \
+ curs_attr.3 attrset.3 curs_attr.3 wattrset.3 \
+ curs_attr.3 standend.3 curs_attr.3 wstandend.3 \
+ curs_attr.3 standout.3 curs_attr.3 wstandout.3
+MLINKS+=curs_beep.3 beep.3 curs_beep.3 flash.3
+MLINKS+=curs_bkgd.3 bkgdset.3 curs_bkgd.3 wbkgdset.3 \
+ curs_bkgd.3 bkgd.3 curs_bkgd.3 wbkgd.3
+MLINKS+=curs_border.3 border.3 curs_border.3 wborder.3 curs_border.3 box.3 \
+ curs_border.3 hline.3 curs_border.3 whline.3 \
+ curs_border.3 vline.3 curs_border.3 wvline.3
+MLINKS+=curs_clear.3 erase.3 curs_clear.3 werase.3 curs_clear.3 clear.3 \
+ curs_clear.3 wclear.3 curs_clear.3 clrtobot.3 \
+ curs_clear.3 wclrtobot.3 curs_clear.3 clrtoeol.3 \
+ curs_clear.3 wclrtoeol.3
+MLINKS+=curs_color.3 start_color.3 curs_color.3 init_pair.3 \
+ curs_color.3 init_color.3 curs_color.3 has_colors.3 \
+ curs_color.3 can_change_color.3 curs_color.3 color_content.3 \
+ curs_color.3 pair_content.3
+MLINKS+=curs_delch.3 delch.3 curs_delch.3 wdelch.3 curs_delch.3 mvdelch.3 \
+ curs_delch.3 mvwdelch.3
+MLINKS+=curs_delln.3 deleteln.3 curs_delln.3 wdeleteln.3 \
+ curs_delln.3 insdelln.3 curs_delln.3 winsdelln.3 \
+ curs_delln.3 insertln.3 curs_delln.3 winsertln.3
+MLINKS+=curs_getch.3 getch.3 curs_getch.3 wgetch.3 curs_getch.3 mvgetch.3 \
+ curs_getch.3 mvwgetch.3 curs_getch.3 ungetch.3
+MLINKS+=curs_getstr.3 getstr.3 curs_getstr.3 wgetstr.3 \
+ curs_getstr.3 mvgetstr.3 curs_getstr.3 mvwgetstr.3 \
+ curs_getstr.3 wgetnstr.3
+MLINKS+=curs_getyx.3 getyx.3 curs_getyx.3 pgetparyx.3 curs_getyx.3 getbegyx.3 \
+ curs_getyx.3 getmaxyx.3
+MLINKS+=curs_inch.3 inch.3 curs_inch.3 winch.3 curs_inch.3 mvinch.3 \
+ curs_inch.3 mvwinch.3
+MLINKS+=curs_inchstr.3 inchstr.3 curs_inchstr.3 inchnstr.3 \
+ curs_inchstr.3 winchstr.3 curs_inchstr.3 winchnstr.3 \
+ curs_inchstr.3 mvinchstr.3 curs_inchstr.3 mvinchnstr.3 \
+ curs_inchstr.3 mvwinchstr.3 curs_inchstr.3 mvwinchnstr.3
+MLINKS+=curs_initscr.3 initscr.3 curs_initscr.3 newterm.3 \
+ curs_initscr.3 endwin.3 curs_initscr.3 isendwin.3 \
+ curs_initscr.3 set_term.3 curs_initscr.3 delscreen.3
+MLINKS+=curs_inopts.3 cbreak.3 curs_inopts.3 nocbreak.3 curs_inopts.3 echo.3 \
+ curs_inopts.3 noecho.3 curs_inopts.3 halfdelay.3 \
+ curs_inopts.3 intrflush.3 curs_inopts.3 keypad.3 curs_inopts.3 meta.3 \
+ curs_inopts.3 nodelay.3 curs_inopts.3 notimeout.3 curs_inopts.3 raw.3 \
+ curs_inopts.3 noraw.3 curs_inopts.3 noqiflush.3 \
+ curs_inopts.3 qiflush.3 curs_inopts.3 timeout.3 \
+ curs_inopts.3 wtimeout.3 curs_inopts.3 typeahead.3
+MLINKS+=curs_insch.3 insch.3 curs_insch.3 winsch.3 curs_insch.3 mvinsch.3 \
+ curs_insch.3 mvwinsch.3
+MLINKS+=curs_insstr.3 insstr.3 curs_insstr.3 insnstr.3 \
+ curs_insstr.3 winsstr.3 curs_insstr.3 winsnstr.3 \
+ curs_insstr.3 mvinsstr.3 curs_insstr.3 mvinsnstr.3 \
+ curs_insstr.3 mvwinsstr.3 curs_insstr.3 mvwinsnstr.3
+MLINKS+=curs_instr.3 instr.3 curs_instr.3 innstr.3 curs_instr.3 winstr.3 \
+ curs_instr.3 winnstr.3 curs_instr.3 mvinstr.3 curs_instr.3 mvinnstr.3 \
+ curs_instr.3 mvwinstr.3 curs_instr.3 mvwinnstr.3
+MLINKS+=curs_kernel.3 def_prog_mode.3 curs_kernel.3 def_shell_mode.3 \
+ curs_kernel.3 reset_prog_mode.3 curs_kernel.3 reset_shell_mode.3 \
+ curs_kernel.3 resetty.3 curs_kernel.3 savetty.3 \
+ curs_kernel.3 getsyx.3 curs_kernel.3 setsyx.3 \
+ curs_kernel.3 ripoffline.3 curs_kernel.3 curs_set.3 \
+ curs_kernel.3 napms.3
+MLINKS+=curs_move.3 move.3 curs_move.3 wmove.3
+MLINKS+=curs_outopts.3 clearok.3 curs_outopts.3 idlok.3 \
+ curs_outopts.3 idcok.3 curs_outopts.3 immedok.3 \
+ curs_outopts.3 leaveok.3 curs_outopts.3 setscrreg.3 \
+ curs_outopts.3 wsetscrreg.3 curs_outopts.3 scrollok.3 \
+ curs_outopts.3 nl.3 curs_outopts.3 nonl.3
+MLINKS+=curs_overlay.3 overlay.3 curs_overlay.3 overwrite.3 \
+ curs_overlay.3 copywin.3
+MLINKS+=curs_pad.3 newpad.3 curs_pad.3 subpad.3 curs_pad.3 prefresh.3 \
+ curs_pad.3 pnoutrefresh.3 curs_pad.3 pechochar.3
+MLINKS+=curs_printw.3 printw.3 curs_printw.3 wprintw.3 \
+ curs_printw.3 mvprintw.3 curs_printw.3 mvwprintw.3 \
+ curs_printw.3 vwprintw.3
+MLINKS+=curs_refresh.3 refresh.3 curs_refresh.3 wrefresh.3 \
+ curs_refresh.3 wnoutrefresh.3 curs_refresh.3 doupdate.3 \
+ curs_refresh.3 redrawwin.3 curs_refresh.3 wredrawln.3
+MLINKS+=curs_scanw.3 scanw.3 curs_scanw.3 wscanw.3 curs_scanw.3 mvscanw.3 \
+ curs_scanw.3 mvwscanw.3 curs_scanw.3 vwscanw.3
+MLINKS+=curs_scr_dmp.3 scr_dump.3 curs_scr_dmp.3 scr_restore.3 \
+ curs_scr_dmp.3 scr_init.3 curs_scr_dmp.3 scr_set.3
+MLINKS+=curs_scroll.3 scroll.3 curs_scroll.3 scrl.3 curs_scroll.3 wscrl.3
+MLINKS+=curs_slk.3 slk_init.3 curs_slk.3 slk_set.3 curs_slk.3 slk_refresh.3 \
+ curs_slk.3 slk_noutrefresh.3 curs_slk.3 slk_label.3 \
+ curs_slk.3 slk_clear.3 curs_slk.3 slk_restore.3 \
+ curs_slk.3 slk_touch.3 curs_slk.3 slk_attron.3 \
+ curs_slk.3 slk_attrset.3 curs_slk.3 slk_attroff.3
+MLINKS+=curs_termatt.3 baudrate.3 curs_termatt.3 erasechar.3 \
+ curs_termatt.3 has_ic.3 curs_termatt.3 has_il.3 \
+ curs_termatt.3 killchar.3 curs_termatt.3 longname.3 \
+ curs_termatt.3 termattrs.3 curs_termatt.3 termname.3
+
+# XXX name clash with termcap(3)
+# MLINKS+= curs_termin.3 tparm.3
+MLINKS+=curs_termin.3 setupterm.3 curs_termin.3 setterm.3 \
+ curs_termin.3 set_curterm.3 curs_termin.3 del_curterm.3 \
+ curs_termin.3 restartterm.3 \
+ curs_termin.3 putp.3 curs_termin.3 vidputs.3 \
+ curs_termin.3 vidattr.3 curs_termin.3 mvcur.3 \
+ curs_termin.3 tigetflag.3 curs_termin.3 tigetnum.3 \
+ curs_termin.3 tigetstr.3
+MLINKS+=curs_touch.3 touchwin.3 curs_touch.3 touchline.3 \
+ curs_touch.3 untouchwin.3 curs_touch.3 wtouchln.3 \
+ curs_touch.3 is_linetouched.3 curs_touch.3 is_wintouched.3
+MLINKS+=curs_util.3 unctrl.3 curs_util.3 keyname.3 \
+ curs_util.3 filter.3 curs_util.3 use_env.3 \
+ curs_util.3 putwin.3 curs_util.3 getwin.3 \
+ curs_util.3 delay_output.3 curs_util.3 flushinp.3
+MLINKS+=curs_window.3 newwin.3 curs_window.3 delwin.3 \
+ curs_window.3 mvwin.3 curs_window.3 subwin.3 \
+ curs_window.3 derwin.3 curs_window.3 mvderwin.3 \
+ curs_window.3 dupwin.3 curs_window.3 wsyncup.3 \
+ curs_window.3 syncok.3 curs_window.3 wcursyncup.3 \
+ curs_window.3 wsyncdown.3
+
+.include <bsd.lib.mk>
OpenPOWER on IntegriCloud